S-function in Simulink

The engine.
Post Reply
inaba
Posts: 2
Joined: Wed May 01, 2019 2:22 pm

S-function in Simulink

Post by inaba » Thu May 02, 2019 11:27 am

Hi,

I am trying to use an S-function in Matlab to use Genie mid-simulation in Simulink. The model needs to be used in the software Veristand, so I need to build the model and therefore generate a function wrapper in C or C++. Does anyone have an example of an S-function wrapper in C or C++ which calls Smile/Genie?

If not, what are the necessary steps to implement the Genie connection to Matlab in C/C++?

Thanks in advance!

Ina

piotr [BayesFusion]
Site Admin
Posts: 18
Joined: Mon Nov 06, 2017 6:41 pm

Re: S-function in Simulink

Post by piotr [BayesFusion] » Tue May 07, 2019 4:51 pm

matsmile.cpp
(9.92 KiB) Downloaded 10 times
At first, you have to make sure, that C++ compiler chosen by Matlab is compatible with Smile binaries.

Code: Select all

mex -setup cpp
If there is compatibility, change directory to the one where the Smile was unpacked.

Code: Select all

cd('full/path/to/smile/directory');
The easiest way I found was to implement new MexFunction class inheriting a matlab::mex::Function.

Code: Select all

.
.
.
class MexFunction : public matlab::mex::Function {
public:
    void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
        std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
        matlab::data::ArrayFactory factory;
        int method = checkMethod(inputs);
        checkArguments(method, outputs, inputs);
        wrapperBegin(method, outputs, inputs);
    }

private:    

.
.
.
    
    //WRAPPER BLOCK


    int nodesCount(const void * netPtr) {
        DSL_network * net = (DSL_network*)netPtr;
        return net->GetNumberOfNodes();
    }
    
    
.
.
.
    
    void wrapperNodesCount(matlab::mex::ArgumentList & outputs, matlab::mex::ArgumentList & inputs) {
        matlab::data::ArrayFactory factory;
        matlab::data::TypedArray<uint64_t> arr = inputs[1];
        auto netPtr = decodePtr(arr[0]);
        outputs[0] = factory.createScalar(nodesCount(netPtr));
    }

.
.
.

};
There's some if ladders (because of input/output validaton), but most important code starts with "WRAPPER BLOCK".
Methods whose names starts with "wrapper" are a "bridge" between Matlab and C++ and those above them do all logic.

You can compile the code with the command:

Code: Select all

mex matsmile.cpp
(it produces matsmile.mexw64)

Example commands:

Code: Select all

NET = matsmile('createnetwork'); % create new DSL_network object
matsmile('readfile', NET, 'hepar.xdsl'); % read network from xdsl file
matsmile('nodescount', NET); % get number of nodes in loaded/created network
matsmile('setevidence' NET, 'alcoholism', 'present'); % set evidence on given node
matsmile('freenetwork', NET); % releases memory, don't forget about that because of memory leaks :)
Tested with MATLAB R2019a and Windows 10.

inaba
Posts: 2
Joined: Wed May 01, 2019 2:22 pm

Re: S-function in Simulink

Post by inaba » Tue May 14, 2019 2:50 pm

Thank you, the connection between Matlab and Genie using C++ works!

However, Matlab is crashing during simulation in Simulink. It seems to be the GetMatrix() function, as the simulation runs fine without this. Are there alternative ways to extract the probability of a state at a particular node? Preferably as an integer so it can be used further in simulation.

Ina

piotr [BayesFusion]
Site Admin
Posts: 18
Joined: Mon Nov 06, 2017 6:41 pm

Re: S-function in Simulink

Post by piotr [BayesFusion] » Wed May 15, 2019 7:00 pm

matsmile.cpp
(11.8 KiB) Downloaded 3 times
I added node and outcome validation, so the debugging process should be easier now. Getting node value depends on its type, but most common case (CPT node) is described here https://support.bayesfusion.com/docs/SM ... value.html. If your network contains Equation nodes, you have to get node value as DSL_valEqEvaluation.

Code: Select all

DSL_valEqEvaluation * eqValue = static_cast<DSL_valEqEvaluation *>(nodeValue);
const vector<double> &discBeliefs = eqValue->GetDiscBeliefs();
But it is still probabilities vector.

If you need integer, chosen node should be observed:

Code: Select all

node->Value()->IsRealEvidence(); 
node->Value()->GetEvidence();
I hope the answer was helpful.

Post Reply