mloptimizer.cpp 6.69 KB
Newer Older
1
2
3
4
5
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>

6
#include "common/config.h"
7
8
#include "optimizers/mloptimizer.h"
#include "toolboxes/errormessages.h"
9
#include <iostream>
10
11

MLOptimizer::MLOptimizer( Config* settings ) : OptimizerBase( settings ) {
12

13
    initializePython();
14

15
16
    // initialize python script
    std::string moduleName = "callNeuralClosure";
17
18
19
20
21
22
23

    _pModule = PyImport_ImportModule( moduleName.c_str() );
    if( !_pModule ) {
        PyErr_Print();
        Py_DecRef( _pModule );
        ErrorMessages::Error( "'" + moduleName + "' can not be imported!", CURRENT_FUNCTION );
    }
24
25
26

    // initialize Network
    initializeNetwork();
27
28
}

29
MLOptimizer::~MLOptimizer() { finalizePython(); }
30

Steffen Schotthöfer's avatar
Steffen Schotthöfer committed
31
void MLOptimizer::Solve( Vector& alpha, Vector& u, const VectorVector& /*moments*/, unsigned /*idx_cell*/ ) {
32

33
34
    // Convert Vector to array
    const unsigned input_size = u.size();
35
    double* nn_input          = new double[u.size()];
36

37
    for( unsigned idx_sys = 0; idx_sys < input_size; idx_sys++ ) {
38
39
40
41
42
        nn_input[idx_sys] = u[idx_sys];
        // std::cout << nn_input[idx_sys] << ", ";
    }

    //  initialize_python();
43
44
45
    double* nn_output = callNetwork( input_size, nn_input );    //  nn_input;

    // std::cout << "Solution found in cell: " << idx_cell << "/8441 \n";
46
47
48

    for( unsigned i = 0; i < input_size; i++ ) {
        // std::cout << nn_output[i] << ", ";
Steffen Schotthöfer's avatar
Steffen Schotthöfer committed
49
        alpha[i] = nn_output[i];
50
    }
51
    //  std::cout << std::endl;
52
    delete[] nn_input;
53
54
}

Steffen Schotthöfer's avatar
Steffen Schotthöfer committed
55
void MLOptimizer::SolveMultiCell( VectorVector& alpha, VectorVector& u, const VectorVector& /*moments*/ ) {
56
57
58
59
60
61
62

    const unsigned batch_size = u.size();       // batch size = number of cells
    const unsigned sol_dim    = u[0].size();    // dimension of input vector = nTotalEntries

    const unsigned n_size = batch_size * sol_dim;    // length of input array

    // Covert input to array
63
    double* nn_input = new double[n_size];
64
65
66
67
68
69
70
71
72
73

    unsigned idx_input = 0;
    for( unsigned idx_cell = 0; idx_cell < batch_size; idx_cell++ ) {
        for( unsigned idx_sys = 0; idx_sys < sol_dim; idx_sys++ ) {
            nn_input[idx_input] = u[idx_cell][idx_sys];
            idx_input++;
        }
    }

    double* nn_output = callNetworkMultiCell( batch_size, sol_dim, nn_input );
74

75
76
77
    unsigned idx_output = 0;
    for( unsigned idx_cell = 0; idx_cell < batch_size; idx_cell++ ) {
        for( unsigned idx_sys = 0; idx_sys < sol_dim; idx_sys++ ) {
Steffen Schotthöfer's avatar
Steffen Schotthöfer committed
78
            alpha[idx_cell][idx_sys] = nn_output[idx_output];
79
80
81
            idx_output++;
        }
    }
82
83

    delete[] nn_output;
84
85
}

86
void MLOptimizer::initNumpy() {
87
88
89
    _import_array();    // Check, if this gives a mem Leak!
}

90
void MLOptimizer::initializePython() {
91
    // Initialize the Python Interpreter
92
    std::string pyPath = KITRT_PYTHON_PATH;
93
    pyPath             = pyPath + "/../ext/neuralEntropy/python";
94
    if( !Py_IsInitialized() ) {
95

96
97
98
99
100
101
        Py_InitializeEx( 0 );
        if( !Py_IsInitialized() ) {
            ErrorMessages::Error( "Python init failed!", CURRENT_FUNCTION );
        }
        PyRun_SimpleString( ( "import sys\nsys.path.append('" + pyPath + "')" ).c_str() );
    }
102

103
    // std::cout << "Python working directory is: " << pyPath << " \n";
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
    initNumpy();
}

