Commit dfe9d9fe authored by Claes Sjofors's avatar Claes Sjofors Committed by Claes Sjöfors

Sim_ModelMLP, MLP model object added

parent fb0ab007
......@@ -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];
}
This diff is collapsed.
......@@ -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