Commit 42b19844 authored by Claes Sjofors's avatar Claes Sjofors

Sim_ModelMLP, MLP model object added

parent d14b36ee
......@@ -57,5 +57,7 @@ void Sim_CylinderTankFo_init(pwr_sClass_Sim_CylinderTankFo* o);
void Sim_CylinderTankFo_exec(plc_sThread* tp, pwr_sClass_Sim_CylinderTankFo* o);
void Sim_FurnaceFo_init(pwr_sClass_Sim_FurnaceFo* o);
void Sim_FurnaceFo_exec(plc_sThread* tp, pwr_sClass_Sim_FurnaceFo* o);
void Sim_ModelMLP_Fo_init(pwr_sClass_Sim_ModelMLP_Fo* o);
void Sim_ModelMLP_Fo_exec(plc_sThread* tp, pwr_sClass_Sim_ModelMLP_Fo* o);
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2019 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_simul_mlp.c */
#include <stdio.h>
#include <math.h>
#include "co_dcli.h"
#include "simul.h"
typedef enum {
mlp_eActivation_No = 0,
mlp_eActivation_Identity = 1,
mlp_eActivation_Logistic = 2,
mlp_eActivation_Tanh = 3,
mlp_eActivation_Relu = 4
} mlp_eActivation;
typedef struct {
unsigned int layers;
unsigned int *layer_sizes;
mlp_eActivation activation;
double **intercepts;
double ***coefs;
double **h;
double *inputs;
double aval[20];
} mlp_sCtx, *mlp_tCtx;
int mlp_import(const char *file, mlp_sCtx *mlp);
void mlp_free(mlp_sCtx *mlp);
void mlp_model(mlp_tCtx mlp, double *x, double *out);
void Sim_ModelMLP_Fo_init(pwr_sClass_Sim_ModelMLP_Fo* o)
{
pwr_sClass_Sim_ModelMLP *co;
pwr_tDlid dlid;
pwr_tStatus sts;
int i;
sts = gdh_DLRefObjectInfoAttrref(
&o->PlcConnect, (void**)&o->PlcConnectP, &dlid);
if (EVEN(sts))
o->PlcConnectP = 0;
co = (pwr_sClass_Sim_ModelMLP *)o->PlcConnectP;
if (!co) {
co->Status = 2;
return;
}
o->ModelP = (mlp_tCtx)calloc(1, sizeof(mlp_sCtx));
co->Status = mlp_import(co->ModelFile, (mlp_tCtx)o->ModelP);
if (EVEN(co->Status))
return;
co->Layers = ((mlp_tCtx)o->ModelP)->layers;
for (i = 0; i < MIN(co->Layers, sizeof(co->LayerSizes)/sizeof(co->LayerSizes[0])); i++)
co->LayerSizes[i] = ((mlp_tCtx)o->ModelP)->layer_sizes[i];
((mlp_tCtx)o->ModelP)->inputs = (double *)calloc(((mlp_tCtx)o->ModelP)->layer_sizes[0],
sizeof(double));
}
void Sim_ModelMLP_Fo_exec(plc_sThread* tp, pwr_sClass_Sim_ModelMLP_Fo* o)
{
pwr_sClass_Sim_ModelMLP *co = (pwr_sClass_Sim_ModelMLP *)o->PlcConnectP;
double out;
int i;
if (!co || EVEN(co->Status))
return;
for (i = 0; i < co->LayerSizes[0]; i++) {
((mlp_tCtx)o->ModelP)->inputs[i] = (double)(**(pwr_tFloat32 **)((char *)&o->In1P + pwr_cInputOffset * i));
}
mlp_model((mlp_tCtx)o->ModelP, ((mlp_tCtx)o->ModelP)->inputs, &out);
o->Out = (pwr_tFloat32)out;
}
int mlp_import(const char *file, mlp_sCtx *mlp)
{
pwr_tFileName fname;
FILE *fp;
char line[2000];
unsigned int i, j, k;
char *s;
dcli_translate_filename(fname, file);
fp = fopen(fname, "r");
if (!fp)
return 0;
while (dcli_read_line(line, sizeof(line), fp)) {
if (strncmp(line, "Layers ", 7) == 0) {
if (sscanf(&line[7], "%d", &mlp->layers) != 1) {
printf("Syntax error\n");
return 0;
}
}
else if (strncmp(line, "LayerSizes ", 11) == 0) {
mlp->layer_sizes = (unsigned int *)calloc(mlp->layers, sizeof(int));
s = line;
for (i = 0; i < mlp->layers; i++) {
s = strchr(s, ' ');
if (!s) {
printf("Syntax error\n");
return 0;
}
s++;
if (sscanf(s, "%d", &mlp->layer_sizes[i]) != 1) {
printf("Syntax error\n");
return 0;
}
}
}
else if (strncmp(line, "Activation ", 11) == 0) {
if (strcmp(&line[11], "identity") == 0)
mlp->activation = mlp_eActivation_Identity;
else if (strcmp(&line[11], "logistic") == 0)
mlp->activation = mlp_eActivation_Logistic;
else if (strcmp(&line[11], "tanh") == 0)
mlp->activation = mlp_eActivation_Tanh;
else if (strcmp(&line[11], "relu") == 0)
mlp->activation = mlp_eActivation_Relu;
else
mlp->activation = mlp_eActivation_No;
}
else if (strncmp(line, "Intercepts", 9) == 0) {
mlp->intercepts = (double **)calloc(mlp->layers - 1, sizeof(double *));
for (i = 0; i < mlp->layers - 1; i++)
mlp->intercepts[i] = (double *)calloc(mlp->layer_sizes[i+1], sizeof(double));
for (i = 0; i < mlp->layers - 1; i++) {
dcli_read_line(line, sizeof(line), fp);
s = line;
for (j = 0; j < mlp->layer_sizes[i+1]; j++) {
if (j != 0) {
s = strchr(s, ' ');
s++;
}
if (sscanf(s, "%lf", &mlp->intercepts[i][j]) != 1) {
printf("Syntax error\n");
return 0;
}
}
}
}
else if (strncmp(line, "Coefs", 5) == 0) {
unsigned int i1, j1, k1;
mlp->coefs = (double ***)calloc(mlp->layers, sizeof(double **));
for (i = 0; i < mlp->layers - 1; i++) {
mlp->coefs[i] = (double **)calloc(mlp->layer_sizes[i+1], sizeof(double));
for ( j = 0; j < mlp->layer_sizes[i+1]; j++) {
mlp->coefs[i][j] = (double *)calloc(mlp->layer_sizes[i], sizeof(double));
}
}
for (i = 0; i < mlp->layers - 1; i++) {
for (j = 0; j < mlp->layer_sizes[i+1]; j++) {
for (k = 0; k < mlp->layer_sizes[i]; k++) {
dcli_read_line(line, sizeof(line), fp);
sscanf(line, "%d %d %d %lf", &i1, &j1, &k1, &mlp->coefs[i][j][k]);
if (i1 != i || j1 != j || k1 != k)
printf("Syntax error\n");
}
}
}
}
}
fclose(fp);
/* Allocate weights */
mlp->h = (double **)calloc(mlp->layers - 1, sizeof(double *));
for (i = 0; i < mlp->layers - 1; i++) {
mlp->h[i] = (double *)calloc(mlp->layer_sizes[i+1], sizeof(double));
}
return 1;
}
void mlp_free(mlp_sCtx *mlp)
{
unsigned int i, j;
for (i = 0; i < mlp->layers - 1; i++)
free(mlp->intercepts[i]);
free(mlp->intercepts);
for (i = 0; i < mlp->layers - 1; i++) {
for ( j = 0; j < mlp->layer_sizes[i+1]; j++)
free(mlp->coefs[i][j]);
free(mlp->coefs[i]);
}
free(mlp->coefs);
for (i = 0; i < mlp->layers; i++)
free(mlp->h[i]);
free(mlp->h);
free(mlp);
}
void mlp_model(mlp_tCtx mlp, double *x, double *out)
{
unsigned int i, j, k;
for (i = 0; i < mlp->layers - 1; i++) {
for (j = 0; j < mlp->layer_sizes[i+1]; j++) {
mlp->h[i][j] = mlp->intercepts[i][j];
for (k = 0; k < mlp->layer_sizes[i]; k++) {
if (i == 0) {
mlp->h[i][j] += mlp->coefs[i][j][k] * x[k];
}
else
mlp->h[i][j] += mlp->coefs[i][j][k] * mlp->h[i-1][k];
}
if (i != mlp->layers - 2) {
switch (mlp->activation) {
case mlp_eActivation_Tanh:
mlp->h[i][j] = tanh(mlp->h[i][j]);
break;
case mlp_eActivation_Identity:
break;
case mlp_eActivation_Relu:
if (mlp->h[i][j] < 0)
mlp->h[i][j] = 0;
break;
case mlp_eActivation_Logistic:
mlp->h[i][j] = 1.0/(1.0 - exp(-mlp->h[i][j]));
break;
default: ;
}
}
}
}
*out = mlp->h[mlp->layers - 2][0];
}
! Generated by wb_print_wbl 07-NOV-2019 13:42:48.29
! Volume Simul
! Version V5.7.0
Volume Simul $ClassVolume 0.0.0.8
Body SysBody 01-JAN-1970 01:00:00.00
Attr NextOix = "_X62"
Attr NextCix = "_X26"
Attr NextTix[0] = "_X7"
Attr NextOix = "_X80"
Attr NextCix = "_X28"
Attr NextTix[0] = "_X8"
EndBody
Object Type $TypeHier 3 28-FEB-2016 17:05:51.66
Object Sim_GenType $TypeDef 1 23-MAY-2016 16:31:35.02
......@@ -2210,5 +2213,393 @@ Volume Simul $ClassVolume 0.0.0.8
EndBody
EndObject
EndObject
!/**
! @Version 1.0
! @Author cs
! @Summary MLP model.
! MLP model.
!
! MLP (MultiLevel Perceptor) model object.
! The MLP is created and trained with the sev_analyser.
! The exported model file is specified in ModelFile.
!
! @b Plc coding
! For plc coding the function object Sim_ModelMLP_Fo is used.
! Create a function object in the plc editor and connect it to the
! current object with the connect function.
!
! @b See also
! @classlink Sim_ModelMLP_Fo basecomponent_sim_modelmlp_fo.html
!*/
Object Sim_ModelMLP $ClassDef 26 07-NOV-2019 12:26:10.35
Body SysBody 07-NOV-2019 12:25:46.68
Attr Editor = 0
Attr Method = 0
Attr Flags = 144
EndBody
Object RtBody $ObjBodyDef 1 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:26:18.41
Attr StructName = "Sim_ModelMLP"
Attr NextAix = "_X22"
EndBody
!/**
! Model file exported from the sev_analyser.
!*/
Object ModelFile $Attribute 15 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "ModelFile"
Attr Size = 40
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
!/**
! Number of hidden layers.
!*/
Object Layers $Attribute 17 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "Layers"
Attr Size = 4
Attr Flags = 1040
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! Size of the hidden layers.
!*/
Object LayerSizes $Attribute 18 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "LayerSizes"
Attr Size = 80
Attr Flags = 1042
Attr Elements = 20
Attr TypeRef = "pwrs:Type-$UInt32"
EndBody
EndObject
!/**
! Activation function.
!*/
Object Activation $Attribute 19 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "Activation"
Attr Size = 16
Attr Flags = 1040
Attr TypeRef = "pwrs:Type-$String16"
EndBody
EndObject
!/**
! Status.
!*/
Object Status $Attribute 20 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "Status"
Attr Size = 4
Attr Flags = 1040
Attr TypeRef = "pwrs:Type-$Status"
EndBody
EndObject
!/**
! @Summary The plc function object connected to this object.
! The plc function object connected to this object.
! This attribute is set when the function object is connected from
! the plc editor by the connect function.
!*/
Object PlcConnect $Attribute 21 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "PlcConnect"
Attr Size = 24
Attr TypeRef = "pwrs:Type-$AttrRef"
EndBody
EndObject
EndObject
Object Template Sim_ModelMLP 2154528768 07-NOV-2019 12:25:46.68
Body RtBody 01-JAN-1970 01:00:00.00
EndBody
EndObject
EndObject
!/**
! @Version 1.0
! @Author cs
! @Code simul_mpl.c
! @Summary Function object to Sim_ModelMLP.
! Function object to Sim_ModelMLP.
!
! @image orm_sim_modelmlp_fo_fo.png
!
! Connect the function object to an object of class or subclass of
! Sim_ModelMLP.
!
! @b See also
! @classlink Sim_ModelMLP simul_modelmlp.html
!*/
Object Sim_ModelMLP_Fo $ClassDef 27 07-NOV-2019 12:26:37.91
Body SysBody 07-NOV-2019 12:25:46.68
Attr Editor = 0
Attr Method = 0
Attr Flags = 144
EndBody
Object RtBody $ObjBodyDef 1 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:26:49.51
Attr StructName = "Sim_ModelMLP_Fo"
Attr NextAix = "_X64"
EndBody
!/**
! Model input value 1
!*/
Object In1 $Input 43 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In1"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In1"
EndBody
EndObject
!/**
! Model input value 2
!*/
Object In2 $Input 44 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In2"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In2"
EndBody
EndObject
!/**
! Model input value 3
!*/
Object In3 $Input 45 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In3"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In3"
EndBody
EndObject
!/**
! Model input value 4
!*/
Object In4 $Input 46 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In4"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In4"
EndBody
EndObject
!/**
! Model input value 5
!*/
Object In5 $Input 47 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In5"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In5"
EndBody
EndObject
!/**
! Model input value 6
!*/
Object In6 $Input 48 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In6"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In6"
EndBody
EndObject
!/**
! Model input value 7
!*/
Object In7 $Input 49 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In7"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In7"
EndBody
EndObject
!/**
! Model input value 8
!*/
Object In8 $Input 50 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In8"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In8"
EndBody
EndObject
!/**
! Model input value 9
!*/
Object In9 $Input 51 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In9"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In9"
EndBody
EndObject
!/**
! Model input value 10
!*/
Object In10 $Input 52 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In10"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In10"
EndBody
EndObject
!/**
! Model input value 11
!*/
Object In11 $Input 53 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In11"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In11"
EndBody
EndObject
!/**
! Model input value 12
!*/
Object In12 $Input 54 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In12"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In12"
EndBody
EndObject
!/**
! Model input value 13
!*/
Object In13 $Input 55 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In13"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In13"
EndBody
EndObject
!/**
! Model input value 14
!*/
Object In14 $Input 56 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In14"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In14"
EndBody
EndObject
!/**
! Model input value 15
!*/
Object In15 $Input 57 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In15"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In15"
EndBody
EndObject
!/**
! Model input value 16
!*/
Object In16 $Input 58 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "In16"
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "In16"
EndBody
EndObject
!/**
! Pointer to scan time.
!*/
Object ScanTime $Intern 59 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "ScanTime"
Attr Flags = 65537
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Pointer to main object.
!*/
Object ModelP $Intern 60 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "ModelP"
Attr Flags = 66577
Attr TypeRef = "pwrs:Type-$Void"
EndBody
EndObject
!/**
! @Summary The main object connected to this object.
! The main object of class CompPID (or a subclass of this class).
! This attribute is set when the object is connected to the main object
! with the connect function in the plc editor.
!*/
Object PlcConnect $Intern 61 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "PlcConnect"
Attr TypeRef = "pwrs:Type-$AttrRef"
EndBody
EndObject
Object PlcConnectP $Intern 62 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "PlcConnectP"
Attr Flags = 67585
Attr TypeRef = "pwrs:Type-$Char"
EndBody
EndObject
!/**
! Model output value.
!*/
Object Out $Output 63 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr PgmName = "Out"
Attr Flags = 1040
Attr TypeRef = "pwrs:Type-$Float32"
Attr GraphName = "Out"
EndBody
EndObject
EndObject
Object DevBody $ObjBodyDef 2 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:26:53.98
Attr StructName = "Sim_ModelMLP_Fo"
Attr NextAix = "_X4"
EndBody
Object PlcNode $Buffer 3 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr Class = "pwrs:Class-$PlcNode"
EndBody
EndObject
EndObject
Object GraphPlcNode $GraphPlcNode 64 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:27:17.93
Attr object_type = 11
Attr parameters[0] = 16
Attr parameters[1] = 4
Attr parameters[2] = 1
Attr parameters[3] = 0
Attr graphmethod = 0
Attr graphindex = 0
Attr default_mask[0] = 3
Attr default_mask[1] = 1
Attr segname_annotation = 1
Attr compmethod = 35
Attr compindex = 0
Attr tracemethod = 0
Attr traceindex = 0
Attr connectmethod = 10
Attr executeordermethod = 2
Attr objname = "ModelMLP_Fo"
Attr graphname = "ModelMLP_Fo"
EndBody
EndObject
Object RtXtt $RtMenu 65 07-NOV-2019 12:25:46.68
Object PlcConnect $MenuRef 66 07-NOV-2019 12:25:46.68
Body SysBody 07-NOV-2019 12:25:46.68
Attr ButtonName = "PlcConnect"
Attr RefAttribute = "PlcConnect"
EndBody
EndObject
EndObject
Object Template Sim_ModelMLP_Fo 2154790912 07-NOV-2019 12:25:46.68
Body RtBody 01-JAN-1970 01:00:00.00
EndBody
Body DevBody 01-JAN-1970 01:00:00.00
EndBody
EndObject
EndObject
EndObject
EndVolume
......@@ -1219,6 +1219,7 @@ palette PlcEditorPalette
class Sim_Delay
class Sim_LagFilter
class Sim_LeadLagFilter
class Sim_ModelMLP_Fo
class Sim_SigGen
class Sim_SignalGeneratorFo
class Sim_Simulink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment