Documentation / Manuel utilisateur en C++ :
The objective of the macro is to perform a FORM SORM study.
This example comes from De Victor's thesis. The problem has three input variables x, fe and M. Each variable follows a normal distribution with the following mean and standard error: x is N(40, 5), fe is N(50, 2.5) and M is N(1000,200). The safety threshold is calculated with M-x*fe and should be positive for a safe solution.
The Script follows the following steps:
a macro section to choose the optimisation solver;
a namespace section;
the definition of the safety function;
the study procedure.
/* possible solver
* direct
#define SOLV TNloptCobyla
* lagragien direct
#define SOLV TNloptBobyqa //doesn't work on this problem
#define SOLV TNloptPraxis
#define SOLV TNloptNelderMead
#define SOLV TNloptSubplexe
* */
#define SOLV TNloptCobyla
using namespace URANIE::DataServer;
using namespace URANIE::Relauncher;
using namespace URANIE::Reoptimizer;
using namespace URANIE::Reliability;
/********** User Function *****************/
static void fselect(double *in, double *res)
{
double x,fe,M;
x=in[0]; fe=in[1]; M=in[2];
/* critere */
res[0] = M-x*fe;
}
/********** Optimization *****************/
void reliabilityFormSorm()
{
/* inputs */
TNormalDistribution x("x", 40, 5),
fe("x2", 50, 2.5),
M("M", 1000, 200);
/* outputs */
TAttribute cont("seuil");
/* starting point */
vector<double> start{-1., -1., 1.};
/* code */
TSimpleTransform fobj;
fobj.setParameters(3, &x, &fe, &M);
TCIntEval fcont("fselect");
fcont.setInputs(3, &x, &fe, &M);
fcont.setOutputs(1, &cont);
TFormEval code(&fobj, &fcont);
TGreaterFit it(0.0);
code.addConstraint(&cont, &it);
/* runner */
TSequentialRun run(&code);
run.startSlave();
if (run.onMaster()) {
/* tds */
TDataServer tds("toto", "tds for vizir test");
code.addAllInputs(&tds);
/*** FORM ***/
/* optimizer */
SOLV solv;
TNlopt nlo(&tds, &run, &solv);
code.addObjective(&nlo);
/* resolution */
nlo.setStartingPoint(start.size(),&start[0]);
nlo.solverLoop();
/* results */
//tds.getTuple()->Scan("*");
/*** SORM ***/
TSorm sorm(&tds, &run);
sorm.solverLoop();
/* results */
tds.getTuple()->Scan("*");
/* cleanup */
run.stopSlave();
}
}
The study procedure requests the definition of:
variables: input variables with their statistical laws and the output variable;
the starting point for the design point optimisation. Take care that it is defined in the normal space (not in the physical space);
evaluation functions; the transformation function, the safety function, and the composition of both of them;
a standard sequential
TRun
;the
TDataServer
with its inputs declaration;the FORM optimisation sequence;
the SORM estimation sequence;
back-up and finalisation.
Processing reliabilityFormSorm.C... |....:....|....:....|....:....|....:....|....:....0050 |....:....|.... ************************************************************************************************************************************************************ * Row * toto__n__ * u_x.u_x * u_x2.u_x2 * u_M.u_M * betaHL.be * form.form * x.x * x2.x2 * M.M * seuil.seu * factor.fa * sorm.sorm * ************************************************************************************************************************************************************ * 0 * 0 * -2.289658 * -0.677000 * 1.8963080 * 3.0490734 * 0.0011477 * 28.551708 * 48.307498 * 1379.2616 * -1.67e-05 * 1.0203699 * 0.0011711 * ************************************************************************************************************************************************************
There are two lines used to show the optimisation progress (evaluation numbers), and then the resulting TDataServer
is
shown. Columns start with two indexes, the three normal variables, the Hasofer-Lind indicator, the FORM estimation,
the three physical variables, the FORM correction, and the SORM estimation.
This example takes over the previous one, and tries to exploit the machine CPU using threads. For this purpose, FORM will use a gradient optimisation algorithm with a finite differences gradient estimation which may use 2*n+1 CPU, and Sorm is able to use 2*(n-1) CPU. For using thread, the code needs to be compiled on the fly using the ROOT facilities.
the main differences between previous Macro are:
the #include section needed for compilation;
the use of a gradient optimisation solver;
the
TCJitEval
(vs theTCIntEval
) uses to define the safety function;the use of
TTreadedRun
for parallelization;the use of a
TGradientEstimationRun
object to parallelize finite differences gradient estimation.
#include "TAttribute.h"
#include "TNormalDistribution.h"
#include "TLogNormalDistribution.h"
#include "TSimpleTransform.h"
#include "TCJitEval.h"
#include "TFormEval.h"
#include "TThreadedRun.h"
#include "TGradientEstimationRun.h"
#include "TDataServer.h"
#include "TOptimFit.h"
#include "TNloptCobyla.h"
#include "TNloptDirect.h"
#include "TNlopt.h"
#include "TSorm.h"
/* possible solver
* gradient
#define SOLV TNloptMMA
#define SOLV TNloptSLSQP
* lagragien gradient
#define SOLV TNloptLBFGS
#define SOLV TNloptNewton
#define SOLV TNloptVariableMetric
*
* */
#define SOLV TNloptMMA
using namespace URANIE::DataServer;
using namespace URANIE::Relauncher;
using namespace URANIE::Reoptimizer;
using namespace URANIE::Reliability;
/********** User Function *****************/
static void fselect(double *in, double *res)
{
double x,fe,M;
x=in[0]; fe=in[1]; M=in[2];
/* critere */
res[0] = M-x*fe;
}
/********** Optimization *****************/
void reliabilityFormSormBis()
{
/* inputs */
TNormalDistribution x("x", 40, 5),
fe("x2", 50, 2.5),
M("M", 1000, 200);
/* outputs */
TAttribute cont("seuil");
/* starting point */
double start[] = {-1., -1., 1.};
/* code */
TSimpleTransform fobj;
fobj.setParameters(3, &x, &fe, &M);
TCJitEval fcont(&fselect);
fcont.setInputs(3, &x, &fe, &M);
fcont.setOutputs(1, &cont);
TFormEval code(&fobj, &fcont);
TGreaterFit it(0.0);
code.addConstraint(&cont, &it);
TThreadedRun trun(&code, 5);
TGradientEstimationRun run(&trun);
run.startSlave();
if (run.onMaster()) {
/* tds */
TDataServer tds("toto", "tds for vizir test");
code.addAllInputs(&tds);
/*** FORM ***/
/* optimizer */
SOLV solv;
TNlopt nlo(&tds, &run, &solv);
code.addObjective(&nlo);
/* resolution */
nlo.setStartingPoint(start);
nlo.solverLoop();
/*** SORM ***/
TSorm sorm(&tds, &run);
sorm.solverLoop();
/* results */
tds.getTuple()->Scan("*");
/* cleanup */
run.stopSlave();
}
}
The console is very similar to the previous one.
Processing reliabilityFormSormBis.C+... !,,,,;,, ************************************************************************************************************************************************************ * Row * toto__n__ * u_x * u_x2 * u_M * betaHL * form * x * x2 * M * seuil * factor * sorm * ************************************************************************************************************************************************************ * 0 * 0 * -2.286037 * -0.677986 * 1.9003293 * 3.0490789 * 0.0011477 * 28.569814 * 48.305034 * 1380.0658 * -1.34e-05 * 1.0204395 * 0.0011711 * ************************************************************************************************************************************************************
You may notice that the evaluation numbers is very low, but each evaluation is equivalent to 7 evaluations. These traces are obtained in a second run: in the first run you will see compiler messages.