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 »

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: 60
Joined: Mon Nov 06, 2017 6:41 pm

Re: S-function in Simulink

Post by piotr [BayesFusion] »

matsmile.cpp
(9.92 KiB) Downloaded 376 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 »

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: 60
Joined: Mon Nov 06, 2017 6:41 pm

Re: S-function in Simulink

Post by piotr [BayesFusion] »

matsmile.cpp
(11.8 KiB) Downloaded 381 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.
piotr [BayesFusion]
Site Admin
Posts: 60
Joined: Mon Nov 06, 2017 6:41 pm

Re: S-function in Simulink

Post by piotr [BayesFusion] »

There is slightly-improved Smile-Matlab wrapper:
matsmile.cpp
(9.78 KiB) Downloaded 353 times
It has minimal functionality to support Discrete Bayesian Networks.

Hello program that uses wrapper looks like this:

Code: Select all

net = matsmile('newNetwork');
matsmile('readFile', net, 'VentureBN.xdsl');
matsmile('setEvidence', net, 'Forecast', 'Moderate');
matsmile('updateBeliefs', net);
beliefs = matsmile('getValue', net, 'Success');
outcomeIds = matsmile('getOutcomeIds', net, 'Success');
fprintf("%s\n", outcomeIds + "=" + beliefs);
matsmile('deleteNetwork', net);
shooltz[BayesFusion]
Site Admin
Posts: 1417
Joined: Mon Nov 26, 2007 5:51 pm

Re: S-function in Simulink

Post by shooltz[BayesFusion] »

The information about calling SMILE from Matlab (including the source code of matsmile.cpp) is now included in main SMILE manual at https://support.bayesfusion.com/docs
Post Reply