void MLOptimizer::initializeNetwork() {
    PyObject *pArgs, *pFunc;    // *pModule,
    // PyArrayObject* np_ret;

    pFunc = PyObject_GetAttrString( _pModule, "initModelCpp" );
    if( !pFunc || !PyCallable_Check( pFunc ) ) {
        PyErr_Print();
        Py_DecRef( _pModule );
        Py_DecRef( pFunc );
        ErrorMessages::Error( "'initModelCpp' is null or not callable!", CURRENT_FUNCTION );
    }

    long int dims[1]     = { 2 };    // input: [modelNumber, maxDegree_N]
    int* input           = new int[2];
    input[0]             = (int)_settings->GetNeuralModel();
    input[1]             = (int)_settings->GetMaxMomentDegree();
    PyObject* inputArray = PyArray_SimpleNewFromData( 1, dims, NPY_INT, (void*)input );

    pArgs = PyTuple_New( 1 );
    PyTuple_SetItem( pArgs, 0, reinterpret_cast<PyObject*>( inputArray ) );

    // Call Python function

    PyObject_CallObject( pFunc, pArgs );    // PyObject

    // np_ret = reinterpret_cast<PyArrayObject*>( pReturn );    // Cast from PyObject to PyArrayObject
    //
    // double* nn_output = reinterpret_cast<double*>( PyArray_DATA( np_ret ) );    // Get Output

    // Finalizing
    Py_DecRef( pFunc );
    // Py_DECREF( np_ret );
139
}
140

141
void MLOptimizer::finalizePython() {
142
143
144
    Py_DecRef( _pModule );
    Py_Finalize();
}
145

146
double* MLOptimizer::callNetwork( const unsigned inputDim, double* nnInput ) {
147

148
149
    PyObject *pArgs, *pReturn, *pFunc;    // *pModule,
    PyArrayObject* np_ret;
150

151
    pFunc = PyObject_GetAttrString( _pModule, "callNetwork" );
152
153
    if( !pFunc || !PyCallable_Check( pFunc ) ) {
        PyErr_Print();
154
        Py_DecRef( _pModule );
155
        Py_DecRef( pFunc );
156
        ErrorMessages::Error( "'callNetwork' is null or not callable!", CURRENT_FUNCTION );
157
158
    }

159
    long int dims[1] = { inputDim };    // Why was this const?
160

161
    PyObject* inputArray = PyArray_SimpleNewFromData( 1, dims, NPY_DOUBLE, (void*)nnInput );
162

163
164
    pArgs = PyTuple_New( 1 );
    PyTuple_SetItem( pArgs, 0, reinterpret_cast<PyObject*>( inputArray ) );
165

166
167
168
169
170
171
172
173
174
175
176
177
178
179
    // Call Python function
    pReturn = PyObject_CallObject( pFunc, pArgs );    // PyObject

    np_ret = reinterpret_cast<PyArrayObject*>( pReturn );    // Cast from PyObject to PyArrayObject

    double* nn_output = reinterpret_cast<double*>( PyArray_DATA( np_ret ) );    // Get Output

    // Finalizing
    Py_DecRef( pFunc );
    Py_DECREF( np_ret );

    return nn_output;
}

180
double* MLOptimizer::callNetworkMultiCell( const unsigned batchSize, const unsigned inputDim, double* nnInput ) {
181
182
183
184

    PyObject *pArgs, *pReturn, *pFunc;
    PyArrayObject* np_ret;

185
    pFunc = PyObject_GetAttrString( _pModule, "callNetworkBatchwise" );
186
187
    if( !pFunc || !PyCallable_Check( pFunc ) ) {
        PyErr_Print();
188
        Py_DecRef( _pModule );
189
        Py_DecRef( pFunc );
190
        ErrorMessages::Error( "'callNetworkBatchwise' is null or not callable!", CURRENT_FUNCTION );
191
    }
192

193
    long int dims[2] = { batchSize, inputDim };    // Why was this const?
194

195
    PyObject* inputArray = PyArray_SimpleNewFromData( 2, dims, NPY_DOUBLE, (void*)nnInput );
196
197
198
199

    pArgs = PyTuple_New( 1 );
    PyTuple_SetItem( pArgs, 0, reinterpret_cast<PyObject*>( inputArray ) );

200
    // Call Python function
201

202
203
204
205
    pReturn = PyObject_CallObject( pFunc, pArgs );    // PyObject

    np_ret = reinterpret_cast<PyArrayObject*>( pReturn );    // Cast from PyObject to PyArrayObject

206
    double* nn_output = reinterpret_cast<double*>( PyArray_DATA( np_ret ) );    // Get Output
207
208
209
210
211

    // Finalizing
    Py_DecRef( pFunc );
    Py_DECREF( np_ret );

212
    return nn_output;
213
}