From efd9b68d2e2bfb1735a79d0d391b22efa3a14ff9 Mon Sep 17 00:00:00 2001 From: "Joao A. Duro" Date: Thu, 31 Dec 2020 13:28:40 +0000 Subject: [PATCH 1/7] Add probabilistic constraint handling to surrogate-based optimizers --- src/libs/tigon/Algorithms/ParEGO.cpp | 213 +++++++-- src/libs/tigon/Algorithms/ParEGO.h | 52 +- src/libs/tigon/Algorithms/sParEGO.cpp | 124 ++++- src/libs/tigon/Algorithms/sParEGO.h | 39 +- .../tigon/Engine/OptimizationLinearFlow.cpp | 6 +- .../ConstraintDirectionFitnessFiltration.cpp | 233 +++++++++ .../ConstraintDirectionFitnessFiltration.h | 45 ++ .../DirectionFitnessFiltration.cpp | 88 ++-- .../DirectionFitnessFiltration.h | 7 +- .../SparegoValidation.cpp | 145 +++++- .../{Sparego => sParEGO}/SparegoValidation.h | 2 +- .../sParEGOInit.cpp} | 32 +- .../SparegoInit.h => sParEGO/sParEGOInit.h} | 12 +- .../ConstrainedSurrogateBasedOptimizer.cpp | 452 ++++++++++++++++++ .../ConstrainedSurrogateBasedOptimizer.h | 82 ++++ .../Composites/SurrogateBasedOptimizer.cpp | 398 ++++++++++++--- .../Composites/SurrogateBasedOptimizer.h | 87 +++- ...urrogateBasedOptimizerWithPerturbation.cpp | 35 +- .../SurrogateBasedOptimizerWithPerturbation.h | 20 +- .../Fitness/GeneralizedDecomposition.cpp | 95 ++-- .../Fitness/GeneralizedDecomposition.h | 8 +- .../Fitness/MOGANonDominanceRanking.cpp | 82 ++-- .../Operators/Fitness/NonDominanceRanking.cpp | 87 ++-- .../Operators/Fitness/NonDominanceRanking.h | 3 +- .../Fitness/RobustnessAssignment.cpp | 5 +- .../tigon/Operators/Fitness/Scalarization.cpp | 96 ++-- .../tigon/Operators/Fitness/Scalarization.h | 37 +- .../tigon/Operators/Fitness/SharedFitness.cpp | 4 +- .../Fitness/UncertainConfidenceRobustness.cpp | 4 +- .../Representation/Functions/IFunction.cpp | 6 +- .../Functions/SingleObjective/Alpine2.cpp | 6 +- .../Functions/SingleObjective/BraninGomez.cpp | 114 +++++ .../Functions/SingleObjective/BraninGomez.h | 44 ++ .../Functions/SingleObjective/CBranin.cpp | 112 +++++ .../Functions/SingleObjective/CBranin.h | 45 ++ .../Functions/SingleObjective/CBraninM1.cpp | 120 +++++ .../Functions/SingleObjective/CBraninM1.h | 45 ++ .../Functions/SingleObjective/Camel.cpp | 113 +++++ .../Functions/SingleObjective/Camel.h | 44 ++ .../SingleObjective/ConstrainedProblems.cpp | 134 ++++++ .../SingleObjective/ConstrainedProblems.h | 32 ++ .../Functions/SingleObjective/Poly1.cpp | 105 ++++ .../Functions/SingleObjective/Poly1.h | 49 ++ .../Functions/SingleObjective/Sasena.cpp | 114 +++++ .../Functions/SingleObjective/Sasena.h | 44 ++ .../ConstrainedExpectedImprovement.cpp | 183 +++++++ .../ConstrainedExpectedImprovement.h | 58 +++ .../ExpectedImprovement.cpp | 54 ++- .../ExpectedImprovement.h | 24 +- .../{ => SurrogateModelling}/FannNetwork.cpp | 4 +- .../{ => SurrogateModelling}/FannNetwork.h | 4 +- .../FeasibleExpectedImprovement.cpp | 140 ++++++ .../FeasibleExpectedImprovement.h | 50 ++ .../FeasibleRandExpectedImprovement.cpp | 153 ++++++ .../FeasibleRandExpectedImprovement.h | 57 +++ .../FeedforwardSurrogate.cpp | 4 +- .../FeedforwardSurrogate.h | 4 +- .../KrigingSurrogate.cpp | 12 +- .../KrigingSurrogate.h | 2 +- .../SurrogateModelling/Likelihood.cpp | 216 +++++++++ .../Functions/SurrogateModelling/Likelihood.h | 57 +++ .../ProbabilityFeasibility.cpp | 128 +++++ .../ProbabilityFeasibility.h | 56 +++ .../ProbabilityFeasibilityBagheri.cpp | 132 +++++ .../ProbabilityFeasibilityBagheri.h | 56 +++ .../RandExpectedImprovement.cpp | 86 ++-- .../RandExpectedImprovement.h | 27 +- .../Representation/Functions/ZDT/ZDT1.cpp | 39 +- .../Representation/Functions/ZDT/ZDT2.cpp | 39 +- src/libs/tigon/Representation/PSets/IPSet.cpp | 42 +- src/libs/tigon/Representation/PSets/IPSet.h | 11 +- src/libs/tigon/Utils/DominanceUtils.cpp | 184 ++++++- src/libs/tigon/Utils/DominanceUtils.h | 11 +- src/libs/tigon/Utils/JsonUtils.cpp | 19 +- src/libs/tigon/Utils/JsonUtils.h | 5 +- .../tigon/Utils/KernelDensityEstimation.cpp | 9 +- src/libs/tigon/Utils/Kriging/DACE.cpp | 338 +++++++++++++ src/libs/tigon/Utils/Kriging/DACE.h | 84 ++++ src/libs/tigon/Utils/Kriging/IKriging.cpp | 41 ++ src/libs/tigon/Utils/Kriging/IKriging.h | 46 ++ .../Utils/{ => Kriging}/KrigingCascade.cpp | 37 +- .../Utils/{ => Kriging}/KrigingCascade.h | 20 +- .../Utils/{ => Kriging}/KrigingVariogram.cpp | 23 +- .../Utils/{ => Kriging}/KrigingVariogram.h | 15 +- .../OrdinaryKriging.cpp} | 67 +-- .../{Kriging.h => Kriging/OrdinaryKriging.h} | 22 +- .../Utils/{ => Kriging}/PowerVariogram.cpp | 17 +- .../Utils/{ => Kriging}/PowerVariogram.h | 11 +- .../{ => Kriging}/SphericalVariogram.cpp | 11 +- .../Utils/{ => Kriging}/SphericalVariogram.h | 12 +- src/libs/tigon/Utils/NormalisationUtils.cpp | 52 +- .../tigon/Utils/ScalarisingSpaceUtils.cpp | 13 +- src/libs/tigon/Utils/ScalarisingSpaceUtils.h | 5 +- src/libs/tigon/Utils/TigonUtils.cpp | 6 +- src/libs/tigon/tigonconstants.h | 50 +- .../test_tigon/test_sparego/tst_sparego.cpp | 283 ++--------- 96 files changed, 5581 insertions(+), 1058 deletions(-) create mode 100644 src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/ConstraintDirectionFitnessFiltration.cpp create mode 100644 src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/ConstraintDirectionFitnessFiltration.h rename src/libs/tigon/Operators/AlgorithmSpecific/{parego => ParEGO}/DirectionFitnessFiltration.cpp (57%) rename src/libs/tigon/Operators/AlgorithmSpecific/{parego => ParEGO}/DirectionFitnessFiltration.h (88%) rename src/libs/tigon/Operators/AlgorithmSpecific/{Sparego => sParEGO}/SparegoValidation.cpp (67%) rename src/libs/tigon/Operators/AlgorithmSpecific/{Sparego => sParEGO}/SparegoValidation.h (97%) rename src/libs/tigon/Operators/AlgorithmSpecific/{Sparego/SparegoInit.cpp => sParEGO/sParEGOInit.cpp} (87%) rename src/libs/tigon/Operators/AlgorithmSpecific/{Sparego/SparegoInit.h => sParEGO/sParEGOInit.h} (86%) create mode 100644 src/libs/tigon/Operators/Composites/ConstrainedSurrogateBasedOptimizer.cpp create mode 100644 src/libs/tigon/Operators/Composites/ConstrainedSurrogateBasedOptimizer.h create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/BraninGomez.cpp create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/BraninGomez.h create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/CBranin.cpp create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/CBranin.h create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/CBraninM1.cpp create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/CBraninM1.h create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/Camel.cpp create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/Camel.h create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/ConstrainedProblems.cpp create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/ConstrainedProblems.h create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/Poly1.cpp create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/Poly1.h create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/Sasena.cpp create mode 100644 src/libs/tigon/Representation/Functions/SingleObjective/Sasena.h create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/ConstrainedExpectedImprovement.cpp create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/ConstrainedExpectedImprovement.h rename src/libs/tigon/Representation/Functions/{ => SurrogateModelling}/ExpectedImprovement.cpp (72%) rename src/libs/tigon/Representation/Functions/{ => SurrogateModelling}/ExpectedImprovement.h (80%) rename src/libs/tigon/Representation/Functions/{ => SurrogateModelling}/FannNetwork.cpp (99%) rename src/libs/tigon/Representation/Functions/{ => SurrogateModelling}/FannNetwork.h (98%) create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleExpectedImprovement.cpp create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleExpectedImprovement.h create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleRandExpectedImprovement.cpp create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleRandExpectedImprovement.h rename src/libs/tigon/Representation/Functions/{ => SurrogateModelling}/FeedforwardSurrogate.cpp (96%) rename src/libs/tigon/Representation/Functions/{ => SurrogateModelling}/FeedforwardSurrogate.h (91%) rename src/libs/tigon/Representation/Functions/{ => SurrogateModelling}/KrigingSurrogate.cpp (90%) rename src/libs/tigon/Representation/Functions/{ => SurrogateModelling}/KrigingSurrogate.h (95%) create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/Likelihood.cpp create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/Likelihood.h create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibility.cpp create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibility.h create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.cpp create mode 100644 src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.h rename src/libs/tigon/Representation/Functions/{ => SurrogateModelling}/RandExpectedImprovement.cpp (66%) rename src/libs/tigon/Representation/Functions/{ => SurrogateModelling}/RandExpectedImprovement.h (64%) create mode 100644 src/libs/tigon/Utils/Kriging/DACE.cpp create mode 100644 src/libs/tigon/Utils/Kriging/DACE.h create mode 100644 src/libs/tigon/Utils/Kriging/IKriging.cpp create mode 100644 src/libs/tigon/Utils/Kriging/IKriging.h rename src/libs/tigon/Utils/{ => Kriging}/KrigingCascade.cpp (76%) rename src/libs/tigon/Utils/{ => Kriging}/KrigingCascade.h (74%) rename src/libs/tigon/Utils/{ => Kriging}/KrigingVariogram.cpp (90%) rename src/libs/tigon/Utils/{ => Kriging}/KrigingVariogram.h (76%) rename src/libs/tigon/Utils/{Kriging.cpp => Kriging/OrdinaryKriging.cpp} (66%) rename src/libs/tigon/Utils/{Kriging.h => Kriging/OrdinaryKriging.h} (83%) rename src/libs/tigon/Utils/{ => Kriging}/PowerVariogram.cpp (89%) rename src/libs/tigon/Utils/{ => Kriging}/PowerVariogram.h (76%) rename src/libs/tigon/Utils/{ => Kriging}/SphericalVariogram.cpp (91%) rename src/libs/tigon/Utils/{ => Kriging}/SphericalVariogram.h (84%) diff --git a/src/libs/tigon/Algorithms/ParEGO.cpp b/src/libs/tigon/Algorithms/ParEGO.cpp index c3c94cb..edaa78f 100644 --- a/src/libs/tigon/Algorithms/ParEGO.cpp +++ b/src/libs/tigon/Algorithms/ParEGO.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -21,8 +21,10 @@ #include #include #include -#include +#include +#include #include +#include #include #include #include @@ -54,8 +56,11 @@ void ParEGO::initialise() new SimplexLatticeDirectionIterator(this); /*1*/ GeneralizedDecomposition* scal = new GeneralizedDecomposition(this); /*2*/ ConstraintPenalty* cnstr = new ConstraintPenalty(this); - /*3*/ DirectionFitnessFiltration* filt = new DirectionFitnessFiltration(this); - /*4*/ SurrogateBasedOptimizer* opt = new SurrogateBasedOptimizer(this); + /*3*/ //DirectionFitnessFiltration* filt = new DirectionFitnessFiltration(this); + /*3*/ ConstraintDirectionFitnessFiltration* filt = + new ConstraintDirectionFitnessFiltration(this); + /*4*/ ConstrainedSurrogateBasedOptimizer* opt = + new ConstrainedSurrogateBasedOptimizer(this); appendOperator(dirs); appendOperator(scal); @@ -63,9 +68,17 @@ void ParEGO::initialise() appendOperator(filt); appendOperator(opt); + TP_defineConstraintHandlingMethod(Tigon::SurrogateBased); scal->TP_defineScalarisingFunction(Tigon::WeightedChebyshevAugmented); scal->TP_defineWeightScopeApproach(Tigon::GlobalWeight); - opt->TP_defineErrorMethod(Tigon::ErrDensityBased); + filt->TP_defineMaxSolutions(Tigon::DefaultMaxSolutionsSurrogateModelling); + opt->TP_defineErrorMethod(Tigon::ErrConfidenceIntervalBased); + //opt->TP_defineErrorMethod(Tigon::ErrDensityBased); + + // Changing the following parameter to 1 delivers better results for the + // tasks of training and searching the surrogate, but it will take longer + // for the optimization task to complete + opt->TP_defineOptimizationSearchQuality(0); addProperty("maxSolutions" , TString("Maximum number of samples for the surrogate model.\n" @@ -73,57 +86,110 @@ void ParEGO::initialise() "the sample is constructed according to the direction " "of the objective vector, and the scalarised function " "value.") - , typeid(int).hash_code()); + , getTType(int)); } -void ParEGO::TP_defineMaxSolutions(int n) +void ParEGO::defineOptimizationSearchQuality(int mode) { - static_cast(operators().at(3))-> - TP_defineMaxSolutions(n); + static_cast(operators().at(4))-> + TP_defineOptimizationSearchQuality(mode); } -int ParEGO::TP_maxSolutions() const +int ParEGO::optimizationSearchQuality() const { - return static_cast(operators().at(3))-> - TP_maxSolutions(); + return static_cast(operators().at(4))-> + TP_optimizationSearchQuality(); +} + +void ParEGO::TP_defineErrorMethod(Tigon::ErrorHandlingMethod err) +{ + static_cast(operators().at(4))-> + TP_defineErrorMethod(err); +} + +Tigon::ErrorHandlingMethod ParEGO::TP_errorMethod() const +{ + return static_cast(operators().at(4))-> + TP_errorMethod(); +} + +void ParEGO::TP_defineConstraintHandlingMethod(Tigon::ConstraintHandlingMethod chm) +{ + m_constraintHandlingMethod = chm; + switch(chm) { + case Tigon::NoConstraintHandling: + static_cast(operators().at(2))-> + defineOutputTags(TStringList({TString("DO_NO_OPERATE")})); + static_cast(operators().at(4))-> + TP_defineDisableConstraintHandling(true); + break; + + case Tigon::PenaltyBased: + static_cast(operators().at(2))-> + defineOutputTags(TStringList({Tigon::TFitness})); + static_cast(operators().at(4))-> + TP_defineDisableConstraintHandling(true); + break; + + case Tigon::SurrogateBased: + default: + static_cast(operators().at(2))-> + defineOutputTags(TStringList({TString("DO_NO_OPERATE")})); + static_cast(operators().at(4))-> + TP_defineDisableConstraintHandling(false); + break; + } } -void ParEGO::TP_defineNeighbourhoodRadius(double r) +Tigon::ConstraintHandlingMethod ParEGO::TP_constraintHandlingMethod() { - static_cast(operators().at(4))-> - TP_defineNeighbourhoodRadius(r); + return m_constraintHandlingMethod; } -double ParEGO::TP_neighbourhoodRadius() const +void ParEGO::TP_defineMaxSolutions(int n) +{ + static_cast(operators().at(3))-> + TP_defineMaxSolutions(n); +} + +int ParEGO::TP_maxSolutions() const { - return static_cast(operators().at(4))-> - TP_neighbourhoodRadius(); + return static_cast(operators().at(3))-> + TP_maxSolutions(); } TVector ParEGO::evaluatedMappings() const { TVector pop = operators().at(4)->outputSet(0)->all(); TVector ret; - for(int i=0; iisEvaluated()) { - ret.push_back(pop[i]); + for(auto sol : pop) { + if(sol->isEvaluated()) { + ret.push_back(sol); } } + return ret; } -TVector ParEGO::newMappings() const +TVector ParEGO::newMappings() const { TVector pop = operators().at(4)->outputSet(0)->all(); TVector ret; - for(int i=0; iisEvaluated()) { - ret.push_back(pop[i]); + for(auto sol : pop) { + if(!sol->isEvaluated()) { + ret.push_back(sol); } } + return ret; } +TVector ParEGO::surrogateMappings() const +{ + TVector pop = operators().at(3)->outputSet(0)->all(); + return pop; +} + void ParEGO::defineReferenceSetSize(int s) { static_cast(operators().at(0))-> @@ -136,16 +202,100 @@ int ParEGO::referenceSetSize() const TP_referenceSetSize(); } -void ParEGO::defineBudgetPerVariable(int n) +void ParEGO::defineBudgetPerVariableSS(int n) +{ + static_cast(operators().at(4))-> + TP_defineBudgetPerVariableSS(n); +} + +int ParEGO::budgetPerVariableSS() const +{ + return static_cast(operators().at(4))-> + TP_budgetPerVariableSS(); +} + +void ParEGO::defineInitialPopsizePerVariableSS(int popsize) +{ + static_cast(operators().at(4))-> + TP_defineInitialPopsizePerVariableSS(popsize); +} + +int ParEGO::initialPopsizePerVariableSS() const +{ + return static_cast(operators().at(4))-> + TP_initialPopsizePerVariableSS(); +} + +void ParEGO::defineStallIterationsSS(int iter) +{ + static_cast(operators().at(4))-> + TP_defineStallIterationsSS(iter); +} + +int ParEGO::stallIterationsSS() const +{ + return static_cast(operators().at(4))-> + TP_stallIterationsSS(); +} + +void ParEGO::defineBudgetPerVariableTS(int n) +{ + static_cast(operators().at(4))-> + TP_defineBudgetPerVariableTS(n); +} + +int ParEGO::budgetPerVariableTS() const +{ + return static_cast(operators().at(4))-> + TP_budgetPerVariableTS(); +} + +void ParEGO::defineInitialPopsizePerVariableTS(int popsize) { - static_cast(operators().at(4))-> - TP_defineBudgetPerVariable(n); + static_cast(operators().at(4))-> + TP_defineInitialPopsizePerVariableTS(popsize); } -int ParEGO::budgetPerVariable() const +int ParEGO::initialPopsizePerVariableTS() const { - return static_cast(operators().at(4))-> - TP_budgetPerVariable(); + return static_cast(operators().at(4))-> + TP_initialPopsizePerVariableTS(); +} + +void ParEGO::defineStallIterationsTS(int iter) +{ + static_cast(operators().at(4))-> + TP_defineStallIterationsTS(iter); +} + +int ParEGO::stallIterationsTS() const +{ + return static_cast(operators().at(4))-> + TP_stallIterationsTS(); +} + +void ParEGO::defineNumberIterations(int iter) +{ + static_cast(operators().at(4))-> + TP_defineNumberIterations(iter); +} + +int ParEGO::numberIterations() const +{ + return static_cast(operators().at(4))-> + TP_numberIterations(); +} + +void ParEGO::defineMultiObjectivization(bool isMultiObjectivizationUsedOrNot) +{ + static_cast(operators().at(4))-> + TP_defineMultiObjectivization(isMultiObjectivizationUsedOrNot); +} + +bool ParEGO::multiObjectivization() const +{ + return static_cast(operators().at(4))-> + TP_multiObjectivization(); } void ParEGO::defineScalarisingFunction(Tigon::ScalarisationType t, double p) @@ -174,4 +324,5 @@ TString ParEGO::description() } // namespace Algorithms } // namespace Tigon + REGISTER_IPSET_FACTORY(Algorithms, ParEGO) diff --git a/src/libs/tigon/Algorithms/ParEGO.h b/src/libs/tigon/Algorithms/ParEGO.h index 8fc2a05..bd05ccd 100644 --- a/src/libs/tigon/Algorithms/ParEGO.h +++ b/src/libs/tigon/Algorithms/ParEGO.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -46,31 +46,65 @@ class LIGER_TIGON_EXPORT ParEGO : public IAlgorithm TString name(); TString description(); - // Algrithm-level properties - void TP_defineMaxSolutions(int n); - int TP_maxSolutions() const; + // Algorithm-level properties + void TP_defineErrorMethod(Tigon::ErrorHandlingMethod err); + Tigon::ErrorHandlingMethod TP_errorMethod() const; - void TP_defineNeighbourhoodRadius(double r); - double TP_neighbourhoodRadius() const; + void TP_defineConstraintHandlingMethod(Tigon::ConstraintHandlingMethod chm); + Tigon::ConstraintHandlingMethod TP_constraintHandlingMethod(); + + // Properties found in the operators of the Algorithm + void TP_defineMaxSolutions(int n); + int TP_maxSolutions() const; // General functions TVector evaluatedMappings() const; TVector newMappings() const; + TVector surrogateMappings() const; // These methods are the operators' properties, and are exposed in Liger // through introspection. They are here for easy interfacing in tests. void defineReferenceSetSize(int s); int referenceSetSize() const; - void defineBudgetPerVariable(int n); - int budgetPerVariable() const; + // Parameters for the optimizer to search the surrogate + void defineBudgetPerVariableSS(int n); + int budgetPerVariableSS() const; + + void defineInitialPopsizePerVariableSS(int popsize); + int initialPopsizePerVariableSS() const; + + void defineStallIterationsSS(int iter); + int stallIterationsSS() const; + + // Parameters for the optimizer to train the surrogate + void defineBudgetPerVariableTS(int n); + int budgetPerVariableTS() const; + + void defineInitialPopsizePerVariableTS(int popsize); + int initialPopsizePerVariableTS() const; + + void defineStallIterationsTS(int iter); + int stallIterationsTS() const; + + + void defineNumberIterations(int iter); + int numberIterations() const; + + void defineMultiObjectivization(bool isMultiObjectivizationUsedOrNot); + bool multiObjectivization() const; // TODO: change this property according to the remaining budget void defineScalarisingFunction(Tigon::ScalarisationType t, double p=1.0); - Tigon::ScalarisationType scalarisingFunction() const; + Tigon::ScalarisationType scalarisingFunction() const; + + void defineOptimizationSearchQuality(int mode); + int optimizationSearchQuality() const; private: void initialise(); + + Tigon::ConstraintHandlingMethod m_constraintHandlingMethod; }; } // namespace Algorithms diff --git a/src/libs/tigon/Algorithms/sParEGO.cpp b/src/libs/tigon/Algorithms/sParEGO.cpp index 8622ae9..969e148 100644 --- a/src/libs/tigon/Algorithms/sParEGO.cpp +++ b/src/libs/tigon/Algorithms/sParEGO.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -19,11 +19,11 @@ #include #include #include -#include +#include #include #include #include -#include +#include #include #include #include @@ -62,13 +62,6 @@ void sParEGO::initialise() /*6*/ SurrogateBasedOptimizerWithPerturbation* opt = new SurrogateBasedOptimizerWithPerturbation(this); - scal->TP_defineScalarisingFunction(Tigon::WeightedChebyshev); - scal->TP_defineWeightScopeApproach(Tigon::GlobalWeight); - iVal->TP_defineIndicatorType(ConfidenceType); - iVal->TP_defineIndicatorParameter(0.9); - opt->TP_defineErrorMethod(Tigon::ErrDensityBased); - - appendOperator(dirs); appendOperator(scal); appendOperator(cnstr); @@ -77,25 +70,48 @@ void sParEGO::initialise() appendOperator(filt); appendOperator(opt); + scal->TP_defineScalarisingFunction(Tigon::WeightedChebyshev); + scal->TP_defineWeightScopeApproach(Tigon::GlobalWeight); + filt->TP_defineMaxSolutions(Tigon::DefaultMaxSolutionsSurrogateModelling); + opt->TP_defineErrorMethod(Tigon::ErrConfidenceIntervalBased); + //opt->TP_defineErrorMethod(Tigon::ErrDensityBased); + opt->TP_defineDensityEstimationBandwidth(Tigon::KDEBandwidthRatio * + TP_neighbourhoodRadius()); + + // Changing the following parameter to 1 delivers better results for the + // tasks of training and searching the surrogate, but it will take longer + // for the optimization task to complete + opt->TP_defineOptimizationSearchQuality(0); + addProperty("maxSolutions" , TString("Maximum number of samples for the surrogate model.\n" "If there are more evaluated solutions than this, " "the sample is constructed according to the direction " "of the objective vector, and the scalarised function " "value.") - , typeid(int).hash_code()); + , getTType(int)); addProperty("neighbourhoodRadius" , TString("Maximum Euclidean distance in normalised decision " "space for two solutions to be considered as neighbours.") - , typeid(double).hash_code()); + , getTType(double)); } -void sParEGO::TP_defineErrorMethod(ErrorHandlingMethod err) +void sParEGO::defineOptimizationSearchQuality(int mode) { - m_errMethod = err; + static_cast(operators().at(6))-> + TP_defineOptimizationSearchQuality(mode); +} + +int sParEGO::optimizationSearchQuality() const +{ + return static_cast(operators().at(6))-> + TP_optimizationSearchQuality(); +} - switch(m_errMethod) { +void sParEGO::TP_defineErrorMethod(ErrorHandlingMethod err) +{ + switch(err) { case Tigon::ErrConfidenceIntervalBased: static_cast(operators().at(3))-> TP_defineConfidenceInSample(ConfidenceDecrease); @@ -109,12 +125,13 @@ void sParEGO::TP_defineErrorMethod(ErrorHandlingMethod err) } static_cast(operators().at(6))-> - TP_defineErrorMethod(m_errMethod); + TP_defineErrorMethod(err); } Tigon::ErrorHandlingMethod sParEGO::TP_errorMethod() const { - return m_errMethod; + return static_cast(operators().at(6))-> + TP_errorMethod(); } void sParEGO::TP_defineMaxSolutions(int n) @@ -147,7 +164,7 @@ TVector sParEGO::evaluatedMappings() const { TVector pop = operators().at(6)->outputSet(0)->all(); TVector ret; - for(int i=0; iisEvaluated()) { ret.push_back(pop[i]); } @@ -159,7 +176,7 @@ TVector sParEGO::newMappings() const { TVector pop = operators().at(6)->outputSet(0)->all(); TVector ret; - for(int i=0; iisEvaluated()) { ret.push_back(pop[i]); } @@ -197,18 +214,79 @@ void sParEGO::definePercentile(double p) TP_definePercentile(p); } -void sParEGO::defineBudgetPerVariable(int n) +void sParEGO::defineBudgetPerVariableSS(int n) { static_cast(operators().at(6))-> - TP_defineBudgetPerVariable(n); + TP_defineBudgetPerVariableSS(n); } -int sParEGO::budgetPerVariable() const +int sParEGO::budgetPerVariableSS() const { return static_cast(operators().at(6))-> - TP_budgetPerVariable(); + TP_budgetPerVariableSS(); +} + +void sParEGO::defineInitialPopsizePerVariableSS(int popsize) +{ + static_cast(operators().at(6))-> + TP_defineInitialPopsizePerVariableSS(popsize); +} + +int sParEGO::initialPopsizePerVariableSS() const +{ + return static_cast(operators().at(6))-> + TP_initialPopsizePerVariableSS(); +} + +void sParEGO::defineStallIterationsSS(int iter) +{ + static_cast(operators().at(6))-> + TP_defineStallIterationsSS(iter); } +int sParEGO::stallIterationsSS() const +{ + return static_cast(operators().at(6))-> + TP_stallIterationsSS(); +} + +void sParEGO::defineBudgetPerVariableTS(int n) +{ + static_cast(operators().at(6))-> + TP_defineBudgetPerVariableTS(n); +} + +int sParEGO::budgetPerVariableTS() const +{ + return static_cast(operators().at(6))-> + TP_budgetPerVariableTS(); +} + +void sParEGO::defineInitialPopsizePerVariableTS(int popsize) +{ + static_cast(operators().at(6))-> + TP_defineInitialPopsizePerVariableTS(popsize); +} + +int sParEGO::initialPopsizePerVariableTS() const +{ + return static_cast(operators().at(6))-> + TP_initialPopsizePerVariableTS(); +} + +void sParEGO::defineStallIterationsTS(int iter) +{ + static_cast(operators().at(6))-> + TP_defineStallIterationsTS(iter); +} + +int sParEGO::stallIterationsTS() const +{ + return static_cast(operators().at(6))-> + TP_stallIterationsTS(); +} + + void sParEGO::defineScalarisingFunction(Tigon::ScalarisationType t, double p) { static_cast(operators().at(1))-> diff --git a/src/libs/tigon/Algorithms/sParEGO.h b/src/libs/tigon/Algorithms/sParEGO.h index 6b9d89e..2de9d7b 100644 --- a/src/libs/tigon/Algorithms/sParEGO.h +++ b/src/libs/tigon/Algorithms/sParEGO.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -52,17 +52,13 @@ class LIGER_TIGON_EXPORT sParEGO : public IAlgorithm public: sParEGO(); sParEGO(IPSet* ipset); - virtual ~sParEGO(); - - void initialise(); + ~sParEGO(); // Information about the node. TString name(); TString description(); - - - // Algrithm-level properties + // Algorithm-level properties void TP_defineErrorMethod(Tigon::ErrorHandlingMethod err); Tigon::ErrorHandlingMethod TP_errorMethod() const; @@ -80,20 +76,41 @@ class LIGER_TIGON_EXPORT sParEGO : public IAlgorithm // through introspection. They are here for easy interfacing in tests. void defineReferenceSetSize(int s); int referenceSetSize() const; + void defineIndicator(TString indicatorType, double indParam=0); double percentile() const; void definePercentile(double p); - void defineBudgetPerVariable(int n); - int budgetPerVariable() const; + // Parameters for the optimizer to search the surrogate + void defineBudgetPerVariableSS(int n); + int budgetPerVariableSS() const; + + void defineInitialPopsizePerVariableSS(int popsize); + int initialPopsizePerVariableSS() const; + + void defineStallIterationsSS(int iter); + int stallIterationsSS() const; + + // Parameters for the optimizer to train the surrogate + void defineBudgetPerVariableTS(int n); + int budgetPerVariableTS() const; + + void defineInitialPopsizePerVariableTS(int popsize); + int initialPopsizePerVariableTS() const; + + void defineStallIterationsTS(int iter); + int stallIterationsTS() const; // TODO: change this property according to the remaining budget - void defineScalarisingFunction(Tigon::ScalarisationType t, double p=1.0); + void defineScalarisingFunction(Tigon::ScalarisationType t, double p=1.0); Tigon::ScalarisationType scalarisingFunction() const; + void defineOptimizationSearchQuality(int mode); + int optimizationSearchQuality() const; + private: - Tigon::ErrorHandlingMethod m_errMethod; + void initialise(); }; } // namespace Algorithms diff --git a/src/libs/tigon/Engine/OptimizationLinearFlow.cpp b/src/libs/tigon/Engine/OptimizationLinearFlow.cpp index 11a415b..602d259 100644 --- a/src/libs/tigon/Engine/OptimizationLinearFlow.cpp +++ b/src/libs/tigon/Engine/OptimizationLinearFlow.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -89,7 +89,7 @@ void OptimizationLinearFlow::evaluate() void OptimizationLinearFlow::clearFlow() { - for(int i=0; iremainingIteratoins(); + return m_nodes.back()->remainingIterations(); } int OptimizationLinearFlow::maxIteration() const diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/ConstraintDirectionFitnessFiltration.cpp b/src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/ConstraintDirectionFitnessFiltration.cpp new file mode 100644 index 0000000..98f64de --- /dev/null +++ b/src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/ConstraintDirectionFitnessFiltration.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include + +#include +#include +#include +#include + +#include + + +namespace Tigon { +namespace Operators { + +ConstraintDirectionFitnessFiltration::ConstraintDirectionFitnessFiltration() +{ + initialise(); +} + +ConstraintDirectionFitnessFiltration:: +ConstraintDirectionFitnessFiltration(Tigon::Representation::IPSet* ipset) + : DirectionFitnessFiltration(ipset) +{ + initialise(); +} + +ConstraintDirectionFitnessFiltration::~ConstraintDirectionFitnessFiltration() +{ + +} + +void ConstraintDirectionFitnessFiltration::evaluateNode() +{ + int nConstraints = constraintVecSize(); + if(nConstraints==0) { + DirectionFitnessFiltration::evaluateNode(); + return; + } + + ISet* iSet = inputSet(0); + if(iSet == nullptr) { + // ERROR + return; + } + int sSize = iSet->size(); + + + ISet* oSet = outputSet(0); + if(oSet == nullptr) { + oSet = appendOutputSet(); + } else { + oSet->clearMappings(); + } + + if((TP_maxSolutions() >= sSize) || (TP_maxSolutions() <= 0)) { + oSet->append(iSet); + return; + } + + // At this stage the number of solutions in the input set exceeds the + // maximum number of solutions + + // Count number of feasible solutions + int nFeasibleSolutions = 0; + for(auto sol : iSet->all()) { + if(sol->isFeasible()) { + nFeasibleSolutions++; + } + } + + /// 1. All solutions are feasible (use DirectionFitnessFiltration criterion) + if(sSize==nFeasibleSolutions) { + DirectionFitnessFiltration::evaluateNode(); + return; + } + + // At this stage there are infeasibile solutions + + TVector threshVec = IElementVecToRealVec(thresholdVec()); + int halfMax = static_cast(std::ceil(TP_maxSolutions()/2.0)); + + /// 2. All solutions are infeasible + if(nFeasibleSolutions == 0) { + + // Select half of the required solutions based on how infeasible they are + TVector sortIdx = sortViolation(iSet, threshVec); + + for(auto idx : mid(sortIdx, 0, halfMax)) { + oSet->append(iSet->at(idx)); + } + + // keep the rest of the solutions + ISet* tempSet = new ISet(); + for(auto idx : mid(sortIdx, halfMax)) { + tempSet->append(iSet->at(idx)); + } + + // Apply criterion from DirectionFitnessFiltration to remaining solutions + int remaining = TP_maxSolutions() - oSet->size(); + TVector selIdx = selection(tempSet, remaining); + for(auto idx : selIdx) { + oSet->append(tempSet->at(idx)); + } + delete tempSet; + return; + } + + /// 3. Mix of feasible and infeasible solutions + int nInfeasibleSolutions = sSize - nFeasibleSolutions; + + // Create two sets, one containing feasible solutions and the other + // containing infeasible solutions + ISet* feasibleSolutions = new ISet(); + ISet* inFeasibleSolutions = new ISet(); + for(auto sol : iSet->all()) { + if(sol->isFeasible()) { + feasibleSolutions->append(sol); + } else { + inFeasibleSolutions->append(sol); + } + } + + // A) Number of infeasible solutions is higher than or equal to halfMax, and + // number of feasible solutions ishigher than or equal to halfMax + if( (nInfeasibleSolutions >= halfMax) && (nFeasibleSolutions >= halfMax) ) + { + if(nFeasibleSolutions == halfMax) { + // select all feasible solutions + oSet->append(feasibleSolutions); + } else { + // From the feasible set select halfMax solutions + // based on criterion from DirectionFitnessFiltration + TVector selIdx = selection(feasibleSolutions, halfMax); + for(auto idx : selIdx) { + oSet->append(feasibleSolutions->at(idx)); + } + } + + // From the set of infeasible solutions select the remaining solutions + // based on how infeasible they are (less infeasible first) + int remaining = TP_maxSolutions() - oSet->size(); + TVector sortIdx = sortViolation(inFeasibleSolutions, threshVec); + for(auto idx : mid(sortIdx, 0, remaining)) { + oSet->append(inFeasibleSolutions->at(idx)); + } + } + // B) Number of infeasible solutions is less than or equal to halfMax, and + // the number of feasible solutions is higher than or equal to halfMax + else if( (nInfeasibleSolutions <= halfMax) && (nFeasibleSolutions >= halfMax) ) + { + // Select all infeasible solutions + oSet->append(inFeasibleSolutions); + + // The remaining solutions are chosen from the feasible set + // based on criterion from DirectionFitnessFiltration + int remaining = TP_maxSolutions() - oSet->size(); + TVector selIdx = selection(feasibleSolutions, remaining); + for(auto idx : selIdx) { + oSet->append(feasibleSolutions->at(idx)); + } + } + // C) Number of infeasible solutions is higher than or equal to halfMax, and + // the number of feasible solutions is less than or equal to halfMax + else if( (nInfeasibleSolutions >= halfMax) && (nFeasibleSolutions <= halfMax) ) + { + // Select all feasible solutions + oSet->append(feasibleSolutions); + + // From the set of infeasible solutions select the remaining solutions + // based on how infeasible they are (less infeasible first) + int remaining = TP_maxSolutions() - oSet->size(); + TVector sortIdx = sortViolation(inFeasibleSolutions, threshVec); + for(auto idx : mid(sortIdx, 0, remaining)) { + oSet->append(inFeasibleSolutions->at(idx)); + } + } else { + throw TException(this->className(), UnrecognisedOption); + } + + delete feasibleSolutions; + delete inFeasibleSolutions; +} + +TVector ConstraintDirectionFitnessFiltration:: +sortViolation(ISet* set, const TVector& threshVec) +{ + TVector cViolation; + cViolation.reserve(set->size()); + for(auto sol : set->all()) { + double violation = solutionConstraintViolation(sol, threshVec); + cViolation.push_back(violation); + } + return indSort(cViolation); +} + +void ConstraintDirectionFitnessFiltration::initialise() +{ + +} + +TString ConstraintDirectionFitnessFiltration::name() +{ + return TString("Constraint Direction Fitness Filtration"); +} + +TString ConstraintDirectionFitnessFiltration::description() +{ + return TString("Sorts the output set according to fitness and " + "direction of the solutions.\n Half of the " + "requested size is sorted according to fitness. " + "the remaining solutions are sorted according to " + "closeness of their direction vector to the current " + "direction vector."); +} + +} // namespace Operators +} // namespace Tigon diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/ConstraintDirectionFitnessFiltration.h b/src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/ConstraintDirectionFitnessFiltration.h new file mode 100644 index 0000000..f49722c --- /dev/null +++ b/src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/ConstraintDirectionFitnessFiltration.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef CONSTRAINTDIRECTIONFITNESSFILTRATION_H +#define CONSTRAINTDIRECTIONFITNESSFILTRATION_H +#include + +namespace Tigon { +namespace Operators { + +class LIGER_TIGON_EXPORT ConstraintDirectionFitnessFiltration : + public DirectionFitnessFiltration +{ +public: + ConstraintDirectionFitnessFiltration(); + ConstraintDirectionFitnessFiltration(Tigon::Representation::IPSet* ipset); + ~ConstraintDirectionFitnessFiltration(); + + void evaluateNode(); + + // Information about the node. + TString name(); + TString description(); + +private: + TVector sortViolation(ISet* set, const TVector& threshVec); + void initialise(); +}; + +} // namespace Operators +} // namespace Tigon + +#endif // CONSTRAINTDIRECTIONFITNESSFILTRATION_H diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/parego/DirectionFitnessFiltration.cpp b/src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/DirectionFitnessFiltration.cpp similarity index 57% rename from src/libs/tigon/Operators/AlgorithmSpecific/parego/DirectionFitnessFiltration.cpp rename to src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/DirectionFitnessFiltration.cpp index eb95ca1..79ba1b3 100644 --- a/src/libs/tigon/Operators/AlgorithmSpecific/parego/DirectionFitnessFiltration.cpp +++ b/src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/DirectionFitnessFiltration.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,7 +13,7 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include +#include #include #include #include @@ -28,7 +28,8 @@ DirectionFitnessFiltration::DirectionFitnessFiltration() initialise(); } -DirectionFitnessFiltration::DirectionFitnessFiltration(Tigon::Representation::IPSet* ipset) +DirectionFitnessFiltration:: +DirectionFitnessFiltration(Tigon::Representation::IPSet* ipset) : IFiltration(ipset) { initialise(); @@ -56,57 +57,77 @@ void DirectionFitnessFiltration::evaluateNode() oSet->clearMappings(); } - if((m_maxSolutions > sSize) || (m_maxSolutions <= 0)) { + if((TP_maxSolutions() >= sSize) || (TP_maxSolutions() <= 0)) { oSet->append(iSet); return; } - /// sort half of the required solution according to fitness + TVector selIdx = selection(iSet, TP_maxSolutions()); + for(auto idx : selIdx) { + oSet->append(iSet->at(idx)); + } +} + +TVector DirectionFitnessFiltration::selection(ISet* set, int maxSolutions) +{ + TVector out; + int halfMax = static_cast(std::ceil(maxSolutions/2.0)); + + /// 1. Select half of the solutions based on their current fitness + + // Sort half of the required solutions according to fitness TVector fitnessVec; - for(int i=0; iat(i)->doubleCost()); + fitnessVec.reserve(set->size()); + for(auto sol : set->all()) { + fitnessVec.push_back(sol->doubleCost()); } - TVector idx = indSort(fitnessVec); + TVector sortIdx = indSort(fitnessVec); - int j = 0; - for( ; j<(m_maxSolutions/2); j++) { - oSet->append(iSet->at(idx[j])); + for(auto idx : mid(sortIdx, 0, halfMax)) { + out.push_back(idx); } // keep the rest of the solutions + TVector tempIdx; ISet* tempSet = new ISet(); - for( ; jappend(iSet->at(idx[j])); + for(auto idx : mid(sortIdx, halfMax)) { + tempSet->append(set->at(idx)); + tempIdx.push_back(idx); // copy the indices of the remaining solutions } - /// Sort the rest of the solutions according to their direction vector - // Normalise the objective vectors - // Only operates on the main Optimization set! + + /// 2. Select the other half based on their proximity to the direction vector + + // Normalise the objective vectors with respect to the ideal and anti-ideal TVector> normalObjectives; TVector ideal = IElementVecToRealVec(idealVec()); TVector antiIdeal = IElementVecToRealVec(antiIdealVec()); - for (int i=0; isize(); i++) { - TVector normVec = tempSet->at(i)->doubleObjectiveVec(); - normaliseToUnitBoxInMemory(normVec, ideal, antiIdeal); + for(auto sol : tempSet->all()) { + TVector normVec = normaliseToUnitBox(sol->doubleObjectiveVec(), + ideal, antiIdeal); // project onto the k-1 simplex toUnitVec(normVec, 1.0); normalObjectives.push_back(normVec); } // Calculate the Euclidean distance of every solution from the current direction - TVector distances(tempSet->size(), 0.0); - TVector dirvec = dirVec(); - for(int i=0; isize(); i++) { - distances[i] = l2dist(normalObjectives[i], dirvec); + TVector distances; + distances.reserve(tempSet->size()); + for(auto objVec : normalObjectives) { + distances.push_back(l2dist(objVec, dirVec())); } + delete tempSet; - // append the closest IMappings to the output set + // Sort the indices based on their distance TVector distInd = indSort(distances); - int remaining = m_maxSolutions - oSet->size(); - for(int i = 0; i < remaining; i++) { - oSet->append(tempSet->at(distInd[i])); + + // Save the indices (the number of indices is equal to remaining) + int remaining = maxSolutions - out.size(); + for(auto idx : mid(distInd, 0, remaining)) { + out.push_back(tempIdx[idx]); } - delete tempSet; + + return out; } void DirectionFitnessFiltration::TP_defineMaxSolutions(int n) @@ -122,11 +143,12 @@ int DirectionFitnessFiltration::TP_maxSolutions() const void DirectionFitnessFiltration::initialise() { addProperty("MaxSolutions" - ,TString("Maximum number of solutions to be used for " - "surrogate modelling. Default of the entire " - "input set is used when the value is " - "non-positive.") - , getType(int)); + ,TString("Maximum number of solutions used to construct the " + "surrogate model. If the value of this parameter is " + "less than, or equal to zero, then the entire input set " + "is used.\n" + "Default is to use the entire input set.") + , getTType(int)); defineInputTags(TStringList({Tigon::TFitness})); diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/parego/DirectionFitnessFiltration.h b/src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/DirectionFitnessFiltration.h similarity index 88% rename from src/libs/tigon/Operators/AlgorithmSpecific/parego/DirectionFitnessFiltration.h rename to src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/DirectionFitnessFiltration.h index 7dfc1cd..de2dc07 100644 --- a/src/libs/tigon/Operators/AlgorithmSpecific/parego/DirectionFitnessFiltration.h +++ b/src/libs/tigon/Operators/AlgorithmSpecific/ParEGO/DirectionFitnessFiltration.h @@ -1,6 +1,6 @@ -/**************************************************************************** +/**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -47,6 +47,9 @@ class LIGER_TIGON_EXPORT DirectionFitnessFiltration : public IFiltration void TP_defineMaxSolutions(int n); int TP_maxSolutions() const; +protected: + TVector selection(ISet* set, int maxSolutions); + private: void initialise(); int m_maxSolutions; diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoValidation.cpp b/src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/SparegoValidation.cpp similarity index 67% rename from src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoValidation.cpp rename to src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/SparegoValidation.cpp index eb509ab..94bff0b 100644 --- a/src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoValidation.cpp +++ b/src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/SparegoValidation.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,7 +13,7 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include +#include #include #include #include @@ -25,8 +25,8 @@ #include #include #include -#include -#include +#include +#include #include @@ -103,6 +103,18 @@ void SparegoValidation::evaluateNode() /// Create a normal distribution for every IElement /// (objectives, constraints, cost) based on neighbourhood information + // data used to estimate the std for solutions without neighbours + TVector solutionsWithoutNeighboursIndex; // indices of solutions + TVector> xKrigingCost; // doubleDecisionVec of each solution + TVector yKrigingCost; // std of each solution + + TVector>> xKrigingObj(objectiveVecSize()); + TVector> yKrigingObj(objectiveVecSize()); + + TVector>> xKrigingCon(constraintVecSize()); + TVector> yKrigingCon(constraintVecSize()); + + SampledDistribution samp; IDistribution* dist; @@ -111,8 +123,8 @@ void SparegoValidation::evaluateNode() TVector inds = m_neighbours[i]; if(inds.empty()) { - // solutions without neighbours, not currently supported - return; + // solutions without neighbours, get the index + solutionsWithoutNeighboursIndex << i; } else { // solutions with neighbours @@ -145,6 +157,9 @@ void SparegoValidation::evaluateNode() double mean = samp.mean(); double std = samp.std(); + xKrigingObj[j] << imap->doubleDecisionVec(); + yKrigingObj[j] << std; + dist = modifyDistParams(mean, std, m_sampleSizes[i]); imap->objectiveVar(j)->defineDist(dist); @@ -163,6 +178,9 @@ void SparegoValidation::evaluateNode() double mean = samp.mean(); double std = samp.std(); + xKrigingCon[j] << imap->doubleDecisionVec(); + yKrigingCon[j] << std; + dist = modifyDistParams(mean, std, m_sampleSizes[i]); imap->constraintVar(j)->defineDist(dist); @@ -183,6 +201,9 @@ void SparegoValidation::evaluateNode() double mean = samp.mean(); double std = samp.std(); + xKrigingCost << imap->doubleDecisionVec(); + yKrigingCost << std; + dist = modifyDistParams(mean, std, m_sampleSizes[i]); imap->cost()->defineDist(dist); @@ -194,6 +215,82 @@ void SparegoValidation::evaluateNode() } } } + + // if there is solutions without neighbours + if(!solutionsWithoutNeighboursIndex.empty()) { + + // set of krigings for the objectives and constraints, respectively + TVector kObjStd(objectiveVecSize()); + TVector kConStd(constraintVecSize()); + + // cost + KrigingSPtr kCostStd = KrigingSPtr(new OrdinaryKriging( + new PowerVariogram(xKrigingCost, yKrigingCost, 0.8))); + + // for each objective + for(int j=0; jat(solIndex); + + // solution decision variable + TVector solDec = imap->doubleDecisionVec(); + + double solMean = imap->doubleCost(); + double solStd = kCostStd->interpolate(solDec); + dist = new NormalDistribution(solMean, + std::max(solStd,Tigon::Epsilon)); + imap->cost()->defineDist(dist); + + + // for each objective + for(int j=0; jdoubleObjectiveVar(j); + double solObjStd = kObjStd[j]->interpolate(solDec); + + dist = new NormalDistribution(solObjMean, + std::max(solObjStd,Tigon::Epsilon)); + imap->objectiveVar(j)->defineDist(dist); + } + + // for each constraint + for(int j=0; jdoubleConstraintVar(j); + double solConStd = kConStd[j]->interpolate(solDec); + + dist = new NormalDistribution(solConMean, + std::max(solConStd,Tigon::Epsilon)); + imap->constraintVar(j)->defineDist(dist); + } + } + + kCostStd.reset(); + + // for each objective + for(int j=0; jclassName(), DomainException); } + // Create distributions for the mean and std + double dof = std::max(sampSize - 1.0, 1.0); + double uStd = nomStd / std::sqrt(sampSize); + + NormalDistribution mean(nomMean, uStd); + ChiSquaredDistribution cs(dof); + switch(m_confType) { + case ConfidenceIncrease: + { + // use the value of the repocrical defined percentile for the mean and std + double mu = mean.percentile(1.0 - m_percentile); + double csPerc = cs.percentile(m_percentile); + double sigma = nomStd * std::sqrt(dof/csPerc); + + dist = new NormalDistribution(mu, sigma); + break; + } + + case ConfidenceDecrease: + { + // use the value of the defined percentile for the mean and std + // the sample size + double mu = mean.percentile(m_percentile); + double csPerc = cs.percentile(1.0 - m_percentile); + double sigma = nomStd * std::sqrt(dof/csPerc); + + dist = new NormalDistribution(mu, sigma); + break; + } + case UnchangedDistribution: default: { diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoValidation.h b/src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/SparegoValidation.h similarity index 97% rename from src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoValidation.h rename to src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/SparegoValidation.h index c4e13c3..b87d6a2 100644 --- a/src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoValidation.h +++ b/src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/SparegoValidation.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoInit.cpp b/src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/sParEGOInit.cpp similarity index 87% rename from src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoInit.cpp rename to src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/sParEGOInit.cpp index 44bbe57..26af9e2 100644 --- a/src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoInit.cpp +++ b/src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/sParEGOInit.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,7 +13,7 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include +#include #include #include #include @@ -27,47 +27,47 @@ namespace Tigon { namespace Operators { -SparegoInit::SparegoInit() +sParEGOInit::sParEGOInit() { initialise(); } -SparegoInit::SparegoInit(Representation::IPSet* ipset) +sParEGOInit::sParEGOInit(Representation::IPSet* ipset) : IInitialisation(ipset) { initialise(); } -SparegoInit::~SparegoInit() +sParEGOInit::~sParEGOInit() { } -void SparegoInit::TP_definePerturbedRatio(double ratio) +void sParEGOInit::TP_definePerturbedRatio(double ratio) { if(ratio >= 0.0 && ratio < 1.0) { m_perturbRatio = ratio; } } -double SparegoInit::TP_perturbedRatio() const +double sParEGOInit::TP_perturbedRatio() const { return m_perturbRatio; } -void SparegoInit::TP_defineNeighbourhoodRadius(double r) +void sParEGOInit::TP_defineNeighbourhoodRadius(double r) { if(r > 0.0 && r <= 1.0) { m_neighbourhoodRadius = r; } } -double SparegoInit::TP_neighbourhoodRadius() const +double sParEGOInit::TP_neighbourhoodRadius() const { return m_neighbourhoodRadius; } -void SparegoInit::evaluateNode() +void sParEGOInit::evaluateNode() { if( outputSets().empty() ) { ISet* oSet = appendOutputSet(); @@ -128,12 +128,12 @@ void SparegoInit::evaluateNode() } } -TString SparegoInit::name() +TString sParEGOInit::name() { return TString("sParEGO Initialisation"); } -TString SparegoInit::description() +TString sParEGOInit::description() { return TString("Generate an initial set of candidate solutions. " "A portion of the set is generated using Latin " @@ -142,11 +142,11 @@ TString SparegoInit::description() "portion."); } -void SparegoInit::initialise() +void sParEGOInit::initialise() { addProperty("PerturbedRatio" , TString("Ratio of perturbed solutions from the entire set size.") - , getType(double)); + , getTType(double)); addProperty("NeighbourhoodRadius" , TString("Maximum distance between solutions to be " @@ -155,7 +155,7 @@ void SparegoInit::initialise() "by sqrt(d), where d is the number of decision " "variables.\nThe default is ") + std::to_string(Tigon::DefaultsParEGOInitPerturbationRatio) - , getType(double)); + , getTType(double)); TP_definePerturbedRatio(Tigon::DefaultsParEGOInitPerturbationRatio); TP_defineNeighbourhoodRadius(Tigon::DefaultNeighbourhoodRadius); @@ -163,4 +163,4 @@ void SparegoInit::initialise() } // namespace Operators } // namespace Tigon -REGISTER_IPSET_FACTORY(Operators,SparegoInit) +REGISTER_IPSET_FACTORY(Operators,sParEGOInit) diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoInit.h b/src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/sParEGOInit.h similarity index 86% rename from src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoInit.h rename to src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/sParEGOInit.h index 30a7262..2ab168e 100644 --- a/src/libs/tigon/Operators/AlgorithmSpecific/Sparego/SparegoInit.h +++ b/src/libs/tigon/Operators/AlgorithmSpecific/sParEGO/sParEGOInit.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -22,7 +22,7 @@ namespace Tigon { namespace Operators { -class LIGER_TIGON_EXPORT SparegoInit : public IInitialisation +class LIGER_TIGON_EXPORT sParEGOInit : public IInitialisation { HANDLE_READ_PROPERTIES_BEGIN(IInitialisation) @@ -35,12 +35,12 @@ class LIGER_TIGON_EXPORT SparegoInit : public IInitialisation WRITE(NeighbourhoodRadius, double, TP_defineNeighbourhoodRadius) HANDLE_WRITE_PROPERTIES_END - DECLARE_CLASS(Tigon::Operators::SparegoInit) + DECLARE_CLASS(Tigon::Operators::sParEGOInit) public: - SparegoInit(); - SparegoInit(Representation::IPSet* ipset); - virtual ~SparegoInit(); + sParEGOInit(); + sParEGOInit(Representation::IPSet* ipset); + virtual ~sParEGOInit(); // Properties diff --git a/src/libs/tigon/Operators/Composites/ConstrainedSurrogateBasedOptimizer.cpp b/src/libs/tigon/Operators/Composites/ConstrainedSurrogateBasedOptimizer.cpp new file mode 100644 index 0000000..57d8164 --- /dev/null +++ b/src/libs/tigon/Operators/Composites/ConstrainedSurrogateBasedOptimizer.cpp @@ -0,0 +1,452 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace Tigon { +namespace Operators { + +ConstrainedSurrogateBasedOptimizer::ConstrainedSurrogateBasedOptimizer() +{ + initialise(); +} + +ConstrainedSurrogateBasedOptimizer:: +ConstrainedSurrogateBasedOptimizer(Representation::IPSet* ipset) + : SurrogateBasedOptimizer(ipset) +{ + initialise(); +} + +ConstrainedSurrogateBasedOptimizer::~ConstrainedSurrogateBasedOptimizer() +{ + +} + +void ConstrainedSurrogateBasedOptimizer::initialise() +{ + addProperty("DisableConstraintHandling" + , TString("Indicates whether or not constraint handling operates " + "disabled or not.\n" + "Default is false, meaning that constraint handling " + "is enabled.") + , getTType(bool)); + addProperty("NumberIterations" + , TString("Number of Iterations to run the multi-objective " + "optimizer to search the surrogate.\n" + "Default is 150.") + , getTType(int)); + + addProperty("MultiObjectivization" + , TString("Indicates whether a multi-objective optimizer or a " + "single-objective optimizer is used to optimize the " + "surrogate model. The multi-objective approach poses " + "as objectives the individual functions required for " + "the calculation of the constrained expected improvement. " + "The functions correspond to the expected improvement " + "and probability of feasibility.\n" + "Default is false, meaning that a single-objective " + "optimizer is used.") + , getTType(bool)); + + TP_defineDisableConstraintHandling(false); + TP_defineNumberIterations(150); + TP_defineMultiObjectivization(false); +} + +ProblemSPtr ConstrainedSurrogateBasedOptimizer:: +setupSingleObjective_CEIProblem(IFunctionSPtr ei, + const TVector& vpf) +{ + TVector vpfs; + vpfs.reserve(vpf.size()); + for(auto funcC : vpf) { + ProbabilityFeasibility* pf = + static_cast(funcC.get()); + vpfs.push_back(pf); + } + + IFunctionSPtr funEIxPF; + switch (TP_errorMethod()) + { + default: + case ErrConfidenceIntervalBased: + { + FeasibleExpectedImprovement* fbs = + static_cast(ei.get()); +// ExpectedImprovement* fbs = static_cast(ei.get()); + funEIxPF = IFunctionSPtr(new ConstrainedExpectedImprovement(fbs, vpfs)); + break; + } + case ErrDensityBased: + { + FeasibleRandExpectedImprovement* rsv = + static_cast(ei.get()); + funEIxPF = IFunctionSPtr(new ConstrainedExpectedImprovement(rsv, vpfs)); + } + } + funEIxPF->defineInputPrpts(decisionVecProperties(), boxConstraints()); + + ProblemSPtr prob(new Problem); + prob->appendFunction(funEIxPF, TVector(), TVector(), TVector{0}); + prob->processProblemDefinition(); + return prob; +} + +ProblemSPtr ConstrainedSurrogateBasedOptimizer:: +setupMultiObjective_CEIProblem(IFunctionSPtr ei, + const TVector& vpf) +{ + // Define problem and append EI function + ProblemSPtr prob(new Problem); + prob->appendFunction(ei); + + int i=1; + for(auto funcC : vpf) { + + // Change the ElementProperties of probability of feasibility functions. + // This ensures that they are treated as separate outputs when added to + // the problem class. + TString name = "PF" + convertToString(i); + TString description = "PF function for the constraint number " + convertToString(i); + ElementPropertiesFactory* elemFact = ElementPropertiesFactory::instance(); + ElementProperties elem = elemFact->createElementProperties(i, name, description, RealType, Maximization); + // Assumption that there is only one output in probability of feasibility function + TVector elemVector{elem}; + funcC->defineOutputPrpts(elemVector); + + prob->appendFunction(funcC); + i++; + } + + prob->processProblemDefinition(); + return prob; +} + +IMappingSPtr ConstrainedSurrogateBasedOptimizer:: +runMultiObjOptimizer(ProblemSPtr prob) +{ + // Generate an initial set from a mixture of perturbations of best existing + // solutions and random LHS + FitnessBasedInit* fInit = new FitnessBasedInit(this); + fInit->defineInputTags(inputTags()); + fInit->TP_defineSetSize(TP_initialPopsizePerVariableSS() * decisionVecSize()); + fInit->evaluateOnlyThisNode(); + + // Create the inside multi-objective optimizer workflow + PSetBase* base = new PSetBase(); + IFormulation* form = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(form); + Evaluator* eval = new Evaluator(init); + Algorithms::NSGAII* alg = new Algorithms::NSGAII(eval); + + form->defineProblem(prob); + init->defineInitialDVecs(fInit->outputSet(0)); + alg->defineMaxIteration(TP_numberIterations()); + + while(alg->remainingIterations() > 0) { + alg->evaluate(); + alg->incrementIteration(); + } + + TStringList tags; + tags << Tigon::TForNextIteration << Tigon::TForSelection; + ISet* npop = alg->setWithTags(tags); + + // Determine EIxPF of all solutions + TVector fitness; + fitness.reserve(npop->size()); + for(auto sol : npop->all()) { + + TVector objs = sol->doubleObjectiveVec(); + double prod = 1.0; + for(auto f : objs) { + prod *= std::fabs(f); + } + fitness.push_back(prod); + } + + // Find the solution with the highest EIxPF value + auto maxElementIndex = std::max_element(fitness.begin(),fitness.end()) - + fitness.begin(); + IMappingSPtr bestSolutionNSGAII = npop->at(maxElementIndex); + + // Free allocated memory + delete alg; + delete eval; + delete init; + delete form; + delete base; + delete fInit; + + return bestSolutionNSGAII; +} + +void ConstrainedSurrogateBasedOptimizer::evaluateNode() +{ + int nConstraints = constraintVecSize(); + if( (nConstraints==0) || TP_disableConstraintHandling() ) { + SurrogateBasedOptimizer::evaluateNode(); + return; + } + + ISet* oSet = outputSet(0); + ISet* iSet = inputSet(0); + + + /// 1. Build GP model for the Expected Improvement + + // Fit a Kriging model to the input set + TVector > xx; + TVector yy; + if(iSet->at(0)->doubleCost() > 0) { // Confidence indicator + for(auto sol : iSet->all()) { + // decision vector + xx.push_back(sol->doubleDecisionVec()); + // function value + yy.push_back(sol->doubleCost()); + } + } else { //Threshold indicator + for(auto sol : iSet->all()) { + // decision vector + xx.push_back(sol->doubleDecisionVec()); + // function value + yy.push_back(-sol->doubleCost()); + } + } + + KrigingSPtr km; + DACE* kinterp = new DACE(); + kinterp->defineBudgetPerVariable(TP_budgetPerVariableTS()); + kinterp->defineInitialPopsizePerVariable(TP_initialPopsizePerVariableTS()); + kinterp->defineStallIterations(TP_stallIterationsTS()); + kinterp->updateData(xx, yy); + if(kinterp->isDecompositionSuccessfull()) { + km = KrigingSPtr(kinterp); + } else { + delete kinterp; + std::cout << "** Decomposition Failed for objective **" << std::endl; + PowerVariogram* powerV = new PowerVariogram(xx, yy); + km = KrigingSPtr(new OrdinaryKriging(powerV)); + } + +// PowerVariogram* powerV = new PowerVariogram(xx, yy); +// KrigingSPtr km = KrigingSPtr(new OrdinaryKriging(powerV)); + km->defineEstimateErrors(true); + + + /// 2. Calculate constraint violation of every solution to use in + /// calculation of feasible f_min in EI + + TVector cViolation; + cViolation.reserve(iSet->size()); + TVector threshVec = IElementVecToRealVec(thresholdVec()); + for(auto sol : iSet->all()) { + double violation = solutionConstraintViolation(sol, threshVec); + cViolation.push_back(violation); + } + + + /// 3. Expected Improvement function + + IFunctionSPtr func; + switch (TP_errorMethod()) + { + case ErrConfidenceIntervalBased: + default: + { + func = IFunctionSPtr(new FeasibleExpectedImprovement(km, cViolation)); +// func = IFunctionSPtr(new ExpectedImprovement(km)); + break; + } + case ErrDensityBased: + { + TVector > samps; + if(oSet->size() == iSet->size()) { + samps = xx; + } else { + for(auto sol : oSet->all()) { + samps.push_back(sol->doubleDecisionVec()); + } + } + FeasibleRandExpectedImprovement* fun = + new FeasibleRandExpectedImprovement(km, samps, cViolation); + fun->defineBandwidth(TP_densityEstimationBandwidth()); + func = IFunctionSPtr(fun); + break; + } + } + + func->defineInputPrpts(decisionVecProperties(), boxConstraints()); + + + /// 4. Build GP models of all constraints and + /// generate the probability of feasibility function + + TVector ck; + ck.reserve(nConstraints); + TVector vpf; + vpf.reserve(nConstraints); + for(int i=0; i cy; + cy.reserve(iSet->size()); + for(auto sol : iSet->all()) { + cy.push_back(sol->doubleConstraintVar(i) - threshVec[i]); + } + + // Construct the Kriging model for the constraint + KrigingSPtr kmC; + DACE* kinterp2 = new DACE(); + kinterp2->defineBudgetPerVariable(TP_budgetPerVariableTS()); + kinterp2->defineInitialPopsizePerVariable(TP_initialPopsizePerVariableTS()); + kinterp2->defineStallIterations(TP_stallIterationsTS()); + kinterp2->updateData(xx, cy); + if(kinterp2->isDecompositionSuccessfull()) { + kmC = KrigingSPtr(kinterp2); + } else { + delete kinterp2; + std::cout << "** Decomposition Failed for the " + << std::to_string(i+1) << "th constraint **" << std::endl; + PowerVariogram* powerVC = new PowerVariogram(xx, cy); + kmC = KrigingSPtr(new OrdinaryKriging(powerVC)); + } + +// PowerVariogram* powerVC = new PowerVariogram(xx, cy); +// KrigingSPtr kmC = KrigingSPtr(new OrdinaryKriging(powerVC)); + kmC->defineEstimateErrors(true); + ck.push_back(kmC); // save the Kriging model to free memory later + + // Construct the probability of feasibility function + ProbabilityFeasibility* pf = new ProbabilityFeasibility(kmC); + IFunctionSPtr funcC = IFunctionSPtr(pf); + funcC->defineInputPrpts(decisionVecProperties(), boxConstraints()); + vpf.push_back(funcC); + } + + + /// 5. Setup the problem and run an optimizer to search the surrogates + + IMappingSPtr bestSolution; + if(TP_multiObjectivization()) { + ProblemSPtr probMultiObj = setupMultiObjective_CEIProblem(func, vpf); + bestSolution = runMultiObjOptimizer(probMultiObj); +// TVector objsNSGAII = bestSolution->doubleObjectiveVec(); +// double prod = 1.0; +// for(auto elem : objsNSGAII) { +// prod *= std::fabs(elem); +// } +// std::cout << "prod(NSGAII) = " << prod << std::endl; + + } else { + ProblemSPtr probSingleObj = setupSingleObjective_CEIProblem(func, vpf); + bestSolution = runOptimizer_AIBased(probSingleObj); +// double prod = std::fabs(bestSolution->doubleObjectiveVar(0)); +// std::cout << "prod(ACROMUSE) = " << prod << std::endl; + } + + /// 6. Create a new solution + + IMappingSPtr imap = createMapping(); + imap->defineDecisionVec(bestSolution->decisionVec()); + imap->defineWeightingVec(dirVec()); + + + /// 7. Free memory associated with GP models + + km.reset(); // free Kriging model of expected improvement function + for(auto c : ck) { + c.reset(); // free Kriging model of probability of feasibility function + } +} + +bool ConstrainedSurrogateBasedOptimizer::TP_disableConstraintHandling() const +{ + return m_disableConstraintHandling; +} + +void ConstrainedSurrogateBasedOptimizer::TP_defineDisableConstraintHandling(bool flag) +{ + m_disableConstraintHandling = flag; +} + +int ConstrainedSurrogateBasedOptimizer::TP_numberIterations() const +{ + return m_numberIterations; +} + +void ConstrainedSurrogateBasedOptimizer::TP_defineNumberIterations(int iter) +{ + if(iter>0) { + m_numberIterations = iter; + } +} + +bool ConstrainedSurrogateBasedOptimizer::TP_multiObjectivization() const +{ + return m_multiObjectivization; +} + +void ConstrainedSurrogateBasedOptimizer:: +TP_defineMultiObjectivization(bool isMultiObjectivizationUsedOrNot) +{ + m_multiObjectivization = isMultiObjectivizationUsedOrNot; +} + +TString ConstrainedSurrogateBasedOptimizer::name() +{ + return("Constrained Surrogate-Based Optimization"); +} + +TString ConstrainedSurrogateBasedOptimizer::description() +{ + return("Creates a surrogate model (Kriging) from the existing solutions and " + "uses this model to construct the constrained expected improvement " + "function. An optimizer searches for a solution that attains the " + "maximum constrained expected improvement.\n" + "The optimal solution is appended to the current set."); +} + +} // namespace Operators +} // namespace Tigon + diff --git a/src/libs/tigon/Operators/Composites/ConstrainedSurrogateBasedOptimizer.h b/src/libs/tigon/Operators/Composites/ConstrainedSurrogateBasedOptimizer.h new file mode 100644 index 0000000..20993cb --- /dev/null +++ b/src/libs/tigon/Operators/Composites/ConstrainedSurrogateBasedOptimizer.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef SURROGATEBASEDOPTIMIZERWITHCONSTRAINTHANDLING_H +#define SURROGATEBASEDOPTIMIZERWITHCONSTRAINTHANDLING_H +#include + +namespace Tigon { +namespace Operators { + +class LIGER_TIGON_EXPORT ConstrainedSurrogateBasedOptimizer + : public SurrogateBasedOptimizer +{ + HANDLE_READ_PROPERTIES_BEGIN(IComposite) + READ(DisableConstraintHandling, TP_disableConstraintHandling) + READ(NumberIterations, TP_numberIterations) + READ(MultiObjectivization, TP_multiObjectivization) + HANDLE_READ_PROPERTIES_END + + HANDLE_WRITE_PROPERTIES_BEGIN(IComposite) + WRITE(DisableConstraintHandling, bool, TP_defineDisableConstraintHandling) + WRITE(NumberIterations, int, TP_defineNumberIterations) + WRITE(MultiObjectivization, bool, TP_defineMultiObjectivization) + HANDLE_WRITE_PROPERTIES_END + + DECLARE_CLASS(Tigon::Operators::ConstrainedSurrogateBasedOptimizer) + +public: + ConstrainedSurrogateBasedOptimizer(); + ConstrainedSurrogateBasedOptimizer(Representation::IPSet* ipset); + ~ConstrainedSurrogateBasedOptimizer(); + + void evaluateNode(); + + // Properties + bool TP_disableConstraintHandling() const; + void TP_defineDisableConstraintHandling(bool flag); + + int TP_numberIterations() const; + void TP_defineNumberIterations(int iter); + + bool TP_multiObjectivization() const; + void TP_defineMultiObjectivization(bool isMultiObjectivizationUsedOrNot); + + // Information about the node + TString name(); + TString description(); + +private: + void initialise(); + + ProblemSPtr setupSingleObjective_CEIProblem( + IFunctionSPtr ei, const TVector& vpf); + ProblemSPtr setupMultiObjective_CEIProblem( + IFunctionSPtr ei, const TVector& vpf); + + /* + * Runs NSGA-II for a fixed number of iterations + */ + IMappingSPtr runMultiObjOptimizer(ProblemSPtr prob); + + bool m_disableConstraintHandling; + int m_numberIterations; + bool m_multiObjectivization; +}; + +} // namespace Operators +} // namespace Tigon + +#endif // SURROGATEBASEDOPTIMIZERWITHCONSTRAINTHANDLING_H diff --git a/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizer.cpp b/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizer.cpp index 56af0f2..6eca2a6 100644 --- a/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizer.cpp +++ b/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizer.cpp @@ -1,6 +1,6 @@ -/**************************************************************************** +/**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -16,19 +16,22 @@ #include #include #include -#include -#include -#include -#include + +#include +#include +#include +#include +#include + +#include +#include #include #include -#include #include #include -#include -#include #include -#include + +#include namespace Tigon { namespace Operators { @@ -51,21 +54,74 @@ SurrogateBasedOptimizer::~SurrogateBasedOptimizer() void SurrogateBasedOptimizer::initialise() { - addProperty("BudgetPerVariable" - , TString("Budget Per Variable") - , getType(int)); - addProperty("NeighbourhoodRadius" - , TString("Neighbourhood Radius") - , getType(double)); - //addProperty("ErrorMethod", , getType()); - - TP_defineBudgetPerVariable(100); - - // an invalid radius that keeps the RandExpectedImprovement default value: - TP_defineNeighbourhoodRadius(Tigon::UseDefaultNeighbourhoodRadius); - TP_defineErrorMethod(ErrDensityBased); - - //defineErrorMethod(Tigon::ErrDensityBased); + addProperty("OptimizationSearchQuality" + , TString("Sets different parameters that influence the tasks of " + "training and searching the surrogate. Two options are " + "available:\n" + "1: produces better quality results (e.g. better " + "convergence) at the expense of having to wait longer " + "for the optimization task to complete.\n" + "0: produces lower quality results (e.g. weaker " + "convergence) but the optimization task runs faster.\n" + "Default is 1.") + , getTType(int)); + + TP_defineOptimizationSearchQuality(1); + + TString bpvSS(std::to_string(TP_budgetPerVariableSS())); + addProperty("BudgetPerVariableSS" + , TString("Budget per variable used by the optimizer to search " + "the surrogate.\n" + "Default is " + bpvSS + ".") + , getTType(int)); + + TString ippvSS(std::to_string(TP_initialPopsizePerVariableSS())); + addProperty("InitialPopsizePerVariableSS" + , TString("Initial population size per variable used by the " + "optimizer to search the surrogate.\n" + "Default is " + ippvSS + ".") + , getTType(int)); + + TString siSS(std::to_string(TP_stallIterationsSS())); + addProperty("StallIterationsSS" + , TString("The number of consecutive iterations used by the " + "termination criterion of the optimizer to search the " + "surrogate.\n" + "Default is " + siSS + ".") + , getTType(int)); + + TString bpvTS(std::to_string(TP_budgetPerVariableTS())); + addProperty("BudgetPerVariableTS" + , TString("Budget per variable used by the optimizer to train " + "the surrogate.\n" + "Default is " + bpvSS + ".") + , getTType(int)); + + TString ippvTS(std::to_string(TP_initialPopsizePerVariableTS())); + addProperty("InitialPopsizePerVariableTS" + , TString("Initial population size per variable used by the " + "optimizer to train the surrogate.\n" + "Default is " + ippvTS + ".") + , getTType(int)); + + TString siTS(std::to_string(TP_stallIterationsTS())); + addProperty("StallIterationsTS" + , TString("The number of consecutive iterations used by the " + "termination criterion of the optimizer to train the " + "surrogate.\n" + "Default is " + siTS + ".") + , getTType(int)); + + + addProperty("DensityEstimationBandwidth" + , TString("Bandwidth for the density estimation approach used by " + "RandExpectedImprovement. When this value is negative " + "the bandwidth is chosen by RandExpectedImprovement.\n" + "Default is -1.") + , getTType(double)); + + TP_defineDensityEstimationBandwidth(-1.0); + TP_defineErrorMethod(Tigon::ErrConfidenceIntervalBased); addOutputTag(Tigon::TForEvaluation); defineInputTags(TStringList({Tigon::TFiltration})); @@ -76,51 +132,70 @@ void SurrogateBasedOptimizer::evaluateNode() ISet* oSet = outputSet(0); ISet* iSet = inputSet(0); + /// 1. Build GP model for the Expected Improvement + // Fit a Kriging model to the input set TVector > xx; TVector yy; if(iSet->at(0)->doubleCost() > 0) { // Confidence indicator - for(int i=0; isize(); i++) { + for(auto sol : iSet->all()) { // decision vector - xx.push_back(iSet->at(i)->doubleDecisionVec()); + xx.push_back(sol->doubleDecisionVec()); // function value - yy.push_back(iSet->at(i)->doubleCost()); + yy.push_back(sol->doubleCost()); } - } else { //Threshold indicator - for(int i=0; isize(); i++) { + } else { // Threshold indicator + for(auto sol : iSet->all()) { // decision vector - xx.push_back(iSet->at(i)->doubleDecisionVec()); + xx.push_back(sol->doubleDecisionVec()); // function value - yy.push_back(-iSet->at(i)->doubleCost()); + yy.push_back(-sol->doubleCost()); } } - PowerVariogram* powerV = new PowerVariogram(xx, yy); - KrigingSPtr km = KrigingSPtr(new Kriging(powerV)); - km->estimateErrors(true); + KrigingSPtr km; + DACE* kinterp = new DACE(); + kinterp->defineBudgetPerVariable(TP_budgetPerVariableTS()); + kinterp->defineInitialPopsizePerVariable(TP_initialPopsizePerVariableTS()); + kinterp->defineStallIterations(TP_stallIterationsTS()); + kinterp->updateData(xx, yy); + if(kinterp->isDecompositionSuccessfull()) { + km = KrigingSPtr(kinterp); + } else { + delete kinterp; + std::cout << "** Decomposition Failed **" << std::endl; + PowerVariogram* powerV = new PowerVariogram(xx, yy); + km = KrigingSPtr(new OrdinaryKriging(powerV)); + } + +// PowerVariogram* powerV = new PowerVariogram(xx, yy); +// KrigingSPtr km = KrigingSPtr(new OrdinaryKriging(powerV)); + km->defineEstimateErrors(true); + + /// 2. Expected Improvement function // Create an IFunction from the Kriging model IFunctionSPtr func; switch (TP_errorMethod()) { case ErrConfidenceIntervalBased: + default: { func = IFunctionSPtr(new ExpectedImprovement(km)); break; } case ErrDensityBased: - default: { TVector > samps; if(oSet->size() == iSet->size()) { samps = xx; } else { - for(int i=0; isize(); i++) { - samps.push_back(oSet->at(i)->doubleDecisionVec()); + for(auto sol : oSet->all()) { + samps.push_back(sol->doubleDecisionVec()); } } RandExpectedImprovement* fun = new RandExpectedImprovement(km, samps); - fun->defineBandwith(Tigon::KDEBandwithRatio * TP_neighbourhoodRadius()); + fun->defineBandwidth(TP_densityEstimationBandwidth()); func = IFunctionSPtr(fun); break; } @@ -128,66 +203,213 @@ void SurrogateBasedOptimizer::evaluateNode() func->defineInputPrpts(decisionVecProperties(), boxConstraints()); + + /// 3. Run an optimizer to search the surrogates + + ProblemSPtr prob(new Problem); + prob->appendFunction(func); + prob->processProblemDefinition(); + IMappingSPtr sol = runOptimizer_AIBased(prob); + + + /// 4. Create a new solution + + // create a new IMapping with the same decision vector as the best solution + IMappingSPtr imap = createMapping(); + TVector newDVec = sol->decisionVec(); + imap->defineDecisionVec(newDVec); + imap->defineWeightingVec(dirVec()); + + + /// 5. Free memory associated with GP model + km.reset(); +} + +IMappingSPtr SurrogateBasedOptimizer::runOptimizer_FEBased(ProblemSPtr prob) +{ // Generate an initial set from a mixture of perturbations of best existing // solutions and random LHS FitnessBasedInit* fInit = new FitnessBasedInit(this); fInit->defineInputTags(inputTags()); - fInit->TP_defineSetSize(10 * decisionVecSize()); + fInit->TP_defineSetSize(TP_initialPopsizePerVariableSS() * + decisionVecSize()); fInit->evaluateOnlyThisNode(); // Create a new workflow PSetBase* base = new PSetBase(); - IFormulation* prob = new IFormulation(base); - UserDefinedInit* init = new UserDefinedInit(prob); + IFormulation* form = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(form); Evaluator* eval = new Evaluator(init); Algorithms::ACROMUSE* alg = new Algorithms::ACROMUSE(eval); - prob->appendFunction(func); + form->defineProblem(prob); init->defineInitialDVecs(fInit->outputSet(0)); - eval->TP_defineSingleObjective(true); - - alg->defineBudget(TP_budgetPerVariable() * decisionVecSize()); + alg->defineBudget(TP_budgetPerVariableSS() * decisionVecSize()); while(alg->remainingBudget() > 0) { alg->evaluate(); alg->incrementIteration(); } - // create a new IMapping with the same decision vector as the best solution - IMappingSPtr imap = createMapping(); - TVector newDVec = alg->bestMapping()->decisionVec(); - imap->defineDecisionVec(newDVec); + IMappingSPtr sol = alg->bestMapping(); delete alg; delete eval; delete init; - delete prob; + delete form; delete base; delete fInit; - km.reset(); + + return sol; } -void SurrogateBasedOptimizer::TP_defineBudgetPerVariable(int n) +IMappingSPtr SurrogateBasedOptimizer::runOptimizer_AIBased(ProblemSPtr prob) +{ + // Generate an initial set from a mixture of perturbations of best existing + // solutions and random LHS + FitnessBasedInit* fInit = new FitnessBasedInit(this); + fInit->defineInputTags(inputTags()); + fInit->TP_defineSetSize(TP_initialPopsizePerVariableSS() * + decisionVecSize()); + fInit->evaluateOnlyThisNode(); + + // Create a new workflow + PSetBase* base = new PSetBase(); + IFormulation* form = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(form); + Evaluator* eval = new Evaluator(init); + Algorithms::ACROMUSE* alg = new Algorithms::ACROMUSE(eval); + + form->defineProblem(prob); + init->defineInitialDVecs(fInit->outputSet(0)); + eval->TP_defineSingleObjective(true); + alg->defineMaxIteration(TP_budgetPerVariableSS() * decisionVecSize()); + + int stallIter = TP_stallIterationsSS(); + TVector scoresDiff; + double prevScore = 0.0; + while(alg->remainingIterations() > 0) { + alg->evaluate(); + + double currentScore = -alg->bestMapping()->doubleObjectiveVar(0); + if(alg->currentIteration()==0) { + prevScore = currentScore; + } + else { + double scoreDiff = std::fabs(prevScore - currentScore); + scoresDiff.push_back(scoreDiff); + } + + if(scoresDiff.size() > stallIter) { + scoresDiff.erase(scoresDiff.begin()); // delete first element + } + + if(alg->currentIteration() > stallIter) { + double diffMean = vectorMean(scoresDiff); + if(diffMean < Tigon::Epsilon) { + break; + } + } + + prevScore = currentScore; + alg->incrementIteration(); + } + //std::cout << "SS iterations: " << alg->currentIteration() << std::endl; + + IMappingSPtr sol = alg->bestMapping(); + + delete alg; + delete eval; + delete init; + delete form; + delete base; + delete fInit; + + return sol; +} + +void SurrogateBasedOptimizer::TP_defineBudgetPerVariableSS(int n) { if(n>0) { - m_budgetPerVar = n; + m_budgetPerVarSS = n; } } -int SurrogateBasedOptimizer::TP_budgetPerVariable() const +int SurrogateBasedOptimizer::TP_budgetPerVariableSS() const { - return m_budgetPerVar; + return m_budgetPerVarSS; } -void SurrogateBasedOptimizer::TP_defineNeighbourhoodRadius(double r) +void SurrogateBasedOptimizer::TP_defineInitialPopsizePerVariableSS(int n) { - m_neighbourhoodRadius = r; + if(n>0) { + m_initialPopsizePerVariableSS = n; + } } -double SurrogateBasedOptimizer::TP_neighbourhoodRadius() const +int SurrogateBasedOptimizer::TP_initialPopsizePerVariableSS() const { - return m_neighbourhoodRadius; + return m_initialPopsizePerVariableSS; +} + +void SurrogateBasedOptimizer::TP_defineStallIterationsSS(int iter) +{ + if(iter>0) { + m_stallIterationsSS = iter; + } +} + +int SurrogateBasedOptimizer::TP_stallIterationsSS() const +{ + return m_stallIterationsSS; +} + +void SurrogateBasedOptimizer::TP_defineBudgetPerVariableTS(int n) +{ + if(n>0) { + m_budgetPerVarTS = n; + } +} + +int SurrogateBasedOptimizer::TP_budgetPerVariableTS() const +{ + return m_budgetPerVarTS; +} + +void SurrogateBasedOptimizer::TP_defineInitialPopsizePerVariableTS(int n) +{ + if(n>0) { + m_initialPopsizePerVariableTS = n; + } +} + +int SurrogateBasedOptimizer::TP_initialPopsizePerVariableTS() const +{ + return m_initialPopsizePerVariableTS; +} + +void SurrogateBasedOptimizer::TP_defineStallIterationsTS(int iter) +{ + if(iter>0) { + m_stallIterationsTS = iter; + } +} + +int SurrogateBasedOptimizer::TP_stallIterationsTS() const +{ + return m_stallIterationsTS; +} + + +double SurrogateBasedOptimizer::TP_densityEstimationBandwidth() const +{ + return m_densityEstimationBandwidth; +} + +void SurrogateBasedOptimizer::TP_defineDensityEstimationBandwidth(double bandwidth) +{ + m_densityEstimationBandwidth = bandwidth; } void SurrogateBasedOptimizer::TP_defineErrorMethod(ErrorHandlingMethod err) @@ -200,18 +422,64 @@ ErrorHandlingMethod SurrogateBasedOptimizer::TP_errorMethod() const return m_errMethod; } +/// +/// \brief SurrogateBasedOptimizer::defineOptimizationSearchQuality +/// Sets different parameters that influence the tasks of training and searching +/// the surrogate. +/// \param mode +/// mode=1 produces better quality results (e.g. better convergence) at the +/// expense of having to wait longer for the optimization task to complete. +/// mode=0: produces lower quality results (e.g. weaker convergence) but the +/// optimization task runs faster. +/// +void SurrogateBasedOptimizer::TP_defineOptimizationSearchQuality(int mode) +{ + switch(mode) + { + case 0: // Parameters for weaker quality results + // Search the surrogate parameters + TP_defineBudgetPerVariableSS(Tigon::DefaultBudgetPerVariableSS_L); + TP_defineInitialPopsizePerVariableSS(Tigon::DefaultInitialPopsizePerVariableSS_L); + TP_defineStallIterationsSS(Tigon::DefaultStallIterationsSS_L); + + // Train the surrogate parameters + TP_defineBudgetPerVariableTS(Tigon::DefaultBudgetPerVariableTS_L); + TP_defineInitialPopsizePerVariableTS(Tigon::DefaultInitialPopsizePerVariableTS_L); + TP_defineStallIterationsTS(Tigon::DefaultStallIterationsTS_L); + break; + case 1: // Parameters for better quality results + default: + // Search the surrogate parameters + TP_defineBudgetPerVariableSS(Tigon::DefaultBudgetPerVariableSS_H); + TP_defineInitialPopsizePerVariableSS(Tigon::DefaultInitialPopsizePerVariableSS_H); + TP_defineStallIterationsSS(Tigon::DefaultStallIterationsSS_H); + + // Train the surrogate parameters + TP_defineBudgetPerVariableTS(Tigon::DefaultBudgetPerVariableTS_H); + TP_defineInitialPopsizePerVariableTS(Tigon::DefaultInitialPopsizePerVariableTS_H); + TP_defineStallIterationsTS(Tigon::DefaultStallIterationsTS_H); + break; + } + m_mode = mode; +} + +int SurrogateBasedOptimizer::TP_optimizationSearchQuality() const +{ + return m_mode; +} TString SurrogateBasedOptimizer::name() { - return TString("Surrogate-Based Optimization"); + return("Surrogate-Based Optimization"); } TString SurrogateBasedOptimizer::description() { - return TString("Creates a surrogate model (Kriging) from the " - "existing solutions and optimizes over this model.\n" - "The optimal solution is appended to the current " - "set.\n"); + return("Creates a surrogate model (Kriging) from the existing solutions and " + "uses this model to construct the expected improvement function. An " + "optimizer is used to search for a solution that attains the maximum " + "expected improvement.\n" + "The optimal solution is appended to the current set.\n"); } } // namespace Operators diff --git a/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizer.h b/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizer.h index 3e03fa4..f4211c4 100644 --- a/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizer.h +++ b/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizer.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -17,6 +17,8 @@ #define SURROGATEBASEDOPTIMIZER_H #include #include +#include +#include using Tigon::ErrorHandlingMethod; @@ -26,15 +28,25 @@ namespace Operators { class LIGER_TIGON_EXPORT SurrogateBasedOptimizer : public IComposite { HANDLE_READ_PROPERTIES_BEGIN(IComposite) - READ(BudgetPerVariable, TP_budgetPerVariable) - READ(NeighbourhoodRadius, TP_neighbourhoodRadius) - //READ(ErrorMethod, TP_errorMethod) + READ(OptimizationSearchQuality, TP_optimizationSearchQuality) + READ(BudgetPerVariableSS, TP_budgetPerVariableSS) + READ(InitialPopsizePerVariableSS, TP_initialPopsizePerVariableSS) + READ(StallIterationsSS, TP_stallIterationsSS) + READ(BudgetPerVariableTS, TP_budgetPerVariableTS) + READ(InitialPopsizePerVariableTS, TP_initialPopsizePerVariableTS) + READ(StallIterationsTS, TP_stallIterationsTS) + READ(DensityEstimationBandwidth, TP_densityEstimationBandwidth) HANDLE_READ_PROPERTIES_END HANDLE_WRITE_PROPERTIES_BEGIN(IComposite) - WRITE(BudgetPerVariable, int, TP_defineBudgetPerVariable) - WRITE(NeighbourhoodRadius, double, TP_defineNeighbourhoodRadius) - //WRITE(ErrorMethod, ErrorHandlingMethod, TP_defineErrorMethod) + WRITE(OptimizationSearchQuality, int, TP_defineOptimizationSearchQuality) + WRITE(BudgetPerVariableSS, int, TP_defineBudgetPerVariableSS) + WRITE(InitialPopsizePerVariableSS, int, TP_defineInitialPopsizePerVariableSS) + WRITE(StallIterationsSS, int, TP_defineStallIterationsSS) + WRITE(BudgetPerVariableTS, int, TP_defineBudgetPerVariableTS) + WRITE(InitialPopsizePerVariableTS, int, TP_defineInitialPopsizePerVariableTS) + WRITE(StallIterationsTS, int, TP_defineStallIterationsTS) + WRITE(DensityEstimationBandwidth, double, TP_defineDensityEstimationBandwidth) HANDLE_WRITE_PROPERTIES_END DECLARE_CLASS(Tigon::Operators::SurrogateBasedOptimizer) @@ -42,30 +54,73 @@ class LIGER_TIGON_EXPORT SurrogateBasedOptimizer : public IComposite public: SurrogateBasedOptimizer(); SurrogateBasedOptimizer(Representation::IPSet* ipset); - virtual ~SurrogateBasedOptimizer(); + ~SurrogateBasedOptimizer(); void evaluateNode(); - // properties - void TP_defineBudgetPerVariable(int n); - int TP_budgetPerVariable() const; + // Properties for the optimizer to search the surrogate + void TP_defineBudgetPerVariableSS(int n); + int TP_budgetPerVariableSS() const; + + void TP_defineInitialPopsizePerVariableSS(int n); + int TP_initialPopsizePerVariableSS() const; + + void TP_defineStallIterationsSS(int iter); + int TP_stallIterationsSS() const; + + // Properties for the optimizer to train the surrogate + void TP_defineBudgetPerVariableTS(int n); + int TP_budgetPerVariableTS() const; - void TP_defineNeighbourhoodRadius(double r); - double TP_neighbourhoodRadius() const; + void TP_defineInitialPopsizePerVariableTS(int n); + int TP_initialPopsizePerVariableTS() const; + + void TP_defineStallIterationsTS(int iter); + int TP_stallIterationsTS() const; + + // Other properties + void TP_defineDensityEstimationBandwidth(double bandwidth); + double TP_densityEstimationBandwidth() const; void TP_defineErrorMethod(ErrorHandlingMethod err); - ErrorHandlingMethod TP_errorMethod() const; + ErrorHandlingMethod TP_errorMethod() const; + + void TP_defineOptimizationSearchQuality(int mode); + int TP_optimizationSearchQuality() const; // Information about the node TString name(); TString description(); +protected: + /* + * Runs ACROMUSE for a fixed number of function evaluations + * (budgetPerVariable x decisionVecSize) + */ + IMappingSPtr runOptimizer_FEBased(ProblemSPtr prob); + + /* + * Runs ACROMUSE with termination criterion based on the average improvement + * of the best fitness over a given number of iterations (StallIterations) + */ + IMappingSPtr runOptimizer_AIBased(ProblemSPtr prob); + private: void initialise(); - int m_budgetPerVar; + int m_budgetPerVarSS; + int m_initialPopsizePerVariableSS; + int m_stallIterationsSS; + + int m_budgetPerVarTS; + int m_initialPopsizePerVariableTS; + int m_stallIterationsTS; + + double m_densityEstimationBandwidth; + + int m_mode; + Tigon::ErrorHandlingMethod m_errMethod; - double m_neighbourhoodRadius; }; } // namespace Operators diff --git a/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizerWithPerturbation.cpp b/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizerWithPerturbation.cpp index efbc76a..470273d 100644 --- a/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizerWithPerturbation.cpp +++ b/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizerWithPerturbation.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -16,19 +16,9 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include + #include #include -#include -#include namespace Tigon { namespace Operators { @@ -51,7 +41,12 @@ SurrogateBasedOptimizerWithPerturbation::~SurrogateBasedOptimizerWithPerturbatio void SurrogateBasedOptimizerWithPerturbation::initialise() { + addProperty("NeighbourhoodRadius" + , TString("Neighbourhood Radius") + , getTType(double)); + // an invalid radius that keeps the RandExpectedImprovement default value: + TP_defineNeighbourhoodRadius(Tigon::UseDefaultNeighbourhoodRadius); } void SurrogateBasedOptimizerWithPerturbation::evaluateNode() @@ -72,8 +67,9 @@ void SurrogateBasedOptimizerWithPerturbation::evaluateNode() BoundedPerturbation* mutat = new BoundedPerturbation(toPerturb); mutat->defineOutputTags(toPerturb->outputTags()); mutat->TP_defineSolutionMutationProbability(1.0); - mutat->TP_definePerturbationRadius(TP_neighbourhoodRadius() * - Tigon::PerturbationRadiusByNeighbourhoodRadius); + double pertRadius = TP_neighbourhoodRadius() * + Tigon::PerturbationRadiusByNeighbourhoodRadius; + mutat->TP_definePerturbationRadius(pertRadius); mutat->evaluateOnlyThisNode(); for(auto sol : mutat->outputSet(0)->all()) { @@ -86,6 +82,17 @@ void SurrogateBasedOptimizerWithPerturbation::evaluateNode() delete toPerturb; } +void SurrogateBasedOptimizerWithPerturbation:: +TP_defineNeighbourhoodRadius(double r) +{ + m_neighbourhoodRadius = r; +} + +double SurrogateBasedOptimizerWithPerturbation::TP_neighbourhoodRadius() const +{ + return m_neighbourhoodRadius; +} + TString SurrogateBasedOptimizerWithPerturbation::name() { return TString("Surrogate-Based Optimization with Pertubation"); diff --git a/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizerWithPerturbation.h b/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizerWithPerturbation.h index 9e42bb1..d59c354 100644 --- a/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizerWithPerturbation.h +++ b/src/libs/tigon/Operators/Composites/SurrogateBasedOptimizerWithPerturbation.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -23,20 +23,36 @@ namespace Operators { class LIGER_TIGON_EXPORT SurrogateBasedOptimizerWithPerturbation : public SurrogateBasedOptimizer { + HANDLE_READ_PROPERTIES_BEGIN(IComposite) + READ(NeighbourhoodRadius, TP_neighbourhoodRadius) + HANDLE_READ_PROPERTIES_END + + HANDLE_WRITE_PROPERTIES_BEGIN(IComposite) + WRITE(NeighbourhoodRadius, double, TP_defineNeighbourhoodRadius) + HANDLE_WRITE_PROPERTIES_END + + + DECLARE_CLASS(Tigon::Operators::SurrogateBasedOptimizerWithPerturbation) public: SurrogateBasedOptimizerWithPerturbation(); SurrogateBasedOptimizerWithPerturbation(Representation::IPSet* ipset); - virtual ~SurrogateBasedOptimizerWithPerturbation(); + ~SurrogateBasedOptimizerWithPerturbation(); void evaluateNode(); + // Properties + void TP_defineNeighbourhoodRadius(double r); + double TP_neighbourhoodRadius() const; + // Information about the node. TString name(); TString description(); private: void initialise(); + + double m_neighbourhoodRadius; }; } // namespace Operators diff --git a/src/libs/tigon/Operators/Fitness/GeneralizedDecomposition.cpp b/src/libs/tigon/Operators/Fitness/GeneralizedDecomposition.cpp index aacfd66..18b4725 100644 --- a/src/libs/tigon/Operators/Fitness/GeneralizedDecomposition.cpp +++ b/src/libs/tigon/Operators/Fitness/GeneralizedDecomposition.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -23,13 +23,6 @@ #include #include -// STL includes -#include -#include - -// Boost includes -#include - namespace Tigon { namespace Operators { @@ -38,7 +31,8 @@ GeneralizedDecomposition::GeneralizedDecomposition() initialise(); } -GeneralizedDecomposition::GeneralizedDecomposition(Tigon::Representation::IPSet* ipset) +GeneralizedDecomposition::GeneralizedDecomposition( + Tigon::Representation::IPSet* ipset) : Scalarization(ipset) { initialise(); @@ -51,9 +45,7 @@ GeneralizedDecomposition::~GeneralizedDecomposition() void GeneralizedDecomposition::initialise() { - m_name = TString("Generalized Decomposition"); - m_description = TString("Assigns every solution in the set a scalar value" - " using Generalised Decomposition."); + } void GeneralizedDecomposition::evaluateNode() @@ -64,10 +56,14 @@ void GeneralizedDecomposition::evaluateNode() /// general method is required in case other scalarising functions are to /// be used in the future. - //int M=objectiveVecSize(); + auto gfunc = [](double w) + { + return 1.0/(w+0.01); + }; + // define the optimal weighting vector TVector weight; - switch(weightScopeApproach()) { + switch(TP_weightScopeApproach()) { case LocalWeight: // do nothing break; @@ -75,51 +71,31 @@ void GeneralizedDecomposition::evaluateNode() default: weight = dirVec(); - std::transform(weight.begin(), weight.end(), weight.begin(), - [](double w) { return 1.0/(w+0.01); }); + std::transform(weight.begin(), weight.end(), weight.begin(), gfunc); toUnitVec(weight, 1.0); -// for(int i=0; i ideal = IElementVecToRealVec(idealVec()); + TVector antiIdeal = IElementVecToRealVec(antiIdealVec()); + while(hasNextOutputSet()) { ISet* oSet = nextOutputSet(); - // Normalise the objective vectors - int setSize = oSet->size(); - TVector > normalObjectives(setSize); - TVector ideal = IElementVecToRealVec(idealVec()); - TVector antiIdeal = IElementVecToRealVec(antiIdealVec()); - for (int i=0; iat(i)->isScalarised()) { - TVector normVec = oSet->at(i)->doubleObjectiveVec(); - normaliseToUnitBoxInMemory(normVec, ideal, antiIdeal); - normalObjectives[i] = normVec; - } - } - - for(int i=0; iall()) { - if(!oSet->at(i)->isScalarised()) { + if(!sol->isScalarised()) { - switch(weightScopeApproach()) { + switch(TP_weightScopeApproach()) { case LocalWeight: // construct local weight - weight = oSet->at(i)->weightingVec(); + weight = sol->weightingVec(); - std::transform(weight.begin(), weight.end(), weight.begin(), - [](double w) { return 1.0/(w+0.01); }); + std::transform(weight.begin(), weight.end(), + weight.begin(), gfunc); toUnitVec(weight, 1.0); -// for(int j=0; jat(i)->weightingVec()[j]; -// } -// toUnitVec(weight, 1.0); break; case GlobalWeight: default: @@ -127,29 +103,36 @@ void GeneralizedDecomposition::evaluateNode() break; } + // normalise the objectives according to the ideal and antiIdeal + TVector normObj = + normaliseToUnitBox(sol->doubleObjectiveVec(), + ideal, antiIdeal); + // Scalarise double cost; switch(TP_scalarisingFunction()) { case (Tigon::WeightedSum): - cost = weightedSum(weight, normalObjectives[i]); + cost = weightedSum(weight, normObj); break; case (Tigon::WeightedChebyshev): - cost = weightedChebyshev(weight, normalObjectives[i]); + cost = weightedChebyshev(weight, normObj); break; case (Tigon::WeightedChebyshevAugmented): - cost = weightedChebyshevAugmented(weight, normalObjectives[i]); + cost = weightedChebyshevAugmented(weight, normObj); break; case (Tigon::WeightedLp): - cost = weightedLp(weight, normalObjectives[i], pNorm()); + cost = weightedLp(weight, normObj, pNorm()); break; default: throw TException(this->className(), UnrecognisedScalarisationFunction); } - oSet->at(i)->defineCost(cost); - if(weightScopeApproach() == LocalWeight) { - oSet->at(i)->defineScalarised(); + sol->defineCost(cost); + + if(TP_weightScopeApproach() == LocalWeight) { + sol->defineScalarised(); } + } } } @@ -157,12 +140,18 @@ void GeneralizedDecomposition::evaluateNode() TString GeneralizedDecomposition::name() { - return m_name; + return TString("Generalized Decomposition"); } TString GeneralizedDecomposition::description() { - return m_description; + return TString("Assigns every solution in the set a scalar value that is " + "determined by a scalarization function according to the " + "concept of generalized decomposition, based on \"Ioannis " + "Giagkiozis, Robin C. Purshouse, Peter J. Fleming, " + "Generalized Decomposition, in International Conference on " + "Evolutionary Multi-Criterion Optimization, EMO 2013, " + "pp 428-442.\""); } } // namespace Operators diff --git a/src/libs/tigon/Operators/Fitness/GeneralizedDecomposition.h b/src/libs/tigon/Operators/Fitness/GeneralizedDecomposition.h index 9476838..05505a2 100644 --- a/src/libs/tigon/Operators/Fitness/GeneralizedDecomposition.h +++ b/src/libs/tigon/Operators/Fitness/GeneralizedDecomposition.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -27,7 +27,7 @@ class LIGER_TIGON_EXPORT GeneralizedDecomposition : public Scalarization public: GeneralizedDecomposition(); GeneralizedDecomposition(Tigon::Representation::IPSet* ipset); - virtual ~GeneralizedDecomposition(); + ~GeneralizedDecomposition(); void evaluateNode(); @@ -35,12 +35,8 @@ class LIGER_TIGON_EXPORT GeneralizedDecomposition : public Scalarization TString name(); TString description(); - - private: void initialise(); - TString m_name; - TString m_description; }; } // namespace Operators diff --git a/src/libs/tigon/Operators/Fitness/MOGANonDominanceRanking.cpp b/src/libs/tigon/Operators/Fitness/MOGANonDominanceRanking.cpp index c4f509e..5ce02ee 100644 --- a/src/libs/tigon/Operators/Fitness/MOGANonDominanceRanking.cpp +++ b/src/libs/tigon/Operators/Fitness/MOGANonDominanceRanking.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -55,7 +55,7 @@ void MOGANonDominanceRanking::initialise() "solutions. Otherwise the constraints have no " "influence in the ranks.\n" "The default value is true.") - , typeid(bool).hash_code()); + , getTType(bool)); addProperty("IsPreferabilityUsed" , TString("If set to true then the ranks of dominance are " @@ -63,13 +63,13 @@ void MOGANonDominanceRanking::initialise() "Otherwise any goal vector has no influence in the " "ranks.\n" "The default value is true.") - , typeid(bool).hash_code()); + , getTType(bool)); addProperty("IsWeakDom" , TString("Indicates if either weak (true) or strong (false) " "dominance relation is used.\n" "The default value is true.") - , typeid(bool).hash_code()); + , getTType(bool)); TP_defineIsConstrainedHandlingUsed(true); TP_defineIsPreferabilityUsed(true); @@ -90,60 +90,57 @@ void MOGANonDominanceRanking::evaluateNode() clearOutputSets(); ISet* iSet = inputSet(0); - TVector goals = goalVec(); - TVector::iterator iter = - std::find_if(goals.begin(),goals.end(), - [](IElementSPtr g){ - tribool rs = *g==g->minValue(); - return (rs.value == false); - }); + bool areGoalsDefined = false; + TVector usedGoals = setGoalVec(); + for(auto val : usedGoals ) { + if(val == true) { + areGoalsDefined = true; + break; + } + } - bool isGoalVectorUsed = ((iter != goals.end()) && + bool isGoalVectorUsed = (areGoalsDefined && TP_isPreferabilityUsed()); bool isThresholdVectorDefined = ((constraintVecSize() > 0) && TP_isConstrainedHandlingUsed()); m_domRelation->defineWeakDom(TP_isWeakDom()); - // build a vector that indicates if goals are used or not - TVector setGoals; + // build a vector that indicates if goals are used or not in double format + TVector setGoals; setGoals.reserve(usedGoals.size()); if(isGoalVectorUsed) { - for(IElementSPtr g : goalVec()) { - if(*g==g->minValue()) { - setGoals.push_back(false); - } - else { - setGoals.push_back(true); - } + for(auto val : usedGoals) { + setGoals.push_back(val); } } + TVector priorities = priorityVec(); + TVector priority; priority.reserve(priorities.size()); + for(auto elem : priorities) { + priority.push_back(elem); + } + // build parameter vector TVector> parameters; if(isGoalVectorUsed && isThresholdVectorDefined) { defineRelationType(PreferabilityConstraintHandlingRelation); - - parameters.resize(5); - parameters[0] = IElementVecToRealVec(goalVec()); - parameters[1] = setGoals; - parameters[2] = IElementVecToRealVec(thresholdVec()); + m_domRelation->defineGoalVec(IElementVecToRealVec(goalVec())); + m_domRelation->defineSetGoals(setGoalVec()); + m_domRelation->definePriorityVec(priorityVec()); + m_domRelation->defineThresholdVec(IElementVecToRealVec(thresholdVec())); } else if(!isGoalVectorUsed && isThresholdVectorDefined) { defineRelationType(ConstraintHandlingDominanceRelation); - - parameters.resize(3); - parameters[0] = IElementVecToRealVec(thresholdVec()); + m_domRelation->defineThresholdVec(IElementVecToRealVec(thresholdVec())); } else if(isGoalVectorUsed && !isThresholdVectorDefined) { defineRelationType(PreferabilityRelation); - - parameters.resize(2); - parameters[0] = IElementVecToRealVec(goalVec()); - parameters[1] = setGoals; - m_domRelation->defineParameters(parameters); + m_domRelation->defineGoalVec(IElementVecToRealVec(goalVec())); + m_domRelation->defineSetGoals(setGoalVec()); + m_domRelation->definePriorityVec(priorityVec()); } else { defineRelationType(NormalDominanceRelation); @@ -163,20 +160,9 @@ void MOGANonDominanceRanking::evaluateNode() IMappingSPtr b = iSet->at(j); // add parameters to the dominance relation for constraint handling - if(isGoalVectorUsed && isThresholdVectorDefined) { - - parameters[3] = a->doubleConstraintVec(); - parameters[4] = b->doubleConstraintVec(); - m_domRelation->defineParameters(parameters); - } - else if(!isGoalVectorUsed && isThresholdVectorDefined) { - - parameters[1] = a->doubleConstraintVec(); - parameters[2] = b->doubleConstraintVec(); - m_domRelation->defineParameters(parameters); - } - else { - // no need to define parameters, or already defined + if(isThresholdVectorDefined) { + m_domRelation->defineConstraintVecA(a->doubleConstraintVec()); + m_domRelation->defineConstraintVecB(b->doubleConstraintVec()); } dom = m_domRelation->isBetterThan(a->doubleObjectiveVec(), diff --git a/src/libs/tigon/Operators/Fitness/NonDominanceRanking.cpp b/src/libs/tigon/Operators/Fitness/NonDominanceRanking.cpp index 0a3f83f..e4a8e72 100644 --- a/src/libs/tigon/Operators/Fitness/NonDominanceRanking.cpp +++ b/src/libs/tigon/Operators/Fitness/NonDominanceRanking.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -54,7 +54,7 @@ void NonDominanceRanking::initialise() "solutions. Otherwise the constraints have no " "influence in the ranks.\n" "The default value is true.") - , typeid(bool).hash_code()); + , getTType(bool)); addProperty("IsPreferabilityUsed" , TString("If set to true then the ranks of dominance are " @@ -62,14 +62,13 @@ void NonDominanceRanking::initialise() "Otherwise any goal vector has no influence in the " "ranks.\n" "The default value is true.") - , typeid(bool).hash_code()); + , getTType(bool)); addProperty("IsWeakDom" , TString("Indicates if either weak (true) or strong (false) " "dominance relation is used.\n" "The default value is true.") - , typeid(bool).hash_code()); - + , getTType(bool)); TP_defineIsConstrainedHandlingUsed(true); TP_defineIsPreferabilityUsed(true); @@ -90,60 +89,57 @@ void NonDominanceRanking::evaluateNode() clearOutputSets(); ISet* iSet = inputSet(0); - TVector goals = goalVec(); - TVector::iterator iter = - std::find_if(goals.begin(),goals.end(), - [](IElementSPtr g){ - tribool rs = *g==g->minValue(); - return (rs.value == false); - }); + bool areGoalsDefined = false; + TVector usedGoals = setGoalVec(); + for(auto val : usedGoals ) { + if(val == true) { + areGoalsDefined = true; + break; + } + } - bool isGoalVectorUsed = ((iter != goals.end()) && + bool isGoalVectorUsed = (areGoalsDefined && TP_isPreferabilityUsed()); bool isThresholdVectorDefined = ((constraintVecSize() > 0) && TP_isConstrainedHandlingUsed()); m_domRelation->defineWeakDom(TP_isWeakDom()); - // build a vector that indicates if goals are used or not - TVector setGoals; - if(isGoalVectorUsed) { - for(IElementSPtr g : goalVec()) { - if(*g==g->minValue()) { - setGoals.push_back(false); - } - else { - setGoals.push_back(true); - } + // build a vector that indicates if goals are used or not in double format + TVector setGoals; setGoals.reserve(usedGoals.size()); + if(isGoalVectorUsed) { + for(auto val : usedGoals) { + setGoals.push_back(val); } } + TVector priorities = priorityVec(); + TVector priority; priority.reserve(priorities.size()); + for(auto elem : priorities) { + priority.push_back(elem); + } + // build parameter vector TVector> parameters; if(isGoalVectorUsed && isThresholdVectorDefined) { defineRelationType(PreferabilityConstraintHandlingRelation); - - parameters.resize(5); - parameters[0] = IElementVecToRealVec(goalVec()); - parameters[1] = setGoals; - parameters[2] = IElementVecToRealVec(thresholdVec()); + m_domRelation->defineGoalVec(IElementVecToRealVec(goalVec())); + m_domRelation->defineSetGoals(setGoalVec()); + m_domRelation->definePriorityVec(priorityVec()); + m_domRelation->defineThresholdVec(IElementVecToRealVec(thresholdVec())); } else if(!isGoalVectorUsed && isThresholdVectorDefined) { defineRelationType(ConstraintHandlingDominanceRelation); - - parameters.resize(3); - parameters[0] = IElementVecToRealVec(thresholdVec()); + m_domRelation->defineThresholdVec(IElementVecToRealVec(thresholdVec())); } else if(isGoalVectorUsed && !isThresholdVectorDefined) { defineRelationType(PreferabilityRelation); - - parameters.resize(2); - parameters[0] = IElementVecToRealVec(goalVec()); - parameters[1] = setGoals; - m_domRelation->defineParameters(parameters); + m_domRelation->defineGoalVec(IElementVecToRealVec(goalVec())); + m_domRelation->defineSetGoals(setGoalVec()); + m_domRelation->definePriorityVec(priorityVec()); } else { defineRelationType(NormalDominanceRelation); @@ -162,20 +158,9 @@ void NonDominanceRanking::evaluateNode() IMappingSPtr b = iSet->at(j); // add parameters to the dominance relation for constraint handling - if(isGoalVectorUsed && isThresholdVectorDefined) { - - parameters[3] = a->doubleConstraintVec(); - parameters[4] = b->doubleConstraintVec(); - m_domRelation->defineParameters(parameters); - } - else if(!isGoalVectorUsed && isThresholdVectorDefined) { - - parameters[1] = a->doubleConstraintVec(); - parameters[2] = b->doubleConstraintVec(); - m_domRelation->defineParameters(parameters); - } - else { - // no need to define parameters, or already defined + if(isThresholdVectorDefined) { + m_domRelation->defineConstraintVecA(a->doubleConstraintVec()); + m_domRelation->defineConstraintVecB(b->doubleConstraintVec()); } dom = m_domRelation->isBetterThan(a->doubleObjectiveVec(), @@ -228,7 +213,7 @@ void NonDominanceRanking::evaluateNode() } void NonDominanceRanking::defineRelationType(DominanceRelationType r) -{ +{ DominanceRelation* temp = m_factory->create(r); if(temp != nullptr) { m_domRelationType = r; diff --git a/src/libs/tigon/Operators/Fitness/NonDominanceRanking.h b/src/libs/tigon/Operators/Fitness/NonDominanceRanking.h index da481bd..dc216ad 100644 --- a/src/libs/tigon/Operators/Fitness/NonDominanceRanking.h +++ b/src/libs/tigon/Operators/Fitness/NonDominanceRanking.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -71,6 +71,7 @@ class LIGER_TIGON_EXPORT NonDominanceRanking : public IFitness void initialise(); private: + void defineRelationType(DominanceRelationType r); bool m_isConstrainedHandlingUsed; diff --git a/src/libs/tigon/Operators/Fitness/RobustnessAssignment.cpp b/src/libs/tigon/Operators/Fitness/RobustnessAssignment.cpp index be5e16d..f955bc8 100644 --- a/src/libs/tigon/Operators/Fitness/RobustnessAssignment.cpp +++ b/src/libs/tigon/Operators/Fitness/RobustnessAssignment.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -59,7 +59,7 @@ void RobustnessAssignment::initialise() addProperty("IndicatorParameter" , TString("Default is 95% (for the confidence " "indicator type).") - , typeid(double).hash_code()); + , getTType(double)); clearAdditionalOutputTags(); TStringList tags; @@ -123,7 +123,6 @@ void RobustnessAssignment::evaluateNode() oSet->at(i)->defineCost(r); } } - } TString RobustnessAssignment::TP_indicatorType() const diff --git a/src/libs/tigon/Operators/Fitness/Scalarization.cpp b/src/libs/tigon/Operators/Fitness/Scalarization.cpp index 6fddc17..31160d3 100644 --- a/src/libs/tigon/Operators/Fitness/Scalarization.cpp +++ b/src/libs/tigon/Operators/Fitness/Scalarization.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -24,17 +24,9 @@ #include #include -// STL includes -#include -#include - -// Boost includes -#include - namespace Tigon { namespace Operators { - Scalarization::Scalarization() { initialise(); @@ -53,22 +45,6 @@ Scalarization::~Scalarization() void Scalarization::initialise() { - m_name = TString("Scalarization"); - m_description = TString("Assigns every solution in the set a scalar value" - " by using scalarization functions."); - -// addProperty("ScalarisingFunction" -// , TString("The available scalarising functions are: weighted sum, " -// "weighted Chebyshev, and weighted Lp.\n" -// "Default is weighted sum.") -// , typeid(Tigon::ScalarisationType).hash_code()); -// addProperty("WeightScopeApproach" -// , TString("The weights used for scalarisation " -// "correspond to the 'local' weight of each solution " -// "or to the 'global' direction vector.\n" -// "Default is global.") -// , typeid(Tigon::WeightScope).hash_code()); - TP_defineScalarisingFunction(Tigon::DefaultScalarisationFunction); TP_defineWeightScopeApproach(Tigon::GlobalWeight); @@ -79,10 +55,9 @@ void Scalarization::initialise() void Scalarization::evaluateNode() { - int M=objectiveVecSize(); // determine the global optimal weighting vector TVector weight; - switch(weightScopeApproach()) { + switch(TP_weightScopeApproach()) { case LocalWeight: // do nothing break; @@ -92,38 +67,20 @@ void Scalarization::evaluateNode() break; } + TVector ideal = IElementVecToRealVec(idealVec()); + TVector antiIdeal = IElementVecToRealVec(antiIdealVec()); + while(hasNextOutputSet()) { ISet* oSet = nextOutputSet(); - // Normalise the objective vectors - int setSize = oSet->size(); - TVector > normalObjectives(setSize); - TVector ideal = IElementVecToRealVec(idealVec()); - TVector antiIdeal = IElementVecToRealVec(antiIdealVec()); - for (int i=0; iat(i)->isScalarised()) { - TVector normVec = oSet->at(i)->doubleObjectiveVec(); - normaliseToUnitBoxInMemory(normVec, ideal, antiIdeal); - normalObjectives[i] = normVec; - } - } - - TVector isScalarised(setSize,false); - TVector costArchive(setSize); - TVector> weights(setSize,TVector(M)); - for(int i=0; iat(i)->isScalarised()) { + for(auto sol : oSet->all()) { - isScalarised[i] = true; + if(!sol->isScalarised()) { // determine the local optimal weighting vector - switch(weightScopeApproach()) { + switch(TP_weightScopeApproach()) { case LocalWeight: - weight = oSet->at(i)->weightingVec(); - - weights[i] = weight; - + weight = sol->weightingVec(); break; case GlobalWeight: default: @@ -131,37 +88,42 @@ void Scalarization::evaluateNode() break; } + // normalise the objectives according to the ideal and antiIdeal + TVector normObj = + normaliseToUnitBox(sol->doubleObjectiveVec(), + ideal, antiIdeal); // Scalarise double cost; switch(TP_scalarisingFunction()) { case (Tigon::WeightedSum): - cost = weightedSum(weight, normalObjectives[i]); + cost = weightedSum(weight, normObj); break; case (Tigon::WeightedChebyshev): - cost = weightedChebyshev(weight, normalObjectives[i]); + cost = weightedChebyshev(weight, normObj); break; case (Tigon::WeightedChebyshevAugmented): - cost = weightedChebyshevAugmented(weight, normalObjectives[i]); + cost = weightedChebyshevAugmented(weight, normObj); break; case (Tigon::WeightedLp): - cost = weightedLp(weight, normalObjectives[i], pNorm()); + cost = weightedLp(weight, normObj, pNorm()); break; default: throw TException(this->className(), UnrecognisedScalarisationFunction); } - costArchive[i] = cost; - oSet->at(i)->defineCost(cost); - if(weightScopeApproach() == LocalWeight) { - oSet->at(i)->defineScalarised(); + + sol->defineCost(cost); + + if(TP_weightScopeApproach() == LocalWeight) { + sol->defineScalarised(); } } } - int p1=0; } } -void Scalarization::TP_defineScalarisingFunction(Tigon::ScalarisationType t, double p) +void Scalarization:: +TP_defineScalarisingFunction(Tigon::ScalarisationType t, double p) { m_scalarisingFunc = t; if(p > 0.0) { @@ -191,19 +153,15 @@ double Scalarization::pNorm() const return m_pNorm; } -Tigon::WeightScope Scalarization::weightScopeApproach() -{ - return m_weightScopeApproach; -} - TString Scalarization::name() { - return m_name; + return TString("Scalarization"); } TString Scalarization::description() { - return m_description; + return TString("Assigns every solution in the set a scalar value that is " + "determined by a scalarization function."); } } // namespace Operators diff --git a/src/libs/tigon/Operators/Fitness/Scalarization.h b/src/libs/tigon/Operators/Fitness/Scalarization.h index 1ac4b39..98a4d14 100644 --- a/src/libs/tigon/Operators/Fitness/Scalarization.h +++ b/src/libs/tigon/Operators/Fitness/Scalarization.h @@ -1,3 +1,18 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ #ifndef SCALARIZATION_H #define SCALARIZATION_H #include @@ -7,22 +22,12 @@ namespace Operators { class LIGER_TIGON_EXPORT Scalarization : public IFitness { - //HANDLE_READ_PROPERTIES_BEGIN(IFitness) - //READ(ScalarisingFunction, TP_scalarisingFunction) - //READ(WeightScopeApproach, TP_weightScopeApproach) - //HANDLE_READ_PROPERTIES_END - - //HANDLE_WRITE_PROPERTIES_BEGIN(IFitness) - //WRITE(ScalarisingFunction, Tigon::ScalarisationType, TP_defineScalarisingFunction) - //WRITE(WeightScopeApproach, Tigon::WeightScope, TP_defineWeightScopeApproach) - //HANDLE_WRITE_PROPERTIES_END - DECLARE_CLASS(Tigon::Operators::Scalarization) public: Scalarization(); Scalarization(Tigon::Representation::IPSet* ipset); - virtual ~Scalarization(); + ~Scalarization(); void evaluateNode(); @@ -30,8 +35,6 @@ class LIGER_TIGON_EXPORT Scalarization : public IFitness TString name(); TString description(); - - // Properties void TP_defineScalarisingFunction(Tigon::ScalarisationType t, double p=1.0); Tigon::ScalarisationType TP_scalarisingFunction() const; @@ -40,17 +43,13 @@ class LIGER_TIGON_EXPORT Scalarization : public IFitness Tigon::WeightScope TP_weightScopeApproach() const; double pNorm() const; - Tigon::WeightScope weightScopeApproach(); private: void initialise(); - TString m_name; - TString m_description; - TVector m_weight; Tigon::ScalarisationType m_scalarisingFunc; - double m_pNorm; - Tigon::WeightScope m_weightScopeApproach; + double m_pNorm; + Tigon::WeightScope m_weightScopeApproach; }; } // namespace Operators diff --git a/src/libs/tigon/Operators/Fitness/SharedFitness.cpp b/src/libs/tigon/Operators/Fitness/SharedFitness.cpp index e8cc821..c8fcf89 100644 --- a/src/libs/tigon/Operators/Fitness/SharedFitness.cpp +++ b/src/libs/tigon/Operators/Fitness/SharedFitness.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -47,7 +47,7 @@ void SharedFitness::initialise() , TString("Controls the linearity of the sharing function.\n" "Defult is 1.0, meaning that the sharing function " "linearly reduces from one to zero.") - , getType(double)); + , getTType(double)); clearOutputTags(); clearAdditionalOutputTags(); diff --git a/src/libs/tigon/Operators/Fitness/UncertainConfidenceRobustness.cpp b/src/libs/tigon/Operators/Fitness/UncertainConfidenceRobustness.cpp index 53850c2..fac8ae4 100644 --- a/src/libs/tigon/Operators/Fitness/UncertainConfidenceRobustness.cpp +++ b/src/libs/tigon/Operators/Fitness/UncertainConfidenceRobustness.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -55,7 +55,7 @@ void UncertainConfidenceRobustness::initialise() "values for them are chosen according to the " "percentile.\n Default is 0.05 (optimistic). " "Maximum is 0.999") - , getType(double)); + , getTType(double)); TP_definePercentile(1.0 - Tigon::DefaultConfidence); } diff --git a/src/libs/tigon/Representation/Functions/IFunction.cpp b/src/libs/tigon/Representation/Functions/IFunction.cpp index f0b3ec7..d73699c 100644 --- a/src/libs/tigon/Representation/Functions/IFunction.cpp +++ b/src/libs/tigon/Representation/Functions/IFunction.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -35,8 +35,8 @@ IFunction::IFunction() , m_isNumInputsModifiable(true) , m_isNumoutputsModifiable(true) { - addProperty("NumberOfInputs", "Number of Inputs", typeid(int).hash_code()); - addProperty("NumberOfOutputs", "Number of Outputs", typeid(int).hash_code()); + addProperty("NumberOfInputs", "Number of Inputs", getTType(int)); + addProperty("NumberOfOutputs", "Number of Outputs", getTType(int)); } IFunction::~IFunction() diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/Alpine2.cpp b/src/libs/tigon/Representation/Functions/SingleObjective/Alpine2.cpp index ed7d484..0402849 100644 --- a/src/libs/tigon/Representation/Functions/SingleObjective/Alpine2.cpp +++ b/src/libs/tigon/Representation/Functions/SingleObjective/Alpine2.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -16,10 +16,6 @@ #include #include #include -#include - - - namespace Tigon { namespace Representation { diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/BraninGomez.cpp b/src/libs/tigon/Representation/Functions/SingleObjective/BraninGomez.cpp new file mode 100644 index 0000000..096babd --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/BraninGomez.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include +#include +#include +#include +REGISTER_IFUNCTION_FACTORY(BraninGomez) + +namespace Tigon { +namespace Representation { + +BraninGomez::BraninGomez() +{ + TP_defineNInputs(2); + TP_defineNOutputs(2); + TString name("BraninGomez function"); + TString description("BraninGomez benchmark problem. A constrained problem where.\n" + " a constraint makes the vicinity of the Pareto-optimal" + " front infeasible.\n" + "The problem consists of one objective functions given by Brain function" + " , two design variables, and an inequality constraint.\n" + "The constraint is given by Gomez function with an additional sine function" + " to increase the modality of the constraint.\n" + "This function is usually evaluated on the square [0,1]^2" + " where the constraint has disjoint domains.\n"); + createFunctionProperties(name, description, FunctionType::Internal); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +BraninGomez::BraninGomez(const BraninGomez& func) +{ + TP_defineNInputs(func.TP_nInputs()); + TP_defineNOutputs(func.TP_nOutputs()); + createFunctionProperties(func.name(), func.description(), func.type()); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +BraninGomez::~BraninGomez() +{ + +} + +void BraninGomez::evaluate(const TVector &inputs, + const TVector &outputs) +{ + if((inputs.size() == TP_nInputs()) && (outputs.size() == TP_nOutputs())) { + TVector x = IElementVecToRealVec(inputs); + TVector y = ConstrainedProblems::BraninGomez(x); + + for(size_t i=0; idefineValue(y[i]); + } + } else { + throw TException(className(), IncorrectProblemFormatException); + } +} + +void BraninGomez::defineInputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector lowerBounds(TP_nInputs(), IElement(RealType, 0.0)); + TVector upperBounds(TP_nInputs(), IElement(RealType, 1.0)); + + varNames << "x1" << "x2"; + varDescriptions << "Decision_variable_1" << "Decision_variable_2"; + typeVec << RealType << RealType; + varUnits << "" << ""; + + createInputProperties(varNames, varDescriptions, typeVec, varUnits, + lowerBounds, upperBounds); +} + +void BraninGomez::defineOutputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector optTypes; + + varNames << "f" << "g"; + varDescriptions << "Objective_function" << + "Inequality_constraint"; + typeVec << RealType << RealType; + varUnits << "" << ""; + optTypes << Minimization << Minimization; + + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/BraninGomez.h b/src/libs/tigon/Representation/Functions/SingleObjective/BraninGomez.h new file mode 100644 index 0000000..8e9c20f --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/BraninGomez.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef BRAINGOMEZ_H +#define BRAINGOMEZ_H + +#include +#include + +namespace Tigon { +namespace Representation { + +class LIGER_TIGON_EXPORT BraninGomez : public IFunction +{ + DECLARE_CLASS(Tigon::Representation::BraninGomez) +public: + BraninGomez(); + BraninGomez(const BraninGomez& func); + ~BraninGomez(); + + void evaluate(const TVector &inputs, + const TVector &outputs); + +private: + void defineInputPrpts(); + void defineOutputPrpts(); +}; + +} // namespace Representation +} // namespace Tigon + +#endif // BRAINGOMEZ_H diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/CBranin.cpp b/src/libs/tigon/Representation/Functions/SingleObjective/CBranin.cpp new file mode 100644 index 0000000..4d50f95 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/CBranin.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include +#include +#include +#include +REGISTER_IFUNCTION_FACTORY(CBranin) + +namespace Tigon { +namespace Representation { + +CBranin::CBranin() +{ + TP_defineNInputs(2); + TP_defineNOutputs(2); + TString name("Constrained Branin function"); + TString description("A constraint variant of the Branin benchmark problem.\n" + "The problem consists of one objective function, two " + "design variables, and one inequality constraint.\n" + "The constraint is a smooth function that makes a part " + "of the search space infeasible and the global " + "constrained optimum is located at the constraint " + "boundary.\n" + "The design variables take values in [0, 1]^2.\n"); + createFunctionProperties(name, description, FunctionType::Internal); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +CBranin::CBranin(const CBranin& func) +{ + TP_defineNInputs(func.TP_nInputs()); + TP_defineNOutputs(func.TP_nOutputs()); + createFunctionProperties(func.name(), func.description(), func.type()); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +CBranin::~CBranin() +{ + +} + +void CBranin::evaluate(const TVector &inputs, + const TVector &outputs) +{ + if((inputs.size() == TP_nInputs()) && (outputs.size() == TP_nOutputs())) { + TVector x = IElementVecToRealVec(inputs); + TVector y = ConstrainedProblems::CBranin(x); + + for(size_t i=0; idefineValue(y[i]); + } + } else { + throw TException(className(), IncorrectProblemFormatException); + } +} + +void CBranin::defineInputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector lowerBounds(TP_nInputs(), IElement(RealType, 0.0)); + TVector upperBounds(TP_nInputs(), IElement(RealType, 1.0)); + + varNames << "x1" << "x2"; + varDescriptions << "Decision_variable_1" << "Decision_variable_2"; + typeVec << RealType << RealType; + varUnits << "" << ""; + + createInputProperties(varNames, varDescriptions, typeVec, varUnits, + lowerBounds, upperBounds); +} + +void CBranin::defineOutputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector optTypes({Minimization, Minimization}); + + varNames << "f1" << "c1"; + varDescriptions << "Objective_function" << + "Inequality_constraint"; + typeVec << RealType << RealType; + varUnits << "" << ""; + + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/CBranin.h b/src/libs/tigon/Representation/Functions/SingleObjective/CBranin.h new file mode 100644 index 0000000..2f22c74 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/CBranin.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef CBRANIN_H +#define CBRANIN_H + +#include +#include + +namespace Tigon { +namespace Representation { + +class LIGER_TIGON_EXPORT CBranin : public IFunction +{ + DECLARE_CLASS(Tigon::Representation::CBranin) + +public: + CBranin(); + CBranin(const CBranin& func); + ~CBranin(); + + void evaluate(const TVector &inputs, + const TVector &outputs); + +private: + void defineInputPrpts(); + void defineOutputPrpts(); +}; + +} // namespace Representation +} // namespace Tigon + +#endif // CBRANIN_H diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/CBraninM1.cpp b/src/libs/tigon/Representation/Functions/SingleObjective/CBraninM1.cpp new file mode 100644 index 0000000..b3754c7 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/CBraninM1.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include +#include +#include +#include +REGISTER_IFUNCTION_FACTORY(CBraninM1) + +namespace Tigon { +namespace Representation { + +CBraninM1::CBraninM1() +{ + TP_defineNInputs(2); + TP_defineNOutputs(2); + TString name("Constrained Branin function M1"); + TString description("A constraint variant of the Branin benchmark problem.\n" + "This implementation modifies the traditional Branin " + "function such that there are two local optima and one " + "global optimum, rather than three global optima of equal " + "value. This modification is suggested by the book " + "\"Engineering Design via Surrogate Modelling, by Andy " + "Keane and others\", where the authors claim that it " + "makes the function more representative of engeneering " + "functions.\n" + "The problem consists of one objective function, two " + "design variables, and one inequality constraint.\n" + "The constraint is a smooth function that makes a part " + "of the search space infeasible and the global " + "constrained optimum is located at the constraint " + "boundary.\n" + "The design variables take values in [0, 1]^2.\n"); + createFunctionProperties(name, description, FunctionType::Internal); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +CBraninM1::CBraninM1(const CBraninM1& func) +{ + TP_defineNInputs(func.TP_nInputs()); + TP_defineNOutputs(func.TP_nOutputs()); + createFunctionProperties(func.name(), func.description(), func.type()); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +CBraninM1::~CBraninM1() +{ + +} + +void CBraninM1::evaluate(const TVector &inputs, + const TVector &outputs) +{ + if((inputs.size() == TP_nInputs()) && (outputs.size() == TP_nOutputs())) { + TVector x = IElementVecToRealVec(inputs); + TVector y = ConstrainedProblems::CBraninM1(x); + + for(size_t i=0; idefineValue(y[i]); + } + } else { + throw TException(className(), IncorrectProblemFormatException); + } +} + +void CBraninM1::defineInputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector lowerBounds(TP_nInputs(), IElement(RealType, 0.0)); + TVector upperBounds(TP_nInputs(), IElement(RealType, 1.0)); + + varNames << "x1" << "x2"; + varDescriptions << "Decision_variable_1" << "Decision_variable_2"; + typeVec << RealType << RealType; + varUnits << "" << ""; + + createInputProperties(varNames, varDescriptions, typeVec, varUnits, + lowerBounds, upperBounds); +} + +void CBraninM1::defineOutputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector optTypes({Minimization, Minimization}); + + varNames << "f1" << "c1"; + varDescriptions << "Objective_function" << + "Inequality_constraint"; + typeVec << RealType << RealType; + varUnits << "" << ""; + + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/CBraninM1.h b/src/libs/tigon/Representation/Functions/SingleObjective/CBraninM1.h new file mode 100644 index 0000000..88fd219 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/CBraninM1.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef CBRANINM1_H +#define CBRANINM1_H + +#include +#include + +namespace Tigon { +namespace Representation { + +class LIGER_TIGON_EXPORT CBraninM1 : public IFunction +{ + DECLARE_CLASS(Tigon::Representation::CBraninM1) + +public: + CBraninM1(); + CBraninM1(const CBraninM1& func); + ~CBraninM1(); + + void evaluate(const TVector &inputs, + const TVector &outputs); + +private: + void defineInputPrpts(); + void defineOutputPrpts(); +}; + +} // namespace Representation +} // namespace Tigon + +#endif // CBRANINM1_H diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/Camel.cpp b/src/libs/tigon/Representation/Functions/SingleObjective/Camel.cpp new file mode 100644 index 0000000..e6c1e7b --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/Camel.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include +#include +#include +#include +REGISTER_IFUNCTION_FACTORY(Camel) + +namespace Tigon { +namespace Representation { + +Camel::Camel() +{ + TP_defineNInputs(2); + TP_defineNOutputs(2); + TString name("Camel function"); + TString description("Camel benchmark problem. A constrained problem where.\n" + " a constraint makes the vicinity of the Pareto-optimal" + " front infeasible.\n" + "The problem consists of one objective functions, two design" + " variables, and a inequality constraint.\n" + "The constraint is multimodal and the global optimum " + " is located close to the local minimum.\n" + "This function is usually evaluated on the square [-2, 2]^2.\n"); + createFunctionProperties(name, description, FunctionType::Internal); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +Camel::Camel(const Camel& func) +{ + TP_defineNInputs(func.TP_nInputs()); + TP_defineNOutputs(func.TP_nOutputs()); + createFunctionProperties(func.name(), func.description(), func.type()); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +Camel::~Camel() +{ + +} + +void Camel::evaluate(const TVector &inputs, + const TVector &outputs) +{ + if((inputs.size() == TP_nInputs()) && (outputs.size() == TP_nOutputs())) { + TVector x = IElementVecToRealVec(inputs); + TVector y = ConstrainedProblems::Camel(x); + + for(size_t i=0; idefineValue(y[i]); + } + } else { + throw TException(className(), IncorrectProblemFormatException); + } +} + +void Camel::defineInputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector lowerBounds(TP_nInputs(), IElement(RealType, -2.0)); + TVector upperBounds(TP_nInputs(), IElement(RealType, 2.0)); + + varNames << "x1" << "x2"; + varDescriptions << "Decision_variable_1" << "Decision_variable_2"; + typeVec << RealType << RealType; + varUnits << "" << ""; + + createInputProperties(varNames, varDescriptions, typeVec, varUnits, + lowerBounds, upperBounds); +} + +void Camel::defineOutputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector optTypes; + + varNames << "f" << "g"; + varDescriptions << "Objective_function" << + "Inequality_constraint"; + typeVec << RealType << RealType; + varUnits << "" << ""; + optTypes << Minimization << Minimization; + + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/Camel.h b/src/libs/tigon/Representation/Functions/SingleObjective/Camel.h new file mode 100644 index 0000000..93440f7 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/Camel.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef CAMEL_H +#define CAMEL_H + +#include +#include + +namespace Tigon { +namespace Representation { + +class LIGER_TIGON_EXPORT Camel : public IFunction +{ + DECLARE_CLASS(Tigon::Representation::Camel) +public: + Camel(); + Camel(const Camel& func); + ~Camel(); + + void evaluate(const TVector &inputs, + const TVector &outputs); + +private: + void defineInputPrpts(); + void defineOutputPrpts(); +}; + +} // namespace Representation +} // namespace Tigon + +#endif // CAMEL_H diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/ConstrainedProblems.cpp b/src/libs/tigon/Representation/Functions/SingleObjective/ConstrainedProblems.cpp new file mode 100644 index 0000000..fff8687 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/ConstrainedProblems.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include +#include + +using namespace boost::math::constants; +using namespace Tigon; + +namespace ConstrainedProblems { + +TVector CBranin(const TVector &x) +{ + TVector b1 {-5.0, 10.0}; + TVector b2 {0.0, 15.0}; + + // rescale x1 from [0,1] to [-5, 10] + // rescale x2 from [0,1] to [0, 15] + double x1 = x[0] * (b1[1]-b1[0]) + b1[0]; + double x2 = x[1] * (b2[1]-b2[0]) + b2[0]; + double PI = pi(); + double a = 1.0; + double b = 5.1/(4.0*PI*PI); + double c = 5.0/PI; + double r = 6.0; + double s = 10.0; + double t = 1.0/(8.0*PI); + + double exp1 = x2 - b*x1*x1 + c*x1 - r; + double exp2 = (1.0 - t)*std::cos(x1); + + TVector y(2, 0.0); + + // objective + y[0] = a*exp1*exp1 + s*exp2 + s; + + // contraint (use original scale) + y[1] = 0.2 - x[0]*x[1]; + + return y; +} + +TVector CBraninM1(const TVector &x) +{ + TVector b1 {-5.0, 10.0}; + TVector b2 {0.0, 15.0}; + + // rescale x1 from [0,1] to [-5, 10] + // rescale x2 from [0,1] to [0, 15] + double x1 = x[0] * (b1[1]-b1[0]) + b1[0]; + double x2 = x[1] * (b2[1]-b2[0]) + b2[0]; + double PI = pi(); + double b = 5.1/(4.0*PI*PI); + double c = 5.0/PI; + double r = 6.0; + double s = 10.0; + double t = 1.0/(8.0*PI); + + double exp1 = x2 - b*x1*x1 + c*x1 - r; + double exp2 = (1.0 - t)*std::cos(x1) + 1.0; // adds 1 + + TVector y(2, 0.0); + + // objective + y[0] = exp1*exp1 + s*exp2 + 5.0*x1; // replaces s by 5x1 + + // constraint (use original scale) + y[1] = 0.2 - x[0]*x[1]; + + return y; +} + +TVector Camel(const TVector &x) +{ + double exp1 = ((4 - 2.1*std::pow(x[0],2) + (std::pow(x[0],4))/3)*std::pow(x[0],2)); + double exp2 = std::pow((1.5*x[1] - (std::cos(31*x[1]))/6),2); + + TVector y(2, 0.0); + + // objectives + y[0] = exp1 + x[0]*x[1] - 4 + 4*std::pow(x[1],2) ; + + // contraints + y[1] = 1.5 - exp2 - x[0]; + + return y; +} + +TVector Sasena(const TVector &x) +{ + TVector y(4, 0.0); + + // objectives + y[0] = - std::pow((x[0] - 1.0), 2.0) - std::pow((x[1] - 0.5), 2.0); + + // contraints + y[1] = std::pow((x[0] - 3.0), 2.0) + + (std::pow((x[1] + 2.0), 2.0))*std::exp(-(std::pow(x[1], 7.0))) - 12.0; + y[2] = 10.0*x[0] + x[1] - 7.0; + y[3] = std::pow((x[0] - 0.5), 2.0) + std::pow((x[1] - 0.5), 2.0) - 0.2; + return y; +} + +TVector BraninGomez(const TVector &x) +{ + double exp1 = x[1] - ((5.1*std::pow(x[0],2))/(4*std::pow(pi(),2))) + (5*x[0]/pi()) - 6; + double exp2 = 10*(1 - 1/(8*pi()))*std::cos(x[0]); + double exp3 = ((4 - 2.1*std::pow(x[0],2) + (std::pow(x[0],4))/3)*std::pow(x[0],2)); + + TVector y(2, 0.0); + + // objectives + y[0] = std::pow(exp1,2) + exp2 + 1/(8*pi()); + + // contraints + y[1] = 6 - exp3 - x[0]*x[1] + (4 - 4*std::pow(x[1],2))*std::pow(x[1],2) - 3*std::sin(6*(1 - x[0])) - 3*std::sin(6*(1 - x[1])); + + return y; +} + +} // namespace ConstrainedProblems diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/ConstrainedProblems.h b/src/libs/tigon/Representation/Functions/SingleObjective/ConstrainedProblems.h new file mode 100644 index 0000000..d6e5ac6 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/ConstrainedProblems.h @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef CONSTRAINEDPROBLEMS_H +#define CONSTRAINEDPROBLEMS_H + +#include + +namespace ConstrainedProblems +{ +Tigon::TVector CBranin(const Tigon::TVector &x); +Tigon::TVector CBraninM1(const Tigon::TVector &x); +Tigon::TVector Camel(const Tigon::TVector &x); +Tigon::TVector Sasena(const Tigon::TVector &x); +Tigon::TVector BraninGomez(const Tigon::TVector &x); + +} // namespace ConstrainedProblems + +#endif // CONSTRAINEDPROBLEMS_H diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/Poly1.cpp b/src/libs/tigon/Representation/Functions/SingleObjective/Poly1.cpp new file mode 100644 index 0000000..4b65113 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/Poly1.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include + +namespace Tigon { +namespace Representation { + +Poly1::Poly1() +{ + TP_defineNInputs(1); + TP_defineNOutputs(1); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +Poly1::Poly1(const Poly1& func) + : Poly1() +{ + +} + + +Poly1::~Poly1() +{ + +} + +void Poly1::evaluate(const TVector &inputs, + const TVector &outputs) +{ + if((inputs.size() == TP_nInputs()) && (outputs.size() == TP_nOutputs())) { + TVector iReal = IElementVecToRealVec(inputs); + + double x = iReal[0]; + double f = std::pow(6.0*x - 2.0, 2.0) * std::sin(12.0*x - 4.0); + + outputs[0]->defineValue(f); + } +} + +void Poly1::defineInputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector lowerBounds(TP_nInputs(), IElement(RealType, 0.0)); + TVector upperBounds(TP_nInputs(), IElement(RealType, 1.0)); + + for(int i = 0; i < TP_nInputs(); i++) { + varNames.push_back("Input_Var_" + std::to_string(i)); + typeVec.push_back(RealType); + varUnits.push_back(""); + varDescriptions.push_back("Input_VarDesc" + std::to_string(i)); + } + + createInputProperties(varNames, varDescriptions, typeVec, varUnits, + lowerBounds, upperBounds); +} + +void Poly1::defineOutputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector optTypes; + + varNames.push_back("Output_Var"); + varDescriptions.push_back("Output_VarDesc"); + typeVec.push_back(RealType); + varUnits.push_back(""); + optTypes.push_back(Minimization); + + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +TString Poly1::name() +{ + return("Poly1"); +} + +TString Poly1::description() +{ + return("Poly1 benchmark problem. Single-objective."); +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/Poly1.h b/src/libs/tigon/Representation/Functions/SingleObjective/Poly1.h new file mode 100644 index 0000000..4cf8f2e --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/Poly1.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef POLY1_H +#define POLY1_H + +#include +#include + +namespace Tigon { +namespace Representation { + +class LIGER_TIGON_EXPORT Poly1 : public IFunction +{ + DECLARE_CLASS(Tigon::Representation::Poly1) + +public: + Poly1(); + Poly1(const Poly1& func); + ~Poly1(); + + // Information about the function(s) + TString name(); + TString description(); + + void evaluate(const TVector &inputs, + const TVector &outputs); + +private: + void defineInputPrpts(); + void defineOutputPrpts(); +}; + +} // namespace Representation +} // namespace Tigon + +#endif // POLY1_H diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/Sasena.cpp b/src/libs/tigon/Representation/Functions/SingleObjective/Sasena.cpp new file mode 100644 index 0000000..aae5869 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/Sasena.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include +#include +#include +#include +REGISTER_IFUNCTION_FACTORY(Sasena) + +namespace Tigon { +namespace Representation { + +Sasena::Sasena() +{ + TP_defineNInputs(2); + TP_defineNOutputs(4); + TString name("Sasena function"); + TString description("Sasena benchmark problem. A constrained problem where.\n" + " a constraint makes the vicinity of the Pareto-optimal" + " front infeasible.\n" + "The problem consists of one objective functions, two design" + " variables, and three inequality constraints.\n" + "Two constraints are active and one inactive.\n" + "This function is usually evaluated on the square [0, 1]^2.\n"); + createFunctionProperties(name, description, FunctionType::Internal); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +Sasena::Sasena(const Sasena& func) +{ + TP_defineNInputs(func.TP_nInputs()); + TP_defineNOutputs(func.TP_nOutputs()); + createFunctionProperties(func.name(), func.description(), func.type()); + defineParallelisable(); + defineIsNumInputsModifiable(false); + defineIsNumoutputsModifiable(false); +} + +Sasena::~Sasena() +{ + +} + +void Sasena::evaluate(const TVector &inputs, + const TVector &outputs) +{ + if((inputs.size() == TP_nInputs()) && (outputs.size() == TP_nOutputs())) { + TVector x = IElementVecToRealVec(inputs); + TVector y = ConstrainedProblems::Sasena(x); + + for(size_t i=0; idefineValue(y[i]); + } + } else { + throw TException(className(), IncorrectProblemFormatException); + } +} + +void Sasena::defineInputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector lowerBounds(TP_nInputs(), IElement(RealType, 0.0)); + TVector upperBounds(TP_nInputs(), IElement(RealType, 1.0)); + + varNames << "x1" << "x2"; + varDescriptions << "Decision_variable_1" << "Decision_variable_2"; + typeVec << RealType << RealType; + varUnits << "" << ""; + + createInputProperties(varNames, varDescriptions, typeVec, varUnits, + lowerBounds, upperBounds); +} + +void Sasena::defineOutputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector optTypes; + + varNames << "f" << "g1" << "g2" << "g3"; + varDescriptions << "Objective_function" << + "Inequality_constraint_1" << + "Inequality_constraint_2" << + "Inequality_constraint_3"; + typeVec << RealType << RealType << RealType << RealType; + varUnits << "" << "" << "" << ""; + optTypes << Minimization << Minimization << Minimization << Minimization; + + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SingleObjective/Sasena.h b/src/libs/tigon/Representation/Functions/SingleObjective/Sasena.h new file mode 100644 index 0000000..ffb79f2 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SingleObjective/Sasena.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef SASENA_H +#define SASENA_H + +#include +#include + +namespace Tigon { +namespace Representation { + +class LIGER_TIGON_EXPORT Sasena : public IFunction +{ + DECLARE_CLASS(Tigon::Representation::Sasena) +public: + Sasena(); + Sasena(const Sasena& func); + ~Sasena(); + + void evaluate(const TVector &inputs, + const TVector &outputs); + +private: + void defineInputPrpts(); + void defineOutputPrpts(); +}; + +} // namespace Representation +} // namespace Tigon + +#endif // SASENA_H diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/ConstrainedExpectedImprovement.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/ConstrainedExpectedImprovement.cpp new file mode 100644 index 0000000..cbfbc90 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/ConstrainedExpectedImprovement.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include + +#include +#include +#include + +#include +#include + +namespace Tigon { +namespace Representation { + + +ConstrainedExpectedImprovement::ConstrainedExpectedImprovement() +{ + TP_defineNInputs(1); + TP_defineNOutputs(3); + defineParallelisable(false); +} + +ConstrainedExpectedImprovement:: +ConstrainedExpectedImprovement(ExpectedImprovement* ei, + const TVector& vpf) + : ConstrainedExpectedImprovement() +{ + defineExpectedImprovement(ei); + defineProbabilityFeasibility(vpf); +} + + +ConstrainedExpectedImprovement::~ConstrainedExpectedImprovement() +{ + +} + +TString ConstrainedExpectedImprovement::name() +{ + return("Constrained Expected Improvement"); +} + +TString ConstrainedExpectedImprovement::description() +{ + return("Implements a fully probabilistic approach where constraints are " + "added to the expected improvement. As a result, if the predicted errors " + "in the constrained model are low and surrogate shows a constrained " + "violation then the expected improvement will also be low, but not " + "zero, since there is a finite possibility that a full evaluation of " + "the constraints may actually reveal a feasible design. Conversely, " + "if the error in the constraints are large then there will be a " + "significant chance that the constraint predictions are wrong and " + "that a new point will, in fact, be feasible. Thus, the expectation " + "of improvement will be greater."); +} + +void ConstrainedExpectedImprovement:: +evaluate(const TVector &inputs, + const TVector &outputs) +{ + // Make a copy of the vector of outputs + TVector outputs_temp; + for(auto output : outputs) { + outputs_temp.push_back(output->clone()); + } + + // Evaluate expected improvement function + m_ei->evaluate(inputs, outputs_temp); +// double ei = std::log10(outputs_temp[0]->value()+std::numeric_limits::epsilon()); + double ei = outputs_temp[0]->value(); + outputs[1]->defineValue(ei); // output for expected improvement + + // Evaluate probability of feasibility function for each constraint + double mpf = 1.0; +// double mpf = 0.0; + for(size_t i = 0; ievaluate(inputs, outputs_temp); +// double pf = std::log10(outputs_temp[0]->value()+std::numeric_limits::epsilon()); + double pf = outputs_temp[0]->value(); + outputs[i+2]->defineValue(pf); // outputs for probability of feasibility + + mpf *= pf; +// mpf += pf; + } + + outputs[0]->defineValue(ei*mpf); // output for EIxPF +// outputs[0]->defineValue(std::log10(ei*mpf + std::numeric_limits::epsilon())); +// outputs[0]->defineValue(ei+mpf); // output for EIxPF +} + +void ConstrainedExpectedImprovement:: +defineExpectedImprovement(ExpectedImprovement* ei) +{ + m_ei = ei; + TP_defineNInputs(ei->model()->inputData()[0].size()); +} + +void ConstrainedExpectedImprovement:: +defineProbabilityFeasibility(const TVector& vpf) +{ + m_vpf = vpf; + TP_defineNOutputs(2+vpf.size()); +} + +void ConstrainedExpectedImprovement::defineInputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector lowerBounds(0); // -inf + TVector upperBounds(0); // inf + + for(int i = 0; i < TP_nInputs(); i++) { + varNames.push_back("Input_Var_" + std::to_string(i)); + varDescriptions.push_back("Input_VarDesc_" + std::to_string(i)); + typeVec.push_back(RealType); + varUnits.push_back(""); + } + createInputProperties(varNames, varDescriptions, typeVec, varUnits, + lowerBounds, upperBounds); +} + +void ConstrainedExpectedImprovement::defineOutputPrpts() +{ + if(TP_nOutputs() < 3) { + return; + } + + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + TVector optTypes; + + varNames << "EIxPF"; + varDescriptions << "EIxPF"; + typeVec << RealType; + varUnits << ""; + optTypes << Maximization; + + // The following outputs are kept for information only + + varNames << "Expected_Improvement"; + varDescriptions << "The expected improvement over the best 'known' point " + "to the Kriging model. Expected improvement is calculated " + "by considering the value for the input as a random " + "number, following a normal distribution with the mean " + "and standard deviation estimated by the Kriging model."; + typeVec << RealType; + varUnits << ""; + optTypes << NonOptimization; + + int nConstraints = TP_nOutputs() - 2; + for(int i=0; i +#include +#include +#include + +namespace Tigon { +namespace Representation { + +class LIGER_TIGON_EXPORT ConstrainedExpectedImprovement : public IFunction +{ +public: + ConstrainedExpectedImprovement(); + ConstrainedExpectedImprovement(ExpectedImprovement* ei, + const TVector& vpf); + ~ConstrainedExpectedImprovement(); + + // Information about the function(s) + TString name(); + TString description(); + + void evaluate(const TVector &inputs, + const TVector &outputs); + + void defineExpectedImprovement(ExpectedImprovement* ei); + void defineProbabilityFeasibility(const TVector& vpf); + + +protected: + void defineInputPrpts(); + void defineOutputPrpts(); + +private: + ExpectedImprovement* m_ei; + TVector m_vpf; +}; + +} // namespace Representation +} // namespace Tigon + +#endif // CONSTRAINEDEXPECTEDIMPROVEMENT_H diff --git a/src/libs/tigon/Representation/Functions/ExpectedImprovement.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/ExpectedImprovement.cpp similarity index 72% rename from src/libs/tigon/Representation/Functions/ExpectedImprovement.cpp rename to src/libs/tigon/Representation/Functions/SurrogateModelling/ExpectedImprovement.cpp index 9fe954e..fadf8ba 100644 --- a/src/libs/tigon/Representation/Functions/ExpectedImprovement.cpp +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/ExpectedImprovement.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,20 +13,19 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include +#include #include #include #include -#include -#include +#include +#include #include -#include - namespace Tigon { namespace Representation { ExpectedImprovement::ExpectedImprovement() + : m_best(0.0), m_worst(0.0) { TP_defineNInputs(1); TP_defineNOutputs(1); @@ -35,16 +34,11 @@ ExpectedImprovement::ExpectedImprovement() } ExpectedImprovement::ExpectedImprovement(KrigingSPtr model) + : ExpectedImprovement() { - TP_defineNInputs(1); - TP_defineNOutputs(1); - defineModel(model); - - m_standardNormal = new NormalDistribution(0.0, 1.0); } - ExpectedImprovement::~ExpectedImprovement() { if(m_standardNormal != nullptr) { @@ -59,33 +53,39 @@ TString ExpectedImprovement::name() TString ExpectedImprovement::description() { - return("A function that estimates the solutin's expected improvement over " + return("A function that estimates the solution's expected improvement over " "the current best known solution, based on Kriging estimation.\n" "Expected improvement is calculated by considering the value for the " "input as a random number, following a normal distribution with the " "mean and standard deviation estimated by the Kriging model."); } -void ExpectedImprovement::evaluate(const TVector &inputs, - const TVector &outputs) +void ExpectedImprovement::evaluate( + const TVector &inputs, + const TVector &outputs) { if(model()) { double val = value(inputs); double err = error(inputs); - double diff = m_best - val; + double diff = best() - val; double expImprove = 0.0; if(err > 0) { expImprove = diff * m_standardNormal->cdf(diff/err) + err * m_standardNormal->pdf(diff/err); + + // normalization + //double maxPDF = 1.0/sqrt(2.0*boost::math::constants::pi()); + //expImprove = expImprove/(diff + std::fabs(worst()-best())*maxPDF); } - outputs[0]->defineValue(-expImprove); + outputs[0]->defineValue(expImprove); +// outputs[0]->defineValue(std::log10(expImprove + std::numeric_limits::epsilon())); } } void ExpectedImprovement::updateBest() { - TVector yy(model()->variogram()->outputData()); + TVector yy(model()->outputData()); m_best = vectorMin(yy); m_worst = vectorMax(yy); } @@ -100,7 +100,7 @@ void ExpectedImprovement::defineOutputPrpts() TVector typeVec; TStringList varUnits; - varNames << "Expected_Improvement"; + varNames << "Expected improvement"; varDescriptions << "The expected improvement over the best 'known' point " "to the Kriging model. Expected improvement is calculated " "by considering the value for the input as a random " @@ -108,7 +108,7 @@ void ExpectedImprovement::defineOutputPrpts() "and standard deviation estimated by the Kriging model."; typeVec << RealType; varUnits << ""; - TVector optTypes({Minimization}); + TVector optTypes({Maximization}); createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); } @@ -129,19 +129,29 @@ double ExpectedImprovement::worst() const } -double ExpectedImprovement::value(TVector inputs) +double ExpectedImprovement::value(const TVector& inputs) { TVector iReal = IElementVecToRealVec(inputs); return model()->interpolate(iReal); } -double ExpectedImprovement::error(TVector inputs) +double ExpectedImprovement::error(const TVector& inputs) { // The model error, is defined by the last vector that was evaluated. T_UNUSED(inputs); return model()->errorEstimate(); } +void ExpectedImprovement::defineBest(double best) +{ + m_best = best; +} + +void ExpectedImprovement::defineWorst(double worst) +{ + m_worst = worst; +} + } // namespace Representation } // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/ExpectedImprovement.h b/src/libs/tigon/Representation/Functions/SurrogateModelling/ExpectedImprovement.h similarity index 80% rename from src/libs/tigon/Representation/Functions/ExpectedImprovement.h rename to src/libs/tigon/Representation/Functions/SurrogateModelling/ExpectedImprovement.h index b7544b9..e1382a9 100644 --- a/src/libs/tigon/Representation/Functions/ExpectedImprovement.h +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/ExpectedImprovement.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -16,7 +16,7 @@ #ifndef EXPECTEDIMPROVEMENT_H #define EXPECTEDIMPROVEMENT_H -#include +#include #include namespace Tigon { @@ -29,7 +29,7 @@ class LIGER_TIGON_EXPORT ExpectedImprovement : public KrigingSurrogate public: ExpectedImprovement(); ExpectedImprovement(KrigingSPtr model); - virtual ~ExpectedImprovement(); + ~ExpectedImprovement(); // Information about the function(s) TString name(); @@ -43,17 +43,21 @@ class LIGER_TIGON_EXPORT ExpectedImprovement : public KrigingSurrogate double best() const; double worst() const; - virtual double value(TVector inputs); - virtual double error(TVector inputs); + virtual double value(const TVector& inputs); + virtual double error(const TVector& inputs); + +protected: + void defineBest(double best); + void defineWorst(double worst); -private: - void defineOutputPrpts(); void updateBest(); - double m_best; - double m_worst; -protected: NormalDistribution* m_standardNormal; + +private: + double m_best; + double m_worst; + void defineOutputPrpts(); }; } // namespace Representation diff --git a/src/libs/tigon/Representation/Functions/FannNetwork.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/FannNetwork.cpp similarity index 99% rename from src/libs/tigon/Representation/Functions/FannNetwork.cpp rename to src/libs/tigon/Representation/Functions/SurrogateModelling/FannNetwork.cpp index ce2cf5e..b27cbf4 100644 --- a/src/libs/tigon/Representation/Functions/FannNetwork.cpp +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/FannNetwork.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -14,7 +14,7 @@ ** ****************************************************************************/ #include -#include +#include namespace Tigon { namespace Representation { diff --git a/src/libs/tigon/Representation/Functions/FannNetwork.h b/src/libs/tigon/Representation/Functions/SurrogateModelling/FannNetwork.h similarity index 98% rename from src/libs/tigon/Representation/Functions/FannNetwork.h rename to src/libs/tigon/Representation/Functions/SurrogateModelling/FannNetwork.h index df44203..8557a2c 100644 --- a/src/libs/tigon/Representation/Functions/FannNetwork.h +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/FannNetwork.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -18,10 +18,8 @@ #include #define FANN_NO_DLL -DISABLE_WARNINGS #include #include -ENABLE_WARNINGS namespace Tigon { namespace Representation { diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleExpectedImprovement.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleExpectedImprovement.cpp new file mode 100644 index 0000000..d6cde48 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleExpectedImprovement.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include + +namespace Tigon { +namespace Representation { + +FeasibleExpectedImprovement::FeasibleExpectedImprovement() + : ExpectedImprovement() +{ + TP_defineNOutputs(1); +} + +FeasibleExpectedImprovement::FeasibleExpectedImprovement(KrigingSPtr model) + : ExpectedImprovement(model) +{ + TP_defineNOutputs(1); +} + +FeasibleExpectedImprovement::FeasibleExpectedImprovement( + KrigingSPtr model, + const TVector& violation) + : ExpectedImprovement() +{ + TP_defineNOutputs(1); + defineModelAndViolation(model, violation); +} + +FeasibleExpectedImprovement::~FeasibleExpectedImprovement() +{ + +} + +TString FeasibleExpectedImprovement::name() +{ + return("Expected Improvement with feasible (or close to feasible) best known " + "solution"); +} + +TString FeasibleExpectedImprovement::description() +{ + return("This function extends the Expected Improvement function by making " + "use of feasibility information about the solutions, to estimate the " + "solution's expected improvement.\n" + "For this, a violation score is associated with each solution, then " + "the solution is said to be feasible if the violation score is " + "smaller than or equal to zero, otherwise the solution is infeasible.\n" + "To determine the best 'known' solution only feasible solutions are " + "considered. In case all solutions are infeasible then the least " + "infeasible solution is chosen. Notably, the higher the violation " + "score, the greater the infeasibility of the solution is.\n" + "The violation score is given by the vector m_violation."); +} + +void FeasibleExpectedImprovement::defineModelAndViolation( + KrigingSPtr model, const TVector &violation) +{ + KrigingSurrogate::defineModel(model); + defineViolation(violation); + updateBest(); +} + +void FeasibleExpectedImprovement::defineViolation(const TVector& violation) +{ + // check that the size of the violation vector is equal to + // the number of solutions in the Kriging model + if(violation.size() == model()->outputData().size()) { + m_violation = violation; + } +} + +void FeasibleExpectedImprovement::updateBest() +{ + if(m_violation.empty()) { + ExpectedImprovement::updateBest(); + return; + } + + TVector yy(model()->outputData()); + defineWorst(vectorMax(yy)); + + TVector yy_feasible; + + for(size_t i=0; i typeVec; + TStringList varUnits; + + varNames << "Feasible expected improvement"; + varDescriptions << "The expected improvement over the best 'known' point " + "to the Kriging model. Expected improvement is calculated " + "by considering the value for the input as a random " + "number, following a normal distribution with the mean " + "and standard deviation estimated by the Kriging model."; + typeVec << RealType; + varUnits << ""; + TVector optTypes({Maximization}); + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleExpectedImprovement.h b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleExpectedImprovement.h new file mode 100644 index 0000000..61e70cc --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleExpectedImprovement.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef FEASIBLEEXPECTEDIMPROVEMENT_H +#define FEASIBLEEXPECTEDIMPROVEMENT_H +#include + +namespace Tigon { +namespace Representation { + +class LIGER_TIGON_EXPORT FeasibleExpectedImprovement : public ExpectedImprovement +{ +public: + FeasibleExpectedImprovement(); + FeasibleExpectedImprovement(KrigingSPtr model); + FeasibleExpectedImprovement(KrigingSPtr model, + const TVector& violation); + ~FeasibleExpectedImprovement(); + + // Information about the function(s) + TString name(); + TString description(); + + +private: + void defineModelAndViolation(KrigingSPtr model, + const TVector& violation); + void defineViolation(const TVector& violation); + void updateBest(); + void defineOutputPrpts(); + + TVector m_violation; +}; + +} // namespace Representation +} // namespace Tigon + +#endif // FEASIBLEEXPECTEDIMPROVEMENT_H diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleRandExpectedImprovement.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleRandExpectedImprovement.cpp new file mode 100644 index 0000000..c649f14 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleRandExpectedImprovement.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include +#include + +namespace Tigon { +namespace Representation { + +FeasibleRandExpectedImprovement::FeasibleRandExpectedImprovement() + : RandExpectedImprovement() +{ + TP_defineNOutputs(1); +} + +FeasibleRandExpectedImprovement:: +FeasibleRandExpectedImprovement(KrigingSPtr model) + : RandExpectedImprovement(model) +{ + TP_defineNOutputs(1); +} + +FeasibleRandExpectedImprovement:: +FeasibleRandExpectedImprovement(KrigingSPtr model, + const TVector> &samples) + : RandExpectedImprovement(model, samples) +{ + TP_defineNOutputs(1); +} + +FeasibleRandExpectedImprovement::FeasibleRandExpectedImprovement( + KrigingSPtr model, + const TVector> &samples, + const TVector& violation) + : RandExpectedImprovement() +{ + TP_defineNOutputs(1); + defineSamples(samples); + defineModelAndViolation(model, violation); +} + +FeasibleRandExpectedImprovement::~FeasibleRandExpectedImprovement() +{ + +} + +void FeasibleRandExpectedImprovement::defineModelAndViolation( + KrigingSPtr model, const TVector &violation) +{ + KrigingSurrogate::defineModel(model); + defineViolation(violation); + updateBest(); +} + +void FeasibleRandExpectedImprovement::defineViolation(const TVector& violation) +{ + // check that the size of the violation vector is equal to + // the number of solutions in the Kriging model + if(violation.size() == model()->outputData().size()) { + m_violation = violation; + } +} + +void FeasibleRandExpectedImprovement::updateBest() +{ + if(m_violation.empty()) { + ExpectedImprovement::updateBest(); + return; + } + + TVector yy(model()->outputData()); + defineWorst(vectorMax(yy)); + + TVector yy_feasible; + + for(size_t i=0; i typeVec; + TStringList varUnits; + + varNames << "Feasible rand expected improvement"; + varDescriptions << "The expected improvement over the best 'known' point " + "to the Kriging model. Expected improvement is calculated " + "by considering the value for the input as a random " + "number, following a normal distribution with the mean " + "and standard deviation estimated by the Kriging model."; + typeVec << RealType; + varUnits << ""; + TVector optTypes({Maximization}); + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleRandExpectedImprovement.h b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleRandExpectedImprovement.h new file mode 100644 index 0000000..64b6581 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeasibleRandExpectedImprovement.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef FEASIBLERANDEXPECTEDIMPROVEMENT_H +#define FEASIBLERANDEXPECTEDIMPROVEMENT_H + +#include +#include + +namespace Tigon { +namespace Representation { + +class LIGER_TIGON_EXPORT FeasibleRandExpectedImprovement : + public RandExpectedImprovement +{ + +public: + FeasibleRandExpectedImprovement(); + FeasibleRandExpectedImprovement(KrigingSPtr model); + FeasibleRandExpectedImprovement(KrigingSPtr model, + const TVector> &samples); + FeasibleRandExpectedImprovement(KrigingSPtr model, + const TVector> &samples, + const TVector& violation); + + ~FeasibleRandExpectedImprovement(); + + // Information about the function(s) + TString name(); + TString description(); + +private: + void defineModelAndViolation(KrigingSPtr model, + const TVector& violation); + void defineViolation(const TVector& violation); + void updateBest(); + void defineOutputPrpts(); + + TVector m_violation; +}; + +} // namespace Representation +} // namespace Tigon + +#endif // FEASIBLERANDEXPECTEDIMPROVEMENT_H diff --git a/src/libs/tigon/Representation/Functions/FeedforwardSurrogate.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeedforwardSurrogate.cpp similarity index 96% rename from src/libs/tigon/Representation/Functions/FeedforwardSurrogate.cpp rename to src/libs/tigon/Representation/Functions/SurrogateModelling/FeedforwardSurrogate.cpp index 7bfe072..39df16b 100644 --- a/src/libs/tigon/Representation/Functions/FeedforwardSurrogate.cpp +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeedforwardSurrogate.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,7 +13,7 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include +#include #include #include #include diff --git a/src/libs/tigon/Representation/Functions/FeedforwardSurrogate.h b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeedforwardSurrogate.h similarity index 91% rename from src/libs/tigon/Representation/Functions/FeedforwardSurrogate.h rename to src/libs/tigon/Representation/Functions/SurrogateModelling/FeedforwardSurrogate.h index 95d8bd2..d0dcc00 100644 --- a/src/libs/tigon/Representation/Functions/FeedforwardSurrogate.h +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/FeedforwardSurrogate.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -18,7 +18,7 @@ #include #include -#include +#include namespace Tigon { namespace Representation { diff --git a/src/libs/tigon/Representation/Functions/KrigingSurrogate.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/KrigingSurrogate.cpp similarity index 90% rename from src/libs/tigon/Representation/Functions/KrigingSurrogate.cpp rename to src/libs/tigon/Representation/Functions/SurrogateModelling/KrigingSurrogate.cpp index e50329d..bae93af 100644 --- a/src/libs/tigon/Representation/Functions/KrigingSurrogate.cpp +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/KrigingSurrogate.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,11 +13,11 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include +#include #include #include -#include -#include +#include +#include @@ -55,7 +55,7 @@ TString KrigingSurrogate::description() return("A function that evaluates a solution by a Kriging model.\n" "The Kriging model is provided after the function is constructed, " "together with the properties of the input and output variables.\n" - "Nuber of inputs and outputs match the Kriging model."); + "Number of inputs and outputs match the Kriging model."); } void KrigingSurrogate::evaluate(const TVector &inputs, @@ -116,7 +116,7 @@ KrigingSPtr KrigingSurrogate::model() const void KrigingSurrogate::defineModel(KrigingSPtr model) { m_model = model; - TP_defineNInputs(m_model->variogram()->nInputs()); + TP_defineNInputs(m_model->inputData()[0].size()); } diff --git a/src/libs/tigon/Representation/Functions/KrigingSurrogate.h b/src/libs/tigon/Representation/Functions/SurrogateModelling/KrigingSurrogate.h similarity index 95% rename from src/libs/tigon/Representation/Functions/KrigingSurrogate.h rename to src/libs/tigon/Representation/Functions/SurrogateModelling/KrigingSurrogate.h index 2653715..0e9cd01 100644 --- a/src/libs/tigon/Representation/Functions/KrigingSurrogate.h +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/KrigingSurrogate.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/Likelihood.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/Likelihood.cpp new file mode 100644 index 0000000..8b58da5 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/Likelihood.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include +#include + +namespace Tigon { +namespace Representation { + +Likelihood::Likelihood() +{ + TP_defineNInputs(1); + TP_defineNOutputs(3); +} + +Likelihood::Likelihood(const TVector>& x, + const TVector& y) + : Likelihood() +{ + defineData(x,y); +} + +Likelihood::~Likelihood() +{ + +} + +TString Likelihood::name() +{ + return("Likelihood"); +} + +TString Likelihood::description() +{ + return("Concentrated ln-likelihood function"); +} + +void Likelihood::evaluate(const TVector &inputs, + const TVector &outputs) +{ + int N = inputs.size(); + if(N != m_xDim) { + throw TException(className(), IncorrectNumberArguments); + } + + TVector theta; theta.reserve(N); + for(auto elem : inputs) { + theta.push_back(std::pow(10.0, elem->value())); + } + + TMatrixReal Gram(m_N, m_N); // Gram matrix + for(int i=0; i::epsilon(); + } + Gram(m_N-1, m_N-1) = 1.0 + std::numeric_limits::epsilon(); + + // Standard Cholesky decomposition (LL^T) of a matrix + Eigen::LLT cholesky(m_N); + cholesky.compute(Gram); + + // Check if decomposition succeed, if not, it means that the matrix is not + // positive definite (perhaps the points are densily packed) + if(cholesky.info() == Eigen::Success) { + + TMatrixReal U = cholesky.matrixU(); + TMatrixReal Ut = U.transpose(); + + TCVectorReal y(m_y.size()); + for(size_t i=0; idefineValue(LnLike); + outputs[1]->defineValue(mu); + outputs[2]->defineValue(sigmaSqr(0)); + return; + } + else { + outputs[0]->defineValue(Tigon::Lowest); + outputs[1]->defineValue(0.0); + outputs[2]->defineValue(1.0); + return; + } +} + +void Likelihood::defineInputPrpts() +{ + TStringList varNames; + TStringList varDescriptions; + TVector typeVec(TP_nInputs(), RealType); + TStringList varUnits(TP_nInputs(), TString("")); + TVector lowerBounds(TP_nInputs(), IElement(RealType, -3.0)); + TVector upperBounds(TP_nInputs(), IElement(RealType, 2.0)); + + for(int i=0; i typeVec; + TStringList varUnits; + TVector optTypes; + + varNames.push_back("LnLike"); + varDescriptions.push_back("Concentrated ln-likelihood"); + typeVec.push_back(RealType); + varUnits.push_back(""); + optTypes.push_back(Maximization); + + varNames.push_back("MeanMLE"); + varDescriptions.push_back("MLE estimate for mean"); + typeVec.push_back(RealType); + varUnits.push_back(""); + optTypes.push_back(NonOptimization); + + varNames.push_back("SigmaSqrMLE"); + varDescriptions.push_back("MLE estimate for sigma square"); + typeVec.push_back(RealType); + varUnits.push_back(""); + optTypes.push_back(NonOptimization); + + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +void Likelihood::defineData(const TVector>& x, + const TVector& y) +{ + if( (x.size()==0) || (y.size()==0) ) { + return; + } + if(x.size() != y.size()) { + return; + } + + m_N = x.size(); + m_xDim = x[0].size(); + + m_x.clear(); + m_y.clear(); + m_x = x; + m_y = y; + + TP_defineNInputs(m_xDim); +} + +TVector> Likelihood::xValues() const +{ + return m_x; +} + +TVector Likelihood::yValues() const +{ + return m_y; +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/Likelihood.h b/src/libs/tigon/Representation/Functions/SurrogateModelling/Likelihood.h new file mode 100644 index 0000000..ef0ebaf --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/Likelihood.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef LIKELIHOOD_H +#define LIKELIHOOD_H + +#include +#include + +namespace Tigon { +namespace Representation { + +class LIGER_TIGON_EXPORT Likelihood : public IFunction +{ +public: + Likelihood(); + Likelihood(const TVector>& x, const TVector& y); + ~Likelihood(); + + // Information about the function(s) + TString name(); + TString description(); + + void evaluate(const TVector &inputs, + const TVector &outputs); + + void defineData(const TVector>& x, const TVector& y); + TVector> xValues() const; + TVector yValues() const; + +private: + void defineInputPrpts(); + void defineOutputPrpts(); + + int m_N; // number of points + int m_xDim; // number of dimensions + + TVector> m_x; // x-data + TVector m_y; // y-data +}; + +} // namespace Representation +} // namespace Tigon + +#endif // LIKELIHOOD_H diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibility.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibility.cpp new file mode 100644 index 0000000..4a63d5d --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibility.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Tigon { +namespace Representation { + +ProbabilityFeasibility::ProbabilityFeasibility() +{ + TP_defineNInputs(1); + TP_defineNOutputs(1); + m_standardNormal = new NormalDistribution(0.0, 1.0); +} + +ProbabilityFeasibility::ProbabilityFeasibility(const KrigingSPtr &model) + : ProbabilityFeasibility() +{ + defineModel(model); +} + + +ProbabilityFeasibility::~ProbabilityFeasibility() +{ + if(m_standardNormal != nullptr) { + delete m_standardNormal; + } +} + +TString ProbabilityFeasibility::name() +{ + return("Probability of feasibility"); +} + +TString ProbabilityFeasibility::description() +{ + return("A function that estimates the solution's probability of being feasible " + "regarding the contraints, based on Kriging estimation.\n" + "Probability of feasibility is calculated by considering the value for the " + "input as a random number, following a normal distribution with the " + "mean and standard deviation estimated by the Kriging model ."); +} + +void ProbabilityFeasibility::evaluate(const TVector &inputs, + const TVector &outputs) +{ + if(model()) { + double val = value(inputs); + double err = error(inputs); + double PF = 0.0; + if(err > 0) { + PF = m_standardNormal->cdf(-(val/err)); + } + outputs[0]->defineValue(PF); + } +} + + +void ProbabilityFeasibility::defineOutputPrpts() +{ + if(TP_nOutputs() != 1) { + return; + } + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + + varNames << "Probability of feasibility"; + varDescriptions << "Determines the probability of the prediction being " + "greater than the constraint limit, i.e. the probability " + "that the constraint is met.\n" + "A Kriging model is fit to the constraint violation " + "values of the solutions, where a positive value " + "indicates that the solution violates the constraint, " + "otherwise the value is zero.\n" + "The probability values are inside the range [0 1]."; + + typeVec << RealType; + varUnits << ""; + TVector optTypes({Maximization}); + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +void ProbabilityFeasibility::defineModel(KrigingSPtr model) +{ + KrigingSurrogate::defineModel(model); +} + + +double ProbabilityFeasibility::value(const TVector &inputs) +{ + TVector iReal = IElementVecToRealVec(inputs); + + return model()->interpolate(iReal); +} + +double ProbabilityFeasibility::error(const TVector &inputs) +{ + // The model error, is defined by the last vector that was evaluated. + T_UNUSED(inputs); + return model()->errorEstimate(); +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibility.h b/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibility.h new file mode 100644 index 0000000..92261d5 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibility.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef PROBABILITYOFFEASIBILITY_H +#define PROBABILITYOFFEASIBILITY_H + +#include +#include + +namespace Tigon { +namespace Representation { +class NormalDistribution; + +class LIGER_TIGON_EXPORT ProbabilityFeasibility : public KrigingSurrogate +{ + +public: + ProbabilityFeasibility(); + ProbabilityFeasibility(const KrigingSPtr &model); + ~ProbabilityFeasibility(); + + // Information about the function(s) + TString name(); + TString description(); + + void evaluate(const TVector &inputs, + const TVector &outputs); + + void defineModel(KrigingSPtr model); + + virtual double value(const TVector& inputs); + virtual double error(const TVector& inputs); + +protected: + NormalDistribution* m_standardNormal; + +private: + void defineOutputPrpts(); +}; + +} // namespace Representation +} // namespace Tigon + +#endif // PROBABILITYOFFEASIBILITY_H diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.cpp new file mode 100644 index 0000000..578c1e3 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace Tigon { +namespace Representation { + +ProbabilityFeasibilityBagheri::ProbabilityFeasibilityBagheri() +{ + TP_defineNInputs(1); + TP_defineNOutputs(1); + m_standardNormal = new NormalDistribution(0.0, 1.0); +} + +ProbabilityFeasibilityBagheri::ProbabilityFeasibilityBagheri(const KrigingSPtr &model) + : ProbabilityFeasibilityBagheri() +{ + defineModel(model); +} + + +ProbabilityFeasibilityBagheri::~ProbabilityFeasibilityBagheri() +{ + if(m_standardNormal != nullptr) { + delete m_standardNormal; + } +} + +TString ProbabilityFeasibilityBagheri::name() +{ + return("Probability of feasibility using Bagheri's modification"); +} + +TString ProbabilityFeasibilityBagheri::description() +{ + return("A function that estimates the solution's probability of being feasible " + "regarding the contraints, based on Kriging estimation.\n" + "Probability of feasibility is calculated by considering the value for the " + "input as a random number, following a normal distribution with the " + "mean and standard deviation estimated by the Kriging model. This modifed function" + "is proposed by Bagheri et al. (GECCO 2017) function that allows solutions arround " + "the boundary a higher chance to be selected ."); +} + +void ProbabilityFeasibilityBagheri::evaluate(const TVector &inputs, + const TVector &outputs) +{ + if(model()) { + double val = value(inputs); + double err = error(inputs); + double PF = 0.0; + if(err > 0) { + PF = 2*m_standardNormal->cdf(-(val/err)); + }; + PF = std::min(PF, 1.0); + outputs[0]->defineValue(PF); + } +} + + +void ProbabilityFeasibilityBagheri::defineOutputPrpts() +{ + if(TP_nOutputs() != 1) { + return; + } + TStringList varNames; + TStringList varDescriptions; + TVector typeVec; + TStringList varUnits; + + varNames << "Probability of feasibility"; + varDescriptions << "Determines the probability of the prediction being " + "greater than the constraint limit, i.e. the probability " + "that the constraint is met.\n" + "A Kriging model is fit to the constraint violation " + "values of the solutions, where a positive value " + "indicates that the solution violates the constraint, " + "otherwise the value is zero.\n" + "The probability values are inside the range [0 1]."; + + typeVec << RealType; + varUnits << ""; + TVector optTypes({Maximization}); + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); +} + +void ProbabilityFeasibilityBagheri::defineModel(KrigingSPtr model) +{ + KrigingSurrogate::defineModel(model); +} + + +double ProbabilityFeasibilityBagheri::value(const TVector &inputs) +{ + TVector iReal = IElementVecToRealVec(inputs); + + return model()->interpolate(iReal); +} + +double ProbabilityFeasibilityBagheri::error(const TVector &inputs) +{ + // The model error, is defined by the last vector that was evaluated. + T_UNUSED(inputs); + return model()->errorEstimate(); +} + +} // namespace Representation +} // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.h b/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.h new file mode 100644 index 0000000..2b1d4a6 --- /dev/null +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef PROBABILITYFEASIBILITYBAGHERI_H +#define PROBABILITYFEASIBILITYBAGHERI_H + +#include +#include + +namespace Tigon { +namespace Representation { +class NormalDistribution; + +class LIGER_TIGON_EXPORT ProbabilityFeasibilityBagheri : public ProbabilityFeasibility +{ + +public: + ProbabilityFeasibilityBagheri(); + ProbabilityFeasibilityBagheri(const KrigingSPtr &model); + ~ProbabilityFeasibilityBagheri(); + + // Information about the function(s) + TString name(); + TString description(); + + void evaluate(const TVector &inputs, + const TVector &outputs); + + void defineModel(KrigingSPtr model); + + virtual double value(const TVector& inputs); + virtual double error(const TVector& inputs); + +protected: + NormalDistribution* m_standardNormal; + +private: + void defineOutputPrpts(); +}; + +} // namespace Representation +} // namespace Tigon + +#endif // PROBABILITYFEASIBILITYBAGHERI_H diff --git a/src/libs/tigon/Representation/Functions/RandExpectedImprovement.cpp b/src/libs/tigon/Representation/Functions/SurrogateModelling/RandExpectedImprovement.cpp similarity index 66% rename from src/libs/tigon/Representation/Functions/RandExpectedImprovement.cpp rename to src/libs/tigon/Representation/Functions/SurrogateModelling/RandExpectedImprovement.cpp index d96f869..a88f759 100644 --- a/src/libs/tigon/Representation/Functions/RandExpectedImprovement.cpp +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/RandExpectedImprovement.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,12 +13,12 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include +#include #include #include #include -#include -#include +#include +#include #include #include #include @@ -30,20 +30,23 @@ namespace Representation { RandExpectedImprovement::RandExpectedImprovement() { - + TP_defineNOutputs(1); } RandExpectedImprovement::RandExpectedImprovement(KrigingSPtr model) : ExpectedImprovement(model) - , m_samples(model->variogram()->inputData()) { + TP_defineNOutputs(1); + defineSamples(model->inputData()); } -RandExpectedImprovement::RandExpectedImprovement(KrigingSPtr model, - TVector > samples) +RandExpectedImprovement::RandExpectedImprovement( + KrigingSPtr model, + const TVector>& samples) : ExpectedImprovement(model) - , m_samples(samples) { + TP_defineNOutputs(1); + defineSamples(samples); } RandExpectedImprovement::~RandExpectedImprovement() @@ -51,23 +54,20 @@ RandExpectedImprovement::~RandExpectedImprovement() } -TString RandExpectedImprovement::name() +void RandExpectedImprovement::defineSamples(const TVector> &samples) { - return("Random Expected Improvement"); + m_samples = samples; + defineDefaultBandwidth(); } -TString RandExpectedImprovement::description() +TVector > RandExpectedImprovement::samples() const { - return("A function that estimates the solutin's expected improvement over " - "the current best known solution, based on Kriging estimation.\n" - "Expected improvement is calculated by considering the value for the " - "input as a random number, following a normal distribution. The mean " - "is the Kriging model estimation, and the error has an inverse " - "correlation to the density of the solution in decision space."); + return m_samples; } -void RandExpectedImprovement::evaluate(const TVector &inputs, - const TVector &outputs) +void RandExpectedImprovement::evaluate( + const TVector &inputs, + const TVector &outputs) { if(model()) { @@ -81,7 +81,7 @@ void RandExpectedImprovement::evaluate(const TVector &inputs, err * m_standardNormal->pdf(diff/err); } - outputs[0]->defineValue(-expImprove); + outputs[0]->defineValue(expImprove); } } @@ -94,34 +94,36 @@ void RandExpectedImprovement::defineOutputPrpts() TStringList varDescriptions; TVector typeVec; TStringList varUnits; - TVector optTypes(TP_nOutputs(), Minimization); - varNames << "Expected_Improvement"; + varNames << "Rand expected improvement"; varDescriptions << "The expected improvement over the best 'known' point " "to the Kriging model. Expected improvement is calculated " "by considering the value for the input as a random " - "number, following a normal distribution. The mean " - "is the Kriging model estimation, and the error has an inverse " - "correlation to the density of the solution in decision space."; + "number, following a normal distribution. The mean is the " + "Kriging model estimation, and the error has an inverse " + "correlation to the density of the solution in decision " + "space."; typeVec << RealType; - varUnits << "" << ""; + varUnits << ""; + TVector optTypes({Maximization}); createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); } -double RandExpectedImprovement::value(TVector inputs) +double RandExpectedImprovement::value(const TVector& inputs) { TVector iReal = IElementVecToRealVec(inputs); return model()->interpolate(iReal); } -double RandExpectedImprovement::error(TVector inputs) +double RandExpectedImprovement::error(const TVector& inputs) { TVector iReal = IElementVecToRealVec(inputs); // calculate the error double density = gaussianKDE(m_samples, iReal, m_bandwidth); - double err = (std::atan(1.0 / density)) / (boost::math::constants::pi()) * 2.0; + double err = (std::atan(1.0 / density)) / + (boost::math::constants::pi()) * 2.0; // scale the error according to the function values err *= (worst() - best()); @@ -129,19 +131,19 @@ double RandExpectedImprovement::error(TVector inputs) return err; } -void RandExpectedImprovement::defineBandwith(double h) +void RandExpectedImprovement::defineBandwidth(double h) { if(h > 0.0) { m_bandwidth = h; } } -double RandExpectedImprovement::bandwith() const +double RandExpectedImprovement::bandwidth() const { return m_bandwidth; } -void RandExpectedImprovement::defineDefaultBandwith() +void RandExpectedImprovement::defineDefaultBandwidth() { int n = m_samples.size(); if(n>0) { @@ -159,7 +161,7 @@ void RandExpectedImprovement::defineDefaultBandwith() h /= d; h /= 100.0; - defineBandwith(h); + defineBandwidth(h); } else { m_bandwidth = 0.01; } @@ -168,5 +170,21 @@ void RandExpectedImprovement::defineDefaultBandwith() } } +TString RandExpectedImprovement::name() +{ + return("Expected improvement with error estimated by the density of " + "solutions in decision space"); +} + +TString RandExpectedImprovement::description() +{ + return("A function that estimates the solution's expected improvement over " + "the current best known solution, based on Kriging estimation.\n" + "Expected improvement is calculated by considering the value for the " + "input as a random number, following a normal distribution. The mean " + "is the Kriging model estimation, and the error has an inverse " + "correlation to the density of the solutions in decision space."); +} + } // namespace Representation } // namespace Tigon diff --git a/src/libs/tigon/Representation/Functions/RandExpectedImprovement.h b/src/libs/tigon/Representation/Functions/SurrogateModelling/RandExpectedImprovement.h similarity index 64% rename from src/libs/tigon/Representation/Functions/RandExpectedImprovement.h rename to src/libs/tigon/Representation/Functions/SurrogateModelling/RandExpectedImprovement.h index abc9c54..756a9a8 100644 --- a/src/libs/tigon/Representation/Functions/RandExpectedImprovement.h +++ b/src/libs/tigon/Representation/Functions/SurrogateModelling/RandExpectedImprovement.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -16,7 +16,7 @@ #ifndef RANDEXPECTEDIMPROVEMENT_H #define RANDEXPECTEDIMPROVEMENT_H -#include +#include #include namespace Tigon { @@ -28,11 +28,15 @@ class LIGER_TIGON_EXPORT RandExpectedImprovement : public ExpectedImprovement public: RandExpectedImprovement(); RandExpectedImprovement(KrigingSPtr model); - RandExpectedImprovement(KrigingSPtr model, TVector > samples); - virtual ~RandExpectedImprovement(); + RandExpectedImprovement(KrigingSPtr model, + const TVector> &samples); + ~RandExpectedImprovement(); - void defineBandwith(double h); - double bandwith() const; + void defineSamples(const TVector> &samples); + TVector> samples() const; + + void defineBandwidth(double h); + double bandwidth() const; // Information about the function(s) TString name(); @@ -41,15 +45,14 @@ class LIGER_TIGON_EXPORT RandExpectedImprovement : public ExpectedImprovement void evaluate(const TVector &inputs, const TVector &outputs); - virtual double value(TVector inputs); - virtual double error(TVector inputs); + virtual double value(const TVector& inputs); + virtual double error(const TVector& inputs); private: - void initialise(); void defineOutputPrpts(); - void defineDefaultBandwith(); - TVector > m_samples; - double m_bandwidth; + void defineDefaultBandwidth(); + TVector> m_samples; + double m_bandwidth; }; } // namespace Representation diff --git a/src/libs/tigon/Representation/Functions/ZDT/ZDT1.cpp b/src/libs/tigon/Representation/Functions/ZDT/ZDT1.cpp index b774b7f..5dd913a 100644 --- a/src/libs/tigon/Representation/Functions/ZDT/ZDT1.cpp +++ b/src/libs/tigon/Representation/Functions/ZDT/ZDT1.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -26,17 +26,13 @@ namespace Representation { ZDT1::ZDT1() { - TP_defineNInputs(2); + TP_defineNInputs(30); TP_defineNOutputs(2); TString name("ZDT1"); - TString description("ZDT1 benchmark problem. A two objectives problem that " - "are to be minimised.\n" - "The problem scalable in terms of the number of " - "variables, which is given by n, and all variables lie " - "in the range [0,1].\n " - "The Pareto front corresponds to 0<=x1<=1 and xi=0 for " - "i=2,..,n.\n, and its shape in objective space is " - "convex."); + TString description("ZDT1 benchmark problem. A two-objective problem having " + "a convex Pareto-optimal set.\n" + "All variables lie in the range [0,1]. The Pareto-optimal " + "region corresponds to 0 <= x1 <= 1 and xi=0 for i=2,...,n."); createFunctionProperties(name, description, FunctionType::Internal); defineParallelisable(); defineIsNumoutputsModifiable(false); @@ -45,7 +41,7 @@ ZDT1::ZDT1() ZDT1::ZDT1(const ZDT1& func) { TP_defineNInputs(func.TP_nInputs()); - TP_defineNOutputs(2); + TP_defineNOutputs(func.TP_nOutputs()); createFunctionProperties(func.name(), func.description(), func.type()); defineParallelisable(); defineIsNumoutputsModifiable(false); @@ -57,14 +53,14 @@ ZDT1::~ZDT1() } void ZDT1::evaluate(const TVector &inputs, - const TVector &outputs) + const TVector &outputs) { - if((inputs.size() == TP_nInputs()) && (outputs.size() == 2) && - (TP_nInputs() > 1)) { + if((inputs.size() == TP_nInputs()) && (outputs.size() == TP_nOutputs()) && + (TP_nInputs() > TP_nOutputs())) { TVector iReal = IElementVecToRealVec(inputs); TVector oReal = ZDT::ZDT1(iReal); - for(int i=0; idefineValue(oReal[i]); } } else { @@ -82,10 +78,10 @@ void ZDT1::defineInputPrpts() TVector upperBounds(TP_nInputs(), IElement(RealType, 1.0)); for(int i = 0; i < TP_nInputs(); i++) { - varNames.push_back("x_" + std::to_string(i+1)); + varNames.push_back("Input_Var_" + std::to_string(i)); typeVec.push_back(RealType); varUnits.push_back(""); - varDescriptions.push_back("Decision variable n." + std::to_string(i+1)); + varDescriptions.push_back("Decision variable"); } createInputProperties(varNames, varDescriptions, typeVec, varUnits, @@ -100,14 +96,15 @@ void ZDT1::defineOutputPrpts() TStringList varUnits; TVector optTypes; - for(int i = 0; i < 2; i++) { - varNames.push_back("f_" + std::to_string(i+1)); - varDescriptions.push_back("Objective function n." + std::to_string(i+1)); + for(int i = 0; i < TP_nOutputs(); i++) { + varNames.push_back("Output_Var_" + std::to_string(i)); + varDescriptions.push_back("Output_VarDesc_" + std::to_string(i)); typeVec.push_back(RealType); varUnits.push_back(""); optTypes.push_back(Minimization); } - createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, + optTypes); } } // namespace Representation diff --git a/src/libs/tigon/Representation/Functions/ZDT/ZDT2.cpp b/src/libs/tigon/Representation/Functions/ZDT/ZDT2.cpp index 9ef948e..f65d110 100644 --- a/src/libs/tigon/Representation/Functions/ZDT/ZDT2.cpp +++ b/src/libs/tigon/Representation/Functions/ZDT/ZDT2.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -26,17 +26,13 @@ namespace Representation { ZDT2::ZDT2() { - TP_defineNInputs(2); + TP_defineNInputs(30); TP_defineNOutputs(2); TString name("ZDT2"); - TString description("ZDT2 benchmark problem. A two objectives problem that " - "are to be minimised.\n" - "The problem scalable in terms of the number of " - "variables, which is given by n, and all variables lie " - "in the range [0,1].\n " - "The Pareto front corresponds to 0<=x1<=1 and xi=0 for " - "i=2,..,n.\n, and its shape in objective space is " - "concave."); + TString description("ZDT2 benchmark problem. A two-objective problem having " + "a nonconvex Pareto-optimal set.\n" + "All variables lie in the range [0,1]. The Pareto-optimal " + "region corresponds to 0 <= x1 <= 1 and xi=0 for i=2,...,n."); createFunctionProperties(name, description, FunctionType::Internal); defineParallelisable(); defineIsNumoutputsModifiable(false); @@ -45,7 +41,7 @@ ZDT2::ZDT2() ZDT2::ZDT2(const ZDT2& func) { TP_defineNInputs(func.TP_nInputs()); - TP_defineNOutputs(2); + TP_defineNOutputs(func.TP_nOutputs()); createFunctionProperties(func.name(), func.description(), func.type()); defineParallelisable(); defineIsNumoutputsModifiable(false); @@ -57,14 +53,14 @@ ZDT2::~ZDT2() } void ZDT2::evaluate(const TVector &inputs, - const TVector &outputs) + const TVector &outputs) { - if((inputs.size() == TP_nInputs()) && (outputs.size() == 2) && - (TP_nInputs() > 1)) { + if((inputs.size() == TP_nInputs()) && (outputs.size() == TP_nOutputs()) && + (TP_nInputs() > TP_nOutputs())) { TVector iReal = IElementVecToRealVec(inputs); TVector oReal = ZDT::ZDT2(iReal); - for(int i=0; idefineValue(oReal[i]); } } else { @@ -82,10 +78,10 @@ void ZDT2::defineInputPrpts() TVector upperBounds(TP_nInputs(), IElement(RealType, 1.0)); for(int i = 0; i < TP_nInputs(); i++) { - varNames.push_back("x_" + std::to_string(i+1)); + varNames.push_back("Input_Var_" + std::to_string(i)); typeVec.push_back(RealType); varUnits.push_back(""); - varDescriptions.push_back("Decision variable n." + std::to_string(i+1)); + varDescriptions.push_back("Decision variable"); } createInputProperties(varNames, varDescriptions, typeVec, varUnits, @@ -100,14 +96,15 @@ void ZDT2::defineOutputPrpts() TStringList varUnits; TVector optTypes; - for(int i = 0; i < 2; i++) { - varNames.push_back("f_" + std::to_string(i+1)); - varDescriptions.push_back("Objective function n." + std::to_string(i+1)); + for(int i = 0; i < TP_nOutputs(); i++) { + varNames.push_back("Output_Var_" + std::to_string(i)); + varDescriptions.push_back("Output_VarDesc_" + std::to_string(i)); typeVec.push_back(RealType); varUnits.push_back(""); optTypes.push_back(Minimization); } - createOutputProperties(varNames, varDescriptions, typeVec, varUnits, optTypes); + createOutputProperties(varNames, varDescriptions, typeVec, varUnits, + optTypes); } } // namespace Representation diff --git a/src/libs/tigon/Representation/PSets/IPSet.cpp b/src/libs/tigon/Representation/PSets/IPSet.cpp index 48291e5..6c4e33a 100644 --- a/src/libs/tigon/Representation/PSets/IPSet.cpp +++ b/src/libs/tigon/Representation/PSets/IPSet.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -763,11 +763,21 @@ TVector IPSet::antiIdealVec() const return d->m_problem->antiIdealVector(); } +TVector IPSet::setGoalVec() const +{ + return d->m_problem->setGoalVector(); +} + TVector IPSet::goalVec() const { return d->m_problem->goalVector(); } +TVector IPSet::priorityVec() const +{ + return d->m_problem->priorityVector(); +} + TVector IPSet::thresholdVec() const { return d->m_problem->thresholdVector(); @@ -880,7 +890,21 @@ bool IPSet::updateNadirVec(IMappingSPtr newIMap) return updated; } -void IPSet::defineGoalVec(const TVector&goals) +void IPSet::defineSetGoalVec(const TVector& setGoals) +{ + d->m_problem->defineSetGoalVector(setGoals); +} + +void IPSet::defineSetGoalVec(int idx, bool setGoal) +{ + if(isInRange(idx, objectiveVecSize())) { + TVector setGoals = d->m_problem->setGoalVector(); + setGoals[idx] = setGoal; + d->m_problem->defineSetGoalVector(setGoals); + } +} + +void IPSet::defineGoalVec(const TVector& goals) { d->m_problem->defineGoalVector(goals); } @@ -894,6 +918,18 @@ void IPSet::defineGoal(int idx, IElementSPtr goal) } } +void IPSet::definePriorityVec(const TVector &priorities) +{ + d->m_problem->definePriorityVector(priorities); +} + +void IPSet::definePriority(int idx, int priority) +{ + if(isInRange(idx, objectiveVecSize())) { + d->m_problem->redefinePriority(idx, priority); + } +} + void IPSet::defineThresholdVec(const TVector&thresholds) { d->m_problem->defineThresholdVector(thresholds); @@ -982,7 +1018,7 @@ void IPSet::setCurrentIteration(int citer) d->m_currentIter = citer; } -int IPSet::remainingIteratoins() const +int IPSet::remainingIterations() const { return (d->m_maxIter) - (d->m_currentIter); } diff --git a/src/libs/tigon/Representation/PSets/IPSet.h b/src/libs/tigon/Representation/PSets/IPSet.h index 46dddb7..5b28bbf 100644 --- a/src/libs/tigon/Representation/PSets/IPSet.h +++ b/src/libs/tigon/Representation/PSets/IPSet.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -159,7 +159,9 @@ class LIGER_TIGON_EXPORT IPSet : public TObject TVector idealVec() const; TVector nadirVec() const; TVector antiIdealVec() const; + TVector setGoalVec() const; TVector goalVec() const; + TVector priorityVec() const; TVector thresholdVec() const; TVector dirVec() const; @@ -175,8 +177,12 @@ class LIGER_TIGON_EXPORT IPSet : public TObject bool updateIdealVec(IMappingSPtr newIMap); bool updateAntiIdealVec(IMappingSPtr newIMap); bool updateNadirVec(IMappingSPtr newIMap); + void defineSetGoalVec(const TVector& setGoals); + void defineSetGoalVec(int idx, bool setGoal); void defineGoalVec(const TVector& goals); void defineGoal(int idx, IElementSPtr goal); + void definePriorityVec(const TVector& priorities); + void definePriority(int idx, int priority); void defineThresholdVec(const TVector& thresholds); void defineThreshold(int idx, IElementSPtr threshold); void defineDirVec(const TVector &dir); @@ -191,7 +197,7 @@ class LIGER_TIGON_EXPORT IPSet : public TObject int currentIteration() const; void incrementIteration(); void setCurrentIteration(int citer); - int remainingIteratoins() const; + int remainingIterations() const; int maxIteration() const; void defineMaxIteration(int nIter); int remainingBudget() const; @@ -240,6 +246,7 @@ class LIGER_TIGON_EXPORT IPSet : public TObject void defineProblem(ProblemSPtr prob); void appendFunction(IFunctionSPtr func); + void updateProblem(); private: diff --git a/src/libs/tigon/Utils/DominanceUtils.cpp b/src/libs/tigon/Utils/DominanceUtils.cpp index 7edc021..e667cbb 100644 --- a/src/libs/tigon/Utils/DominanceUtils.cpp +++ b/src/libs/tigon/Utils/DominanceUtils.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -31,7 +31,7 @@ tribool weakDominance(const TVector &a, const TVector &b) bool aDominate(false); bool bDominate(false); - for(int i=0; i &a, const TVector &b, } +TVector dominanceCount(const ISet* set, bool weakDom) +{ + return dominanceCount(set->all(), weakDom); +} + +TVector dominanceCount(const TVector& set, bool weakDom) +{ + int N = set.size(); + TVector domCount(N, 0); + + // Compare all solutions + tribool dom; + for(int i=0; i nonDominanceSort(const ISet* set, bool weakDom) { TVector IMappings = set->all(); @@ -687,7 +723,7 @@ tribool preferability(const TVector &a, const TVector &g, bool weakDom) { - int Nobj = a.size(); + size_t Nobj = a.size(); /// Classification of the solutions /// 0: solution meets all goals @@ -695,7 +731,7 @@ tribool preferability(const TVector &a, int aclass=0; int bclass=0; - for(int k=0; k g[k]) { aclass=1; @@ -704,7 +740,7 @@ tribool preferability(const TVector &a, } } - for(int k=0; k g[k]) { bclass=1; @@ -723,7 +759,7 @@ tribool preferability(const TVector &a, AbetterB = AequalB = BbetterA = BequalA = 1; - for(int k=0; k g[k]) { // a does not meet the goal if(weakDom) { @@ -764,7 +800,7 @@ tribool preferability(const TVector &a, * based on those objectives which satisfy their goals */ AbetterB = AequalB = BbetterA = 1; - for (int k=0; k &a, return incomparable; } +LIGER_TIGON_EXPORT +tribool preferability(const TVector &a, + const TVector &b, + const TVector &g, + const TVector &p, + bool weakDom) +{ + int maxElem = *min_element(p.begin(), p.end()); + int minElem = *max_element(p.begin(), p.end()); + for(size_t i=0; i maxElem) { + maxElem = p[i]; + } + if(p[i] < minElem) { + minElem = p[i]; + } + } + } + + if ((maxElem==minElem) && (maxElem==1)){ // if there is only one priority level + return preferability(a,b,g); + } + else { // if there is more than one priority level + + // Store the indices of the objectives with the highest priority + TVector mp_idx; + for(size_t i = 0; i g[idx]) { + aclass=1; + break; + } + } + } + + int bclass=0; + for(auto idx : mp_idx) { + if(!areDoublesEqual(g[idx],Tigon::Lowest)) { // only for set goals + if(b[idx] > g[idx]) { + bclass=1; + break; + } + } + } + + if(aclass < bclass) { + return true; // A is preferred + } else if(aclass > bclass) { + return false; // B is preferred + } + + // it reaches this point if both solutions have objectives that violate + // the goals, or both totally satisfy the goals + + int AequalB, BequalA, AbetterB, BbetterA; + AbetterB = AequalB = BbetterA = BequalA = 1; + + for(auto idx : mp_idx) { + if(!areDoublesEqual(g[idx],Tigon::Lowest)) { // only for set goals + if(a[idx] > g[idx]) { // A does not meet the goal + if(weakDom) { + AbetterB *= (a[idx] <= b[idx]); + } else { + AbetterB *= (a[idx] < b[idx]); + } + AequalB *= (a[idx] == b[idx]); + } + if(b[idx] > g[idx]) { // B does not meet the goal + if(weakDom) { + BbetterA *= (b[idx] <= a[idx]); + } else { + BbetterA *= (b[idx] < a[idx]); + } + BequalA *= (b[idx] == a[idx]); + } + } + } + + // check if A and B are totally different + if (!(AequalB && BequalA)) { + + // check if A dominates B with respect to the components that A + // does not meet the goal + if ((AbetterB && !AequalB) || (AequalB && !BequalA)) + return true; + + // check if B dominates A with respect to the components that B + // does not meet the goal + if ((BbetterA && !BequalA) || (BequalA && !AequalB)) + return false; + + return incomparable; + } + + if( (maxElem == minElem) && (maxElem>1)) { + // Constraint satisfaction special case + return incomparable; + } + + /* this point is only reached in case the decision is * + * based on objectives with lower priority levels */ + + size_t Nobj = a.size(); + + TVector a2; + TVector b2; + TVector g2; + TVector p2; + + // Select objectives and corresponding goals with priority level lower + // than the current maximum + for(size_t k=0; k nonDominanceSort(const ISet* set, const TVector& goal, bool weakDom) { diff --git a/src/libs/tigon/Utils/DominanceUtils.h b/src/libs/tigon/Utils/DominanceUtils.h index 2ef9893..69d28b0 100644 --- a/src/libs/tigon/Utils/DominanceUtils.h +++ b/src/libs/tigon/Utils/DominanceUtils.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -37,6 +37,11 @@ tribool epsilonDominance(const TVector &a, const TVector &b, double epsilon=Epsilon); +LIGER_TIGON_EXPORT +TVector dominanceCount(const ISet* set, bool weakDom=true); +LIGER_TIGON_EXPORT +TVector dominanceCount(const TVector& set, bool weakDom=true); + LIGER_TIGON_EXPORT TVector nonDominanceSort(const ISet* set, bool weakDom=true); LIGER_TIGON_EXPORT @@ -103,6 +108,10 @@ LIGER_TIGON_EXPORT tribool preferability(const TVector &a, const TVector &b, const TVector &g, bool weakDom=true); LIGER_TIGON_EXPORT +tribool preferability(const TVector &a, const TVector &b, + const TVector &g, const TVector &p, + bool weakDom=true); +LIGER_TIGON_EXPORT TVector nonDominanceSort(const ISet* set, const TVector& goal, bool weakDom = true); LIGER_TIGON_EXPORT diff --git a/src/libs/tigon/Utils/JsonUtils.cpp b/src/libs/tigon/Utils/JsonUtils.cpp index 1816163..ae6b941 100644 --- a/src/libs/tigon/Utils/JsonUtils.cpp +++ b/src/libs/tigon/Utils/JsonUtils.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -92,6 +92,14 @@ JsonArray toJsonArray(const TVector &vec) return jArray; } +JsonArray toJsonArray(const TVector &vec) +{ + JsonArray jArray; + std::transform(vec.begin(), vec.end(),std::back_inserter(jArray), + [](int t) {return t;}); + return jArray; +} + JsonArray toJsonArray(const TVector &vec) { JsonArray jArray; @@ -395,7 +403,9 @@ JsonObject problemToJsonObject(const ProblemSPtr prob) } jprob["pVector"] = toJsonArrayFullInfo(prob->parameterVector()); + jprob["setGoals"] = toJsonArray(prob->setGoalVector()); jprob["goals"] = toJsonArrayDoubleValue(prob->goalVector()); + jprob["priorities"] = toJsonArray(prob->priorityVector()); jprob["thresholds"] = toJsonArrayDoubleValue(prob->thresholdVector()); jprob["isExternalParameters"] = toJsonArray(prob->isExternalParameters()); @@ -553,6 +563,13 @@ void fromJsonArray(const JsonArray &jarray, TVector& vec) [](const JsonValue jval) {return jval.toDouble();}); } +void fromJsonArray(const JsonArray &jarray, TVector& vec) +{ + std::transform(jarray.constBegin(), jarray.constEnd(), + std::back_inserter(vec), + [](const JsonValue jval) {return jval.toInt();}); +} + void fromJsonArray(const JsonArray &jarray, TVector& vec) { if(vec.size() > 0) vec.clear(); diff --git a/src/libs/tigon/Utils/JsonUtils.h b/src/libs/tigon/Utils/JsonUtils.h index d06aa91..c6c8565 100644 --- a/src/libs/tigon/Utils/JsonUtils.h +++ b/src/libs/tigon/Utils/JsonUtils.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -56,11 +56,14 @@ LIGER_TIGON_EXPORT void fromJsonArrayFullInfo(JsonArray array, /// TVector LIGER_TIGON_EXPORT JsonArray toJsonArray(const TVector& vec); +LIGER_TIGON_EXPORT JsonArray toJsonArray(const TVector& vec); LIGER_TIGON_EXPORT JsonArray toJsonArray(const TVector& vec); LIGER_TIGON_EXPORT JsonArray toJsonArray(const TVector > &vec); LIGER_TIGON_EXPORT void fromJsonArray(const JsonArray& jarray, TVector &vec); LIGER_TIGON_EXPORT +void fromJsonArray(const JsonArray& jarray, TVector &vec); +LIGER_TIGON_EXPORT void fromJsonArray(const JsonArray& jarray, TVector &vec); LIGER_TIGON_EXPORT void fromJsonArray(const JsonArray& jarray, TVector >& vec); diff --git a/src/libs/tigon/Utils/KernelDensityEstimation.cpp b/src/libs/tigon/Utils/KernelDensityEstimation.cpp index 994fa40..e001c5a 100644 --- a/src/libs/tigon/Utils/KernelDensityEstimation.cpp +++ b/src/libs/tigon/Utils/KernelDensityEstimation.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -19,9 +19,8 @@ #include #include - -using namespace boost; using namespace std; +using namespace boost::math::constants; namespace Tigon { @@ -37,7 +36,7 @@ double gaussianKDE(const TVector>& xx, double dist = l2dist(xx[i], xq); f += std::exp(-dist*dist / twoHSquare); } - f /= std::pow(twoHSquare * boost::math::constants::pi(), d/2.0) ; + f /= std::pow(twoHSquare * pi(), d/2.0) ; f /= n; return f; @@ -93,7 +92,7 @@ double gaussianKDE(const TVector &xx, double xq, double h) for(int i=0; i()); + f += std::exp(-u*u/2.0)/std::sqrt(2.0*pi()); } f /= n*h; diff --git a/src/libs/tigon/Utils/Kriging/DACE.cpp b/src/libs/tigon/Utils/Kriging/DACE.cpp new file mode 100644 index 0000000..ac24908 --- /dev/null +++ b/src/libs/tigon/Utils/Kriging/DACE.cpp @@ -0,0 +1,338 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Tigon { +using namespace Operators; +using Algorithms::ACROMUSE; +} + +namespace Tigon { + +DACE::DACE() + : m_predictionErrorEstimate(0.0) +{ + // default values (ACROMUSE) + defineBudgetPerVariable(DefaultBudgetPerVariableTS_H); + defineInitialPopsizePerVariable(DefaultInitialPopsizePerVariableTS_H); + defineStallIterations(DefaultStallIterationsTS_H); + + // default values (Model data) + TVector> x(3); + x[0] << 0.3 << 0.1; + x[1] << 0.4 << 0.7; + x[2] << 0.8 << 0.3; + + TVector y; + y << 0.9 << 0.2 << 0.1; + + TVector theta; + theta << 67.023 << 75.23; + + updateData(x, y, theta); + + configureDACE(); +} + +void DACE::updateData(const TVector>& x, + const TVector& y, + const TVector& theta) +{ + + // There needst to be at least two points + if(x.size() < 2) { + return; + } + if(x[0].size() < 1) { + return; + } + + if(x.size() != y.size()) { + return; + } + + m_x = x; + m_y = y; + + m_N = m_x.size(); + m_xDim = m_x[0].size(); + + if(theta.size() != m_x[0].size()) { + m_theta.resize(m_x[0].size()); + searchTheta(); + } else { + m_theta = theta; // user-defined theta + } + configureDACE(); +} + +DACE::~DACE() +{ + +} + +double DACE::interpolate(const TVector& xstar) +{ + if(xstar.size() != m_x[0].size()) { + return 0.0; + } + + TMatrixReal psi (m_N, 1); + for(int i=0; i > DACE::inputData() const +{ + return m_x; +} + +TVector DACE::outputData() const +{ + return m_y; +} + +// Find the hyperparameter (theta) via MLE +void DACE::searchTheta() +{ + IFunctionSPtr func = IFunctionSPtr(new Likelihood(m_x, m_y)); + TVector paramInd, objInd, cnstrInd, unusedInd; + objInd << 0; + unusedInd << 1 << 2; + ProblemSPtr prob(new Problem); + prob->appendFunction(func, paramInd, cnstrInd, objInd, unusedInd); + prob->processProblemDefinition(); + + // Create a new workflow + PSetBase* base = new PSetBase(); + IFormulation* form = new IFormulation(base); + LHSInit* init = new LHSInit(form); + Evaluator* eval = new Evaluator(init); + ACROMUSE* alg = new ACROMUSE(eval); + + int nDvec = m_xDim; + form->defineProblem(prob); + init->TP_defineSetSize(initialPopsizePerVariable() * nDvec); + eval->TP_defineSingleObjective(true); + alg->defineMaxIteration(budgetPerVariable() * nDvec); + + int stallIter = stallIterations(); + TVector scoresDiff; + double prevScore = 0.0; + while(alg->remainingIterations() > 0) { + alg->evaluate(); + + IMappingSPtr sol = alg->bestMapping(); + double currentScore = -sol->doubleCost(); + if(alg->currentIteration()==0) { + prevScore = currentScore; + } + else { + double scoreDiff = std::fabs(prevScore - currentScore); + scoresDiff.push_back(scoreDiff); + } + + if(scoresDiff.size() > stallIter) { + scoresDiff.erase(scoresDiff.begin()); // delete first element + } + + if(alg->currentIteration() > stallIter) { + double diffMean = vectorMean(scoresDiff); + if(diffMean < Tigon::Epsilon) { + break; + } + } + + prevScore = currentScore; + alg->incrementIteration(); + } + + TVector sol = alg->bestMapping()->doubleDecisionVec(); + for(size_t i=0; icurrentIteration() << std::endl; +// std::cout << "MLE parameters: " << m_theta << std::endl; + + delete alg; + delete eval; + delete init; + delete form; + delete base; +} + +void DACE::updateGramMatrix() +{ + m_Gram.resize(m_N, m_N); + for(int i=0; i::epsilon(); + } + m_Gram(m_N-1, m_N-1) = 1.0 + std::numeric_limits::epsilon(); +} + +void DACE::configureDACE() +{ + updateGramMatrix(); + + // Standard Cholesky decomposition (LL^T) of a matrix + Eigen::LLT cholesky(m_N); + cholesky.compute(m_Gram); + + // Check if decomposition succeed, if not, it means that the matrix is not + // positive definite (perhaps the points are densily packed) + if(cholesky.info() == Eigen::Success) { + m_isDecompositionSuccessfull = true; + } else { + m_isDecompositionSuccessfull = false; + } + + TMatrixReal U = cholesky.matrixU(); + TMatrixReal Ut = U.transpose(); + + TCVectorReal y(m_y.size()); + for(size_t i=0; i0) { + m_budgetPerVar = n; + } +} + +int DACE::budgetPerVariable() const +{ + return m_budgetPerVar; +} + +void DACE::defineInitialPopsizePerVariable(int n) +{ + if(n>0) { + m_initialPopsizePerVariable = n; + } +} + +int DACE::initialPopsizePerVariable() const +{ + return m_initialPopsizePerVariable; +} + + +void DACE::defineStallIterations(int iter) +{ + if(iter>0) { + m_stallIterations = iter; + } +} + +int DACE::stallIterations() const +{ + return m_stallIterations; +} + +TVector DACE::theta() const +{ + return m_theta; +} + +bool DACE::isDecompositionSuccessfull() const +{ + return m_isDecompositionSuccessfull; +} + + +} // namespace Tigon diff --git a/src/libs/tigon/Utils/Kriging/DACE.h b/src/libs/tigon/Utils/Kriging/DACE.h new file mode 100644 index 0000000..38fb6dc --- /dev/null +++ b/src/libs/tigon/Utils/Kriging/DACE.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef DACE_H +#define DACE_H +#include +#include +#include + +namespace Tigon { + +class LIGER_TIGON_EXPORT DACE : public IKriging +{ +public: + DACE(); + ~DACE(); + + void updateData(const TVector>& x, + const TVector& y, + const TVector& theta = TVector()); + + double interpolate(const TVector& xstar); + double errorEstimate(); + + TVector > inputData() const; + TVector outputData() const; + + // Properties (read and write) + void defineBudgetPerVariable(int n); + int budgetPerVariable() const; + + void defineInitialPopsizePerVariable(int n); + int initialPopsizePerVariable() const; + + void defineStallIterations(int iter); + int stallIterations() const; + + // read-only properties + TVector theta() const; + bool isDecompositionSuccessfull() const; + +private: + void searchTheta(); + void configureDACE(); + void updateGramMatrix(); + + int m_xDim; // number of dimensions + int m_N; // number of points + + TVector> m_x; // x-data + TVector m_y; // y-data + TVector m_theta; // parameter for Kriging radial basis function + + // Determined by Kriging + TMatrixReal m_U; + TMatrixReal m_Ut; + TMatrixReal m_U_solve_Ut_solve_residual; + double m_mu; + double m_sigmaSqr; + double m_predictionErrorEstimate; + TMatrixReal m_Gram; // Gram matrix + bool m_isDecompositionSuccessfull; + + // ACROMUSE parameters + int m_budgetPerVar; + int m_initialPopsizePerVariable; + int m_stallIterations; +}; + +} // namespace Tigon + +#endif // DACE_H diff --git a/src/libs/tigon/Utils/Kriging/IKriging.cpp b/src/libs/tigon/Utils/Kriging/IKriging.cpp new file mode 100644 index 0000000..a1fa000 --- /dev/null +++ b/src/libs/tigon/Utils/Kriging/IKriging.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#include + +namespace Tigon { + +IKriging::IKriging() + : m_estimateErrors(false) +{ + +} + +IKriging::~IKriging() +{ + +} + +void IKriging::defineEstimateErrors(bool est) +{ + m_estimateErrors = est; +} + +bool IKriging::estimateErrors() const +{ + return m_estimateErrors; +} + +} // namespace Tigon diff --git a/src/libs/tigon/Utils/Kriging/IKriging.h b/src/libs/tigon/Utils/Kriging/IKriging.h new file mode 100644 index 0000000..c17b9fd --- /dev/null +++ b/src/libs/tigon/Utils/Kriging/IKriging.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) +** +** This file is part of Liger. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ +#ifndef IKRIGING_H +#define IKRIGING_H + +#include +#include + +namespace Tigon { + +class LIGER_TIGON_EXPORT IKriging +{ +public: + IKriging(); + virtual ~IKriging(); + + virtual double interpolate(const TVector & xstar) = 0; + virtual double errorEstimate() = 0; + + virtual TVector > inputData() const = 0; + virtual TVector outputData() const = 0; + + void defineEstimateErrors(bool est); + bool estimateErrors() const; + +private: + // Indicates if the error of the predictions are to be estimated or not + bool m_estimateErrors; +}; + +} // namespace Tigon + +#endif // IKRIGING_H diff --git a/src/libs/tigon/Utils/KrigingCascade.cpp b/src/libs/tigon/Utils/Kriging/KrigingCascade.cpp similarity index 76% rename from src/libs/tigon/Utils/KrigingCascade.cpp rename to src/libs/tigon/Utils/Kriging/KrigingCascade.cpp index f65025b..1b0d301 100644 --- a/src/libs/tigon/Utils/KrigingCascade.cpp +++ b/src/libs/tigon/Utils/Kriging/KrigingCascade.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,11 +13,11 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include namespace Tigon { @@ -26,9 +26,8 @@ KrigingCascade::KrigingCascade() m_produceErrorEstimates = false; } -KrigingCascade::KrigingCascade(TVector > XX, - TVector > YY, - TString basis) +KrigingCascade::KrigingCascade(const TVector>& XX, + const TVector>& YY, TString basis) { m_produceErrorEstimates = false; bool isok = true; @@ -47,7 +46,7 @@ KrigingCascade::KrigingCascade(TVector > XX, int ny = YY[0].size(); - Kriging* interp; + OrdinaryKriging* interp; TVector > yl; yl.resize(YY[0].size()); for(int i=0; i > XX, // TODO - other variograms if(basis == "power") { for(int i=0; i variograms) +KrigingCascade::KrigingCascade(const TVector& variograms) { m_produceErrorEstimates = false; for(int i=0; iinputData()[0].size(); } @@ -127,12 +126,12 @@ TVector KrigingCascade::errors() return empty; } -TVector KrigingCascade::interpolators() +TVector KrigingCascade::interpolators() { return m_interpolators; } -void KrigingCascade::append(Kriging* interpolator) +void KrigingCascade::append(OrdinaryKriging* interpolator) { if(interpolator != nullptr) { m_interpolators.push_back(interpolator); @@ -160,7 +159,7 @@ void KrigingCascade::enableErrorEstimates() m_produceErrorEstimates = true; int sz = m_interpolators.size(); for(int i=0; iestimateErrors(true); + m_interpolators[i]->defineEstimateErrors(true); } } @@ -169,7 +168,7 @@ void KrigingCascade::disableErrorEstimates() m_produceErrorEstimates = false; int sz = m_interpolators.size(); for(int i=0; iestimateErrors(false); + m_interpolators[i]->defineEstimateErrors(false); } } diff --git a/src/libs/tigon/Utils/KrigingCascade.h b/src/libs/tigon/Utils/Kriging/KrigingCascade.h similarity index 74% rename from src/libs/tigon/Utils/KrigingCascade.h rename to src/libs/tigon/Utils/Kriging/KrigingCascade.h index ff26345..a74e7b4 100644 --- a/src/libs/tigon/Utils/KrigingCascade.h +++ b/src/libs/tigon/Utils/Kriging/KrigingCascade.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -17,29 +17,25 @@ #define KRIGINGCASCADE_H #include #include -DISABLE_WARNINGS #include -ENABLE_WARNINGS - namespace Tigon { -class Kriging; +class OrdinaryKriging; class KrigingVariogram; class LIGER_TIGON_EXPORT KrigingCascade { public: KrigingCascade(); - KrigingCascade(TVector > XX, - TVector > YY, - TString basis); - KrigingCascade(TVector variograms); + KrigingCascade(const TVector>& XX, + const TVector>& YY, TString basis); + KrigingCascade(const TVector& variograms); ~KrigingCascade(); TVector interpolate(TVector x); TVector errors(); - TVector interpolators(); - void append(Kriging* interpolator); + TVector interpolators(); + void append(OrdinaryKriging* interpolator); void clear(); void fitVariogram(); @@ -50,7 +46,7 @@ class LIGER_TIGON_EXPORT KrigingCascade int m_xDim; bool m_produceErrorEstimates; TVector m_errors; - TVector m_interpolators; + TVector m_interpolators; }; } // namespace Tigon diff --git a/src/libs/tigon/Utils/KrigingVariogram.cpp b/src/libs/tigon/Utils/Kriging/KrigingVariogram.cpp similarity index 90% rename from src/libs/tigon/Utils/KrigingVariogram.cpp rename to src/libs/tigon/Utils/Kriging/KrigingVariogram.cpp index c97e6ce..307e5b3 100644 --- a/src/libs/tigon/Utils/KrigingVariogram.cpp +++ b/src/libs/tigon/Utils/Kriging/KrigingVariogram.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,7 +13,7 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include +#include #include namespace Tigon { @@ -79,8 +79,8 @@ void KrigingVariogram::assignC(double val) } } -void KrigingVariogram::assignVariogramData(TVector > x, - TVector y) +void KrigingVariogram::assignVariogramData(const TVector>& x, + const TVector& y) { if((x.size() == 0) || (y.size() == 0)) { return; @@ -94,7 +94,8 @@ void KrigingVariogram::assignVariogramData(TVector > x, m_y = y; } -void KrigingVariogram::calculateEmpiricalVariogram(TCVectorReal dist, TCVectorReal Zx) +void KrigingVariogram::calculateEmpiricalVariogram(const TCVectorReal& dist, + const TCVectorReal& Zx) { // dist: || xi-xj ||_2 // Zx contains all realization of x's, i.e z(xi) @@ -143,8 +144,9 @@ void KrigingVariogram::calculateEmpiricalVariogram(TCVectorReal dist, TCVectorRe } } -void KrigingVariogram::calculateEmpiricalVariogram(TVector > x, - TVector y) +void KrigingVariogram::calculateEmpiricalVariogram( + const TVector>& x, + const TVector& y) { if(x.size() != y.size()) { return; @@ -157,7 +159,7 @@ void KrigingVariogram::calculateEmpiricalVariogram(TVector > x, for(int i=0; i KrigingVariogram::outputData() const return m_y; } -TCVectorReal KrigingVariogram::interiorPointSolver(TMatrixReal Q, TCVectorReal c, - TMatrixReal A, TCVectorReal b) +TCVectorReal KrigingVariogram::interiorPointSolver( + const TMatrixReal& Q, const TCVectorReal& c, + const TMatrixReal& A, const TCVectorReal& b) { // Interior point solver int64 m = A.rows(); diff --git a/src/libs/tigon/Utils/KrigingVariogram.h b/src/libs/tigon/Utils/Kriging/KrigingVariogram.h similarity index 76% rename from src/libs/tigon/Utils/KrigingVariogram.h rename to src/libs/tigon/Utils/Kriging/KrigingVariogram.h index 6bf11da..cba2d86 100644 --- a/src/libs/tigon/Utils/KrigingVariogram.h +++ b/src/libs/tigon/Utils/Kriging/KrigingVariogram.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -37,8 +37,10 @@ class LIGER_TIGON_EXPORT KrigingVariogram virtual double beta() const; /// Empirical variograms - void calculateEmpiricalVariogram(TCVectorReal dist, TCVectorReal Zx); - void calculateEmpiricalVariogram(TVector > x, TVector y); + void calculateEmpiricalVariogram(const TCVectorReal& dist, + const TCVectorReal& Zx); + void calculateEmpiricalVariogram(const TVector>& x, + const TVector& y); TCVectorReal empiricalVariograms() const; TCVectorReal empiricalLags() const; @@ -46,7 +48,8 @@ class LIGER_TIGON_EXPORT KrigingVariogram void assignAlpha(double val); void assignNugget(double val); void assignC(double val); - void assignVariogramData(TVector > x, TVector y); + void assignVariogramData(const TVector>& x, + const TVector& y); double alpha() const; double paramC() const; double nugget() const; @@ -56,8 +59,8 @@ class LIGER_TIGON_EXPORT KrigingVariogram TVector outputData() const; /// Utilities - TCVectorReal interiorPointSolver(TMatrixReal Q, TCVectorReal c, - TMatrixReal A, TCVectorReal b); + TCVectorReal interiorPointSolver(const TMatrixReal& Q, const TCVectorReal& c, + const TMatrixReal& A, const TCVectorReal& b); private: double m_alpha; double m_c0; diff --git a/src/libs/tigon/Utils/Kriging.cpp b/src/libs/tigon/Utils/Kriging/OrdinaryKriging.cpp similarity index 66% rename from src/libs/tigon/Utils/Kriging.cpp rename to src/libs/tigon/Utils/Kriging/OrdinaryKriging.cpp index 469a599..676bbce 100644 --- a/src/libs/tigon/Utils/Kriging.cpp +++ b/src/libs/tigon/Utils/Kriging/OrdinaryKriging.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,16 +13,14 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include +#include #include - namespace Tigon { -Kriging::Kriging() +OrdinaryKriging::OrdinaryKriging() { // Default constructor - m_estimateErrors = false; m_xDim = 0; m_N = 0; m_lastEstimate = 0; @@ -32,9 +30,8 @@ Kriging::Kriging() m_variogram = 0; } -Kriging::Kriging(KrigingVariogram* vargram, const TVector &err) +OrdinaryKriging::OrdinaryKriging(KrigingVariogram* vargram, const TVector &err) { - m_estimateErrors = false; m_xDim = 0; m_N = 0; m_lastEstimate = 0; @@ -46,14 +43,14 @@ Kriging::Kriging(KrigingVariogram* vargram, const TVector &err) assignVariogram(vargram, err); } -Kriging::~Kriging() +OrdinaryKriging::~OrdinaryKriging() { if(m_variogram) { delete m_variogram; } } -void Kriging::assignVariogram(KrigingVariogram* vargram, const TVector &err) +void OrdinaryKriging::assignVariogram(KrigingVariogram* vargram, const TVector &err) { if(m_variogram) { delete m_variogram; @@ -62,9 +59,10 @@ void Kriging::assignVariogram(KrigingVariogram* vargram, const TVector & configureKriging(err); } -double Kriging::interpolate(const TVector &xstar) { +double OrdinaryKriging::interpolate(const TVector &xstar) { for(int i = 0; i < m_N; i++) { - m_vStar(i) = m_variogram->value(l2dist(m_variogram->inputData()[i], xstar)); + double dist = l2dist(inputData()[i], xstar); + m_vStar(i) = m_variogram->value(dist); } m_vStar(m_N) = 1.0; @@ -72,24 +70,24 @@ double Kriging::interpolate(const TVector &xstar) { m_lastEstimate = 0.0; for (int i = 0; i < m_N; i++) { - m_lastEstimate += m_weight(i)*m_variogram->outputData()[i]; + m_lastEstimate += m_weight(i)*outputData()[i]; } - if(m_estimateErrors) { + if(estimateErrors()) { // Prediction error std m_predictionErrorEstimate = 0.0; for(int i = 0; i < m_N; i++) { m_predictionErrorEstimate += m_weight(i)*m_vStar(i); } - m_predictionErrorEstimate = std::sqrt(std::abs(m_predictionErrorEstimate)); + m_predictionErrorEstimate = std::sqrt(std::fabs(m_predictionErrorEstimate)); // Local error std m_localErrorEstimate = 0.0; for(int i = 0; i < m_N; i++) { m_localErrorEstimate += m_weight(i)*m_weight(i) - *(m_variogram->outputData()[i]-m_lastEstimate) - *(m_variogram->outputData()[i]-m_lastEstimate); + *(outputData()[i]-m_lastEstimate) + *(outputData()[i]-m_lastEstimate); } m_localErrorEstimate = std::sqrt(m_localErrorEstimate); @@ -104,41 +102,46 @@ double Kriging::interpolate(const TVector &xstar) { return m_lastEstimate; } -void Kriging::estimateErrors(bool est) -{ - m_estimateErrors = est; -} - -double Kriging::localErrorStd() +double OrdinaryKriging::localErrorStd() { return m_localErrorEstimate; } -double Kriging::krigingErrorStd() +double OrdinaryKriging::krigingErrorStd() { return m_krigingStdEstimate; } -double Kriging::combinedErrorStd() +double OrdinaryKriging::combinedErrorStd() { return std::sqrt(m_localErrorEstimate*m_krigingStdEstimate); } -double Kriging::errorEstimate() +double OrdinaryKriging::errorEstimate() { return combinedErrorStd(); } -KrigingVariogram* Kriging::variogram() const +TVector> OrdinaryKriging::inputData() const +{ + return m_variogram->inputData(); +} + +TVector OrdinaryKriging::outputData() const +{ + return m_variogram->outputData(); +} + +KrigingVariogram* OrdinaryKriging::variogram() const { return m_variogram; } -void Kriging::configureKriging(const TVector &err) +void OrdinaryKriging::configureKriging(const TVector &err) { - m_N = m_variogram->inputData().size(); - m_xDim = m_variogram->inputData()[0].size(); - m_estimateErrors = false; + m_N = inputData().size(); + m_xDim = inputData()[0].size(); + defineEstimateErrors(false); m_dStar.resize(m_N+1); m_vStar.resize(m_N+1); @@ -148,8 +151,8 @@ void Kriging::configureKriging(const TVector &err) for(int i = 0; i < m_N; i++) { for(int j = i; j < m_N; j++) { - m_V(i, j) = m_variogram->value(l2dist(m_variogram->inputData()[i], - m_variogram->inputData()[j])); + double dist = l2dist(inputData()[i], inputData()[j]); + m_V(i, j) = m_variogram->value(dist); m_V(j, i) = m_V(i, j); } m_V(i, m_N) = 1.0; diff --git a/src/libs/tigon/Utils/Kriging.h b/src/libs/tigon/Utils/Kriging/OrdinaryKriging.h similarity index 83% rename from src/libs/tigon/Utils/Kriging.h rename to src/libs/tigon/Utils/Kriging/OrdinaryKriging.h index a978da3..50ef293 100644 --- a/src/libs/tigon/Utils/Kriging.h +++ b/src/libs/tigon/Utils/Kriging/OrdinaryKriging.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -17,29 +17,25 @@ #define KRIGING_H #include #include -#include -DISABLE_WARNINGS #include -ENABLE_WARNINGS +#include +#include namespace Tigon { class KrigingVariogram; -class LIGER_TIGON_EXPORT Kriging +class LIGER_TIGON_EXPORT OrdinaryKriging : public IKriging { public: - Kriging(); - Kriging(KrigingVariogram* vargram, const TVector &err = TVector()); - ~Kriging(); + OrdinaryKriging(); + OrdinaryKriging(KrigingVariogram* vargram, const TVector &err = TVector()); + ~OrdinaryKriging(); /// Variogram and interpolation void assignVariogram(KrigingVariogram* vargram, const TVector &err = TVector()); KrigingVariogram* variogram() const; double interpolate(const TVector & xstar); - /// Error standard deviations - void estimateErrors(bool est); - // Square root of weighted average of the differences // between the estimate and data values, f(x*) and f(x_i), // capturing the local variation of the data values @@ -59,13 +55,15 @@ class LIGER_TIGON_EXPORT Kriging // By dafault, combined error std is returned. double errorEstimate(); + TVector > inputData() const; + TVector outputData() const; + private: void configureKriging(const TVector &err); int m_xDim; int m_N; - bool m_estimateErrors; double m_lastEstimate; double m_predictionErrorEstimate; double m_localErrorEstimate; diff --git a/src/libs/tigon/Utils/PowerVariogram.cpp b/src/libs/tigon/Utils/Kriging/PowerVariogram.cpp similarity index 89% rename from src/libs/tigon/Utils/PowerVariogram.cpp rename to src/libs/tigon/Utils/Kriging/PowerVariogram.cpp index 688810b..39bb2d9 100644 --- a/src/libs/tigon/Utils/PowerVariogram.cpp +++ b/src/libs/tigon/Utils/Kriging/PowerVariogram.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -13,12 +13,13 @@ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ****************************************************************************/ -#include +#include #include namespace Tigon { -PowerVariogram::PowerVariogram(TVector > x, TVector y) +PowerVariogram::PowerVariogram(const TVector>& x, + const TVector& y) : KrigingVariogram(0.0, 1.0, 1.0) { assignNugget(0.0); @@ -26,7 +27,8 @@ PowerVariogram::PowerVariogram(TVector > x, TVector y) fitVariogram(); } -PowerVariogram::PowerVariogram(TVector > x, TVector y, +PowerVariogram::PowerVariogram(const TVector>& x, + const TVector& y, double eta, double nug) : KrigingVariogram(0.0, 1.0, 1.0) { @@ -76,7 +78,7 @@ void PowerVariogram::fitVariogram() for(int i=0; i > x, TVector y) +void PowerVariogram::fitVariogramLS(const TVector>& x, + const TVector& y) { if(x.size() != y.size()) { return; @@ -178,7 +181,7 @@ void PowerVariogram::fitVariogramLS(TVector > x, TVector for(int i=0; i #include -#include +#include namespace Tigon { class LIGER_TIGON_EXPORT PowerVariogram : public KrigingVariogram { public: - PowerVariogram(TVector > x, TVector y); - PowerVariogram(TVector > x, TVector y, + PowerVariogram(const TVector>& x, const TVector& y); + PowerVariogram(const TVector>& x, const TVector& y, double eta, double nug=0.0); ~PowerVariogram(); double value(const double h) const; void fitVariogram(); - void fitVariogramLS(TVector > x, TVector y); + void fitVariogramLS(const TVector>& x, + const TVector& y); void assignEta(double val); double eta() const; diff --git a/src/libs/tigon/Utils/SphericalVariogram.cpp b/src/libs/tigon/Utils/Kriging/SphericalVariogram.cpp similarity index 91% rename from src/libs/tigon/Utils/SphericalVariogram.cpp rename to src/libs/tigon/Utils/Kriging/SphericalVariogram.cpp index c97dc4a..be6df0e 100644 --- a/src/libs/tigon/Utils/SphericalVariogram.cpp +++ b/src/libs/tigon/Utils/Kriging/SphericalVariogram.cpp @@ -1,9 +1,10 @@ -#include +#include namespace Tigon { -SphericalVariogram::SphericalVariogram(TVector > xx, TVector y, double nug) +SphericalVariogram::SphericalVariogram(const TVector>& xx, + const TVector& y, double nug) : KrigingVariogram(nug, 0, 1), m_lamda0(0.01), m_lamdaUp(11), @@ -88,7 +89,9 @@ SphericalVariogram::~SphericalVariogram() } -int SphericalVariogram::lsqLM(TCVectorReal& y_input, TCVectorReal& x_input, TCVectorReal& W, double& c, double& r) +int SphericalVariogram::lsqLM(const TCVectorReal& y_input, + const TCVectorReal& x_input, + const TCVectorReal& W, double& c, double& r) { rHistory.clear(); cHistory.clear(); @@ -168,7 +171,7 @@ int SphericalVariogram::lsqLM(TCVectorReal& y_input, TCVectorReal& x_input, TCVe wDist = dist.array() * W.array(); newError = dist.dot(wDist); - if(std::abs(error - newError) < m_tolerance) { + if(std::fabs(error - newError) < m_tolerance) { done++; } else { done = 0; } diff --git a/src/libs/tigon/Utils/SphericalVariogram.h b/src/libs/tigon/Utils/Kriging/SphericalVariogram.h similarity index 84% rename from src/libs/tigon/Utils/SphericalVariogram.h rename to src/libs/tigon/Utils/Kriging/SphericalVariogram.h index f1257ae..d643b71 100644 --- a/src/libs/tigon/Utils/SphericalVariogram.h +++ b/src/libs/tigon/Utils/Kriging/SphericalVariogram.h @@ -2,12 +2,8 @@ #define SPHERICALVARIOGRAM_H #include #include -#include - -DISABLE_WARNINGS +#include #include -ENABLE_WARNINGS - #include #include @@ -16,7 +12,8 @@ namespace Tigon { class LIGER_TIGON_EXPORT SphericalVariogram : public KrigingVariogram { public: - SphericalVariogram(TVector > xx, TVector y, double nug = 0); + SphericalVariogram(const TVector>& xx, + const TVector& y, double nug = 0); ~SphericalVariogram(); double value(const double h) const; @@ -46,7 +43,8 @@ class LIGER_TIGON_EXPORT SphericalVariogram : public KrigingVariogram private: double m_r; //Range value calculated from a and b. If a or b is negative r is complex. - int lsqLM(TCVectorReal& y_input, TCVectorReal& x_input, TCVectorReal& W, double &c, double &r); + int lsqLM(const TCVectorReal& y_input, const TCVectorReal& x_input, + const TCVectorReal& W, double &c, double &r); double variogramFunction(const double h, const double c, const double r) const; double dfunctiondc(const double h, const double r) const; double dfunctiondr(const double h, const double c, const double r) const; diff --git a/src/libs/tigon/Utils/NormalisationUtils.cpp b/src/libs/tigon/Utils/NormalisationUtils.cpp index b26acfd..504b774 100644 --- a/src/libs/tigon/Utils/NormalisationUtils.cpp +++ b/src/libs/tigon/Utils/NormalisationUtils.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -24,16 +24,17 @@ namespace Tigon { double magnitudeAndDirectionP(TVector& vec, double p) { double magnitude = 0.0; - for(int i=0; i < vec.size(); i++) { - magnitude += std::pow(vec[i], p); + for(auto v : vec) { + magnitude += std::pow(v, p); } + magnitude = std::pow(magnitude, 1.0 / p); if(magnitude == 0.0) { return magnitude; } - for(int i=0; i < vec.size(); i++) { + for(size_t i=0; i < vec.size(); i++) { vec[i] /= magnitude; } return magnitude; @@ -42,12 +43,13 @@ double magnitudeAndDirectionP(TVector& vec, double p) double magnitudeAndDirectionP(TVector& vec, double p) { double magnitude = 0.0; - for(int i=0; i < vec.size(); i++) { - magnitude += std::pow(vec[i]->value(), p); + for(auto v : vec) { + magnitude += std::pow(v->value(), p); } + magnitude = std::pow(magnitude, 1.0 / p); - for(int i=0; i < vec.size(); i++) { + for(size_t i=0; i < vec.size(); i++) { *vec[i] = *vec[i] / magnitude; } return magnitude; @@ -66,14 +68,14 @@ void toUnitVec(TVector& vec, double norm) void scale(TVector& vec, double factor) { - for(int i=0; i < vec.size(); i++) { + for(size_t i=0; i < vec.size(); i++) { vec[i] *= factor; } } void scale(TVector vec, double factor) { - for(int i=0; i < vec.size(); i++) { + for(size_t i=0; i < vec.size(); i++) { *vec[i] = *vec[i] * factor; } } @@ -108,7 +110,7 @@ void normaliseToUnitInterval(IElement& val, void normaliseToUnitBoxInMemory(TVector& vec, const TVector& lBounds, const TVector& uBounds) { - for(int i=0; i < vec.size(); i++) { + for(size_t i=0; i < vec.size(); i++) { if(vec[i] <= lBounds[i]) { vec[i] = 0.0; } else if(vec[i] >= uBounds[i]) { @@ -125,7 +127,7 @@ void normaliseToUnitBoxInMemory(TVector vec, TVector lBounds = IElementVecToRealVec(box->lowerBounds()); TVector uBounds = IElementVecToRealVec(box->upperBounds()); - for(int i=0; i < vec.size(); i++) { + for(size_t i=0; i < vec.size(); i++) { vec[i]->defineType(RealType); if(*vec[i] <= lBounds[i]) { vec[i]->defineValue(0.0); @@ -142,7 +144,7 @@ TVector normaliseToUnitBox(const TVector& vec, const TVector& uBounds) { TVector ret(vec.size()); - for(int i=0; i < vec.size(); i++) { + for(size_t i=0; i < vec.size(); i++) { if(vec[i] <= lBounds[i]) { ret[i] = 0.0; } else if(vec[i] >= uBounds[i]) { @@ -186,7 +188,7 @@ void scaleBackFromUnitBox(TVector& vec, const TVector& lBounds, /// \attention The normalisation of elements out-of-bounds is inconsistent. /// The CODEM problems seem to lead this situation. /// Further checks are needed here. - for(int i=0; i < vec.size(); i++) { + for(size_t i=0; i < vec.size(); i++) { if(vec[i] > 1.0) { //vec[i] = uBounds[i]; vec[i] = uBounds[i] - (1.0 - vec[i]) * (uBounds[i] - lBounds[i]); @@ -204,7 +206,7 @@ void scaleBackFromUnitBox(TVector vec, BoxConstraintsDataSPtr box) TVector lBounds = IElementVecToRealVec(box->lowerBounds()); TVector uBounds = IElementVecToRealVec(box->upperBounds()); - for(int i=0; i < vec.size(); i++) { + for(size_t i=0; i < vec.size(); i++) { if(*vec[i] >= 1.0) { vec[i]->defineValue(uBounds[i]); } else if(*vec[i] <= 0.0) { @@ -227,7 +229,7 @@ TVector normaliseForSimplexLattice(const TVector &vec, // components not set in the original vector are kept temporarily // in the normalised vector - for(int i=0; i m, TVector c, { double ret = -1.0; int nElems = m.size(); - if( (c.size() == nElems) && (box->size() == nElems) ) { + if( (c.size() == m.size()) && (box->size() == nElems) ) { TVector diff(nElems, 0.0); for(int i = 0; i < nElems; i++) { double interval = box->upperBound(i).value() - box->lowerBound(i).value(); @@ -272,7 +274,7 @@ double normalisedDistanceP(TVector m, TVector c, diff[i] = 1.0 / interval; } } else { - diff[i] = std::abs(m[i]->value() - c[i]->value()) / interval; + diff[i] = std::fabs(m[i]->value() - c[i]->value()) / interval; } } ret = magnitudeAndDirectionP(diff, p); @@ -285,11 +287,11 @@ double normalisedDistanceVecP(const TVector &m, const TVector &c { double ret = -1.0; int nElems = m.size(); - if( (c.size() == nElems) && (box->size() == nElems) ) { + if( (c.size() == m.size()) && (box->size() == nElems) ) { TVector diff(nElems, 0.0); for(int i = 0; i < nElems; i++) { double interval = box->upperBound(i).value() - box->lowerBound(i).value(); - diff[i] = std::abs(m[i] - c[i]) / interval; + diff[i] = std::fabs(m[i] - c[i]) / interval; } ret = magnitudeAndDirectionP(diff, p); } @@ -300,15 +302,17 @@ double normalisedDistanceVecP(const TVector &m, const TVector &c double directedBoxedIntervalLength(const TVector dir, double p) { double maxComponent = 0.0; - for(int i=0; i < dir.size(); i++) { - if(dir[i] > maxComponent) { - maxComponent = dir[i]; + for(auto d : dir) { + if(d > maxComponent) { + maxComponent = d; } } + double len = 0.0; - for(int i=0; i < dir.size(); i++) { - len += std::pow((dir[i] / maxComponent), p); + for(auto d : dir) { + len += std::pow((d / maxComponent), p); } + len = std::pow(len, 1.0 / p); return len; } diff --git a/src/libs/tigon/Utils/ScalarisingSpaceUtils.cpp b/src/libs/tigon/Utils/ScalarisingSpaceUtils.cpp index c6cd1d0..1c5326c 100644 --- a/src/libs/tigon/Utils/ScalarisingSpaceUtils.cpp +++ b/src/libs/tigon/Utils/ScalarisingSpaceUtils.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -16,6 +16,9 @@ #include #include #include +#include +#include +#include namespace Tigon { @@ -31,9 +34,11 @@ double scalarisingSpace(const TVector >& objectiveSet, TVector normObj; TVector cost(n); + double minCost = 0; double ret = 0; // Loop through all directions for(int nDir=0; nDir >& objectiveSet, TVector cost_real(n); TVector cost_inferred(n); + double minCost = 0; double ret = 0; // Loop through all directions for(int nDir=0; nDir >& objectiveSet, TVector cost_real(n); TVector cost_inferred(n); + double minCost = 0; double ret = 0; // Loop through all directions for(int nDir=0; nDir > >& objecti int nSampSize = objectiveSet[0][0].size(); double cost_real = 0; TVector cost_inferred(n); + double minCost = 0; double ret = 0; // Loop through all directions for(int nDir=0; nDir -#include + +using namespace Tigon::Representation; namespace Tigon { diff --git a/src/libs/tigon/Utils/TigonUtils.cpp b/src/libs/tigon/Utils/TigonUtils.cpp index 94c5ed1..98c5d60 100644 --- a/src/libs/tigon/Utils/TigonUtils.cpp +++ b/src/libs/tigon/Utils/TigonUtils.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -139,8 +139,8 @@ bool isGoalDefined(IElementSPtr goal) bool areDoublesEqual(double a, double b) { - double c = std::max(std::abs(a),std::abs(b)); - double relDif = (c==0.0) ? 0.0 : std::abs(a-b) / c; + double c = std::max(std::fabs(a),std::fabs(b)); + double relDif = (c==0.0) ? 0.0 : std::fabs(a-b) / c; return relDif < Epsilon; } diff --git a/src/libs/tigon/tigonconstants.h b/src/libs/tigon/tigonconstants.h index c83cfac..71acd3c 100644 --- a/src/libs/tigon/tigonconstants.h +++ b/src/libs/tigon/tigonconstants.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -166,6 +166,12 @@ enum ErrorHandlingMethod { ErrConfidenceIntervalBased }; +enum ConstraintHandlingMethod { + NoConstraintHandling, + PenaltyBased, + SurrogateBased +}; + enum ArchiveUpdateStatus { UnchangedArchive, AddedToArchive, @@ -188,7 +194,9 @@ enum ProblemDefinitionStatus { IllDefinedIdealVec, IllDefinedAntiIdealVec, IllDefinedNadirVec, + IllDefinedSetGoalVec, IllDefinedGoalVec, + IllDefinedPriorityVec, IllDefinedThresholdVec, IllDefinedUncertaintyVec, IllDefinedFuncOutUncertaintyVec, @@ -238,7 +246,6 @@ enum DominanceRelationType { PreferabilityConstraintHandlingRelation }; - /// IMapping constants const TVector EmptyType; const TVector > EmptyIOMap; @@ -322,6 +329,33 @@ const double AcK(0.5); const double AcK1(0.4); const double AcK2(0.8); +// ACROMUSE parameters for surrogate based optimization +// Parameters for high computationally intensive optimization search +// Search the surrogate +const int DefaultBudgetPerVariableSS_H(100); +const int DefaultInitialPopsizePerVariableSS_H(20); +const int DefaultStallIterationsSS_H(20); +// Train the surrogate +const int DefaultBudgetPerVariableTS_H(100); +const int DefaultInitialPopsizePerVariableTS_H(20); +const int DefaultStallIterationsTS_H(20); + +// Parameters for low computationally intensive optimization search +// Search the surrogate +const int DefaultBudgetPerVariableSS_L(40); +const int DefaultInitialPopsizePerVariableSS_L(5); +const int DefaultStallIterationsSS_L(3); +// Train the surrogate +const int DefaultBudgetPerVariableTS_L(40); +const int DefaultInitialPopsizePerVariableTS_L(5); +const int DefaultStallIterationsTS_L(3); + + +// Normal Mutation +const double DefaultMutationSigma(-1.0); +const double DefaultWidthPercent(0.1); +const double DefaultMutationStepSize(-1.0); + // NSGA-II const double DefaultCrossoverDistributionIndex(15.0); const double DefaultMutationDistributionIndex(20.0); @@ -336,19 +370,22 @@ const int DefaultMaxNumberReplacements(2); const double DefaultReplacementProbability(0.1); // ParEGO +const int DefaultMaxSolutionsSurrogateModelling(100); + +// sParEGO const double UseDefaultNeighbourhoodRadius(-1.0); -const double KDEBandwithRatio(0.1); +const double KDEBandwidthRatio(0.1); const double PerturbationRadiusByNeighbourhoodRadius(0.5); const double DefaultNeighbourhoodRadius(0.1); -const TString SampleSizes("Sample sizes"); //multipack key - -// sParEGO const double DefaultsParEGOInitPerturbationRatio(0.5); +const TString SampleSizes("Sample sizes"); //multipack key // MOGA const double DefaultErrorSigmaEstimation(1e-6); const double DefaultSharingFunctionAlpha(1.0); +// InterwovenSystemHandler +const int DefaultNumberPointsForKDE(100); enum ConfidenceInSampleType { UnchangedDistribution, @@ -371,6 +408,7 @@ const double GenericRobustnessParameter(0.0); /// Exception Constants const TString DivisionByZeroException("Division by zero."); +const TString IncorrectNumberArguments("Incorrect number of arguments."); const TString IncorrectProblemFormatException("Incorrect problem format."); const TString RangeException("Range errors in internal computation."); const TString DomainException("Parameter outside the valid range."); diff --git a/tests/auto/test_tigon/test_sparego/tst_sparego.cpp b/tests/auto/test_tigon/test_sparego/tst_sparego.cpp index cb2f621..221d5b9 100644 --- a/tests/auto/test_tigon/test_sparego/tst_sparego.cpp +++ b/tests/auto/test_tigon/test_sparego/tst_sparego.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -42,8 +42,6 @@ private slots: void test_UncertainRobustness(); void test_DirectionFiltration(); void test_FitnessBasedInit(); - void test_ExpectedImprovement(); - void test_RandExpectedImprovement(); void test_SurrogateBasedOptimizer(); void test_sParEGO_workflow(); void test_sParEGO(); @@ -229,7 +227,7 @@ void tst_sparego::test_SparegoInit() PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); - SparegoInit* init = new SparegoInit(prob); + sParEGOInit* init = new sParEGOInit(prob); NeighbourhoodFiltration* nFilt = new NeighbourhoodFiltration(init); init->addOutputTag(Tigon::TForNeighbourhoods); @@ -390,7 +388,7 @@ void tst_sparego::test_SparegoValidation() PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); - SparegoInit* init = new SparegoInit(prob); + sParEGOInit* init = new sParEGOInit(prob); Evaluator* eval = new Evaluator(init); SimplexLatticeDirectionIterator* dirs = new SimplexLatticeDirectionIterator(eval); @@ -493,7 +491,7 @@ void tst_sparego::test_UncertainRobustness() PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); - SparegoInit* init = new SparegoInit(prob); + sParEGOInit* init = new sParEGOInit(prob); Evaluator* eval = new Evaluator(init); SimplexLatticeDirectionIterator* dirs = new SimplexLatticeDirectionIterator(eval); @@ -641,7 +639,7 @@ void tst_sparego::test_DirectionFiltration() PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); - SparegoInit* init = new SparegoInit(prob); + sParEGOInit* init = new sParEGOInit(prob); Evaluator* eval = new Evaluator(init); SimplexLatticeDirectionIterator* dirs = @@ -697,7 +695,7 @@ void tst_sparego::test_FitnessBasedInit() PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); - SparegoInit* init = new SparegoInit(prob); + sParEGOInit* init = new sParEGOInit(prob); Evaluator* eval = new Evaluator(init); SimplexLatticeDirectionIterator* dirs = new SimplexLatticeDirectionIterator(eval); @@ -746,241 +744,6 @@ void tst_sparego::test_FitnessBasedInit() delete base; } -void tst_sparego::test_ExpectedImprovement() -{ - // Use one IPSet to evaluate a set of solutions on a single objective - // problem - PSetBase* base = new PSetBase(); - IFormulation* prob = new IFormulation(base); - UserDefinedInit* init = new UserDefinedInit(prob); - Evaluator* eval = new Evaluator(init); - eval->TP_defineSingleObjective(true); - - - IFunctionSPtr func = IFunctionSPtr(new Alpine2); - func->TP_defineNInputs(1); - prob->appendFunction(func); - prob->evaluate(); - - ISet* evaluatedPoints = new ISet; - for(double i=0.0; i<=10.0; i+=2.3) { - IMappingSPtr imap = prob->createOptimizationMapping(evaluatedPoints); - imap->defineDecisionVar(0, IElement(i)); - } - for(double i=0.6; i<10.0; i*=2) { - IMappingSPtr imap = prob->createOptimizationMapping(evaluatedPoints); - imap->defineDecisionVar(0, IElement(i)); - } - init->defineInitialSet(evaluatedPoints); - - eval->evaluate(); - - // Fit a Kriging model to the evaluated pionts - ISet* eSet = init->outputSet(0); - TVector > xx; - TVector yy; - for(int i=0; isize(); i++) { - // decision vector - xx.push_back(eSet->at(i)->doubleDecisionVec()); - // function value - yy.push_back(eSet->at(i)->doubleCost()); - } - - PowerVariogram* powerV = new PowerVariogram(xx, yy, 1.999); - KrigingSPtr km = KrigingSPtr(new Kriging(powerV)); - km->estimateErrors(true); - - /// Use a new IPSet to evaluate a dense set of solutions on the Kriging - /// model and to evaluate its expected improvement - - // Create IFunctions from the Kriging model - IFunctionSPtr func2 = IFunctionSPtr(new KrigingSurrogate(km)); - IFunctionSPtr func3 = IFunctionSPtr(new ExpectedImprovement(km)); - - // Kriging model results - PSetBase* base2 = new PSetBase(); - IFormulation* prob2 = new IFormulation(base2); - UserDefinedInit* init2 = new UserDefinedInit(prob2); - Evaluator* eval2 = new Evaluator(init2); - - prob2->appendFunction(func2); - prob2->appendFunction(func3); - - prob2->evaluate(); - - // Create query points - TVector xq; - ISet* queryPoints = new ISet; - - for(double x=0.0; x<=10.0; x += 0.01) { - xq.push_back(x); - IMappingSPtr imap = prob2->createOptimizationMapping(queryPoints); - imap->defineDecisionVar(0, IElement(x)); - } - - init2->defineInitialSet(queryPoints); - - eval2->evaluate(); - - - delete eval2; - delete init2; - delete prob2; - delete base2; - delete eval; - delete init; - delete prob; - delete base; -} - -void tst_sparego::test_RandExpectedImprovement() -{ - // Use one IPSet to evaluate a set of solutions on a single objective - // problem - PSetBase* base = new PSetBase(); - IFormulation* prob = new IFormulation(base); - UserDefinedInit* init = new UserDefinedInit(prob); - Evaluator* eval = new Evaluator(init); - eval->TP_defineSingleObjective(true); - - IFunctionSPtr func = IFunctionSPtr(new Alpine2); - func->TP_defineNInputs(1); - prob->appendFunction(func); - prob->evaluate(); - - ISet* evaluatedPoints = new ISet; - TVector tVec(1, RealType); - for(double i=0.0; i<=10.0; i+=2.3) { - IMappingSPtr imap = prob->createOptimizationMapping(evaluatedPoints); - imap->defineDecisionVar(0, IElement(i)); - } - for(double i=0.6; i<10.0; i*=2) { - IMappingSPtr imap = prob->createOptimizationMapping(evaluatedPoints); - imap->defineDecisionVar(0, IElement(i)); - } - init->defineInitialSet(evaluatedPoints); - - eval->evaluate(); - - // Fit a Kriging model to the evaluated pionts - ISet* eSet = init->outputSet(0); - TVector > xx; - TVector yy; - for(int i=0; isize(); i++) { - // decision vector - xx.push_back(eSet->at(i)->doubleDecisionVec()); - // function value - yy.push_back(eSet->at(i)->doubleCost()); - } - - PowerVariogram* powerV = new PowerVariogram(xx, yy, 1.999); - KrigingSPtr km = KrigingSPtr(new Kriging(powerV)); - km->estimateErrors(true); - - /// Use a new IPSet to evaluate a dense set of solutions on the Kriging - /// model and to evaluate its expected improvement - - // Create query points - TVector xq; - ISet* queryPoints = new ISet; - - for(double x=0.0; x<=10.0; x += 0.01) { - xq.push_back(x); - IMappingSPtr imap = prob->createOptimizationMapping(queryPoints); - imap->defineDecisionVar(0, IElement(x)); - } - - // Create an IFunction from the Kriging model - IFunctionSPtr func2 = IFunctionSPtr(new RandExpectedImprovement(km)); - // ((RandExpectedImprovement*)func2.get())->TP_defineBandwith( - // ((RandExpectedImprovement*)func2.get())->TP_bandwith() / 10.0); - - // Expected improvement results - PSetBase* base2 = new PSetBase(); - IFormulation* prob2 = new IFormulation(base2); - UserDefinedInit* init2 = new UserDefinedInit(prob2); - Evaluator* eval2 = new Evaluator(init2); - eval2->TP_defineSingleObjective(true); - - prob2->appendFunction(func2); - init2->defineInitialSet(queryPoints); - - eval2->evaluate(); - - // write the results to an .m file: - QFile file("tst_randExpectedImprovement.m"); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - return; - } - QTextStream out(&file); - ISet* expImp = init2->outputSet(0); - - out << "figure(4)\n" - "clc;clear;clf;\n\n" - - "x = (0:0.01:10)';\n" - "y = -sqrt(x).*sin(x);\n" << endl; - - out << "% Evaluated points:" << endl << "xx = ["; - for(int i=0; i - value(queryPoints->at(i)->decisionVec()); - out << yq << "; "; - } - out << "];" << endl << "err = ["; - for(int i=0; i - error(queryPoints->at(i)->decisionVec()); - - out << err << "; "; - } - out << "];" << endl << endl; - - out << "% Expected improvement:" << endl << "expImp = ["; - for(int i=0; iat(i)->doubleCost(); - out << -ei << "; "; - } - out << "];" << endl; - - out << "% Plot the results\n" - "realFunc = plot(x,y,'b'); hold on;\n" - "TigonReal = plot(xx,yy,'ok','MarkerFaceColor','k');\n" - "Model = plot(xq, yq, '--r', 'lineWidth', 2);\n" - "Error = plot(xq, err, 'r');\n" - "ExpectedImprovement = plot(xq, expImp*5, '-.g');\n\n" - "legend([realFunc, TigonReal, Model, Error, ExpectedImprovement],...\n" - "'Real function', 'Sample points', ...\n" - "'Kriging estimation', 'Estimation error', " - "'Expected improvement *5',...\n" - "'location', 'northWest');\n" - "grid on;\n" - "title('Kernel density-based error');" << endl; - - delete eval2; - delete init2; - delete prob2; - delete base2; - delete eval; - delete init; - delete prob; - delete base; -} - void tst_sparego::test_SurrogateBasedOptimizer() { TRAND.defineSeed(0); @@ -995,7 +758,7 @@ void tst_sparego::test_SurrogateBasedOptimizer() PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); - SparegoInit* init = new SparegoInit(prob); + sParEGOInit* init = new sParEGOInit(prob); Evaluator* eval = new Evaluator(init); SimplexLatticeDirectionIterator* dirs = new SimplexLatticeDirectionIterator(eval); @@ -1021,6 +784,7 @@ void tst_sparego::test_SurrogateBasedOptimizer() val->TP_defineNeighbourhoodRadius(nRaduis); opt->TP_defineNeighbourhoodRadius(nRaduis); + opt->TP_defineOptimizationSearchQuality(0); iVal->defineIndicator(ConfidenceType, 0.9); @@ -1054,7 +818,7 @@ void tst_sparego::test_sParEGO_workflow() PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); - SparegoInit* init = new SparegoInit(prob); + sParEGOInit* init = new sParEGOInit(prob); Evaluator* eval = new Evaluator(init); SimplexLatticeDirectionIterator* dirs = new SimplexLatticeDirectionIterator(eval); @@ -1081,7 +845,9 @@ void tst_sparego::test_sParEGO_workflow() val->TP_defineNeighbourhoodRadius(nRaduis); eval->defineBudget(budget); + opt->TP_defineErrorMethod(Tigon::ErrConfidenceIntervalBased); opt->TP_defineNeighbourhoodRadius(nRaduis); + opt->TP_defineOptimizationSearchQuality(0); iVal->defineIndicator(ConfidenceType, 0.9); @@ -1116,10 +882,11 @@ void tst_sparego::test_sParEGO() double nRaduis = 0.2; int budget = 14; int maxSurrogateSize = 30; + int stallIterations = 10; PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); - SparegoInit* init = new SparegoInit(prob); + sParEGOInit* init = new sParEGOInit(prob); Evaluator* eval = new Evaluator(init); sParEGO* alg = new sParEGO(eval); @@ -1139,6 +906,15 @@ void tst_sparego::test_sParEGO() alg->defineBudget(budget); + alg->TP_defineErrorMethod(Tigon::ErrConfidenceIntervalBased); + + // The following change in the default settings makes ACROMUSE run faster, + // but it is only intended for this test to pass without Qt timeout. + alg->defineStallIterationsSS(10); // default 20 + alg->defineBudgetPerVariableTS(40); // default 100 + alg->defineInitialPopsizePerVariableTS(5); // default 20 + alg->defineStallIterationsTS(3); // default 20 + while(alg->remainingBudget() > 0) { alg->evaluate(); alg->incrementIteration(); @@ -1162,11 +938,12 @@ void tst_sparego::test_LogDirectionVector() // the maximum distance for neighbourhood is 0.2*sqrt(8) ~= 0.56569 double nRaduis = 0.2; int maxSurrogateSize = 10; + int stallIterations = 10; /// sParEGO optimization workflow PSetBase* base = new PSetBase(); IFormulation* form = new IFormulation(base); - SparegoInit* init = new SparegoInit(form); + sParEGOInit* init = new sParEGOInit(form); Evaluator* eval = new Evaluator(init); sParEGO* alg = new sParEGO(eval); @@ -1182,6 +959,12 @@ void tst_sparego::test_LogDirectionVector() alg->defineIndicator(ConfidenceType, 0.9); alg->defineBudget(budget); + // The following change in the default settings makes ACROMUSE run faster, + // but it is only intended for this test to pass without Qt timeout. + alg->defineStallIterationsSS(10); // default 20 + alg->defineBudgetPerVariableTS(40); // default 100 + alg->defineInitialPopsizePerVariableTS(5); // default 20 + alg->defineStallIterationsTS(3); // default 20 while(alg->remainingBudget() > 0) { alg->evaluate(); @@ -1231,6 +1014,7 @@ void tst_sparego::test_sParEGOWithMonteCarloValidation() int nIter = 2; int maxSurrogateSize = 100; double confidenceLevel = 0.9; + int stallIterations = 10; int budget = 0; for(int i=1; i<=(nDirs*nIter); i++) { @@ -1246,7 +1030,7 @@ void tst_sparego::test_sParEGOWithMonteCarloValidation() /// create the workflow PSetBase* base = new PSetBase(); IFormulation* form = new IFormulation(base); - SparegoInit* init = new SparegoInit(form); + sParEGOInit* init = new sParEGOInit(form); SimplexLatticeDirectionIterator* dirs = new SimplexLatticeDirectionIterator(init); @@ -1277,7 +1061,8 @@ void tst_sparego::test_sParEGOWithMonteCarloValidation() opt->defineBudget(budget); opt->TP_defineNeighbourhoodRadius(nRaduis); - opt->TP_defineErrorMethod(Tigon::ErrDensityBased); + opt->TP_defineErrorMethod(Tigon::ErrConfidenceIntervalBased); + opt->TP_defineOptimizationSearchQuality(0); iVal->defineIndicator(ConfidenceType, confidenceLevel); From 09f4e1f26255ab870d30f74a734804e7db4704d1 Mon Sep 17 00:00:00 2001 From: "Joao A. Duro" Date: Thu, 31 Dec 2020 19:02:39 +0000 Subject: [PATCH 2/7] Address problems --- src/libs/tigon/Core/TObject.h | 2 +- .../MOEADNeighbourhoodUpdate.cpp | 4 +- .../Operators/Convergence/IConvergence.cpp | 2 +- .../Convergence/RandomHypervolume.cpp | 6 +- .../Convergence/RobustScalarisingSpace.cpp | 8 +- .../Convergence/ScalarisingSpace.cpp | 2 +- .../ValidationWithScalarisation.cpp | 2 +- .../Filtrations/FiltrationForDirection.cpp | 4 +- .../MultiMemberTournamentForDirection.cpp | 12 +- .../MultiMemberTournamentForPerturbation.cpp | 4 +- .../Filtrations/RandSetReplacement.cpp | 4 +- .../Filtrations/RouletteWheelSelection.cpp | 2 +- .../Operators/Filtrations/TruncateSets.cpp | 2 +- .../ProblemGenerator/ProblemGenerator.cpp | 40 +- .../Initialisation/UserDefinedInit.cpp | 6 +- .../Initialisation/WeightVectorInit.cpp | 2 +- .../Perturbations/BoundedPerturbation.cpp | 2 +- .../Representation/Mappings/IMapping.cpp | 2 +- .../tigon/Representation/Problems/Problem.cpp | 165 +++++++-- .../tigon/Representation/Problems/Problem.h | 78 ++-- src/libs/tigon/Tigon.h | 33 +- .../Utils/Dominance/ConstrDomRelation.cpp | 40 +- .../tigon/Utils/Dominance/ConstrDomRelation.h | 22 +- .../Utils/Dominance/DominanceRelation.cpp | 35 +- .../tigon/Utils/Dominance/DominanceRelation.h | 22 +- .../Utils/Dominance/IOrderedRelation.cpp | 37 -- .../tigon/Utils/Dominance/IOrderedRelation.h | 40 -- .../tigon/Utils/Dominance/Preferability.cpp | 179 +++++++-- .../tigon/Utils/Dominance/Preferability.h | 32 +- .../PreferabilityConstraintHandling.cpp | 80 +--- .../PreferabilityConstraintHandling.h | 25 +- src/libs/tigon/tigon.pro | 81 +++-- src/libs/tigon/tigon_global.h | 10 +- .../initialisations/qopsparegoinitnode.cpp | 6 +- .../test_interpolators/tst_interpolators.cpp | 342 ++++++++++++++++-- .../test_tigon/test_parego/tst_parego.cpp | 6 - .../manual_parego/manual_parego.cpp | 2 - 37 files changed, 892 insertions(+), 449 deletions(-) delete mode 100644 src/libs/tigon/Utils/Dominance/IOrderedRelation.cpp delete mode 100644 src/libs/tigon/Utils/Dominance/IOrderedRelation.h diff --git a/src/libs/tigon/Core/TObject.h b/src/libs/tigon/Core/TObject.h index c04543f..41fa637 100644 --- a/src/libs/tigon/Core/TObject.h +++ b/src/libs/tigon/Core/TObject.h @@ -24,7 +24,7 @@ namespace Tigon { typedef std::size_t TTypeHash; typedef TTuple TPropertyInfo; -#define getType(t) typeid(t).hash_code() +#define getTType(t) typeid(t).hash_code() namespace Constants { const TString TypeConversionFailure("Cannot convert string to required type"); diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/MOEADNeighbourhoodUpdate.cpp b/src/libs/tigon/Operators/AlgorithmSpecific/MOEADNeighbourhoodUpdate.cpp index 4a9c09e..6b255c1 100644 --- a/src/libs/tigon/Operators/AlgorithmSpecific/MOEADNeighbourhoodUpdate.cpp +++ b/src/libs/tigon/Operators/AlgorithmSpecific/MOEADNeighbourhoodUpdate.cpp @@ -69,14 +69,14 @@ void MOEADNeighbourhoodUpdate::initialise() TString("Defines the maximum number of solutions that can be " "replaced by the same child solution.\n" "The default is 2") - , getType(int)); + , getTType(int)); addProperty("IsGeneralisedDecomposition" , TString("Flag that indicates if the weight vectors follow the" " principles of generalised decomposition or if the" " original weight vectors are to be used instead.\n" "The default is false\n") - ,getType(bool)); + ,getTType(bool)); TP_defineScalarisingFunction(Tigon::DefaultScalarisationFunction); TP_defineMaxNumberReplacements(Tigon::DefaultMaxNumberReplacements); diff --git a/src/libs/tigon/Operators/Convergence/IConvergence.cpp b/src/libs/tigon/Operators/Convergence/IConvergence.cpp index d5d530e..cbbb454 100644 --- a/src/libs/tigon/Operators/Convergence/IConvergence.cpp +++ b/src/libs/tigon/Operators/Convergence/IConvergence.cpp @@ -57,7 +57,7 @@ void IConvergence::initialise() , TString("Disable the operator during the optimization " "process, and only operates after the " "termination criteria are satisfied.") - , getType(bool)); + , getTType(bool)); addInputTag(Tigon::TForConvergence); TP_defineOperateOnFinal(false); diff --git a/src/libs/tigon/Operators/Convergence/RandomHypervolume.cpp b/src/libs/tigon/Operators/Convergence/RandomHypervolume.cpp index 6343d02..6311ad9 100644 --- a/src/libs/tigon/Operators/Convergence/RandomHypervolume.cpp +++ b/src/libs/tigon/Operators/Convergence/RandomHypervolume.cpp @@ -53,11 +53,11 @@ void RandomHypervolume::initialise() "quantify the the random hypervolume " "measure.\n" "Default is confidence indicator.") - , getType(TString)); + , getTType(TString)); addProperty("IndicatorParameter" , TString("Default is 95% (for the confidence " "indicator type).") - , getType(double)); + , getTType(double)); addProperty("NSamples" , TString("Number of samples from each random " "objective vector.\nIf the objectives " @@ -69,7 +69,7 @@ void RandomHypervolume::initialise() "must be a positive integer.\nDefault " "is ") + std::to_string(DefaultMonteCarloSample) - , getType(int)); + , getTType(int)); m_isDefinedRef = false; m_factory = &RobustnessIndicatorFactory::instance(); diff --git a/src/libs/tigon/Operators/Convergence/RobustScalarisingSpace.cpp b/src/libs/tigon/Operators/Convergence/RobustScalarisingSpace.cpp index f0feeb5..d9ecca0 100644 --- a/src/libs/tigon/Operators/Convergence/RobustScalarisingSpace.cpp +++ b/src/libs/tigon/Operators/Convergence/RobustScalarisingSpace.cpp @@ -14,13 +14,15 @@ ** ****************************************************************************/ #include +#include +#include #include #include #include #include #include #include -#include +#include namespace Tigon { namespace Operators { @@ -46,13 +48,13 @@ void RobustScalarisingSpace::initialise() addProperty("neighbourhoodRadius" , TString("Maximum Euclidean distance in normalised decision " "space for two solutions to be considered as neighbours") - , getType(double)); + , getTType(double)); addProperty("ReferenceSetSize", TString("The size of the reference set.\n" "When a certain size is requested,\n" "the actual size is equal or larger. Default is 1."), - getType(int)); + getTType(int)); TP_defineNeighbourhoodRadius(Tigon::DefaultNeighbourhoodRadius); TP_defineReferenceSetSizeRobustScalarisingSpace(1); diff --git a/src/libs/tigon/Operators/Convergence/ScalarisingSpace.cpp b/src/libs/tigon/Operators/Convergence/ScalarisingSpace.cpp index 05b97bc..60276d4 100644 --- a/src/libs/tigon/Operators/Convergence/ScalarisingSpace.cpp +++ b/src/libs/tigon/Operators/Convergence/ScalarisingSpace.cpp @@ -46,7 +46,7 @@ void ScalarisingSpace::initialise() TString("The size of the reference set.\n" "When a certain size is requested,\n" "the actual size is equal or larger. Default is 1."), - getType(int)); + getTType(int)); TP_defineReferenceSetSizeScalarisingSpace(1); } diff --git a/src/libs/tigon/Operators/Evaluators/ValidationWithScalarisation.cpp b/src/libs/tigon/Operators/Evaluators/ValidationWithScalarisation.cpp index fbcdc64..816f92d 100644 --- a/src/libs/tigon/Operators/Evaluators/ValidationWithScalarisation.cpp +++ b/src/libs/tigon/Operators/Evaluators/ValidationWithScalarisation.cpp @@ -326,7 +326,7 @@ void ValidationWithScalarisation::initialise() " principles of generalised decomposition or if the" " original weight vectors are to be used instead.\n" "The default is false\n") - ,getType(bool)); + ,getTType(bool)); TP_defineIsGeneralisedDecomposition(true); TP_defineScalarisingFunction(Tigon::DefaultScalarisationFunction); diff --git a/src/libs/tigon/Operators/Filtrations/FiltrationForDirection.cpp b/src/libs/tigon/Operators/Filtrations/FiltrationForDirection.cpp index c010be5..5077c92 100644 --- a/src/libs/tigon/Operators/Filtrations/FiltrationForDirection.cpp +++ b/src/libs/tigon/Operators/Filtrations/FiltrationForDirection.cpp @@ -50,12 +50,12 @@ void FiltrationForDirection::initialise() addProperty("InputSetSize" , TString("Number of solutions to select for each sub-set. Default is 2") - , getType(int)); + , getTType(int)); addProperty("OutputSetSize" , TString("Maximum number of new solutions created by the direction operator " "from each input set. " "Default is 0") - , getType(int)); + , getTType(int)); addInputTag(Tigon::TForSelection); addOutputTag(Tigon::TForDirection); diff --git a/src/libs/tigon/Operators/Filtrations/MultiMemberTournamentForDirection.cpp b/src/libs/tigon/Operators/Filtrations/MultiMemberTournamentForDirection.cpp index 435d3eb..7449b61 100644 --- a/src/libs/tigon/Operators/Filtrations/MultiMemberTournamentForDirection.cpp +++ b/src/libs/tigon/Operators/Filtrations/MultiMemberTournamentForDirection.cpp @@ -34,15 +34,15 @@ MultiMemberTournamentForDirection::MultiMemberTournamentForDirection() , TString("Number of new solution created by the " "operator divided by the number of solutions " "in the input set. Default is 0.5") - , getType(double)); + , getTType(double)); addProperty("OutputSetSize" , TString("Number of solutions to select for each " "sub-set. Default is 2.") - , getType(int)); + , getTType(int)); addProperty("TournamentSize" , TString("Number of participants in each tournament.\n" "Default is 2.") - , getType(int)); + , getTType(int)); m_name = TString("Multi-member tournament selection for direction"); m_description = TString("Randomly chooses n solutions from the input set, " @@ -68,15 +68,15 @@ MultiMemberTournamentForDirection(Tigon::Representation::IPSet* ipset) , TString("Number of new solution created by the " "operator divided by the number of solutions " "in the input set. Default is 0.5") - , getType(double)); + , getTType(double)); addProperty("OutputSetSize" , TString("Number of solutions to select for each " "sub-set. Default is 2.") - , getType(int)); + , getTType(int)); addProperty("TournamentSize" , TString("Number of participants in each tournament.\n" "Default is 2.") - , getType(int)); + , getTType(int)); m_name = TString("Multi-member tournament selection for direction"); m_description = TString("Randomly chooses n solutions from the input set, " diff --git a/src/libs/tigon/Operators/Filtrations/MultiMemberTournamentForPerturbation.cpp b/src/libs/tigon/Operators/Filtrations/MultiMemberTournamentForPerturbation.cpp index 79db8e9..3f58545 100644 --- a/src/libs/tigon/Operators/Filtrations/MultiMemberTournamentForPerturbation.cpp +++ b/src/libs/tigon/Operators/Filtrations/MultiMemberTournamentForPerturbation.cpp @@ -96,11 +96,11 @@ void MultiMemberTournamentForPerturbation::initialise() , TString("Number of new solution created by the " "operator divided by the number of solutions " "in the input set. Default is 0.5") - , getType(double)); + , getTType(double)); addProperty("TournamentSize" , TString("Number of participants in each tournament. Default is 2.") - , getType(int)); + , getTType(int)); m_name = TString("Multi-member tournament selection for perturbation"); m_description = TString("Randomly chooses n solutions from the input set, " diff --git a/src/libs/tigon/Operators/Filtrations/RandSetReplacement.cpp b/src/libs/tigon/Operators/Filtrations/RandSetReplacement.cpp index b9291b7..77dbe10 100644 --- a/src/libs/tigon/Operators/Filtrations/RandSetReplacement.cpp +++ b/src/libs/tigon/Operators/Filtrations/RandSetReplacement.cpp @@ -53,12 +53,12 @@ void RandSetReplacement::initialise() addProperty("ReplacementProbability" , TString("Specifies the probability associated with" "each replacement operation. Default is 10%") - , getType(double)); + , getTType(double)); addProperty("ReplacementSetTags" , TString("Specifies the Sets with a given tag that are to replace some input sets\n" "The default is TMainOptimizationSet.") - , getType(TString)); + , getTType(TString)); defineReplacementProbability(Tigon::DefaultReplacementProbability); defineReplacementSetTags(TStringList({Tigon::TMainOptimizationSet})); diff --git a/src/libs/tigon/Operators/Filtrations/RouletteWheelSelection.cpp b/src/libs/tigon/Operators/Filtrations/RouletteWheelSelection.cpp index 9b0a754..6cdda03 100644 --- a/src/libs/tigon/Operators/Filtrations/RouletteWheelSelection.cpp +++ b/src/libs/tigon/Operators/Filtrations/RouletteWheelSelection.cpp @@ -108,7 +108,7 @@ void RouletteWheelSelection::initialise() , TString("Number of solutions in the output set.\n" "Default is -1, meaning that the size of the output " "set is set to be equal to the size of the input set.") - , getType(int)); + , getTType(int)); m_outputSetSize = -1; diff --git a/src/libs/tigon/Operators/Filtrations/TruncateSets.cpp b/src/libs/tigon/Operators/Filtrations/TruncateSets.cpp index c7108a8..f820440 100644 --- a/src/libs/tigon/Operators/Filtrations/TruncateSets.cpp +++ b/src/libs/tigon/Operators/Filtrations/TruncateSets.cpp @@ -46,7 +46,7 @@ void TruncateSets::initialise() addProperty("SetSize" , TString("Specifies the size of the output set.") - , getType(int)); + , getTType(int)); addOutputTag(Tigon::TForResize); diff --git a/src/libs/tigon/Operators/Formulations/ProblemGenerator/ProblemGenerator.cpp b/src/libs/tigon/Operators/Formulations/ProblemGenerator/ProblemGenerator.cpp index 725ecab..416c0a5 100644 --- a/src/libs/tigon/Operators/Formulations/ProblemGenerator/ProblemGenerator.cpp +++ b/src/libs/tigon/Operators/Formulations/ProblemGenerator/ProblemGenerator.cpp @@ -107,27 +107,27 @@ IFunctionSPtr ProblemGenerator::createFunctionByName(const TString &className, */ void ProblemGenerator::initialise() { - addProperty("funcTypes", "Function Types", getType(TString)); - addProperty("funcPathes", "Function Pathes", getType(TString)); - addProperty("funcPrpts", "Function Properties", getType(TString)); - addProperty("iprts", "iprts", getType(TString)); - addProperty("oprts", "oprts", getType(TString)); - addProperty("lbounds", "lbounds", getType(TString)); - addProperty("ubounds", "ubounds", getType(TString)); - addProperty("paramValueVec", "paramValueVec", getType(TString)); - addProperty("externalParam", "externalParam", getType(TString)); - addProperty("externalParamGroups", "externalParamGroups", getType(TString)); + addProperty("funcTypes", "Function Types", getTType(TString)); + addProperty("funcPathes", "Function Pathes", getTType(TString)); + addProperty("funcPrpts", "Function Properties", getTType(TString)); + addProperty("iprts", "iprts", getTType(TString)); + addProperty("oprts", "oprts", getTType(TString)); + addProperty("lbounds", "lbounds", getTType(TString)); + addProperty("ubounds", "ubounds", getTType(TString)); + addProperty("paramValueVec", "paramValueVec", getTType(TString)); + addProperty("externalParam", "externalParam", getTType(TString)); + addProperty("externalParamGroups", "externalParamGroups", getTType(TString)); addProperty("externalParamGroupDataPathes", "externalParamGroupDataPathes", - getType(TString)); - addProperty("goals", "goals", getType(TString)); - addProperty("thresholds", "thresholds", getType(TString)); - addProperty("dVecUncertainties", "dVecUncertaintiesJson", getType(TString)); - addProperty("funcOutUncertainties", "funcOutUncertaintiesJson", getType(TString)); - addProperty("f2dMap", "f2dMap", getType(TString)); - addProperty("f2pMap", "f2pMap", getType(TString)); - addProperty("f2oMap", "f2oMap", getType(TString)); - addProperty("f2cMap", "f2cMap", getType(TString)); - addProperty("f2uMap", "f2uMap", getType(TString)); + getTType(TString)); + addProperty("goals", "goals", getTType(TString)); + addProperty("thresholds", "thresholds", getTType(TString)); + addProperty("dVecUncertainties", "dVecUncertaintiesJson", getTType(TString)); + addProperty("funcOutUncertainties", "funcOutUncertaintiesJson", getTType(TString)); + addProperty("f2dMap", "f2dMap", getTType(TString)); + addProperty("f2pMap", "f2pMap", getTType(TString)); + addProperty("f2oMap", "f2oMap", getTType(TString)); + addProperty("f2cMap", "f2cMap", getTType(TString)); + addProperty("f2uMap", "f2uMap", getTType(TString)); } void ProblemGenerator::evaluateNode() diff --git a/src/libs/tigon/Operators/Initialisation/UserDefinedInit.cpp b/src/libs/tigon/Operators/Initialisation/UserDefinedInit.cpp index 3272af0..6fdb029 100644 --- a/src/libs/tigon/Operators/Initialisation/UserDefinedInit.cpp +++ b/src/libs/tigon/Operators/Initialisation/UserDefinedInit.cpp @@ -210,13 +210,13 @@ void UserDefinedInit::initialise() { addProperty("InitialSetFilePath", TString("Path of file that contains initial decision vectors") - , getType(TString)); + , getTType(TString)); addProperty("SelectedIteration", TString("Selected iteration from file"), - getType(int)); + getTType(int)); addProperty("TotalIterations", TString("Total number of iterations in the populations file"), - getType(int)); + getTType(int)); TP_defineSetSize(0); m_filePath = ""; diff --git a/src/libs/tigon/Operators/Initialisation/WeightVectorInit.cpp b/src/libs/tigon/Operators/Initialisation/WeightVectorInit.cpp index 2d9aeac..8faf8aa 100644 --- a/src/libs/tigon/Operators/Initialisation/WeightVectorInit.cpp +++ b/src/libs/tigon/Operators/Initialisation/WeightVectorInit.cpp @@ -59,7 +59,7 @@ void WeightVectorInit::initialise() " gives a total number of weight vectors that is equal" " to or higher than the population size." "Default is -1") - , getType(int)); + , getTType(int)); // m_propertyNames.push_back("Regularisation approach that determines the association between weight vectors and solutions"); // m_propertyDescriptions.push_back("When weight vectors are created, or modified, they need to be associated with " diff --git a/src/libs/tigon/Operators/Perturbations/BoundedPerturbation.cpp b/src/libs/tigon/Operators/Perturbations/BoundedPerturbation.cpp index a9ff5ee..f3a8f70 100644 --- a/src/libs/tigon/Operators/Perturbations/BoundedPerturbation.cpp +++ b/src/libs/tigon/Operators/Perturbations/BoundedPerturbation.cpp @@ -47,7 +47,7 @@ void BoundedPerturbation::initialise() "different scales, the distance is multiplied " "by sqrt(d), where d is the number of decision " "variables.\nThe default is 0.05") - ,getType(double)); + ,getTType(double)); TP_definePerturbationRadius(0.05); diff --git a/src/libs/tigon/Representation/Mappings/IMapping.cpp b/src/libs/tigon/Representation/Mappings/IMapping.cpp index e185e05..9666e0f 100644 --- a/src/libs/tigon/Representation/Mappings/IMapping.cpp +++ b/src/libs/tigon/Representation/Mappings/IMapping.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/libs/tigon/Representation/Problems/Problem.cpp b/src/libs/tigon/Representation/Problems/Problem.cpp index 2c2790d..7638826 100644 --- a/src/libs/tigon/Representation/Problems/Problem.cpp +++ b/src/libs/tigon/Representation/Problems/Problem.cpp @@ -1,6 +1,6 @@ -/**************************************************************************** +/**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -52,7 +52,9 @@ Problem::Problem() , m_nadirDefined (false) , m_antiIdealDefined (false) , m_boxConstraintsDefined (false) + , m_setGoalVecDefined (false) , m_goalVecDefined (false) + , m_priorityVecDefined (false) , m_thresholdVecDefined (false) { @@ -90,7 +92,9 @@ Problem::Problem(const Problem &prob) , m_nadirDefined (prob.m_nadirDefined) , m_antiIdealDefined (prob.m_antiIdealDefined) , m_boxConstraintsDefined (prob.m_boxConstraintsDefined) + , m_setGoalVecDefined (prob.m_setGoalVecDefined) , m_goalVecDefined (prob.m_goalVecDefined) + , m_priorityVecDefined (prob.m_priorityVecDefined) , m_thresholdVecDefined (prob.m_thresholdVecDefined) , m_d2KrigingMap (prob.m_d2KrigingMap) , m_pvecExternal (prob.m_pvecExternal) @@ -146,10 +150,19 @@ Problem::Problem(const Problem &prob) m_boxConstraints = prob.m_boxConstraints->clone(); } + m_setGoalVec.clear(); + for(size_t i=0; iclone()); + } + m_priorityVec.clear(); + for(auto elem : prob.m_priorityVec) { + m_priorityVec.push_back(elem); } m_thresholdVec.clear(); @@ -207,7 +220,9 @@ Problem::~Problem() m_f2pMap.clear(); m_f2cMap.clear(); m_f2uMap.clear(); + m_setGoalVec.clear(); m_goalVec.clear(); + m_priorityVec.clear(); m_thresholdVec.clear(); if(!m_fvec.empty()) { @@ -441,11 +456,21 @@ TVector Problem::cVecOptTypes() const return getOptTypes(m_cvecPrpts); } +TVector Problem::setGoalVector() const +{ + return m_setGoalVec; +} + TVector Problem::goalVector() const { return m_goalVec; } +TVector Problem::priorityVector() const +{ + return m_priorityVec; +} + TVector Problem::thresholdVector() const { return m_thresholdVec; @@ -516,11 +541,6 @@ TVector > Problem::funcOutUncertainties() const return m_fOutUncertainties; } -TVector Problem::isExternalParameters() const -{ - return m_pvecExternal; -} - void Problem::defineProbProperties(ProblemProperties probprp) { m_problemPrpts = probprp; @@ -795,6 +815,13 @@ void Problem::defineF2uMap(const TVector > &map) m_definitionStatus = UnprocessedChanges; } +void Problem::defineSetGoalVector(const TVector &setGoals) +{ + m_setGoalVec = setGoals; + m_setGoalVecDefined = true; + m_definitionStatus = UnprocessedChanges; +} + void Problem::defineGoalVector(const TVector &goals) { m_goalVec = goals; @@ -802,6 +829,13 @@ void Problem::defineGoalVector(const TVector &goals) m_definitionStatus = UnprocessedChanges; } +void Problem::redefineSetGoal(int idx, bool setGoal) +{ + if(isInRange(idx, m_setGoalVec.size())) { + m_setGoalVec[idx] = setGoal; + } +} + void Problem::redefineGoal(int idx, IElementSPtr goal) { if(isInRange(idx, m_goalVec.size())) { @@ -809,6 +843,20 @@ void Problem::redefineGoal(int idx, IElementSPtr goal) } } +void Problem::definePriorityVector(const TVector &priorities) +{ + m_priorityVec = priorities; + m_priorityVecDefined = true; + m_definitionStatus = UnprocessedChanges; +} + +void Problem::redefinePriority(int idx, int priority) +{ + if(isInRange(idx, m_priorityVec.size())) { + m_priorityVec[idx] = priority; + } +} + void Problem::defineThresholdVector(const TVector &thold) { m_thresholdVec = thold; @@ -1052,7 +1100,8 @@ ProblemDefinitionStatus Problem::processProblemDefinition() if(indexOf(params, inputs[j].ID()) == -1) { params.push_back(inputs[j].ID()); } - } else { // the input is a decision variable + } + else { // the input is a decision variable // check if the decision variable already exists if(indexOf(dVars, inputs[j].ID()) == -1) { dVars.push_back(inputs[j].ID()); @@ -1093,12 +1142,15 @@ ProblemDefinitionStatus Problem::processProblemDefinition() // inputs TVector inputs = m_fvec[i]->inputPrpts(); for(int j=0; j fInPrprts = m_fvec[i]->inputPrpts(); BoxConstraintsDataSPtr fBox = m_fvec[i]->boxConstraints(); @@ -1244,7 +1298,8 @@ ProblemDefinitionStatus Problem::processProblemDefinition() } else if(m_f2dMap[i].size() > k) { m_f2dMap[i][k] = j; } else { - // ERROR - every input was supposed to appear already. + // ERROR - every input was supposed to appear + // already. } break; } @@ -1260,15 +1315,20 @@ ProblemDefinitionStatus Problem::processProblemDefinition() nDVars = m_dvecPrpts.size(); m_dvecPrptsDefined = true; m_pvecPrptsDefined = true; + + + } else { + m_definitionStatus = IllDefinedDVecMaps; + return m_definitionStatus; } } // outputs if(nOVars == 0) { - if(nConstrs != 0) { - m_definitionStatus = IllDefinedOVecMaps; - return m_definitionStatus; - } else { + if( (nConstrs==0) && (nUVars==0) ) { + + // nOVars, nConstrs and nUVars are zero + for(int i=0; i fOutPrprts = m_fvec[i]->outputPrpts(); for(int j=0; j k) { m_f2oMap[i][k] = j; } else { - // ERROR - every output was supposed to appear already. + // ERROR - every output was supposed to appear + // already. } break; } @@ -1298,6 +1359,10 @@ ProblemDefinitionStatus Problem::processProblemDefinition() m_ovecPrptsDefined = true; m_cvecPrptsDefined = true; m_uvecPrptsDefined = true; + + } else { + m_definitionStatus = IllDefinedOVecMaps; + return m_definitionStatus; } } @@ -1309,14 +1374,19 @@ ProblemDefinitionStatus Problem::processProblemDefinition() int nInputs = m_fvec[i]->TP_nInputs(); TVector dMap = m_f2dMap[i]; TVector pMap = m_f2pMap[i]; - // TVector inputDefined(nInputs, false); + for(int j=0; jsize() != nDVars) { m_definitionStatus = IllDefinedBoxConstraints; @@ -1497,7 +1568,8 @@ ProblemDefinitionStatus Problem::processProblemDefinition() m_boxConstraints->defineUpperBounds(ubs); } } else { - m_boxConstraints = BoxConstraintsDataSPtr(new BoxConstraintsData(m_dvecPrpts)); + m_boxConstraints = + BoxConstraintsDataSPtr(new BoxConstraintsData(m_dvecPrpts)); // assign limits from the functions for(int i=0; i Problem::isExternalParameters() const +{ + return m_pvecExternal; +} + int Problem::numberExternalParameters() const { return std::count(m_pvecExternal.cbegin(), m_pvecExternal.cend(), true); diff --git a/src/libs/tigon/Representation/Problems/Problem.h b/src/libs/tigon/Representation/Problems/Problem.h index cdf7388..66f1b03 100644 --- a/src/libs/tigon/Representation/Problems/Problem.h +++ b/src/libs/tigon/Representation/Problems/Problem.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -46,7 +46,7 @@ class LIGER_TIGON_EXPORT Problem /// Variable/parameter/objective/constraint/unused Properties /// \note The fastest way to get ids, names, unites, descriptions, /// and types of the elements is to get their properties first and - /// then access the corresspoding memeber function. + /// then access the corresspoding member function. TVector dPrpts() const; TVector oPrpts() const; TVector pPrpts() const; @@ -86,18 +86,20 @@ class LIGER_TIGON_EXPORT Problem TVector oVecOptTypes() const; TVector cVecOptTypes() const; + TVector setGoalVector() const; TVector goalVector() const; + TVector priorityVector() const; TVector thresholdVector() const; TVector idealVector() const; TVector antiIdealVector() const; TVector nadirVector() const; TVector functionVec() const; - TVector > f2dMap() const; - TVector > f2oMap() const; - TVector > f2pMap() const; - TVector > f2cMap() const; - TVector > f2uMap() const; + TVector> f2dMap() const; + TVector> f2oMap() const; + TVector> f2pMap() const; + TVector> f2cMap() const; + TVector> f2uMap() const; BoxConstraintsDataSPtr boxConstraints() const; @@ -106,8 +108,7 @@ class LIGER_TIGON_EXPORT Problem TVector dVecUncertainties() const; TVector > funcOutUncertainties() const; - TVector isExternalParameters() const; - + /// Properties void defineProbProperties(ProblemProperties probprp); void defineDVecPrpts(const TVector &dvecPrpts); void defineOVecPrpts(const TVector &ovecPrpts); @@ -115,6 +116,7 @@ class LIGER_TIGON_EXPORT Problem void defineCVecPrpts(const TVector &cvecPrpts); void defineUVecPrpts(const TVector &uvecPrpts); + /// Types void defineDVecTypes(const TVector &dvecTypes); void defineOVecTypes(const TVector &ovecTypes); void definePVecTypes(const TVector &pvecTypes); @@ -123,6 +125,7 @@ class LIGER_TIGON_EXPORT Problem void redefineDVarType (int idx, ElementType dvarType); void redefineParamType(int idx, ElementType paramType); + /// Optimization Types void defineOVecOptimizationTypes(const TVector &ovecOptTypes); void defineCVecOptimizationTypes(const TVector &cvecOptTypes); void redefineObjOptimizationType (int idx, OptimizationType optType); @@ -138,14 +141,18 @@ class LIGER_TIGON_EXPORT Problem * A value of -1 means that the variable does not map to the function. */ void defineFunctionVec(const TVector &fvec); - void defineF2dMap(const TVector > &map); - void defineF2oMap(const TVector > &map); - void defineF2pMap(const TVector > &map); - void defineF2cMap(const TVector > &map); - void defineF2uMap(const TVector > &map); - + void defineF2dMap(const TVector> &map); + void defineF2oMap(const TVector> &map); + void defineF2pMap(const TVector> &map); + void defineF2cMap(const TVector> &map); + void defineF2uMap(const TVector> &map); + + void defineSetGoalVector(const TVector &setGoals); + void redefineSetGoal(int idx, bool setGoal); void defineGoalVector(const TVector &goals); void redefineGoal(int idx, IElementSPtr goal); + void definePriorityVector(const TVector &priorities); + void redefinePriority(int idx, int priority); void defineThresholdVector(const TVector &thold); void redefineThreshold(int idx, IElementSPtr thold); void defineIdealVector(const TVector &ideal); @@ -155,22 +162,23 @@ class LIGER_TIGON_EXPORT Problem void defineParameterVector(const TVector &pvec); void defineExternalParameters(const TVector &extpar); - void defineDVecUncertainties(const TVector &umaps); - void redefineDVarUncertainty(int idx, UncertaintyMapping* umap); - void defineFuncOutUncertainties(const TVector > &umaps); - void redefineFuncOutputUncertainty(int funcIdx, int outputIdx, - UncertaintyMapping* umap); + void defineDVecUncertainties(const TVector &umaps); + void redefineDVarUncertainty(int idx, UncertaintyMapping* umap); + void defineFuncOutUncertainties(const TVector> + &umaps); + void redefineFuncOutputUncertainty(int funcIdx, int outputIdx, + UncertaintyMapping* umap); /*! * \brief updateIdeal, updateAntiIdeal, updateNadir * \param newVec * \return true if the vector is changed */ - bool updateIdeal(const TVector &newVec); + bool updateIdeal(const TVector &newVec); bool updateAntiIdeal(const TVector &newVec); bool updateNadir(const TVector &newVec); - void defineBoxConstraints(BoxConstraintsDataSPtr box); + void defineBoxConstraints(BoxConstraintsDataSPtr box); /*! * \brief appendFunction @@ -184,6 +192,8 @@ class LIGER_TIGON_EXPORT Problem * \param outObjIdx - a list of indices of function outputs that are * considerd as objectives. IMPORTANT: the default of empty vector means ALL * outputs are objectives. + * \param outUnuIdx - a list of indices of outputs that are not used by the + * optimization process. Default is empty, i.e., no unused outputs. */ void appendFunction(IFunctionSPtr func, const TVector &inParamIdx = TVector(), @@ -197,6 +207,8 @@ class LIGER_TIGON_EXPORT Problem /// External parameters /// ******************* + TVector isExternalParameters() const; + int numberExternalParameters() const; TVector externalParametersIndices() const; TVector usePriorForExternalParameters() const; @@ -263,15 +275,15 @@ class LIGER_TIGON_EXPORT Problem TVector m_cvecPrpts; TVector m_uvecPrpts; - TVector m_fvec; - TVector > m_fInPMap; - TVector > m_fOutOMap; - TVector > m_fOutCMap; - TVector > m_f2dMap; - TVector > m_f2oMap; - TVector > m_f2pMap; - TVector > m_f2cMap; - TVector > m_f2uMap; + TVector m_fvec; + TVector> m_fInPMap; + TVector> m_fOutOMap; + TVector> m_fOutCMap; + TVector> m_f2dMap; + TVector> m_f2oMap; + TVector> m_f2pMap; + TVector> m_f2cMap; + TVector> m_f2uMap; TVector m_parameterVec; @@ -286,7 +298,9 @@ class LIGER_TIGON_EXPORT Problem /// for parameters BoxConstraintsDataSPtr m_boxConstraints; + TVector m_setGoalVec; TVector m_goalVec; + TVector m_priorityVec; TVector m_thresholdVec; ProblemDefinitionStatus m_definitionStatus; @@ -305,7 +319,9 @@ class LIGER_TIGON_EXPORT Problem bool m_nadirDefined; bool m_antiIdealDefined; bool m_boxConstraintsDefined; + bool m_setGoalVecDefined; bool m_goalVecDefined; + bool m_priorityVecDefined; bool m_thresholdVecDefined; /// Objective reduction diff --git a/src/libs/tigon/Tigon.h b/src/libs/tigon/Tigon.h index 21d8976..9e16d90 100644 --- a/src/libs/tigon/Tigon.h +++ b/src/libs/tigon/Tigon.h @@ -77,12 +77,7 @@ #include #include #include -#include -#include #include -#include -#include -#include #include #include #include @@ -92,6 +87,16 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -219,9 +224,9 @@ #include // Operators - Algorithm specific -#include -#include -#include +#include +#include +#include #include #include #include @@ -267,11 +272,13 @@ #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/src/libs/tigon/Utils/Dominance/ConstrDomRelation.cpp b/src/libs/tigon/Utils/Dominance/ConstrDomRelation.cpp index 11dbdb4..70863fc 100644 --- a/src/libs/tigon/Utils/Dominance/ConstrDomRelation.cpp +++ b/src/libs/tigon/Utils/Dominance/ConstrDomRelation.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -97,30 +97,6 @@ tribool ConstrDomRelation::isBetterThan(const TVector &a, return dom; } -void ConstrDomRelation::defineParameters(const TVector>& c) -{ - if(c.size()==3) { - defineThresholdVec(c[0]); - defineConstraintVecA(c[1]); - defineConstraintVecB(c[2]); - } -} - -double ConstrDomRelation::solutionConstraintViolation( - const TVector& g) const -{ - double constrViolation = 0.0; - int C = g.size(); - for(int i=0; i 0.0) { - constrViolation += diff; - } - } - - return constrViolation; -} - void ConstrDomRelation::defineThresholdVec(const TVector &t) { m_thresholdVec = t; @@ -151,6 +127,20 @@ TVector ConstrDomRelation::constraintVecB() const return m_constrainedVecB; } +double ConstrDomRelation::solutionConstraintViolation( + const TVector& g) const +{ + double constrViolation = 0.0; + int C = g.size(); + for(int i=0; i 0.0) { + constrViolation += diff; + } + } + + return constrViolation; +} } // namespace Representation } // namespace Tigon diff --git a/src/libs/tigon/Utils/Dominance/ConstrDomRelation.h b/src/libs/tigon/Utils/Dominance/ConstrDomRelation.h index de70aa2..4952f55 100644 --- a/src/libs/tigon/Utils/Dominance/ConstrDomRelation.h +++ b/src/libs/tigon/Utils/Dominance/ConstrDomRelation.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -21,7 +21,18 @@ namespace Tigon { namespace Representation { -class LIGER_TIGON_EXPORT ConstrDomRelation : public DominanceRelation +/** + * @brief The ConstrDomRelation class + * Note that this class uses virtual inheritance from DominanceRelation. + * This ensures that there will be only one instance of DominanceRelation in a + * diamond inheritance case. Currently the classes DominanceRelation, Preferability, + * ConstrDomRelation and PreferabilityConstraintHandling are organised in a + * diamond inheritance structure. When a pointer or reference to DominanceRelation + * is initialised with PreferabilityConstraintHandling, there will be only one + * instance of DominanceRelation, as opposed to two in case virtual inheritance + * wasn't used. + */ +class LIGER_TIGON_EXPORT ConstrDomRelation : virtual public DominanceRelation { public: ConstrDomRelation(); @@ -29,8 +40,7 @@ class LIGER_TIGON_EXPORT ConstrDomRelation : public DominanceRelation tribool isBetterThan(const TVector &a, const TVector &b) const; - void defineParameters(const TVector>& c); - + // Parameters void defineThresholdVec(const TVector& t); TVector thresholdVec() const; @@ -40,10 +50,10 @@ class LIGER_TIGON_EXPORT ConstrDomRelation : public DominanceRelation void defineConstraintVecB(const TVector& bg); TVector constraintVecB() const; - -private: +protected: double solutionConstraintViolation(const TVector& g) const; +private: TVector m_thresholdVec; TVector m_constrainedVecA; TVector m_constrainedVecB; diff --git a/src/libs/tigon/Utils/Dominance/DominanceRelation.cpp b/src/libs/tigon/Utils/Dominance/DominanceRelation.cpp index 83d6917..7bba818 100644 --- a/src/libs/tigon/Utils/Dominance/DominanceRelation.cpp +++ b/src/libs/tigon/Utils/Dominance/DominanceRelation.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -25,7 +25,6 @@ DominanceRelation::DominanceRelation() } - DominanceRelation::~DominanceRelation() { @@ -60,5 +59,37 @@ bool DominanceRelation::weakDom() const return m_weakDom; } +void DominanceRelation::defineGoalVec(const TVector& g) +{ + T_UNUSED(g); +} + + +void DominanceRelation::defineSetGoals(const TVector &gSet) +{ + T_UNUSED(gSet); +} + + +void DominanceRelation::definePriorityVec(const TVector& p) +{ + T_UNUSED(p); +} + +void DominanceRelation::defineThresholdVec(const TVector &t) +{ + T_UNUSED(t); +} + +void DominanceRelation::defineConstraintVecA(const TVector &ag) +{ + T_UNUSED(ag); +} + +void DominanceRelation::defineConstraintVecB(const TVector &bg) +{ + T_UNUSED(bg); +} + } // namespace Representation } // namespace Tigon diff --git a/src/libs/tigon/Utils/Dominance/DominanceRelation.h b/src/libs/tigon/Utils/Dominance/DominanceRelation.h index ac0d963..f24b35b 100644 --- a/src/libs/tigon/Utils/Dominance/DominanceRelation.h +++ b/src/libs/tigon/Utils/Dominance/DominanceRelation.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -16,27 +16,37 @@ #ifndef DOMINANCERELATION_H #define DOMINANCERELATION_H -#include +#include +#include namespace Tigon { namespace Representation { -class LIGER_TIGON_EXPORT DominanceRelation : public IOrderedRelation +class LIGER_TIGON_EXPORT DominanceRelation { public: DominanceRelation(); - ~DominanceRelation(); + virtual ~DominanceRelation(); - tribool isBetterThan(const TVector &a, const TVector &b) const; + virtual tribool isBetterThan(const TVector &a, + const TVector &b) const; tribool dominates(const TVector &a, const TVector &b) const; + // Parameters void defineWeakDom(bool c); bool weakDom() const; + // Exposed methods from derived classes + virtual void defineGoalVec(const TVector& g); + virtual void defineSetGoals(const TVector& gSet); + virtual void definePriorityVec(const TVector& p); + virtual void defineThresholdVec(const TVector& t); + virtual void defineConstraintVecA(const TVector& ag); + virtual void defineConstraintVecB(const TVector& bg); + private: bool m_weakDom; - }; } // namespace Representation diff --git a/src/libs/tigon/Utils/Dominance/IOrderedRelation.cpp b/src/libs/tigon/Utils/Dominance/IOrderedRelation.cpp deleted file mode 100644 index c601d8f..0000000 --- a/src/libs/tigon/Utils/Dominance/IOrderedRelation.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) -** -** This file is part of Liger. -** -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General -** Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -****************************************************************************/ -#include - -namespace Tigon { -namespace Representation { - -IOrderedRelation::IOrderedRelation() -{ - -} - -IOrderedRelation::~IOrderedRelation() -{ - -} - -void IOrderedRelation::defineParameters(const TVector> &c) -{ - T_UNUSED(c); -} - -} // namespace Representation -} // namespace Tigon diff --git a/src/libs/tigon/Utils/Dominance/IOrderedRelation.h b/src/libs/tigon/Utils/Dominance/IOrderedRelation.h deleted file mode 100644 index 81a9603..0000000 --- a/src/libs/tigon/Utils/Dominance/IOrderedRelation.h +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) -** -** This file is part of Liger. -** -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General -** Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -****************************************************************************/ -#ifndef IIORDEREDRELATION_H -#define IIORDEREDRELATION_H - -#include -#include - -namespace Tigon { -namespace Representation { - -class LIGER_TIGON_EXPORT IOrderedRelation -{ -public: - IOrderedRelation(); - virtual ~IOrderedRelation(); - - virtual tribool isBetterThan(const TVector &a, - const TVector &b) const = 0; - - virtual void defineParameters(const TVector>& c); -}; - -} // namespace Representation -} // namespace Tigon - -#endif // IIORDEREDRELATION_H diff --git a/src/libs/tigon/Utils/Dominance/Preferability.cpp b/src/libs/tigon/Utils/Dominance/Preferability.cpp index 2e3d9b9..cdfcfc5 100644 --- a/src/libs/tigon/Utils/Dominance/Preferability.cpp +++ b/src/libs/tigon/Utils/Dominance/Preferability.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -37,13 +37,15 @@ tribool Preferability::isBetterThan(const TVector &a, return dominates(a,b); } - return preferability(a, b); + return preferability(a, b, goalVec(), setGoals(), priorityVec()); } tribool Preferability::preferability(const TVector &a, - const TVector &b) const + const TVector &b, + const TVector &g, + const TVector &s) const { - int Nobj = a.size(); + size_t Nobj = a.size(); /// Classification of the solutions /// 0: solution meets all goals @@ -51,18 +53,18 @@ tribool Preferability::preferability(const TVector &a, int aclass=0; int bclass=0; - for(int k=0; k goalVec()[k]) { + for(size_t k=0; k g[k]) { aclass=1; break; } } } - for(int k=0; k goalVec()[k]) { + for(size_t k=0; k g[k]) { bclass=1; break; } @@ -79,9 +81,9 @@ tribool Preferability::preferability(const TVector &a, AbetterB = AequalB = BbetterA = BequalA = 1; - for(int k=0; k goalVec()[k]) { // a does not meet the goal + for(size_t k=0; k g[k]) { // a does not meet the goal if(weakDom()) { AbetterB *= (a[k] <= b[k]); } else { @@ -89,7 +91,7 @@ tribool Preferability::preferability(const TVector &a, } AequalB *= (a[k] == b[k]); } - if(b[k] > goalVec()[k]) { // b does not meet the goal + if(b[k] > g[k]) { // b does not meet the goal if(weakDom()) { BbetterA *= (b[k] <= a[k]); } else { @@ -120,7 +122,7 @@ tribool Preferability::preferability(const TVector &a, * based on those objectives which satisfy their goals */ AbetterB = AequalB = BbetterA = 1; - for (int k=0; k &a, return incomparable; } - - -void Preferability::defineParameters(const TVector > &c) +tribool Preferability::preferability(const TVector &a, + const TVector &b, + const TVector &g, + const TVector &s, + const TVector &p) const { - if( c.size()==2 ) { - defineGoalVec(c[0]); - - TVector p1; - for(auto p : c[1]) { - p1.push_back((bool)p); + int maxElem = *min_element(p.begin(), p.end()); + int minElem = *max_element(p.begin(), p.end()); + for(size_t i=0; i maxElem) { + maxElem = p[i]; + } + if(p[i] < minElem) { + minElem = p[i]; + } } + } - defineSetGoals(p1); + if ((maxElem==minElem) && (maxElem==1)){ // if there is only one priority level + return preferability(a,b,g,s); } + else { // if there is more than one priority level + + // Store the indices of the objectives with the highest priority + TVector mp_idx; + for(size_t i = 0; i g[idx]) { + aclass=1; + break; + } + } + } + + int bclass=0; + for(auto idx : mp_idx) { + if(s[idx]) { // only for set goals + if(b[idx] > g[idx]) { + bclass=1; + break; + } + } + } + + if(aclass < bclass) { + return true; // A is preferred + } else if(aclass > bclass) { + return false; // B is preferred + } + + int AequalB, BequalA, AbetterB, BbetterA; + AbetterB = AequalB = BbetterA = BequalA = 1; + + for(auto idx : mp_idx) { + if(s[idx]) { // only for set goals + if(a[idx] > g[idx]) { // A does not meet the goal + if(weakDom()) { + AbetterB *= (a[idx] <= b[idx]); + } else { + AbetterB *= (a[idx] < b[idx]); + } + AequalB *= (a[idx] == b[idx]); + } + if(b[idx] > g[idx]) { // B does not meet the goal + if(weakDom()) { + BbetterA *= (b[idx] <= a[idx]); + } else { + BbetterA *= (b[idx] < a[idx]); + } + BequalA *= (b[idx] == a[idx]); + } + } + } + + // check if A and B are totally different + if (!(AequalB && BequalA)) { + + // check if A dominates B with respect to the components that A + // does not meet the goal + if ((AbetterB && !AequalB) || (AequalB && !BequalA)) + return true; + + // check if B dominates A with respect to the components that B + // does not meet the goal + if ((BbetterA && !BequalA) || (BequalA && !AequalB)) + return false; + + return incomparable; + } + + if( (maxElem == minElem) && (maxElem>1)) { + // Constraint satisfaction special case + return incomparable; + } + + /* this point is only reached in case the decision is * + * based on objectives with lower priority levels */ + + size_t Nobj = a.size(); + + TVector a2; + TVector b2; + TVector g2; + TVector s2; + TVector p2; + + // Select objectives and corresponding goals with priority level lower + // than the current maximum + for(size_t k=0; k &g) +void Preferability::defineGoalVec(const TVector& g) { m_goalVec = g; } @@ -180,6 +298,15 @@ TVector Preferability::setGoals() const return m_setGoals; } +void Preferability::definePriorityVec(const TVector& p) +{ + m_priorityVec = p; +} + +TVector Preferability::priorityVec() const +{ + return m_priorityVec; +} } // namespace Representation } // namespace Tigon diff --git a/src/libs/tigon/Utils/Dominance/Preferability.h b/src/libs/tigon/Utils/Dominance/Preferability.h index 1386bad..13db051 100644 --- a/src/libs/tigon/Utils/Dominance/Preferability.h +++ b/src/libs/tigon/Utils/Dominance/Preferability.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -21,7 +21,18 @@ namespace Tigon { namespace Representation { -class LIGER_TIGON_EXPORT Preferability : public DominanceRelation +/** + * @brief The Preferability class + * Note that this class uses virtual inheritance from DominanceRelation. + * This ensures that there will be only one instance of DominanceRelation in a + * diamond inheritance case. Currently the classes DominanceRelation, Preferability, + * ConstrDomRelation and PreferabilityConstraintHandling are organised in a + * diamond inheritance structure. When a pointer or reference to DominanceRelation + * is initialised with PreferabilityConstraintHandling, there will be only one + * instance of DominanceRelation, as opposed to two in case virtual inheritance + * wasn't used. + */ +class LIGER_TIGON_EXPORT Preferability : virtual public DominanceRelation { public: Preferability(); @@ -30,20 +41,31 @@ class LIGER_TIGON_EXPORT Preferability : public DominanceRelation tribool isBetterThan(const TVector &a, const TVector &b) const; tribool preferability(const TVector &a, - const TVector &b) const; + const TVector &b, + const TVector &g, + const TVector &s) const; - // Parameters - void defineParameters(const TVector>& c); + tribool preferability(const TVector &a, + const TVector &b, + const TVector &g, + const TVector &s, + const TVector &p) const; + // Parameters void defineGoalVec(const TVector& g); TVector goalVec() const; void defineSetGoals(const TVector& gSet); TVector setGoals() const; + void definePriorityVec(const TVector& p); + TVector priorityVec() const; + private: TVector m_goalVec; TVector m_setGoals; + TVector m_priorityVec; + }; } // namespace Representation diff --git a/src/libs/tigon/Utils/Dominance/PreferabilityConstraintHandling.cpp b/src/libs/tigon/Utils/Dominance/PreferabilityConstraintHandling.cpp index 5ad4880..b5de706 100644 --- a/src/libs/tigon/Utils/Dominance/PreferabilityConstraintHandling.cpp +++ b/src/libs/tigon/Utils/Dominance/PreferabilityConstraintHandling.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -46,35 +46,13 @@ tribool PreferabilityConstraintHandling::isBetterThan(const TVector &a, } else { - // Normal preferability with just goals - dom = preferability(a, b); + // Preferability with goals and priorities + dom = preferability(a, b, goalVec(), setGoals(), priorityVec()); } return dom; } -void PreferabilityConstraintHandling::defineParameters( - const TVector> &c) -{ - if( (c.size()==2) || (c.size()==5) ) { - defineGoalVec(c[0]); - - TVector p1; - for(auto p : c[1]) { - p1.push_back((bool)p); - } - - defineSetGoals(p1); - } - - if(c.size()==5) { - defineThresholdVec(c[2]); - defineConstraintVecA(c[3]); - defineConstraintVecB(c[4]); - } -} - - tribool PreferabilityConstraintHandling::preferability_constraint( const TVector &a, const TVector &b) const { @@ -129,8 +107,8 @@ tribool PreferabilityConstraintHandling::preferability_constraint( } else { - // normal preferability - dom = preferability(a, b); + // normal preferability + dom = preferability(a, b, goalVec(), setGoals(), priorityVec()); } } } @@ -138,53 +116,5 @@ tribool PreferabilityConstraintHandling::preferability_constraint( return dom; } -double PreferabilityConstraintHandling::solutionConstraintViolation( - const TVector& g) const -{ - double constrViolation = 0.0; - int C = g.size(); - for(int i=0; i 0.0) { - constrViolation += diff; - } - } - - return constrViolation; -} - -void PreferabilityConstraintHandling::defineThresholdVec( - const TVector &t) -{ - m_thresholdVec = t; -} - -TVector PreferabilityConstraintHandling::thresholdVec() const -{ - return m_thresholdVec; -} - -void PreferabilityConstraintHandling::defineConstraintVecA( - const TVector &ag) -{ - m_constrainedVecA=ag; -} - -TVector PreferabilityConstraintHandling::constraintVecA() const -{ - return m_constrainedVecA; -} - -void PreferabilityConstraintHandling::defineConstraintVecB( - const TVector &bg) -{ - m_constrainedVecB=bg; -} - -TVector PreferabilityConstraintHandling::constraintVecB() const -{ - return m_constrainedVecB; -} - } // namespace Representation } // namespace Tigon diff --git a/src/libs/tigon/Utils/Dominance/PreferabilityConstraintHandling.h b/src/libs/tigon/Utils/Dominance/PreferabilityConstraintHandling.h index 34d9ea6..9a7f66a 100644 --- a/src/libs/tigon/Utils/Dominance/PreferabilityConstraintHandling.h +++ b/src/libs/tigon/Utils/Dominance/PreferabilityConstraintHandling.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2019 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -17,11 +17,14 @@ #define PREFERABILITYCONSTRAINTHANDLING_H #include +#include namespace Tigon { namespace Representation { -class LIGER_TIGON_EXPORT PreferabilityConstraintHandling : public Preferability +class LIGER_TIGON_EXPORT PreferabilityConstraintHandling : + public Preferability, + public ConstrDomRelation { public: PreferabilityConstraintHandling(); @@ -29,26 +32,8 @@ class LIGER_TIGON_EXPORT PreferabilityConstraintHandling : public Preferability tribool isBetterThan(const TVector &a, const TVector &b) const; - void defineParameters(const TVector> &c); - tribool preferability_constraint(const TVector &a, const TVector &b) const; - - void defineThresholdVec(const TVector& t); - TVector thresholdVec() const; - - void defineConstraintVecA(const TVector& ag); - TVector constraintVecA() const; - - void defineConstraintVecB(const TVector& bg); - TVector constraintVecB() const; - -private: - double solutionConstraintViolation(const TVector& g) const; - - TVector m_thresholdVec; - TVector m_constrainedVecA; - TVector m_constrainedVecB; }; } // namespace Representation diff --git a/src/libs/tigon/tigon.pro b/src/libs/tigon/tigon.pro index d3a9177..0c76158 100644 --- a/src/libs/tigon/tigon.pro +++ b/src/libs/tigon/tigon.pro @@ -99,11 +99,13 @@ SOURCES += \ Utils/RBFInverseMultiQuadric.cpp \ Utils/RBFBasis.cpp \ Utils/RBFInterpolatorCascade.cpp \ - Utils/KrigingVariogram.cpp \ - Utils/Kriging.cpp \ - Utils/PowerVariogram.cpp \ - Utils/KrigingCascade.cpp \ - Utils/SphericalVariogram.cpp \ + Utils/Kriging/DACE.cpp \ + Utils/Kriging/IKriging.cpp \ + Utils/Kriging/KrigingCascade.cpp \ + Utils/Kriging/KrigingVariogram.cpp \ + Utils/Kriging/OrdinaryKriging.cpp \ + Utils/Kriging/PowerVariogram.cpp \ + Utils/Kriging/SphericalVariogram.cpp \ Representation/Distributions/IDistribution.cpp \ Representation/Distributions/UniformDistribution.cpp \ Representation/Distributions/LinearDistribution.cpp \ @@ -135,12 +137,18 @@ SOURCES += \ Representation/Functions/DTLZ/DTLZ2.cpp \ Representation/Functions/DTLZ/DTLZ5_2.cpp \ Representation/Functions/DTLZ/DTLZ5_3.cpp \ - Representation/Functions/KrigingSurrogate.cpp \ + Representation/Functions/SurrogateModelling/KrigingSurrogate.cpp \ + Representation/Functions/SurrogateModelling/ExpectedImprovement.cpp \ + Representation/Functions/SurrogateModelling/RandExpectedImprovement.cpp \ + Representation/Functions/SurrogateModelling/FeedforwardSurrogate.cpp \ + Representation/Functions/SurrogateModelling/FannNetwork.cpp \ + Representation/Functions/SurrogateModelling/ConstrainedExpectedImprovement.cpp \ + Representation/Functions/SurrogateModelling/FeasibleExpectedImprovement.cpp \ + Representation/Functions/SurrogateModelling/FeasibleRandExpectedImprovement.cpp \ + Representation/Functions/SurrogateModelling/ProbabilityFeasibility.cpp \ + Representation/Functions/SurrogateModelling/Likelihood.cpp \ + Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.cpp \ Representation/Functions/SingleObjective/Alpine2.cpp \ - Representation/Functions/ExpectedImprovement.cpp \ - Representation/Functions/RandExpectedImprovement.cpp \ - Representation/Functions/FeedforwardSurrogate.cpp \ - Representation/Functions/FannNetwork.cpp \ Utils/ScalarisingFunctions.cpp \ Utils/ProjectionUtils.cpp \ Utils/NormalisationUtils.cpp \ @@ -172,6 +180,7 @@ SOURCES += \ Representation/Indicators/ThresholdIndicator.cpp \ Operators/Composites/IComposite.cpp \ Operators/Composites/SurrogateBasedOptimizer.cpp \ + Operators/Composites/ConstrainedSurrogateBasedOptimizer.cpp \ Operators/Transformations/Normalisation.cpp \ Operators/Initialisation/FitnessBasedInit.cpp \ Operators/Filtrations/MultiMemberTournamentForDirection.cpp \ @@ -179,10 +188,14 @@ SOURCES += \ Operators/AlgorithmSpecific/ACROMUSE/AcromuseDiversity.cpp \ Operators/AlgorithmSpecific/ACROMUSE/AcromuseFiltrationForDirection.cpp \ Operators/AlgorithmSpecific/ACROMUSE/AcromuseFiltrationForPerturbation.cpp \ - Operators/Transformations/Denormalisation.cpp \ Operators/AlgorithmSpecific/ACROMUSE/AcromuseMutation.cpp \ Operators/AlgorithmSpecific/ACROMUSE/AcromuseEliteFiltration.cpp \ - Operators/AlgorithmSpecific/parego/DirectionFitnessFiltration.cpp \ + Operators/AlgorithmSpecific/ParEGO/DirectionFitnessFiltration.cpp \ + Operators/AlgorithmSpecific/ParEGO/ConstraintDirectionFitnessFiltration.cpp \ + Operators/AlgorithmSpecific/MOEADNeighbourhoodUpdate.cpp \ + Operators/AlgorithmSpecific/sParEGO/sParEGOInit.cpp \ + Operators/AlgorithmSpecific/sParEGO/SparegoValidation.cpp \ + Operators/Transformations/Denormalisation.cpp \ Algorithms/ACROMUSE.cpp \ Operators/Initialisation/UserDefinedInit.cpp \ Representation/Distributions/ChiSquaredDistribution.cpp \ @@ -209,7 +222,6 @@ SOURCES += \ Representation/Elements/IElementOperations.cpp \ Representation/Mappings/IMappingOperations.cpp \ Utils/IElementUtils.cpp \ - Operators/AlgorithmSpecific/MOEADNeighbourhoodUpdate.cpp \ Engine/TigonFunctionFactory.cpp \ Operators/Filtrations/TruncateSets.cpp \ Operators/Filtrations/TournamentFiltrationForDirection.cpp \ @@ -251,8 +263,6 @@ SOURCES += \ Utils/CorrelationMatrix.cpp \ Utils/ObjectiveReduction.cpp \ Algorithms/sParEGO.cpp \ - Operators/AlgorithmSpecific/Sparego/SparegoInit.cpp \ - Operators/AlgorithmSpecific/Sparego/SparegoValidation.cpp \ Operators/Evaluators/ValidationWithScalarisation.cpp \ Representation/Functions/CODeM/CODeMDistribution.cpp \ Representation/Functions/CODeM/CODeMOperators.cpp \ @@ -263,7 +273,6 @@ SOURCES += \ Representation/Functions/CODeM/UncertaintyKernel.cpp \ Utils/Dominance/ConstrDomRelation.cpp \ Utils/Dominance/DominanceRelation.cpp \ - Utils/Dominance/IOrderedRelation.cpp \ Utils/Dominance/Preferability.cpp \ Utils/Dominance/PreferabilityConstraintHandling.cpp \ Algorithms/MOGA.cpp \ @@ -334,11 +343,13 @@ HEADERS += \ Utils/RBFInverseMultiQuadric.h \ Utils/RBFBasis.h \ Utils/RBFInterpolatorCascade.h \ - Utils/KrigingVariogram.h \ - Utils/Kriging.h \ - Utils/PowerVariogram.h \ - Utils/KrigingCascade.h \ - Utils/SphericalVariogram.h \ + Utils/Kriging/DACE.h \ + Utils/Kriging/IKriging.h \ + Utils/Kriging/KrigingCascade.h \ + Utils/Kriging/KrigingVariogram.h \ + Utils/Kriging/OrdinaryKriging.h \ + Utils/Kriging/PowerVariogram.h \ + Utils/Kriging/SphericalVariogram.h \ Representation/Distributions/IDistribution.h \ Representation/Distributions/UniformDistribution.h \ Representation/Distributions/LinearDistribution.h \ @@ -391,12 +402,18 @@ HEADERS += \ Representation/Functions/DTLZ/DTLZ5_2.h \ Representation/Functions/DTLZ/DTLZ5_3.h \ Representation/Functions/ExampleFunction.h \ - Representation/Functions/KrigingSurrogate.h \ + Representation/Functions/SurrogateModelling/KrigingSurrogate.h \ + Representation/Functions/SurrogateModelling/ExpectedImprovement.h \ + Representation/Functions/SurrogateModelling/RandExpectedImprovement.h \ + Representation/Functions/SurrogateModelling/FeedforwardSurrogate.h \ + Representation/Functions/SurrogateModelling/FannNetwork.h \ + Representation/Functions/SurrogateModelling/ConstrainedExpectedImprovement.h \ + Representation/Functions/SurrogateModelling/FeasibleExpectedImprovement.h \ + Representation/Functions/SurrogateModelling/FeasibleRandExpectedImprovement.h \ + Representation/Functions/SurrogateModelling/ProbabilityFeasibility.h \ + Representation/Functions/SurrogateModelling/Likelihood.h \ + Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.h \ Representation/Functions/SingleObjective/Alpine2.h \ - Representation/Functions/ExpectedImprovement.h \ - Representation/Functions/FeedforwardSurrogate.h \ - Representation/Functions/FannNetwork.h \ - Representation/Functions/RandExpectedImprovement.h \ Operators/Formulations/IFormulation.h \ Representation/Problems/Problem.h \ Representation/Properties/FunctionPropertiesData.h \ @@ -414,10 +431,14 @@ HEADERS += \ Operators/AlgorithmSpecific/ACROMUSE/AcromuseDiversity.h \ Operators/AlgorithmSpecific/ACROMUSE/AcromuseFiltrationForDirection.h \ Operators/AlgorithmSpecific/ACROMUSE/AcromuseFiltrationForPerturbation.h \ - Operators/Transformations/Denormalisation.h \ Operators/AlgorithmSpecific/ACROMUSE/AcromuseMutation.h \ Operators/AlgorithmSpecific/ACROMUSE/AcromuseEliteFiltration.h \ - Operators/AlgorithmSpecific/parego/DirectionFitnessFiltration.h \ + Operators/AlgorithmSpecific/ParEGO/DirectionFitnessFiltration.h \ + Operators/AlgorithmSpecific/ParEGO/ConstraintDirectionFitnessFiltration.h \ + Operators/AlgorithmSpecific/MOEADNeighbourhoodUpdate.h \ + Operators/AlgorithmSpecific/sParEGO/sParEGOInit.h \ + Operators/AlgorithmSpecific/sParEGO/SparegoValidation.h \ + Operators/Transformations/Denormalisation.h \ Algorithms/ACROMUSE.h \ Operators/Initialisation/UserDefinedInit.h \ Representation/Distributions/ChiSquaredDistribution.h \ @@ -447,7 +468,6 @@ HEADERS += \ Representation/Mappings/IMappingOperations.h \ Representation/Mappings/UncertaintyMapping.h \ Utils/IElementUtils.h \ - Operators/AlgorithmSpecific/MOEADNeighbourhoodUpdate.h \ Operators/Filtrations/TruncateSets.h \ Operators/Filtrations/TournamentFiltrationForDirection.h \ Factories/RobustnessIndicatorFactory.h \ @@ -496,8 +516,6 @@ HEADERS += \ Utils/CorrelationMatrix.h \ Utils/ObjectiveReduction.h \ Algorithms/sParEGO.h \ - Operators/AlgorithmSpecific/Sparego/SparegoInit.h \ - Operators/AlgorithmSpecific/Sparego/SparegoValidation.h \ Operators/Evaluators/ValidationWithScalarisation.h \ Representation/Functions/CODeM/CODeMDistribution.h \ Representation/Functions/CODeM/CODeMOperators.h \ @@ -508,7 +526,6 @@ HEADERS += \ Representation/Functions/CODeM/UncertaintyKernel.h \ Utils/Dominance/ConstrDomRelation.h \ Utils/Dominance/DominanceRelation.h \ - Utils/Dominance/IOrderedRelation.h \ Utils/Dominance/Preferability.h \ Utils/Dominance/PreferabilityConstraintHandling.h \ Algorithms/MOGA.h \ diff --git a/src/libs/tigon/tigon_global.h b/src/libs/tigon/tigon_global.h index 1871f12..e1fc82c 100644 --- a/src/libs/tigon/tigon_global.h +++ b/src/libs/tigon/tigon_global.h @@ -76,9 +76,9 @@ ENABLE_WARNINGS #include #include -typedef Eigen::Matrix TMatrixReal; -typedef Eigen::Matrix TCVectorReal; -typedef Eigen::Matrix TRVectorReal; +typedef Eigen::MatrixXd TMatrixReal; +typedef Eigen::VectorXd TCVectorReal; +typedef Eigen::RowVectorXd TRVectorReal; typedef std::complex TComplex; typedef long long int64; typedef unsigned long long uint64; @@ -96,11 +96,11 @@ BOOST_TRIBOOL_THIRD_STATE(incomparable) /// in all compilers, use the following. //template using SPtr = TSharedPointer; namespace Tigon { -class Kriging; +class IKriging; class PolynomialRegression; class MultiPolynomialRegression; -typedef TSharedPointer KrigingSPtr; +typedef TSharedPointer KrigingSPtr; typedef TSharedPointer PolyRegressionSPtr; typedef TSharedPointer MPolyRegressionSPtr; diff --git a/src/plugins/qtigon/operators/initialisations/qopsparegoinitnode.cpp b/src/plugins/qtigon/operators/initialisations/qopsparegoinitnode.cpp index 200ec50..ac6a174 100644 --- a/src/plugins/qtigon/operators/initialisations/qopsparegoinitnode.cpp +++ b/src/plugins/qtigon/operators/initialisations/qopsparegoinitnode.cpp @@ -50,7 +50,7 @@ QOpSparegoInitNode::QOpSparegoInitNode() m_backgroundColor = Qt::white; setNumberOfOutputs(1); setNumberOfInputs(1); - setData(new SparegoInit); + setData(new sParEGOInit); QFile img_file(":/qtigon/images/qopsparegoinitnode.svg"); if(img_file.exists()) { @@ -117,10 +117,10 @@ void QOpSparegoInitNode::writeDataProperties(QXmlStreamWriter &xmlWriter) void QOpSparegoInitNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED(event) - SparegoInit* thisOp = static_cast(data()); + sParEGOInit* thisOp = static_cast(data()); if(thisOp) { m_dialog->setup(thisOp); m_dialog->show(); m_dialog->raise(); } -} \ No newline at end of file +} diff --git a/tests/auto/test_tigon/test_interpolators/tst_interpolators.cpp b/tests/auto/test_tigon/test_interpolators/tst_interpolators.cpp index e900445..3bcfbaf 100644 --- a/tests/auto/test_tigon/test_interpolators/tst_interpolators.cpp +++ b/tests/auto/test_tigon/test_interpolators/tst_interpolators.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -22,6 +22,7 @@ #include #include +#include using namespace std; using namespace Tigon; @@ -75,11 +76,15 @@ private slots: void test_SphericalVariogram(); - void test_Kriging_Fitting(); - void test_Kriging_ErrorEstimates_1DExample(); - void test_Kriging_ErrorEstimates_2DExample(); - void test_Kriging_SimpleExample(); - void test_KrigingAssignVariogram(); + void test_DACE_Fitting(); + void test_DACE_ErrorEstimates_1DExample(); + void test_DACE_ErrorEstimates_2DExample(); + + void test_OrdinaryKriging_Fitting(); + void test_OrdinaryKriging_ErrorEstimates_1DExample(); + void test_OrdinaryKriging_ErrorEstimates_2DExample(); + void test_OrdinaryKriging_SimpleExample(); + void test_OrdinaryKrigingAssignVariogram(); #ifdef TEST_KRIGING_CASCADE void test_KrigingCascade(); void test_KrigingCascadeFromVariograms(); @@ -131,20 +136,21 @@ void tst_interpolators::test_initEps() } -void inline vector1DToMatlabCommand(TString vecName, TVector value) +void inline vector1DToMatlabCommand(TString vecName, const TVector& value) { cout << vecName << " = ["; - for(int i=0; i > value) +void inline vector2DToMatlabCommand(TString vecName, + const TVector>& value) { cout << vecName << " = ["; - for(int i = 0; i < value.size(); i++) { - for(int j=0; j > x; + TVector y; + TVector > xq; + TVector yqref; + int n = 100; + int dimx = 3; + int nq = 10*n; + + x.resize(n); + y.resize(n); + xq.resize(nq); + yqref.resize(nq); + + TRAND.defineSeed(time(NULL)); + for(int i = 0; i(RAND_MAX); + double bias = 0.0; + y[i] = std::pow(x[i][0], 3) + std::pow(x[i][1] - x[i][2], 2)+bias; + } + std::cout << std::endl; + for(int i = 0; i < nq; i++) { + xq[i].resize(dimx); + for(int j=0; jdefineEstimateErrors(false); + kinterp->defineStallIterations(5); + kinterp->defineInitialPopsizePerVariable(20); + kinterp->defineBudgetPerVariable(40); + kinterp->updateData(x, y); + double kerr = 0.0; + for(int i = 0; i < nq; i++) { + kerr += std::pow(yqref[i] - kinterp->interpolate(xq[i]), 2); + } + cout << "Kriging error (MSE): " << kerr/nq << endl << endl; + + delete kinterp; +} + +double inline func1D(double x) +{ + return (x+1.0)*std::sin(std::pow(x, 2))+15; // shift it up by 30 +} + +void tst_interpolators::test_DACE_ErrorEstimates_1DExample() +{ + TVector > x; + TVector y; + TVector > xq; + TVector yq; + TVector yqref; + // ref points for the function + TVector > xx; + TVector yy; + int dimx = 1; + double lbound = 2; + double ubound = 6; + int n1 = 20; + int n2 = 10; + int nq = 50; + int nref = 1000; + + x.resize(n1+n2); + y.resize(n1+n2); + xq.resize(nq); + yq.resize(nq); + yqref.resize(nq); + xx.resize(nref); + yy.resize(nref); + + // TODO - use Tigon random generator + TRAND.defineSeed(1); + for(int i = 0; idefineEstimateErrors(true); + kinterp->defineStallIterations(5); + kinterp->defineInitialPopsizePerVariable(20); + kinterp->defineBudgetPerVariable(40); + kinterp->updateData(x, y); + + // Error checks + TVector actualError; + TVector predictionErrStd; + double mse = 0.0; + for(int i = 0; i < nq; i++) { + yq[i] = kinterp->interpolate(xq[i]); + mse += std::pow(yqref[i] - yq[i], 2); + actualError.push_back(std::abs(yqref[i] - yq[i])); + predictionErrStd.push_back(kinterp->errorEstimate()); + } + mse = mse/nq; + cout << "Kriging error (MSE): " << mse << endl << endl; +#ifdef KRIGING_PLOT_IN_MATLAB + cout<< "%Matlab command for plotting =========== " << endl << endl; + cout << "close all; clear;" << endl; + vector2DToMatlabCommand("x1", mid(x, 0, n1)); + vector2DToMatlabCommand("x2", mid(x,n1,n1+n2)); + vector1DToMatlabCommand("y", y); + vector2DToMatlabCommand("xq", xq); + vector1DToMatlabCommand("yq", yq); + vector2DToMatlabCommand("xx", xx); + vector1DToMatlabCommand("yy", yy); + vector1DToMatlabCommand("actualError", actualError); + vector1DToMatlabCommand("errorEstimate", predictionErrStd); + cout << "x = [x1; x2];" + << "figure; hold on; " + << "yyaxis left; " + << "plot(xx,yy, \'.\', \'Color\', [0.7 0.7 0.7]); " + << "plot(x,y, \'+\'); " + << "plot(xq, yq, 'd'); " + << "ylabel(\'Prediction\'); " + << "yyaxis right; " + << "plot(xq, errorEstimate, \'Marker\', \'x\'); " + << "ylabel(\'Error\'); " + << "hold off; grid on; " + << "legend({\'Ref\' \'Sample\' \'Prediction\' \'errorEstimate\'});" + << endl; + cout << endl << "%=================================" << endl << endl; +#endif + delete kinterp; +} + +void tst_interpolators::test_DACE_ErrorEstimates_2DExample() +{ + TVector > x; + TVector y; + TVector > xq; + TVector yq; + TVector yqref; + int dimx = 2; + int n1 = 20; + int n2 = 5; + int nq = 10; + + x.resize(n1+n2); + y.resize(n1+n2); + xq.resize(nq); + yq.resize(nq); + yqref.resize(nq); + + // TODO - use Tigon random generator + TRAND.defineSeed(1); + for(int i = 0; idefineEstimateErrors(true); + kinterp->defineStallIterations(5); + kinterp->defineInitialPopsizePerVariable(20); + kinterp->defineBudgetPerVariable(40); + kinterp->updateData(x, y); + + // Error checks + TVector actualError; + TVector predictionErrStd; + double mse = 0.0; + for(int i = 0; i < nq; i++) { + yq[i] = kinterp->interpolate(xq[i]); + mse += std::pow(yqref[i] - yq[i], 2); + cout << "\t(" << xq[i][0] << "," << xq[i][1] + << ") |-> " << yq[i] + << " (actual: " << yqref[i] << ")" + << "\terr: " << std::abs(yqref[i] - yq[i]) + << "\t kvariance est: " + << kinterp->errorEstimate() + << endl; + actualError.push_back(std::abs(yqref[i] - yq[i])); + predictionErrStd.push_back(kinterp->errorEstimate()); + } + mse = mse/nq; + cout << "Kriging error (MSE): " << mse << endl << endl; + + #ifdef KRIGING_PLOT_IN_MATLAB + // Matlab command for plotting + cout << "close all; clear;" << endl; + vector2DToMatlabCommand("x1", mid(x,0, n1)); + vector2DToMatlabCommand("x2", mid(x,n1,n1+n2)); + vector1DToMatlabCommand("y", y); + vector2DToMatlabCommand("xq", xq); + vector1DToMatlabCommand("yq", yq); + vector1DToMatlabCommand("actualError", actualError); + vector1DToMatlabCommand("errorEstimate", predictionErrStd); + cout << "x = [x1; x2];" + << "figure; hold on; " + << "syms x1 x2; " + << "h = fsurf(x1^2 + (x1-x2/2)^2, [0 10 0 10]); " + << "h(1).FaceAlpha = 0.2; " + << "plot3(x(:,1),x(:,2), y, \'o\', \'MarkerFaceColor\',\'b\'); " + << "plot3(xq(:,1),xq(:,2), yq, \'ro\', \'MarkerFaceColor\',\'r\'); " + << "hold off; grid on; " + << "legend({\'Ref\' \'Sample\' \'Prediction\'});" + << endl + << "figure; hold on; " + << "syms x1 x2; " + << "h = fsurf(x1^2 + (x1-x2/2)^2, [0 10 0 10]); " + << "h(1).FaceAlpha = 0.2; " + << "scatter3(xq(:,1),xq(:,2), yq, 10^7.*errorEstimate); " + << "hold off; grid on; " + << "legend({\'Ref\' \'Prediction\'});" + << endl; + cout << endl << "%=================================" << endl << endl; +#endif + + delete kinterp; +} + +void tst_interpolators::test_OrdinaryKriging_Fitting() { TVector > x; TVector y; @@ -12386,7 +12661,7 @@ void tst_interpolators::test_Kriging_Fitting() } cout << " === Fixed eta 0.8 ====" << endl; - Kriging* kinterp = new Kriging(); + OrdinaryKriging* kinterp = new OrdinaryKriging(); kinterp->assignVariogram(new PowerVariogram(x, y, 0.8)); cout << "Fixed eta : " << kinterp->variogram()->eta() << endl; cout << "beta : " << kinterp->variogram()->beta()<< endl; @@ -12398,7 +12673,7 @@ void tst_interpolators::test_Kriging_Fitting() cout << "Kriging error (MSE): " << kerr/nq << endl << endl; cout << " === Fixed eta 1.5 ====" << endl; - kinterp = new Kriging(new PowerVariogram(x, y, 1.5)); + kinterp = new OrdinaryKriging(new PowerVariogram(x, y, 1.5)); cout << "Fixed eta : " << kinterp->variogram()->eta() << endl; cout << "beta : " << kinterp->variogram()->beta()<< endl; QCOMPARE(kinterp->variogram()->eta(), 1.5); @@ -12409,7 +12684,7 @@ void tst_interpolators::test_Kriging_Fitting() cout << "Kriging error (MSE): " << kerr/nq << endl << endl; cout << " === Fitted eta ====" << endl; - kinterp = new Kriging(new PowerVariogram(x, y)); + kinterp = new OrdinaryKriging(new PowerVariogram(x, y)); cout << "Fitted eta: " << kinterp->variogram()->eta() << endl; cout << "beta : " << kinterp->variogram()->beta()<< endl; kerr = 0.0; @@ -12421,7 +12696,7 @@ void tst_interpolators::test_Kriging_Fitting() cout << " === eta from Regression ====" << endl; PowerVariogram* vg = new PowerVariogram(x, y); vg->fitVariogramLS(x, y); - kinterp = new Kriging(vg); + kinterp = new OrdinaryKriging(vg); cout << "eta from regression : " << kinterp->variogram()->eta() << endl; cout << "beta from regression : " << kinterp->variogram()->beta() << endl; kerr = 0.0; @@ -12431,12 +12706,7 @@ void tst_interpolators::test_Kriging_Fitting() cout << "Kriging error (MSE): " << kerr/nq << endl << endl; } -double inline func1D(double x) -{ - return (x+1.0)*std::sin(std::pow(x, 2))+15; // shift it up by 30 -} - -void tst_interpolators::test_Kriging_ErrorEstimates_1DExample() +void tst_interpolators::test_OrdinaryKriging_ErrorEstimates_1DExample() { TVector > x; TVector y; @@ -12497,8 +12767,8 @@ void tst_interpolators::test_Kriging_ErrorEstimates_1DExample() yy[i] = func1D(xx[i][0]); } - Kriging* kinterp = new Kriging(new PowerVariogram(x, y, 1.9999)); - kinterp->estimateErrors(true); + OrdinaryKriging* kinterp = new OrdinaryKriging(new PowerVariogram(x, y, 1.9999)); + kinterp->defineEstimateErrors(true); cout << "eta : " << kinterp->variogram()->eta() << endl; cout << "beta : " << kinterp->variogram()->beta()<< endl; @@ -12523,8 +12793,8 @@ void tst_interpolators::test_Kriging_ErrorEstimates_1DExample() #ifdef KRIGING_PLOT_IN_MATLAB cout<< "%Matlab command for plotting =========== " << endl << endl; cout << "close all; clear;" << endl; - vector2DToMatlabCommand("x1", x.mid(0, n1)); - vector2DToMatlabCommand("x2", x.mid(n1,n1+n2)); + vector2DToMatlabCommand("x1", mid(x,0, n1)); + vector2DToMatlabCommand("x2", mid(x,n1,n1+n2)); vector1DToMatlabCommand("y", y); vector2DToMatlabCommand("xq", xq); vector1DToMatlabCommand("yq", yq); @@ -12552,7 +12822,7 @@ void tst_interpolators::test_Kriging_ErrorEstimates_1DExample() #endif } -void tst_interpolators::test_Kriging_ErrorEstimates_2DExample() +void tst_interpolators::test_OrdinaryKriging_ErrorEstimates_2DExample() { TVector > x; TVector y; @@ -12595,8 +12865,8 @@ void tst_interpolators::test_Kriging_ErrorEstimates_2DExample() yqref[i] = std::pow(xq[i][0], 2) + std::pow(xq[i][0] - xq[i][1]/2.0, 2); } - Kriging* kinterp = new Kriging(new PowerVariogram(x, y)); - kinterp->estimateErrors(true); + OrdinaryKriging* kinterp = new OrdinaryKriging(new PowerVariogram(x, y)); + kinterp->defineEstimateErrors(true); cout << "eta : " << kinterp->variogram()->eta() << endl; cout << "beta : " << kinterp->variogram()->beta()<< endl; @@ -12629,8 +12899,8 @@ void tst_interpolators::test_Kriging_ErrorEstimates_2DExample() #ifdef KRIGING_PLOT_IN_MATLAB // Matlab command for plotting cout << "close all; clear;" << endl; - vector2DToMatlabCommand("x1", x.mid(0, n1)); - vector2DToMatlabCommand("x2", x.mid(n1,n1+n2)); + vector2DToMatlabCommand("x1", mid(x,0, n1)); + vector2DToMatlabCommand("x2", mid(x,n1,n1+n2)); vector1DToMatlabCommand("y", y); vector2DToMatlabCommand("xq", xq); vector1DToMatlabCommand("yq", yq); @@ -12647,7 +12917,7 @@ void tst_interpolators::test_Kriging_ErrorEstimates_2DExample() #endif } -void tst_interpolators::test_Kriging_SimpleExample() +void tst_interpolators::test_OrdinaryKriging_SimpleExample() { TVector > x(7); TVector y(7); @@ -12669,13 +12939,13 @@ void tst_interpolators::test_Kriging_SimpleExample() xq[0] = 65; xq[1] = 137; - Kriging* kinterp = new Kriging(new PowerVariogram(x, y)); - kinterp->estimateErrors(true); + OrdinaryKriging* kinterp = new OrdinaryKriging(new PowerVariogram(x, y)); + kinterp->defineEstimateErrors(true); double yq = kinterp->interpolate(xq); qDebug() << yq; } -void tst_interpolators::test_KrigingAssignVariogram() +void tst_interpolators::test_OrdinaryKrigingAssignVariogram() { using namespace Tigon; TVector > x; @@ -12710,7 +12980,7 @@ void tst_interpolators::test_KrigingAssignVariogram() yqref[i] = std::pow(xq[i][0], 3) + std::pow(xq[i][1] - xq[i][2], 2); } - Kriging* kinterp = new Kriging(); + OrdinaryKriging* kinterp = new OrdinaryKriging(); kinterp->assignVariogram(new PowerVariogram(x, y, 0.8)); cout << "Num of samples: " << kinterp->variogram()->inputData().size() << endl; diff --git a/tests/auto/test_tigon/test_parego/tst_parego.cpp b/tests/auto/test_tigon/test_parego/tst_parego.cpp index c7b206c..094a594 100644 --- a/tests/auto/test_tigon/test_parego/tst_parego.cpp +++ b/tests/auto/test_tigon/test_parego/tst_parego.cpp @@ -83,7 +83,6 @@ void tst_parego::test_SurrogateBasedOptimizer() int popSize = 100; int budget = popSize+nDirs*1; int maxSurrogateSize = 50; - double nRaduis = 0.2; PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); @@ -109,7 +108,6 @@ void tst_parego::test_SurrogateBasedOptimizer() scal->TP_defineWeightScopeApproach(Tigon::GlobalWeight); filt->TP_defineMaxSolutions(maxSurrogateSize); opt->TP_defineErrorMethod(Tigon::ErrDensityBased); - opt->TP_defineNeighbourhoodRadius(nRaduis); eval->evaluate(); ISet* oSet = eval->outputSet(0); @@ -135,7 +133,6 @@ void tst_parego::test_ParEGO_workflow() int popSize = 100; int budget = popSize+nDirs*1; int maxSurrogateSize = 50; - double nRaduis = 0.2; PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); @@ -162,7 +159,6 @@ void tst_parego::test_ParEGO_workflow() scal->TP_defineWeightScopeApproach(Tigon::GlobalWeight); filt->TP_defineMaxSolutions(maxSurrogateSize); opt->TP_defineErrorMethod(Tigon::ErrDensityBased); - opt->TP_defineNeighbourhoodRadius(nRaduis); while(opt->remainingBudget() > 0) { opt->evaluate(); @@ -204,7 +200,6 @@ void tst_parego::test_ParEGO() int popSize = 100; int budget = popSize+nDirs*1; int maxSurrogateSize = 50; - double nRaduis = 0.2; PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); @@ -220,7 +215,6 @@ void tst_parego::test_ParEGO() init->TP_defineSetSize(popSize); alg->defineReferenceSetSize(nDirs); alg->TP_defineMaxSolutions(maxSurrogateSize); - alg->TP_defineNeighbourhoodRadius(nRaduis); alg->defineBudget(budget); while(alg->remainingBudget() > 0) { diff --git a/tests/manual/manual_tigon/manual_parego/manual_parego.cpp b/tests/manual/manual_tigon/manual_parego/manual_parego.cpp index 79839b7..53d9103 100644 --- a/tests/manual/manual_tigon/manual_parego/manual_parego.cpp +++ b/tests/manual/manual_tigon/manual_parego/manual_parego.cpp @@ -43,7 +43,6 @@ void bmk_ParEGO_DTLZ2() int popSize = 100; int budget = popSize+nDirs*10; int maxSurrogateSize = 50; - double nRaduis = 0.2; PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); @@ -61,7 +60,6 @@ void bmk_ParEGO_DTLZ2() alg->defineReferenceSetSize(nDirs); alg->defineScalarisingFunction(Tigon::WeightedChebyshevAugmented); alg->TP_defineMaxSolutions(maxSurrogateSize); - alg->TP_defineNeighbourhoodRadius(nRaduis); alg->defineBudget(budget); From dd579d40aab4831af4a191efe4a0b4d5672efe4c Mon Sep 17 00:00:00 2001 From: "Joao A. Duro" Date: Fri, 1 Jan 2021 16:40:29 +0000 Subject: [PATCH 3/7] Add tests --- src/libs/tigon/Tigon.h | 3 + src/libs/tigon/tigon.pro | 14 + .../test_tigon/test_parego/tst_parego.cpp | 1751 ++++++++++++++++- 3 files changed, 1745 insertions(+), 23 deletions(-) diff --git a/src/libs/tigon/Tigon.h b/src/libs/tigon/Tigon.h index 9e16d90..5ae6033 100644 --- a/src/libs/tigon/Tigon.h +++ b/src/libs/tigon/Tigon.h @@ -78,6 +78,8 @@ #include #include #include +#include +#include #include #include #include @@ -135,6 +137,7 @@ #include #include #include +#include // Operators - Convergence #include diff --git a/src/libs/tigon/tigon.pro b/src/libs/tigon/tigon.pro index 0c76158..fe3eee3 100644 --- a/src/libs/tigon/tigon.pro +++ b/src/libs/tigon/tigon.pro @@ -149,6 +149,13 @@ SOURCES += \ Representation/Functions/SurrogateModelling/Likelihood.cpp \ Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.cpp \ Representation/Functions/SingleObjective/Alpine2.cpp \ + Representation/Functions/SingleObjective/ConstrainedProblems.cpp \ + Representation/Functions/SingleObjective/BraninGomez.cpp \ + Representation/Functions/SingleObjective/Camel.cpp \ + Representation/Functions/SingleObjective/Sasena.cpp \ + Representation/Functions/SingleObjective/CBranin.cpp \ + Representation/Functions/SingleObjective/CBraninM1.cpp \ + Representation/Functions/SingleObjective/Poly1.cpp \ Utils/ScalarisingFunctions.cpp \ Utils/ProjectionUtils.cpp \ Utils/NormalisationUtils.cpp \ @@ -414,6 +421,13 @@ HEADERS += \ Representation/Functions/SurrogateModelling/Likelihood.h \ Representation/Functions/SurrogateModelling/ProbabilityFeasibilityBagheri.h \ Representation/Functions/SingleObjective/Alpine2.h \ + Representation/Functions/SingleObjective/ConstrainedProblems.h \ + Representation/Functions/SingleObjective/BraninGomez.h \ + Representation/Functions/SingleObjective/Camel.h \ + Representation/Functions/SingleObjective/Sasena.h \ + Representation/Functions/SingleObjective/CBranin.h \ + Representation/Functions/SingleObjective/CBraninM1.h \ + Representation/Functions/SingleObjective/Poly1.h \ Operators/Formulations/IFormulation.h \ Representation/Problems/Problem.h \ Representation/Properties/FunctionPropertiesData.h \ diff --git a/tests/auto/test_tigon/test_parego/tst_parego.cpp b/tests/auto/test_tigon/test_parego/tst_parego.cpp index 094a594..49e037d 100644 --- a/tests/auto/test_tigon/test_parego/tst_parego.cpp +++ b/tests/auto/test_tigon/test_parego/tst_parego.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2020 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -21,15 +21,16 @@ #include -#define TST_PAREGO_OPERATORS -#define PAREGO_WORK_FLOW - using namespace std; using namespace Tigon; using namespace Tigon::Representation; using namespace Tigon::Operators; using namespace Tigon::Algorithms; +#define TST_PAREGO_OPERATORS +#define PAREGO_WORK_FLOW +//#define PLOT_IN_MATLAB + //TESTED_COMPONENT=src/libs/tigon/.... class tst_parego : public QObject { @@ -39,7 +40,16 @@ class tst_parego : public QObject private slots: #ifdef TST_PAREGO_OPERATORS + void test_ExpectedImprovement_Alpine2Func(); + void test_RandExpectedImprovement_Alpine2Func(); + void test_ExpectedImprovement_Poly1Func(); + void test_FeasibleExpectedImprovement(); + void test_FeasibleRandExpectedImprovement(); + void test_ProbabilityFeasibility(); + void test_ProbabilityFeasibilityModified(); + void test_ConstrainedExpectedImprovement(); void test_SurrogateBasedOptimizer(); + void test_ConstrainedSurrogateBasedOptimizer(); #endif #ifdef PAREGO_WORK_FLOW @@ -50,7 +60,7 @@ private slots: inline void dispVector(TVector vec, string sep = "\t", string endLine = "\n") { - for(int i=0; i vec, string sep = "\t", string endLine = inline void writeVector(QTextStream &st, TVector vec, QString sep = "\t", QString endLine = "\n") { - for(int i=0; i vec, QString sep = "\t" st << endLine; } - #ifdef TST_PAREGO_OPERATORS +void tst_parego::test_ExpectedImprovement_Alpine2Func() +{ + // Use one IPSet to evaluate a set of solutions on a single objective + // problem + PSetBase* base = new PSetBase(); + IFormulation* prob = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(prob); + Evaluator* eval = new Evaluator(init); + eval->TP_defineSingleObjective(true); + + IFunctionSPtr func = IFunctionSPtr(new Alpine2); + func->TP_defineNInputs(1); + prob->appendFunction(func); + prob->evaluate(); + + ISet* providedPoints = new ISet; + for(double i=0.0; i<=10.0; i+=2.3) { + IMappingSPtr imap = prob->createOptimizationMapping(providedPoints); + imap->defineDecisionVar(0, IElement(i)); + } + for(double i=0.6; i<10.0; i*=2) { + IMappingSPtr imap = prob->createOptimizationMapping(providedPoints); + imap->defineDecisionVar(0, IElement(i)); + } + init->defineInitialSet(providedPoints); + + eval->evaluate(); + + + /// Use a new IPSet to evaluate a dense set of solutions on the Kriging + /// model and to evaluate its expected improvement + + // Fit a Kriging model to the evaluated pionts + ISet* eSet = init->outputSet(0); + TVector > xx; + TVector yy; + for(auto sol : eSet->all()) { + // decision vector + xx.push_back(sol->doubleDecisionVec()); + // function value + yy.push_back(sol->doubleCost()); + } + + DACE* kinterp = new DACE(); + kinterp->updateData(xx, yy); + KrigingSPtr km = KrigingSPtr(kinterp); +// PowerVariogram* powerV = new PowerVariogram(xx, yy); +// KrigingSPtr km = KrigingSPtr(new OrdinaryKriging(powerV)); + km->defineEstimateErrors(true); + + // Construct the expected improvement function + IFunctionSPtr func2 = IFunctionSPtr(new ExpectedImprovement(km)); + + // Create the new IPSet + PSetBase* base2 = new PSetBase(); + IFormulation* prob2 = new IFormulation(base2); + UserDefinedInit* init2 = new UserDefinedInit(prob2); + Evaluator* eval2 = new Evaluator(init2); + + prob2->appendFunction(func2); + prob2->evaluate(); + + // Create query points + TVector xq; + ISet* queryPoints = new ISet; + for(double x=0.0; x<=10.0; x += 0.01) { + xq.push_back(x); + IMappingSPtr imap = prob2->createOptimizationMapping(queryPoints); + imap->defineDecisionVar(0, IElement(x)); + } + init2->defineInitialSet(queryPoints); + + eval2->TP_defineSingleObjective(true); + eval2->evaluate(); + + TVector valueEI; valueEI.reserve(xq.size()); + TVector errorEI; errorEI.reserve(xq.size()); + + ExpectedImprovement* fExpImpr = + static_cast(func2.get()); + for(auto sol : queryPoints->all()) { + // to get the appropriate error always call value() first + valueEI.push_back(fExpImpr->value(sol->decisionVec())); + errorEI.push_back(fExpImpr->error(sol->decisionVec())); + } + +#ifdef PLOT_IN_MATLAB + // write the results to an .m file: + QFile file("tst_expectedImprovement.m"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + QTextStream out(&file); + + out << "% Evaluated points:" << endl; + + out << "xx = ["; + for(auto x : xx) { + writeVector(out, x," ","; "); + } + out << "];" << endl; + + out << "yy = ["; + for(auto y : yy) { + out << y << "; "; + } + out << "];" << endl<< endl; + + // query points + out << "% Model estimation:" << endl << "xq = ["; + for(auto x : xq) { + out << x << "; "; + } + out << "];" << endl; + + + out << "yq = ["; + for(auto value : valueEI) { + out << value << "; "; + } + out << "];" << endl; + + out << "err = ["; + for(auto error: errorEI) { + out << error << "; "; + } + out << "];" << endl << endl; + + ISet* expImp = init2->outputSet(0); + out << "% Expected improvement:" << endl; + out << "expImp = ["; + for(auto sol : expImp->all()) { + double ei = sol->doubleCost(); + out << -ei << "; "; + } + out << "];" << endl; + + out << "syms x;\n" + "y = -sqrt(x).*sin(x);" << endl; + + out << "% Plot the results\n" + "figure; hold on;\n" + "yyaxis left;\n" + "realFunc = fplot(y,[0 10]);\n" + "TigonReal = plot(xx,yy,'ok','MarkerFaceColor','k');\n" + "Model = plot(xq, yq, '--r', 'lineWidth', 2);\n" + "ExpectedImprovement = plot(xq, expImp, '-.g');\n\n" + "ylabel('$y = -\\sqrt{x}\\sin{x}$','Interpreter','latex','FontSize',24);\n" + "yyaxis right;\n" + "Error = plot(xq, err, 'r');\n" + "ylabel('Estimation error ($\\hat{\\sigma}$)','Interpreter','latex','FontSize',24);\n" + "legend([realFunc, TigonReal, Model, ExpectedImprovement, Error],...\n" + "'Real function', 'Sample points', ...\n" + "'Kriging estimation', 'Expected improvement', " + "'Estimation error',...\n" + "'location', 'northWest');\n" + "xlabel('Decision space','FontSize',24);\n" + "grid on;\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('ExpectedImprovement_KrigingEstimatedError_Alpine2.png','-dpng');" << endl; + file.close(); +#endif + + delete eval2; + delete init2; + delete prob2; + delete base2; + delete eval; + delete init; + delete prob; + delete base; +} + +void tst_parego::test_RandExpectedImprovement_Alpine2Func() +{ + // Use one IPSet to evaluate a set of solutions on a single objective + // problem + PSetBase* base = new PSetBase(); + IFormulation* prob = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(prob); + Evaluator* eval = new Evaluator(init); + eval->TP_defineSingleObjective(true); + + IFunctionSPtr func = IFunctionSPtr(new Alpine2); + func->TP_defineNInputs(1); + prob->appendFunction(func); + prob->evaluate(); + + ISet* providedPoints = new ISet; + for(double i=0.0; i<=10.0; i+=2.3) { + IMappingSPtr imap = prob->createOptimizationMapping(providedPoints); + imap->defineDecisionVar(0, IElement(i)); + } + for(double i=0.6; i<10.0; i*=2) { + IMappingSPtr imap = prob->createOptimizationMapping(providedPoints); + imap->defineDecisionVar(0, IElement(i)); + } + init->defineInitialSet(providedPoints); + + eval->evaluate(); + + + /// Use a new IPSet to evaluate a dense set of solutions on the Kriging + /// model and to evaluate its expected improvement + + // Fit a Kriging model to the evaluated pionts + ISet* eSet = init->outputSet(0); + TVector > xx; + TVector yy; + for(auto sol : eSet->all()) { + // decision vector + xx.push_back(sol->doubleDecisionVec()); + // function value + yy.push_back(sol->doubleCost()); + } + + DACE* kinterp = new DACE(); + kinterp->updateData(xx, yy); + KrigingSPtr km = KrigingSPtr(kinterp); +// PowerVariogram* powerV = new PowerVariogram(xx, yy); +// KrigingSPtr km = KrigingSPtr(new OrdinaryKriging(powerV)); + km->defineEstimateErrors(true); + + // Construct the rand expected improvement function + IFunctionSPtr func2 = IFunctionSPtr(new RandExpectedImprovement(km)); + + // Create the new IPSet + PSetBase* base2 = new PSetBase(); + IFormulation* prob2 = new IFormulation(base2); + UserDefinedInit* init2 = new UserDefinedInit(prob2); + Evaluator* eval2 = new Evaluator(init2); + eval2->TP_defineSingleObjective(true); + + // Create an IFunction from the Kriging model + prob2->appendFunction(func2); + prob2->evaluate(); + + // Create query points + TVector xq; + ISet* queryPoints = new ISet; + for(double x=0.0; x<=10.0; x += 0.01) { + xq.push_back(x); + IMappingSPtr imap = prob2->createOptimizationMapping(queryPoints); + imap->defineDecisionVar(0, IElement(x)); + } + init2->defineInitialSet(queryPoints); + + eval2->TP_defineSingleObjective(true); + eval2->evaluate(); + +#ifdef PLOT_IN_MATLAB + // write the results to an .m file: + QFile file("tst_randExpectedImprovement.m"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + QTextStream out(&file); + ISet* expImp = init2->outputSet(0); + + out << "% Evaluated points:" << endl; + + out << "xx = ["; + for(auto x : xx) { + writeVector(out, x," ","; "); + } + out << "];" << endl; + + out << "yy = ["; + for(auto y : yy) { + out << y << "; "; + } + out << "];" << endl<< endl; + + out << "% Model estimation:" << endl << "xq = ["; + for(auto x : xq) { + out << x << "; "; + } + out << "];" << endl; + + RandExpectedImprovement* randExp = + static_cast(func2.get()); + out << "yq = ["; + for(auto sol : queryPoints->all()) { + double yq = randExp->value(sol->decisionVec()); + out << yq << "; "; + } + out << "];" << endl; + + out << "err = ["; + for(auto sol : queryPoints->all()) { + double err = randExp->error(sol->decisionVec()); + out << err << "; "; + } + out << "];" << endl << endl; + + double h = randExp->bandwidth(); + TVector> samples = randExp->samples(); + out << "% Density with bandwidth = " << h << endl << "density = ["; + for(auto sol : queryPoints->all()) { + double density = gaussianKDE(samples, sol->doubleDecisionVec(), h); + out << density << "; "; + } + out << "];" << endl << endl; + + + out << "% Expected improvement:" << endl; + out << "expImp = ["; + for(auto sol : expImp->all()) { + double ei = sol->doubleCost(); + out << -ei << "; "; + } + out << "];" << endl; + + out << "syms x;\n" + "y = -sqrt(x).*sin(x);" << endl; + + out << "% Plot the results\n" + "figure; hold on;\n" + "yyaxis left;\n" + "realFunc = fplot(y,[0 10]);\n" + "TigonReal = plot(xx,yy,'ok','MarkerFaceColor','k');\n" + "Model = plot(xq, yq, '--r', 'lineWidth', 2);\n" + "ExpectedImprovement = plot(xq, expImp, '-.g');\n\n" + "ylabel('$y = -\\sqrt{x}\\sin{x}$','Interpreter','latex','FontSize',24);\n" + "yyaxis right;\n" + "Density = plot(xq, density, 'k');" + "UnscaledError = plot(xq, atan(1./density).*(2/pi), 'y');" + "Error = plot(xq, err, 'r');\n" + "ylabel('Estimation error ($\\hat{\\sigma}$)','Interpreter','latex','FontSize',24);\n" + "legend([realFunc, TigonReal, Model, ExpectedImprovement, Density, UnscaledError, Error],...\n" + "'Real function', 'Sample points', ...\n" + "'Kriging estimation', 'Expected improvement', 'Density with bandwidth: " << h << " '," << " ...\n" + "'Unscaled estimation error', 'Estimation error', ...\n" + "'location', 'northWest');\n" + "xlabel('Decision space','FontSize',24);\n" + "grid on;\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('RandExpectedImprovement_KernelDensityBasedError_Alpine2.png','-dpng');" << endl; + file.close(); +#endif + + delete eval2; + delete init2; + delete prob2; + delete base2; + delete eval; + delete init; + delete prob; + delete base; +} + +void tst_parego::test_ExpectedImprovement_Poly1Func() +{ + // Use one IPSet to evaluate a set of solutions on a single objective + // problem + PSetBase* base = new PSetBase(); + IFormulation* prob = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(prob); + Evaluator* eval = new Evaluator(init); + eval->TP_defineSingleObjective(true); + + IFunctionSPtr func = IFunctionSPtr(new Poly1); + func->TP_defineNInputs(1); + prob->appendFunction(func); + prob->evaluate(); + + ISet* providedPoints = new ISet; + // points + TVector training_points; + training_points << 0.0 << 0.15 << 0.24 << 0.31 << 0.33 << 0.36 << 0.5 << 1.0; + + for(auto point : training_points) { + IMappingSPtr imap = prob->createOptimizationMapping(providedPoints); + imap->defineDecisionVar(0, IElement(point)); + } + + init->defineInitialSet(providedPoints); + eval->evaluate(); + + /// Use a new IPSet to evaluate a dense set of solutions on the Kriging + /// model and to evaluate its expected improvement + + // Fit a Kriging model to the evaluated pionts + ISet* eSet = init->outputSet(0); + TVector > xx; + TVector yy; + for(auto sol : eSet->all()) { + // decision vector + xx.push_back(sol->doubleDecisionVec()); + // function value + yy.push_back(sol->doubleCost()); + } + + DACE* kinterp = new DACE(); + kinterp->updateData(xx, yy); + KrigingSPtr km = KrigingSPtr(kinterp); +// PowerVariogram* powerV = new PowerVariogram(xx, yy); +// KrigingSPtr km = KrigingSPtr(new OrdinaryKriging(powerV)); + km->defineEstimateErrors(true); + + // Construct the expected improvement function + IFunctionSPtr func2 = IFunctionSPtr(new ExpectedImprovement(km)); + + // Create the new IPSet + PSetBase* base2 = new PSetBase(); + IFormulation* prob2 = new IFormulation(base2); + UserDefinedInit* init2 = new UserDefinedInit(prob2); + Evaluator* eval2 = new Evaluator(init2); + + prob2->appendFunction(func2); + prob2->evaluate(); + + // Create query points + TVector xq; + ISet* queryPoints = new ISet; + for(double x=0.0; x<=(1.0+Tigon::Epsilon); x += 0.001) { + xq.push_back(x); + IMappingSPtr imap = prob2->createOptimizationMapping(queryPoints); + imap->defineDecisionVar(0, IElement(x)); + } + init2->defineInitialSet(queryPoints); + + eval2->TP_defineSingleObjective(true); + eval2->evaluate(); + + TVector valueEI; valueEI.reserve(xq.size()); + TVector errorEI; errorEI.reserve(xq.size()); + + ExpectedImprovement* fExpImpr = + static_cast(func2.get()); + for(auto sol : queryPoints->all()) { + // to get the appropriate error always call value() first + valueEI.push_back(fExpImpr->value(sol->decisionVec())); + errorEI.push_back(fExpImpr->error(sol->decisionVec())); + } + +#ifdef PLOT_IN_MATLAB + // write the results to an .m file: + QFile file("tst_expectedImprovement_Poly1.m"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + QTextStream out(&file); + + out << "% Evaluated points:" << endl; + + out << "xx = ["; + for(auto x : xx) { + writeVector(out, x," ","; "); + } + out << "];" << endl; + + out << "yy = ["; + for(auto y : yy) { + out << y << "; "; + } + out << "];" << endl<< endl; + + out << "% Model estimation:" << endl << "xq = ["; + for(auto x : xq) { + out << x << "; "; + } + out << "];" << endl; + + out << "yq = ["; + for(auto value : valueEI) { + out << value << "; "; + } + out << "];" << endl; + + out << "err = ["; + for(auto error: errorEI) { + out << error << "; "; + } + out << "];" << endl << endl; + + ISet* expImp = init2->outputSet(0); + out << "% Expected improvement:" << endl; + out << "expImp = ["; + for(auto sol : expImp->all()) { + double ei = sol->doubleCost(); + out << -ei << "; "; + } + out << "];" << endl; + + out << "syms x;\n" + "y = (6*x-2)^2 * sin(12*x-4);" << endl; + + out << "% Plot the results\n" + "figure; hold on;\n" + "yyaxis left;\n" + "realFunc = fplot(y,[0 1]);\n" + "TigonReal = plot(xx,yy,'ok','MarkerFaceColor','k');\n" + "Model = plot(xq, yq, '--r', 'lineWidth', 2);\n" + "ExpectedImprovement = plot(xq, expImp, '-.g');\n\n" + "ylabel('$y = (6x-2)^2 \\sin(12x-4)$','Interpreter','latex','FontSize',24);\n" + "yyaxis right;\n" + "Error = plot(xq, err), 'r');\n" + "ylabel('Estimation error ($\\hat{\\sigma}$)','Interpreter','latex','FontSize',24);\n" + "ylim([0 4]);\n" + "legend([realFunc, TigonReal, Model, ExpectedImprovement, Error],...\n" + "'Real function', 'Sample points', ...\n" + "'Kriging estimation', 'Expected improvement', " + "'Estimation error',...\n" + "'location', 'northWest');\n" + "xlabel('Decision space','FontSize',24);\n" + "grid on;\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('ExpectedImprovement_KrigingEstimatedError_Poly1.png','-dpng');" << endl; + file.close(); +#endif + + delete eval2; + delete init2; + delete prob2; + delete base2; + delete eval; + delete init; + delete prob; + delete base; +} + +void tst_parego::test_FeasibleExpectedImprovement() +{ + // Use one IPSet to evaluate a set of solutions on a single objective + // problem + PSetBase* base = new PSetBase(); + IFormulation* prob = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(prob); + Evaluator* eval = new Evaluator(init); + eval->TP_defineSingleObjective(true); + + IFunctionSPtr func = IFunctionSPtr(new CBraninM1); + ProblemSPtr problem(new Problem); + problem->appendFunction(func, TVector(), TVector({1})); + problem->processProblemDefinition(); + + TVector threshVec({0.0}); + TVector types({RealType}); + TVector thVec = createIElementSPtrVector(threshVec, types); + problem->defineThresholdVector(thVec); + problem->processProblemDefinition(); + + prob->defineProblem(problem); + prob->evaluate(); + + ISet* providedPoints = new ISet; + // Generate 6 points + TVector> training_points; + training_points << TVector({0.25, 0.24}); // infeasible + training_points << TVector({0.08, 0.58}); // infeasible + training_points << TVector({0.75, 0.06}); // infeasible + training_points << TVector({0.42, 0.92}); // feasible + training_points << TVector({0.58, 0.42}); // feasible + training_points << TVector({0.91, 0.75}); // feasible + + for(auto point : training_points) { + IMappingSPtr imap = prob->createOptimizationMapping(providedPoints); + imap->defineDecisionVar(0, IElement(point[0])); + imap->defineDecisionVar(1, IElement(point[1])); + } + + init->defineInitialSet(providedPoints); + + eval->evaluate(); + + + /// Use a new IPSet to evaluate a dense set of solutions on the Kriging + /// model and to evaluate its expected improvement + + // Fit a Kriging model to the evaluated points + ISet* eSet = init->outputSet(0); + TVector > xx; + TVector yy; + for(auto sol : eSet->all()) { + // decision vector + xx.push_back(sol->doubleDecisionVec()); + // function value + yy.push_back(sol->doubleCost()); + } + + DACE* kinterp = new DACE(); + kinterp->updateData(xx, yy); + KrigingSPtr km = KrigingSPtr(kinterp); +// PowerVariogram* powerV = new PowerVariogram(xx, yy); +// KrigingSPtr km = KrigingSPtr(new OrdinaryKriging(powerV)); + km->defineEstimateErrors(true); + + // Calculate constraint violation of the evaluated points + TVector cViolation; + cViolation.reserve(eSet->size()); + for(auto sol : eSet->all()) { + double violation = solutionConstraintViolation(sol, threshVec); + cViolation.push_back(violation); + } + + // Create an IFunction from the Kriging model + IFunctionSPtr func2 = IFunctionSPtr(new ExpectedImprovement(km)); + IFunctionSPtr func3 = IFunctionSPtr(new FeasibleExpectedImprovement(km, cViolation)); + + // Create the new IPSet + PSetBase* base2 = new PSetBase(); + IFormulation* prob2 = new IFormulation(base2); + UserDefinedInit* init2 = new UserDefinedInit(prob2); + Evaluator* eval2 = new Evaluator(init2); + + prob2->appendFunction(func2); + prob2->appendFunction(func3); + prob2->evaluate(); + + // Create query points + TVector> xq; + ISet* queryPoints = new ISet; + for(double x1=0.0; x1<=(1.0+Tigon::Epsilon); x1 += 0.01) { + for(double x2=0.0; x2<=(1.0+Tigon::Epsilon); x2 += 0.01) { + xq.push_back(TVector({x1, x2})); + IMappingSPtr imap = prob2->createOptimizationMapping(queryPoints); + imap->defineDecisionVar(0, IElement(x1)); + imap->defineDecisionVar(1, IElement(x2)); + imap->defineEvaluated(false); + } + } + init2->defineInitialSet(queryPoints); + + eval2->evaluate(); + + TVector valueFEI; valueFEI.reserve(xq.size()); + TVector errorFEI; errorFEI.reserve(xq.size()); + + FeasibleExpectedImprovement* fExpImp = + static_cast(func3.get()); + for(auto sol : queryPoints->all()) { + // to get the appropriate error always call value() first + valueFEI.push_back(fExpImp->value(sol->decisionVec())); + errorFEI.push_back(fExpImp->error(sol->decisionVec())); + } + +#ifdef PLOT_IN_MATLAB + // write the results to an .m file: + QFile file("tst_feasibleExpectedImprovement_CBraninM1.m"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + QTextStream out(&file); + ISet* expImp = init2->outputSet(0); + + out << "% Evaluated points:" << endl; + + out << "xx = ["; + for(auto x : xx) { + writeVector(out, x," ","; "); + } + out << "];" << endl; + + out << "yy = ["; + for(auto y : yy) { + out << y << "; "; + } + out << "];" << endl<< endl; + + // query points + out << "% Model estimation:" << endl << "xq = ["; + for(auto xvec : xq) { + out << "["; + for(auto x : xvec) { + out << x << " "; + } + out << "]; "; + } + out << "];" << endl; + + out << "yq = ["; + for(auto value : valueFEI) { + out << value << "; "; + } + out << "];" << endl; + + out << "err = ["; + for(auto error: errorFEI) { + out << error << "; "; + } + out << "];" << endl << endl; + + out << "% Expected Improvement:" << endl; + out << "expImp = ["; + for(auto sol : expImp->all()) { + double ei = sol->doubleObjectiveVar(0); + out << -ei << "; "; + } + out << "];" << endl; + + out << "% Feasible Expected Improvement:" << endl; + out << "fExpImp = ["; + for(auto sol : expImp->all()) { + double fei = sol->doubleObjectiveVar(1); + out << -fei << "; "; + } + out << "];" << endl; + + out << "\n% Plot the results\n" + "figure(1);\n" + "ModelX = reshape(xq(:,1),[101, 101]);\n" + "ModelY = reshape(xq(:,2),[101, 101]);\n" + "ModelBranin = reshape(yq,[101, 101]);\n" + "BraninFuncContour = contourf(ModelX,ModelY,ModelBranin,30);\n" + "hold on;\n" + "TrainingPoints = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc.LineWidth=3.0;\n" + "colorbar;\n" + "xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Kriging prediction of the Branin function');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('KrigingModelPrediction_CBraninM1.png','-dpng');" + "\n" + "figure(2);\n" + "ModelError = reshape(err,[101, 101]);\n" + "BraninFuncContour = contourf(ModelX,ModelY,ModelError,30);\n" + "hold on;\n" + "TrainingPoints = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc.LineWidth=3.0;\n" + "colorbar;\n" + "xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Kriging prediction error of the Branin function');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('KrigingModelError_CBraninM1.png','-dpng');" + "\n" + "figure(3);\n" + "ExpImp = reshape(expImp,[101, 101]);\n" + "ExpectedImprovement = contourf(ModelX,ModelY,ExpImp,30);\n" + "hold on;\n" + "TrainingPoints = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc.LineWidth=3.0;\n" + "colorbar;\n" + "xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Expected Improvement');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('ExpImp_CBraninM1.png','-dpng');" + "\n" + "figure(4);\n" + "FExpImp = reshape(fExpImp,[101, 101]);\n" + "FExpectedImprovement = contourf(ModelX,ModelY,FExpImp,30);\n" + "hold on;\n" + "TrainingPoints = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc.LineWidth=3.0;\n" + "colorbar;\n" + "xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Feasible Expected Improvement');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('FExpImp_CBraninM1.png','-dpng');" + "\n" << endl; + file.close(); +#endif + + delete eval2; + delete init2; + delete prob2; + delete base2; + delete eval; + delete init; + delete prob; + delete base; +} + +void tst_parego::test_FeasibleRandExpectedImprovement() +{ + // Use one IPSet to evaluate a set of solutions on a single objective + // problem + PSetBase* base = new PSetBase(); + IFormulation* prob = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(prob); + Evaluator* eval = new Evaluator(init); + eval->TP_defineSingleObjective(true); + + IFunctionSPtr func = IFunctionSPtr(new CBraninM1); + ProblemSPtr problem(new Problem); + problem->appendFunction(func, TVector(), TVector({1})); + problem->processProblemDefinition(); + + TVector threshVec({0.0}); + TVector types({RealType}); + TVector thVec = createIElementSPtrVector(threshVec, types); + problem->defineThresholdVector(thVec); + problem->processProblemDefinition(); + + prob->defineProblem(problem); + prob->evaluate(); + + ISet* providedPoints = new ISet; + // Generate 6 points + TVector> training_points; + training_points << TVector({0.25, 0.24}); // infeasible + training_points << TVector({0.08, 0.58}); // infeasible + training_points << TVector({0.75, 0.06}); // infeasible + training_points << TVector({0.42, 0.92}); // feasible + training_points << TVector({0.58, 0.42}); // feasible + training_points << TVector({0.91, 0.75}); // feasible + + for(auto point : training_points) { + IMappingSPtr imap = prob->createOptimizationMapping(providedPoints); + imap->defineDecisionVar(0, IElement(point[0])); + imap->defineDecisionVar(1, IElement(point[1])); + } + + init->defineInitialSet(providedPoints); + + eval->evaluate(); + + // Fit a Kriging model to the evaluated points + ISet* eSet = init->outputSet(0); + TVector > xx; + TVector yy; + for(auto sol : eSet->all()) { + // decision vector + xx.push_back(sol->doubleDecisionVec()); + // function value + yy.push_back(sol->doubleCost()); + } + + DACE* kinterp = new DACE(); + kinterp->updateData(xx, yy); + KrigingSPtr km = KrigingSPtr(kinterp); +// PowerVariogram* powerV = new PowerVariogram(xx, yy); +// KrigingSPtr km = KrigingSPtr(new OrdinaryKriging(powerV)); + km->defineEstimateErrors(true); + + /// Use a new IPSet to evaluate a dense set of solutions on the Kriging + /// model and to evaluate its expected improvement + + // Calculate constraint violation of every evaluated solution + TVector cViolation; + cViolation.reserve(eSet->size()); + for(auto sol : eSet->all()) { + double violation = solutionConstraintViolation(sol, threshVec); + cViolation.push_back(violation); + } + + // Expected improvement results + PSetBase* base2 = new PSetBase(); + IFormulation* prob2 = new IFormulation(base2); + UserDefinedInit* init2 = new UserDefinedInit(prob2); + Evaluator* eval2 = new Evaluator(init2); + eval2->TP_defineSingleObjective(true); + + // Create an IFunction from the Kriging model + IFunctionSPtr func2 = + IFunctionSPtr(new FeasibleRandExpectedImprovement(km, xx, cViolation)); + + prob2->appendFunction(func2); + prob2->evaluate(); + + // Create query points + TVector> xq; + ISet* queryPoints = new ISet; + for(double x1=0.0; x1<=(1.0+Tigon::Epsilon); x1 += 0.01) { + for(double x2=0.0; x2<=(1.0+Tigon::Epsilon); x2 += 0.01) { + xq.push_back(TVector({x1, x2})); + IMappingSPtr imap = prob2->createOptimizationMapping(queryPoints); + imap->defineDecisionVar(0, IElement(x1)); + imap->defineDecisionVar(1, IElement(x2)); + imap->defineEvaluated(false); + } + } + init2->defineInitialSet(queryPoints); + + eval2->evaluate(); + + TVector errorFEI; errorFEI.reserve(xq.size()); + FeasibleRandExpectedImprovement* fExpImp = + static_cast(func2.get()); + for(auto sol : queryPoints->all()) { + // to get the appropriate error always call value() first + fExpImp->value(sol->decisionVec()); + errorFEI.push_back(fExpImp->error(sol->decisionVec())); + } + +#ifdef PLOT_IN_MATLAB + // write the results to an .m file: + QFile file("tst_feasibleRandExpectedImprovement.m"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + QTextStream out(&file); + ISet* expImp = init2->outputSet(0); + + out << "% Evaluated points:" << endl; + + out << "xx = ["; + for(auto x : xx) { + writeVector(out, x," ","; "); + } + out << "];" << endl; + + out << "yy = ["; + for(auto y : yy) { + out << y << "; "; + } + out << "];" << endl<< endl; + + // query points + out << "% Model estimation:" << endl << "xq = ["; + for(auto xvec : xq) { + out << "["; + for(auto x : xvec) { + out << x << " "; + } + out << "]; "; + } + out << "];" << endl; + + out << "err = ["; + for(auto error: errorFEI) { + out << error << "; "; + } + out << "];" << endl << endl; + + out << "% Feasible Rand Expected Improvement:" << endl; + out << "fExpImp = ["; + for(auto sol : expImp->all()) { + double fei = sol->doubleObjectiveVar(0); + out << -fei << "; "; + } + out << "];" << endl; + + out << "\n% Plot the results\n" + "ModelX = reshape(xq(:,1),[101, 101]);\n" + "ModelY = reshape(xq(:,2),[101, 101]);\n" + "\n" + "figure(1);\n" + "ModelError = reshape(err,[101, 101]);\n" + "BraninFuncContour = contourf(ModelX,ModelY,ModelError,30);\n" + "hold on;\n" + "TrainingPoints = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc.LineWidth=3.0;\n" + "colorbar;\n" + "xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Density based prediction error of the Branin function');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('FRandExpImpError_CBraninM1.png','-dpng');" + "\n" + "figure(2);\n" + "FExpImp = reshape(fExpImp,[101, 101]);\n" + "FExpectedImprovement = contourf(ModelX,ModelY,FExpImp,30);\n" + "hold on;\n" + "TrainingPoints = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc.LineWidth=3.0;\n" + "colorbar;\n" + "xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Feasible Rand Expected Improvement');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('FRandExpImp_CBraninM1.png','-dpng');" + "\n" << endl; + file.close(); +#endif + + delete eval2; + delete init2; + delete prob2; + delete base2; + delete eval; + delete init; + delete prob; + delete base; +} + +void tst_parego::test_ProbabilityFeasibility() +{ + // Use one IPSet to evaluate a set of solutions on a single objective + // problem + PSetBase* base = new PSetBase(); + IFormulation* prob = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(prob); + Evaluator* eval = new Evaluator(init); + eval->TP_defineSingleObjective(true); + + IFunctionSPtr func = IFunctionSPtr(new CBraninM1); + ProblemSPtr problem(new Problem); + problem->appendFunction(func, TVector(), TVector({1})); + problem->processProblemDefinition(); + + TVector threshVec({0.0}); + TVector types({RealType}); + TVector thVec = createIElementSPtrVector(threshVec, types); + problem->defineThresholdVector(thVec); + problem->processProblemDefinition(); + + prob->defineProblem(problem); + prob->evaluate(); + + ISet* providedPoints = new ISet; + // Generate 6 points + TVector> training_points; + training_points << TVector({0.25, 0.24}); // infeasible + training_points << TVector({0.08, 0.58}); // infeasible + training_points << TVector({0.75, 0.06}); // infeasible + training_points << TVector({0.42, 0.92}); // feasible + training_points << TVector({0.58, 0.42}); // feasible + training_points << TVector({0.91, 0.75}); // feasible + + for(auto point : training_points) { + IMappingSPtr imap = prob->createOptimizationMapping(providedPoints); + imap->defineDecisionVar(0, IElement(point[0])); + imap->defineDecisionVar(1, IElement(point[1])); + } + + init->defineInitialSet(providedPoints); + + eval->evaluate(); + + + /// Use a new IPSet to evaluate a dense set of solutions on the Kriging + /// model and to evaluate its expected improvement and probability of feasibility + + // Fit a Kriging model to the constraint violation values of the evaluated solutions + ISet* eSet = init->outputSet(0); + TVector > xx; + xx.reserve(eSet->size()); + TVector cy; + cy.reserve(eSet->size()); + for(auto sol : eSet->all()) { + // decision vector + xx.push_back(sol->doubleDecisionVec()); + // constraint violation value + cy.push_back(sol->doubleConstraintVar(0) - threshVec[0]); + } + + DACE* kinterp = new DACE(); + kinterp->updateData(xx, cy); + KrigingSPtr kmC = KrigingSPtr(kinterp); +// PowerVariogram* powerVC = new PowerVariogram(xx, cy); +// KrigingSPtr kmC = KrigingSPtr(new OrdinaryKriging(powerVC)); + kmC->defineEstimateErrors(true); + + // Construct the feasible expected improvement and probability of feasibility functions + IFunctionSPtr func2 = IFunctionSPtr(new ProbabilityFeasibility(kmC)); + + // Create the new IPSet + PSetBase* base2 = new PSetBase(); + IFormulation* prob2 = new IFormulation(base2); + UserDefinedInit* init2 = new UserDefinedInit(prob2); + Evaluator* eval2 = new Evaluator(init2); + eval2->TP_defineSingleObjective(true); + + prob2->appendFunction(func2); + prob2->evaluate(); + + // Create query points + TVector> xq; + ISet* queryPoints = new ISet; + for(double x1=0.0; x1<=(1.0+Tigon::Epsilon); x1 += 0.01) { + for(double x2=0.0; x2<=(1.0+Tigon::Epsilon); x2 += 0.01) { + xq.push_back(TVector({x1, x2})); + IMappingSPtr imap = prob2->createOptimizationMapping(queryPoints); + imap->defineDecisionVar(0, IElement(x1)); + imap->defineDecisionVar(1, IElement(x2)); + imap->defineEvaluated(false); + } + } + init2->defineInitialSet(queryPoints); + + eval2->evaluate(); + +#ifdef PLOT_IN_MATLAB + // write the results to an .m file: + QFile file("tst_probabilityOfFeasibility.m"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + QTextStream out(&file); + + out << "% Evaluated points:" << endl; + + out << "xx = ["; + for(auto x : xx) { + writeVector(out, x," ","; "); + } + out << "];" << endl; + + // query points + out << "% Model estimation:" << endl << "xq = ["; + for(auto xvec : xq) { + out << "["; + for(auto x : xvec) { + out << x << " "; + } + out << "]; "; + } + out << "];" << endl; + + ISet* expImp = init2->outputSet(0); + out << "% Probability of feasibility:" << endl; + out << "pf = ["; + for(auto sol : expImp->all()) { + double fei = sol->doubleObjectiveVar(0); + out << -fei << "; "; + } + out << "];" << endl; + + out << "\n% Plot the results\n" + "ModelX = reshape(xq(:,1),[101, 101]);\n" + "ModelY = reshape(xq(:,2),[101, 101]);\n" + "figure;\n" + "PF = reshape(pf,[101, 101]);\n" + "ProbabilityFeasibility = contourf(ModelX,ModelY,PF,30);\n" + "hold on;\n" + "TrainingPoints = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc.LineWidth=3.0;\n" + "colorbar;\n" + "xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Probability of Feasibility');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('ProbabilityFeasibility_CBraninM1.png','-dpng');" + "\n" << endl; + file.close(); +#endif + + delete eval2; + delete init2; + delete prob2; + delete base2; + delete eval; + delete init; + delete prob; + delete base; +} + +void tst_parego::test_ProbabilityFeasibilityModified() +{ + // Use one IPSet to evaluate a set of solutions on a single objective + // problem + PSetBase* base = new PSetBase(); + IFormulation* prob = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(prob); + Evaluator* eval = new Evaluator(init); + eval->TP_defineSingleObjective(true); + + IFunctionSPtr func = IFunctionSPtr(new CBraninM1); + ProblemSPtr problem(new Problem); + problem->appendFunction(func, TVector(), TVector({1})); + problem->processProblemDefinition(); + + TVector threshVec({0.0}); + TVector types({RealType}); + TVector thVec = createIElementSPtrVector(threshVec, types); + problem->defineThresholdVector(thVec); + problem->processProblemDefinition(); + + prob->defineProblem(problem); + prob->evaluate(); + + ISet* providedPoints = new ISet; + // Generate 6 points + TVector> training_points; + training_points << TVector({0.25, 0.24}); // infeasible + training_points << TVector({0.08, 0.58}); // infeasible + training_points << TVector({0.75, 0.7}); // feasible + training_points << TVector({0.42, 0.92}); // feasible + training_points << TVector({0.58, 0.42}); // feasible + training_points << TVector({0.91, 0.75}); // feasible + + for(auto point : training_points) { + IMappingSPtr imap = prob->createOptimizationMapping(providedPoints); + imap->defineDecisionVar(0, IElement(point[0])); + imap->defineDecisionVar(1, IElement(point[1])); + } + + init->defineInitialSet(providedPoints); + + eval->evaluate(); + + + /// Use a new IPSet to evaluate a dense set of solutions on the Kriging + /// model and to evaluate its expected improvement and the probability of feasibility + /// modified version of Bagheri's et al. (2017) + + // Fit a Kriging model to the constraint violation values of the evaluated solutions + ISet* eSet = init->outputSet(0); + TVector > xx; + xx.reserve(eSet->size()); + TVector cy; + cy.reserve(eSet->size()); + for(auto sol : eSet->all()) { + // decision vector + xx.push_back(sol->doubleDecisionVec()); + // constraint violation value + cy.push_back(sol->doubleConstraintVar(0) - threshVec[0]); + } + + DACE* kinterpm = new DACE(); + kinterpm->updateData(xx, cy); + KrigingSPtr kmCm = KrigingSPtr(kinterpm); +// PowerVariogram* powerVCm = new PowerVariogram(xx, cy); +// KrigingSPtr kmCm = KrigingSPtr(new Kriging(powerVCm)); + kmCm->defineEstimateErrors(true); + + // Construct the feasible expected improvement and modified probability of feasibility + IFunctionSPtr func2 = IFunctionSPtr(new ProbabilityFeasibilityBagheri(kmCm)); + + // Create the new IPSet + PSetBase* base2 = new PSetBase(); + IFormulation* prob2 = new IFormulation(base2); + UserDefinedInit* init2 = new UserDefinedInit(prob2); + Evaluator* eval2 = new Evaluator(init2); + eval2->TP_defineSingleObjective(true); + + prob2->appendFunction(func2); + prob2->evaluate(); + + // Create query points + TVector> xqm; + ISet* queryPoints = new ISet; + for(double x1=0.0; x1<=(1.0+Tigon::Epsilon); x1 += 0.01) { + for(double x2=0.0; x2<=(1.0+Tigon::Epsilon); x2 += 0.01) { + xqm.push_back(TVector({x1, x2})); + IMappingSPtr imap = prob2->createOptimizationMapping(queryPoints); + imap->defineDecisionVar(0, IElement(x1)); + imap->defineDecisionVar(1, IElement(x2)); + imap->defineEvaluated(false); + } + } + init2->defineInitialSet(queryPoints); + + eval2->evaluate(); + + /// Use a new IPSet to evaluate a dense set of solutions on the Kriging + /// model and to evaluate its expected improvement and the probability of feasibility + /// function to compare the results with the modfied version + + DACE* kinterp = new DACE(); + kinterp->updateData(xx, cy); + KrigingSPtr kmC = KrigingSPtr(kinterp); +// PowerVariogram* powerVC = new PowerVariogram(xx, cy); +// KrigingSPtr kmC = KrigingSPtr(new Kriging(powerVC)); + kmC->defineEstimateErrors(true); + + // Construct the feasible expected improvement and probability of feasibility functions + IFunctionSPtr func3 = IFunctionSPtr(new ProbabilityFeasibility(kmC)); + + // Create the new IPSet + PSetBase* base3 = new PSetBase(); + IFormulation* prob3 = new IFormulation(base3); + UserDefinedInit* init3 = new UserDefinedInit(prob3); + Evaluator* eval3 = new Evaluator(init3); + eval3->TP_defineSingleObjective(true); + + prob3->appendFunction(func3); + prob3->evaluate(); + + // Create query points + TVector> xq; + ISet* queryPoints2 = new ISet; + for(double x1=0.0; x1<=(1.0+Tigon::Epsilon); x1 += 0.01) { + for(double x2=0.0; x2<=(1.0+Tigon::Epsilon); x2 += 0.01) { + xq.push_back(TVector({x1, x2})); + IMappingSPtr imap = prob3->createOptimizationMapping(queryPoints2); + imap->defineDecisionVar(0, IElement(x1)); + imap->defineDecisionVar(1, IElement(x2)); + imap->defineEvaluated(false); + } + } + init3->defineInitialSet(queryPoints2); + + eval3->evaluate(); + + + // write the results to an .m file: + QFile file("tst_probabilityOfFeasibilityModified.m"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + QTextStream out(&file); + ISet* pfm = init2->outputSet(0); + ISet* pf = init3->outputSet(0); + + out << "% Evaluated points:" << endl; + + out << "xx = ["; + for(auto x : xx) { + writeVector(out, x," ","; "); + } + out << "];" << endl; + + // query points + out << "% Model estimation for modified pf:" << endl << "xq_m = ["; + for(auto xvecm : xqm) { + out << "["; + for(auto x : xvecm) { + out << x << " "; + } + out << "]; "; + } + out << "];" << endl; + + out << "% Model estimation for pf:" << endl << "xq = ["; + for(auto xvec : xq) { + out << "["; + for(auto x : xvec) { + out << x << " "; + } + out << "]; "; + } + out << "];" << endl; + + out << "% Probability of feasibility modified:" << endl; + out << "pf_m = ["; + for(auto sol : pfm->all()) { + double feim = sol->doubleObjectiveVar(0); + out << -feim << "; "; + } + out << "];" << endl; + + out << "% Probability of feasibility:" << endl; + out << "pf = ["; + for(auto sol : pf->all()) { + double fei = sol->doubleObjectiveVar(0); + out << -fei << "; "; + } + out << "];" << endl; + + out << "\n% Plot the results\n" + "ModelX = reshape(xq(:,1),[101, 101]);\n" + "ModelY = reshape(xq(:,2),[101, 101]);\n" + "ModelX_m = reshape(xq_m(:,1),[101, 101]);\n" + "ModelY_m = reshape(xq_m(:,2),[101, 101]);\n" + "figure;\n" + "subplot(1,2,1)\n" + "PF = reshape(pf,[101, 101]);\n" + "ProbabilityFeasibility = contourf(ModelX,ModelY,PF,30);\n" + "hold on;\n" + "TrainingPoints = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc.LineWidth=3.0;\n" + "colorbar;xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Probability of Feasibility');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "subplot(1,2,2)\n" + "PF_m = reshape(pf_m,[101, 101]);\n" + "ProbabilityFeasibilityModified = contourf(ModelX_m,ModelY_m,PF_m,30);\n" + "hold on;\n" + "TrainingPoints_m = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc_m = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc_m.LineWidth=3.0;\n" + "colorbar;xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Probability of Feasibility Modified');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('ProbabilityFeasibilityModified_CBraninM1.png','-dpng');" + "\n" << endl; + file.close(); + + delete eval3; + delete init3; + delete prob3; + delete base3; + delete eval2; + delete init2; + delete prob2; + delete base2; + delete eval; + delete init; + delete prob; + delete base; +} + +void tst_parego::test_ConstrainedExpectedImprovement() +{ + // Use one IPSet to evaluate a set of solutions on a single objective + // problem + PSetBase* base = new PSetBase(); + IFormulation* prob = new IFormulation(base); + UserDefinedInit* init = new UserDefinedInit(prob); + Evaluator* eval = new Evaluator(init); + eval->TP_defineSingleObjective(true); + + IFunctionSPtr func = IFunctionSPtr(new CBraninM1); + ProblemSPtr problem(new Problem); + problem->appendFunction(func, TVector(), TVector({1})); + problem->processProblemDefinition(); + + TVector threshVec({0.0}); + TVector types({RealType}); + TVector thVec = createIElementSPtrVector(threshVec, types); + problem->defineThresholdVector(thVec); + problem->processProblemDefinition(); + + prob->defineProblem(problem); + prob->evaluate(); + + ISet* providedPoints = new ISet; + // Generate 6 points + TVector> training_points; + training_points << TVector({0.25, 0.24}); // infeasible + training_points << TVector({0.08, 0.58}); // infeasible + training_points << TVector({0.75, 0.06}); // infeasible + training_points << TVector({0.42, 0.92}); // feasible + training_points << TVector({0.58, 0.42}); // feasible + training_points << TVector({0.91, 0.75}); // feasible + + for(auto point : training_points) { + IMappingSPtr imap = prob->createOptimizationMapping(providedPoints); + imap->defineDecisionVar(0, IElement(point[0])); + imap->defineDecisionVar(1, IElement(point[1])); + } + + init->defineInitialSet(providedPoints); + + eval->evaluate(); + + + /// Use a new IPSet to evaluate a dense set of solutions on the Kriging + /// model and to evaluate its expected improvement and probability of feasibility + + // Fit a Kriging model to the evaluated points + ISet* eSet = init->outputSet(0); + TVector > xx; + TVector yy; + for(auto sol : eSet->all()) { + // decision vector + xx.push_back(sol->doubleDecisionVec()); + // function value + yy.push_back(sol->doubleCost()); + } + + DACE* kinterp = new DACE(); + kinterp->updateData(xx, yy); + KrigingSPtr km = KrigingSPtr(kinterp); +// PowerVariogram* powerV = new PowerVariogram(xx, yy); +// KrigingSPtr km = KrigingSPtr(new OrdinaryKriging(powerV)); + km->defineEstimateErrors(true); + + // Calculate constraint violation of every evaluated solution + TVector cViolation; + cViolation.reserve(eSet->size()); + for(auto sol : eSet->all()) { + double violation = solutionConstraintViolation(sol, threshVec); + cViolation.push_back(violation); + } + + // Construct the Kriging model for the constraint + TVector cy; + cy.reserve(eSet->size()); + for(auto sol : eSet->all()) { + double constr = sol->doubleConstraintVar(0) - threshVec[0]; + cy.push_back(constr); + } + + DACE* kinterp2 = new DACE(); + kinterp2->updateData(xx, cy); + KrigingSPtr kmC = KrigingSPtr(kinterp2); +// PowerVariogram* powerVC = new PowerVariogram(xx, cy); +// KrigingSPtr kmC = KrigingSPtr(new OrdinaryKriging(powerVC)); + kmC->defineEstimateErrors(true); + + // Construct the feasible expected improvement and probability of feasibility functions + + FeasibleExpectedImprovement* fei = new FeasibleExpectedImprovement(km, cViolation); + FeasibleRandExpectedImprovement* frei = new FeasibleRandExpectedImprovement(km, xx, cViolation); + TVector vfpf({new ProbabilityFeasibility(kmC)}); + IFunctionSPtr func2 = + IFunctionSPtr(new ConstrainedExpectedImprovement(fei, vfpf)); + IFunctionSPtr func3 = + IFunctionSPtr(new ConstrainedExpectedImprovement(frei, vfpf)); + + // Change the name of the outputs of func3 + ElementPropertiesFactory* elemFact = ElementPropertiesFactory::instance(); + TString name1 = "RandFEIxPF"; TString description1 = "RandFEIxPF"; + TString name2 = "RandFEI"; TString description2 = "RandFEI"; + TString name3 = "PF2"; TString description3 = "PF2"; + ElementProperties elem1 = elemFact->createElementProperties(0, name1, description1, RealType, Maximization); + ElementProperties elem2 = elemFact->createElementProperties(0, name2, description2, RealType, Maximization); + ElementProperties elem3 = elemFact->createElementProperties(0, name3, description3, RealType, Maximization); + TVector funcProp = func3->outputPrpts(); + funcProp[0] = elem1; + funcProp[1] = elem2; + funcProp[2] = elem3; + func3->defineOutputPrpts(funcProp); + + // Create the new IPSet + PSetBase* base2 = new PSetBase(); + IFormulation* prob2 = new IFormulation(base2); + UserDefinedInit* init2 = new UserDefinedInit(prob2); + Evaluator* eval2 = new Evaluator(init2); + + ProblemSPtr problem2(new Problem); + problem2->appendFunction(func2, TVector(), TVector(), TVector{0}); + problem2->appendFunction(func3, TVector(), TVector(), TVector{0}); + problem2->processProblemDefinition(); + + prob2->defineProblem(problem2); + prob2->evaluate(); + + // Create query points + TVector> xq; + ISet* queryPoints = new ISet; + for(double x1=0.0; x1<=(1.0+Tigon::Epsilon); x1 += 0.01) { + for(double x2=0.0; x2<=(1.0+Tigon::Epsilon); x2 += 0.01) { + xq.push_back(TVector({x1, x2})); + IMappingSPtr imap = prob2->createOptimizationMapping(queryPoints); + imap->defineDecisionVar(0, IElement(x1)); + imap->defineDecisionVar(1, IElement(x2)); + imap->defineEvaluated(false); + } + } + init2->defineInitialSet(queryPoints); + + eval2->evaluate(); + +#ifdef PLOT_IN_MATLAB + // write the results to an .m file: + QFile file("tst_constrainedExpectedImprovement.m"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + return; + } + QTextStream out(&file); + + out << "% Evaluated points:" << endl; + + out << "xx = ["; + for(auto x : xx) { + writeVector(out, x," ","; "); + } + out << "];" << endl; + + out << "yy = ["; + for(auto y : yy) { + out << y << "; "; + } + out << "];" << endl<< endl; + + // query points + out << "% Model estimation:" << endl << "xq = ["; + for(auto xvec : xq) { + out << "["; + for(auto x : xvec) { + out << x << " "; + } + out << "]; "; + } + out << "];" << endl; + + ISet* expImp = init2->outputSet(0); + out << "% Constrained Expected Improvement:" << endl; + out << "cExpImp = ["; + for(auto sol : expImp->all()) { + double val = sol->doubleObjectiveVar(0); + out << -val << "; "; + } + out << "];" << endl; + + out << "% Constrained Rand Expected Improvement:" << endl; + out << "cRandExpImp = ["; + for(auto sol : expImp->all()) { + double val = sol->doubleObjectiveVar(1); + out << -val << "; "; + } + out << "];" << endl; + + out << "% Feasible Expected Improvement:" << endl; + out << "fExpImp = ["; + for(auto sol : expImp->all()) { + double val = sol->doubleUnusedVar(0); + out << val << "; "; + } + out << "];" << endl; + + out << "% Probability of Improvement:" << endl; + out << "probImp = ["; + for(auto sol : expImp->all()) { + double val = sol->doubleUnusedVar(1); + out << val << "; "; + } + out << "];" << endl; + + out << "% Feasible Rand Expected Improvement:" << endl; + out << "fRandExpImp = ["; + for(auto sol : expImp->all()) { + double val = sol->doubleUnusedVar(2); + out << val << "; "; + } + out << "];" << endl; + + out << "\n% Plot the results\n" + "ModelX = reshape(xq(:,1),[101, 101]);\n" + "ModelY = reshape(xq(:,2),[101, 101]);\n" + "figure(1);\n" + "CExpImp = reshape(cExpImp,[101, 101]);\n" + "CExpectedImprovement = contourf(ModelX,ModelY,CExpImp,30);\n" + "hold on;\n" + "TrainingPoints = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc.LineWidth=3.0;\n" + "colorbar;\n" + "xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Constrained Expected Improvement');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('CExpImp_CBraninM1.png','-dpng');" + "\n" + "figure(2);\n" + "CRandExpImp = reshape(cRandExpImp,[101, 101]);\n" + "CRandExpectedImprovement = contourf(ModelX,ModelY,CRandExpImp,30);\n" + "hold on;\n" + "TrainingPoints = plot(xx(:,1),xx(:,2),'ok');\n" + "ConstraintFunc = fimplicit(@(x1,x2) x1*x2 - 0.2, [0 1 0 1],'-k');\n" + "ConstraintFunc.LineWidth=3.0;\n" + "colorbar;\n" + "xlabel('x_1'); ylabel('x_2');\n" + "title('Contours of the Constrained Rand Expected Improvement');\n" + "x0=10; y0=10; width=800; height=600;\n" + "set(gcf,'position',[x0,y0,width,height]);\n" + "print('CRandExpImp_CBraninM1.png','-dpng');" + "\n" << endl; + file.close(); +#endif + + delete eval2; + delete init2; + delete prob2; + delete base2; + delete eval; + delete init; + delete prob; + delete base; +} + void tst_parego::test_SurrogateBasedOptimizer() { TRAND.defineSeed(0); @@ -81,7 +1732,6 @@ void tst_parego::test_SurrogateBasedOptimizer() int oVecSize = 2; int nDirs = 10; int popSize = 100; - int budget = popSize+nDirs*1; int maxSurrogateSize = 50; PSetBase* base = new PSetBase(); @@ -102,12 +1752,12 @@ void tst_parego::test_SurrogateBasedOptimizer() prob->appendFunction(func); init->TP_defineSetSize(popSize); - eval->defineBudget(budget); dirs->TP_defineReferenceSetSize(nDirs); scal->TP_defineScalarisingFunction(Tigon::WeightedChebyshevAugmented); scal->TP_defineWeightScopeApproach(Tigon::GlobalWeight); filt->TP_defineMaxSolutions(maxSurrogateSize); - opt->TP_defineErrorMethod(Tigon::ErrDensityBased); + opt->TP_defineErrorMethod(Tigon::ErrConfidenceIntervalBased); + opt->TP_defineOptimizationSearchQuality(0); eval->evaluate(); ISet* oSet = eval->outputSet(0); @@ -119,6 +1769,55 @@ void tst_parego::test_SurrogateBasedOptimizer() QCOMPARE(oSet->size(), popSize+1); } +void tst_parego::test_ConstrainedSurrogateBasedOptimizer() +{ + TRAND.defineSeed(0); + cout.precision(4); + + int popSize = 100; + + IFunctionSPtr func(new CTP1); + TVector paramInd, objInd, cnstrInd; + objInd << 0 << 1; + cnstrInd << 2 << 3; + + ProblemSPtr prob(new Problem); + prob->appendFunction(func, paramInd, cnstrInd, objInd); + prob->processProblemDefinition(); + + TVector threshVec(2, 0.0); + TVector types(2, RealType); + TVector thVec = createIElementSPtrVector(threshVec, types); + prob->defineThresholdVector(thVec); + prob->processProblemDefinition(); + + PSetBase* base = new PSetBase(); + IFormulation* form = new IFormulation(base); + form->defineProblem(prob); + + LHSInit* init = new LHSInit(form); + init->TP_defineSetSize(popSize); + + Evaluator* eval = new Evaluator(init); + + /// ParEGO starts + SimplexLatticeDirectionIterator* dirs = + new SimplexLatticeDirectionIterator(eval); + GeneralizedDecomposition* scal = new GeneralizedDecomposition(dirs); + DirectionFitnessFiltration* filt = new DirectionFitnessFiltration(scal); + ConstrainedSurrogateBasedOptimizer* opt = + new ConstrainedSurrogateBasedOptimizer(filt); + + opt->TP_defineOptimizationSearchQuality(0); + eval->evaluate(); + ISet* oSet = eval->outputSet(0); + QCOMPARE(oSet->size(), popSize); + + /// checks that ConstrainedSurrogateBasedOptimizer adds a solution to the main + /// optimization set + opt->evaluate(); + QCOMPARE(oSet->size(), popSize+1); +} #endif #ifdef PAREGO_WORK_FLOW @@ -129,9 +1828,9 @@ void tst_parego::test_ParEGO_workflow() int dVecSize = 5; int oVecSize = 2; - int nDirs = 10; + int nDirs = 5; int popSize = 100; - int budget = popSize+nDirs*1; + int budget = popSize + nDirs * 1; int maxSurrogateSize = 50; PSetBase* base = new PSetBase(); @@ -145,7 +1844,8 @@ void tst_parego::test_ParEGO_workflow() GeneralizedDecomposition* scal = new GeneralizedDecomposition(dirs); ConstraintPenalty* pnlt = new ConstraintPenalty(scal); DirectionFitnessFiltration* filt = new DirectionFitnessFiltration(pnlt); - SurrogateBasedOptimizer* opt = new SurrogateBasedOptimizer(filt); + ConstrainedSurrogateBasedOptimizer* opt = + new ConstrainedSurrogateBasedOptimizer(filt); IFunctionSPtr func = IFunctionSPtr(new DTLZ1); func->TP_defineNInputs(dVecSize); @@ -157,8 +1857,12 @@ void tst_parego::test_ParEGO_workflow() dirs->TP_defineReferenceSetSize(nDirs); scal->TP_defineScalarisingFunction(Tigon::WeightedChebyshevAugmented); scal->TP_defineWeightScopeApproach(Tigon::GlobalWeight); + pnlt->defineOutputTags(TStringList({TString("DO_NO_OPERATE")})); filt->TP_defineMaxSolutions(maxSurrogateSize); - opt->TP_defineErrorMethod(Tigon::ErrDensityBased); + + opt->TP_defineErrorMethod(Tigon::ErrConfidenceIntervalBased); + opt->TP_defineDisableConstraintHandling(true); + opt->TP_defineOptimizationSearchQuality(0); while(opt->remainingBudget() > 0) { opt->evaluate(); @@ -169,9 +1873,9 @@ void tst_parego::test_ParEGO_workflow() cout << "\tDirection vector: \t"; dispVector(opt->dirVec(), "\t", "\n"); cout << "\tLast solutions added: \n"; - for(int i = 0; i < pop->size(); i++) { - if(!(pop->at(i)->isEvaluated())) { - dispVector(pop->at(i)->doubleDecisionVec(), "\t", "\n"); + for(auto sol : pop->all()) { + if(!sol->isEvaluated()) { + dispVector(sol->doubleDecisionVec(), "\t", "\n"); } } @@ -196,9 +1900,9 @@ void tst_parego::test_ParEGO() int dVecSize = 5; int oVecSize = 2; - int nDirs = 10; + int nDirs = 5; int popSize = 100; - int budget = popSize+nDirs*1; + int budget = popSize + nDirs * 1; int maxSurrogateSize = 50; PSetBase* base = new PSetBase(); @@ -216,6 +1920,9 @@ void tst_parego::test_ParEGO() alg->defineReferenceSetSize(nDirs); alg->TP_defineMaxSolutions(maxSurrogateSize); alg->defineBudget(budget); + alg->defineOptimizationSearchQuality(0); + alg->TP_defineErrorMethod(Tigon::ErrConfidenceIntervalBased); + alg->TP_defineConstraintHandlingMethod(Tigon::NoConstraintHandling); while(alg->remainingBudget() > 0) { alg->evaluate(); @@ -225,8 +1932,8 @@ void tst_parego::test_ParEGO() dispVector(alg->dirVec(), "\t", "\n"); cout << "\tLast solutions added: \t"; TVector newMaps = alg->newMappings(); - for(int i=0; idoubleDecisionVec(), "\t", "\n\t\t\t\t"); + for(auto sol : newMaps) { + dispVector(sol->doubleDecisionVec(), "\t", "\n\t\t\t\t"); } cout << endl; cout << "\tNumber of IMappings: " << alg->evaluatedMappings().size() + 1 @@ -241,8 +1948,6 @@ void tst_parego::test_ParEGO() delete prob; delete base; } - - #endif QTEST_GUILESS_MAIN(tst_parego) From 5bab59608c9d881caed6cbdadc4d02e87d682aa2 Mon Sep 17 00:00:00 2001 From: "Joao A. Duro" Date: Fri, 1 Jan 2021 23:34:03 +0000 Subject: [PATCH 4/7] Fix to ACROMUSE --- .../ACROMUSE/AcromuseEliteFiltration.cpp | 20 +++++++++---------- .../ACROMUSE/AcromuseEliteFiltration.h | 6 ++---- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/ACROMUSE/AcromuseEliteFiltration.cpp b/src/libs/tigon/Operators/AlgorithmSpecific/ACROMUSE/AcromuseEliteFiltration.cpp index 687181f..4231f58 100644 --- a/src/libs/tigon/Operators/AlgorithmSpecific/ACROMUSE/AcromuseEliteFiltration.cpp +++ b/src/libs/tigon/Operators/AlgorithmSpecific/ACROMUSE/AcromuseEliteFiltration.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2021 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -45,19 +45,17 @@ void AcromuseEliteFiltration::evaluateNode() clearOutputSets(); ISet* iSet = setsUnion(inputSets()); - int sSize = iSet->size(); - int idx = -1; - double best = Tigon::Highest; - for(int i=0; iat(i)->doubleCost(); - if(f < best){ - best = f; - idx = i; - } + TVector cost; + cost.reserve(iSet->size()); + for(auto sol : iSet->all()) { + cost.push_back(sol->doubleCost()); } + int bestIdx = std::min_element(cost.begin(), cost.end()) - cost.begin(); + ISet* oSet = appendOutputSet(); - oSet->append(iSet->at(idx)); + oSet->append(iSet->at(bestIdx)); + delete iSet; } diff --git a/src/libs/tigon/Operators/AlgorithmSpecific/ACROMUSE/AcromuseEliteFiltration.h b/src/libs/tigon/Operators/AlgorithmSpecific/ACROMUSE/AcromuseEliteFiltration.h index 3b68cd1..12a2156 100644 --- a/src/libs/tigon/Operators/AlgorithmSpecific/ACROMUSE/AcromuseEliteFiltration.h +++ b/src/libs/tigon/Operators/AlgorithmSpecific/ACROMUSE/AcromuseEliteFiltration.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2021 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -27,7 +27,7 @@ class LIGER_TIGON_EXPORT AcromuseEliteFiltration : public IFiltration public: AcromuseEliteFiltration(); AcromuseEliteFiltration(Tigon::Representation::IPSet* ipset); - virtual ~AcromuseEliteFiltration(); + ~AcromuseEliteFiltration(); void evaluateNode(); @@ -39,8 +39,6 @@ class LIGER_TIGON_EXPORT AcromuseEliteFiltration : public IFiltration protected: void initialise(); - TString m_name; - TString m_description; }; From 4f8681202df48c7880b9986eb6ea15beb267f327 Mon Sep 17 00:00:00 2001 From: "Joao A. Duro" Date: Fri, 1 Jan 2021 23:45:26 +0000 Subject: [PATCH 5/7] Fix to SimplexLatticeDirectionIterator and clean up --- src/libs/tigon/Operators/Directions/IDirection.cpp | 6 +++--- .../tigon/Operators/Directions/SBXCrossOver.cpp | 2 +- .../Directions/SimplexLatticeDirectionIterator.cpp | 14 ++++++++------ src/libs/tigon/Operators/Evaluators/IEvaluator.cpp | 9 +++++---- src/libs/tigon/Operators/Evaluators/Validation.cpp | 6 +++--- .../Filtrations/FitnessEliteSelection.cpp | 4 ++-- .../Filtrations/NeighbourhoodFiltration.cpp | 8 ++++---- .../tigon/Operators/Filtrations/PSAClustering.cpp | 6 +++--- .../Operators/Filtrations/PSAEliteSelection.cpp | 2 +- .../Filtrations/RandFiltrationForModification.cpp | 4 ++-- .../Filtrations/RandFiltrationForPerturbation.cpp | 6 +++--- .../TournamentFiltrationForDirection.cpp | 4 ++-- .../TournamentFiltrationForModification.cpp | 4 ++-- .../Fitness/NonDominanceRankingParametric.cpp | 2 +- .../Operators/Initialisation/IInitialisation.cpp | 2 +- .../Operators/Perturbations/IPerturbation.cpp | 4 ++-- .../Operators/Perturbations/PolynomialMutation.cpp | 9 ++++----- .../tigon/Operators/Terminations/ITermination.cpp | 4 ++-- 18 files changed, 49 insertions(+), 47 deletions(-) diff --git a/src/libs/tigon/Operators/Directions/IDirection.cpp b/src/libs/tigon/Operators/Directions/IDirection.cpp index 42627d2..d333fd8 100644 --- a/src/libs/tigon/Operators/Directions/IDirection.cpp +++ b/src/libs/tigon/Operators/Directions/IDirection.cpp @@ -107,17 +107,17 @@ void IDirection::initialise() addProperty("SolutionCrossoverProbability" , TString("Probability of applying crossover to a solution. " "Default is 0.9.") - , typeid(double).hash_code()); + , getTType(double)); addProperty("VariableCrossoverProbability" , TString("Probability of applying crossover to a variable in a solution. " "Default is 0.5.") - , typeid(double).hash_code()); + , getTType(double)); addProperty("VariableSwapCrossoverProbability" , TString("Probability of swapping a variable between two created child solutions. " "Default is 0.5.") - , typeid(double).hash_code()); + , getTType(double)); TP_defineSolutionCrossoverProbability(Tigon::DefaultCrossoverSolutionProbability); TP_defineVariableCrossoverProbability(Tigon::DefaultCrossoverVariableProbability); diff --git a/src/libs/tigon/Operators/Directions/SBXCrossOver.cpp b/src/libs/tigon/Operators/Directions/SBXCrossOver.cpp index ced520e..9ef7ad9 100644 --- a/src/libs/tigon/Operators/Directions/SBXCrossOver.cpp +++ b/src/libs/tigon/Operators/Directions/SBXCrossOver.cpp @@ -42,7 +42,7 @@ void SBXCrossOver::initialise() , TString("Controls the remoteness of the children " "from the parents (see reference). " "Default is 15.0") - , typeid(double).hash_code()); + , getTType(double)); TP_defineCrossoverDistributionIndex(Tigon::DefaultCrossoverDistributionIndex); diff --git a/src/libs/tigon/Operators/Directions/SimplexLatticeDirectionIterator.cpp b/src/libs/tigon/Operators/Directions/SimplexLatticeDirectionIterator.cpp index d7edd6e..1f8b125 100644 --- a/src/libs/tigon/Operators/Directions/SimplexLatticeDirectionIterator.cpp +++ b/src/libs/tigon/Operators/Directions/SimplexLatticeDirectionIterator.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2021 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -49,11 +49,12 @@ SimplexLatticeDirectionIterator::~SimplexLatticeDirectionIterator() void SimplexLatticeDirectionIterator::initialise() { - addProperty("ReferenceSetSize", - TString("The size of the reference set.\n" - "When a certain size is requseted,\n" - "the actual size is equal or larger. Default is 1"), - typeid(int).hash_code()); + addProperty("ReferenceSetSize" + , TString("The size of the reference set.\n" + "When a certain size is requseted,\n" + "the actual size is equal or larger.\n" + "Default is 1.") + , getTType(int)); TP_defineReferenceSetSize(1); defineKeepArchive(true); // to enable calculation of the nadir vector @@ -129,6 +130,7 @@ void SimplexLatticeDirectionIterator::nextDirection() m_currentVec = 0; } else { m_currentVec = 0; + m_referenceSet = Tigon::shuffle(m_referenceSet); } defineDirVec(m_referenceSet[m_currentVec]); } diff --git a/src/libs/tigon/Operators/Evaluators/IEvaluator.cpp b/src/libs/tigon/Operators/Evaluators/IEvaluator.cpp index bbe0ecf..89d1f4a 100644 --- a/src/libs/tigon/Operators/Evaluators/IEvaluator.cpp +++ b/src/libs/tigon/Operators/Evaluators/IEvaluator.cpp @@ -84,19 +84,20 @@ void IEvaluator::initialise() { addProperty("ParallelEvaluation" , TString("Every IMapping is evaluated in a " - "separate thread."), typeid(bool).hash_code()); + "separate thread.") + , getTType(bool)); addProperty("CountEvaluations" , TString("The evaluation counter is incremented " "after the evaluation of each solution.") - , typeid(bool).hash_code()); + , getTType(bool)); addProperty("CountPerFunction" , TString("Every function increments the " "evaluation counter by one.") - , typeid(bool).hash_code()); + , getTType(bool)); addProperty("SingleObjective" , TString("The fitness is set to the first " "objective after evaluation.") - , typeid(bool).hash_code()); + , getTType(bool)); TP_defineParallel(false); TP_defineCountEvaluations(true); diff --git a/src/libs/tigon/Operators/Evaluators/Validation.cpp b/src/libs/tigon/Operators/Evaluators/Validation.cpp index 8ca0cf4..4255573 100644 --- a/src/libs/tigon/Operators/Evaluators/Validation.cpp +++ b/src/libs/tigon/Operators/Evaluators/Validation.cpp @@ -202,16 +202,16 @@ void Validation::initialise() addProperty("NEvaluations" , TString("Number of repeated evaluations of every " "IMapping.\nDefault is ") - , typeid(int).hash_code()); + , getTType(int)); addProperty("OperateOnFinal" , TString("Disable the repeated evaluations during " "the optimization process, and only validate " "the final solutions.") - , typeid(bool).hash_code()); + , getTType(bool)); addProperty("DefineEvaluated" , TString("Indicates if the solutions are to be set as " "evaluated or not.") - , typeid(bool).hash_code()); + , getTType(bool)); addAdditionalOutputTag(Tigon::TValidation); diff --git a/src/libs/tigon/Operators/Filtrations/FitnessEliteSelection.cpp b/src/libs/tigon/Operators/Filtrations/FitnessEliteSelection.cpp index ff18975..cd0dd7a 100644 --- a/src/libs/tigon/Operators/Filtrations/FitnessEliteSelection.cpp +++ b/src/libs/tigon/Operators/Filtrations/FitnessEliteSelection.cpp @@ -29,7 +29,7 @@ FitnessEliteSelection::FitnessEliteSelection() addProperty("EliteRatio" , TString("Proportion of the Elite solutions of the " "total population. Default is half.") - , typeid(double).hash_code()); + , getTType(double)); m_name = TString("Fitness-Based Elite Selection"); m_description = TString("Creates a set with the best solutions selected " @@ -47,7 +47,7 @@ FitnessEliteSelection::FitnessEliteSelection(Tigon::Representation::IPSet* ipset { addProperty("EliteRatio", TString("Proportion of the Elite solutions of the total population. Default is half.") - ,typeid(double).hash_code()); + , getTType(double)); m_name = TString("Fitness-Based Elite Selection"); m_description = TString("Creates a set with the best solutions selected " diff --git a/src/libs/tigon/Operators/Filtrations/NeighbourhoodFiltration.cpp b/src/libs/tigon/Operators/Filtrations/NeighbourhoodFiltration.cpp index 50338e1..483adff 100644 --- a/src/libs/tigon/Operators/Filtrations/NeighbourhoodFiltration.cpp +++ b/src/libs/tigon/Operators/Filtrations/NeighbourhoodFiltration.cpp @@ -65,21 +65,21 @@ void NeighbourhoodFiltration::initialise() "different scales, the distance is multiplied " "by sqrt(d), where d is the number of decision " "variables.\nThe default is 0.1.") - , typeid(double).hash_code()); + , getTType(double)); addProperty("MaxSolutions" , TString("Maximum number of solutions to be used for " "surrogate modelling. Default of the entire " "input set is used when the value is " "non-positive.") - , typeid(int).hash_code()); + , getTType(int)); addProperty("NeighbourhoodSize" , TString("Number of neighbours attributed to each solution.\n") - , typeid(int).hash_code()); + , getTType(int)); addProperty("IsClearOutputSets" , TString("This property flag, if set to true clears the existing " "Outputsets, otherwise the outputsets are not clear.\n" "The default is true.\n") - , typeid(bool).hash_code()); + , getTType(bool)); // addProperty("DistanceMeasureSelection" // , TString("Selects the distance measure used to determine the " // "neighbourhoods. The available options are " diff --git a/src/libs/tigon/Operators/Filtrations/PSAClustering.cpp b/src/libs/tigon/Operators/Filtrations/PSAClustering.cpp index f8921d0..c96f8c2 100644 --- a/src/libs/tigon/Operators/Filtrations/PSAClustering.cpp +++ b/src/libs/tigon/Operators/Filtrations/PSAClustering.cpp @@ -45,19 +45,19 @@ void PSAClustering::initialise() { addProperty("numberOfClusters" , TString("Number of cluster with similar IMappings") - , typeid(int).hash_code()); + , getTType(int)); addProperty("normalised" , TString("Cluster the set according to the objective " "vectors or design vectors.\n" "Evaluate DVec is false for objective vectors " "(default) and true for design vectors.") - , typeid(bool).hash_code()); + , getTType(bool)); addProperty("evaluateDVec" , TString("Normalise every dimension to values between 0-1. \n" "Default is true.") - , typeid(int).hash_code()); + , getTType(int)); TP_defineNumberOfClusters(1); TP_defineNormalised(true); diff --git a/src/libs/tigon/Operators/Filtrations/PSAEliteSelection.cpp b/src/libs/tigon/Operators/Filtrations/PSAEliteSelection.cpp index 40803da..a221223 100644 --- a/src/libs/tigon/Operators/Filtrations/PSAEliteSelection.cpp +++ b/src/libs/tigon/Operators/Filtrations/PSAEliteSelection.cpp @@ -45,7 +45,7 @@ void PSAEliteSelection::initialise() addProperty("EliteRatio" , TString("Proportion of the Elite solutions of the total" " population. Default is half.") - , typeid(double).hash_code()); + , getTType(double)); m_name = TString("PSA Elite Selection"); m_description = TString("Creates a set with the best solutions selected from sets of non-dominace ranks.\n"); diff --git a/src/libs/tigon/Operators/Filtrations/RandFiltrationForModification.cpp b/src/libs/tigon/Operators/Filtrations/RandFiltrationForModification.cpp index 010084f..692bd98 100644 --- a/src/libs/tigon/Operators/Filtrations/RandFiltrationForModification.cpp +++ b/src/libs/tigon/Operators/Filtrations/RandFiltrationForModification.cpp @@ -65,8 +65,8 @@ int RandFiltrationForModification::TP_poolSize() const { void RandFiltrationForModification::initialise() { - addProperty("PoolSize", "Number of solutions to select. Default is 1", - typeid(int).hash_code()); + addProperty("PoolSize", "Number of solutions to select. Default is 1" + , getTType(int)); m_name = TString("Random selection for modification"); m_description = TString("Creates a set of solutions selected randomly from a set tagged \"for selection\".\n"); diff --git a/src/libs/tigon/Operators/Filtrations/RandFiltrationForPerturbation.cpp b/src/libs/tigon/Operators/Filtrations/RandFiltrationForPerturbation.cpp index a93193a..24f6afc 100644 --- a/src/libs/tigon/Operators/Filtrations/RandFiltrationForPerturbation.cpp +++ b/src/libs/tigon/Operators/Filtrations/RandFiltrationForPerturbation.cpp @@ -27,7 +27,7 @@ RandFiltrationForPerturbation::RandFiltrationForPerturbation() ,TString("Number of new solution created by the operator " "divided by the number of solutions in the input set. " "Default is 1") - ,typeid(double).hash_code()); + , getTType(double)); m_name = TString("Random filtration for Perturbation"); m_description = TString("Creates a set of solutions selected randomly " "from the set tagged \"for modification\".\n" @@ -44,10 +44,10 @@ RandFiltrationForPerturbation::RandFiltrationForPerturbation(Tigon::Representati : IFiltration(ipset) { addProperty("RatioOfNewSolutions" - ,TString("Number of new solution created by the operator " + , TString("Number of new solution created by the operator " "divided by the number of solutions in the input set. " "Default is 1") - ,typeid(double).hash_code()); + , getTType(double)); m_name = TString("Random filtration for Perturbation"); m_description = TString("Creates a set of solutions selected randomly from the set tagged \"for modification\".\n"); m_description += TString("The set is tagged \"For Perturbation\".\n"); diff --git a/src/libs/tigon/Operators/Filtrations/TournamentFiltrationForDirection.cpp b/src/libs/tigon/Operators/Filtrations/TournamentFiltrationForDirection.cpp index 5894ad4..2711af9 100644 --- a/src/libs/tigon/Operators/Filtrations/TournamentFiltrationForDirection.cpp +++ b/src/libs/tigon/Operators/Filtrations/TournamentFiltrationForDirection.cpp @@ -55,13 +55,13 @@ void TournamentFiltrationForDirection::initialise() addProperty("MappingsPerSet", TString("This is the number of mappings of each Set that " "is to be sent \"for direction\".\n" "The default is 2 mappings per set") - , typeid(int).hash_code()); + , getTType(int)); addProperty("NumberOfMappings", TString("This is the total number of mappings that can be " "added to the output set" "The default is -1 which means that the entire " "input set is selected into the output set") - , typeid(int).hash_code()); + , getTType(int)); // addProperty("SelectionMethod", TString("This property allows the user to select the method, " // " utilised by this operator, for picking the " diff --git a/src/libs/tigon/Operators/Filtrations/TournamentFiltrationForModification.cpp b/src/libs/tigon/Operators/Filtrations/TournamentFiltrationForModification.cpp index 1d35476..fa28cbe 100644 --- a/src/libs/tigon/Operators/Filtrations/TournamentFiltrationForModification.cpp +++ b/src/libs/tigon/Operators/Filtrations/TournamentFiltrationForModification.cpp @@ -28,7 +28,7 @@ TournamentFiltrationForModification::TournamentFiltrationForModification() { addProperty("ChildrenRatio" , TString("Proportion of the Children solutions of the total population. Default is half.") - , typeid(double).hash_code()); + , getTType(double)); addInputTag(Tigon::TForSelection); addInputTag(Tigon::TFitness); @@ -42,7 +42,7 @@ TournamentFiltrationForModification::TournamentFiltrationForModification(Tigon:: { addProperty("ChildrenRatio" , TString("Proportion of the Children solutions of the total population. Default is half.") - , typeid(double).hash_code()); + , getTType(double)); addInputTag(Tigon::TForSelection); addInputTag(Tigon::TFitness); diff --git a/src/libs/tigon/Operators/Fitness/NonDominanceRankingParametric.cpp b/src/libs/tigon/Operators/Fitness/NonDominanceRankingParametric.cpp index 15827c6..1115e26 100644 --- a/src/libs/tigon/Operators/Fitness/NonDominanceRankingParametric.cpp +++ b/src/libs/tigon/Operators/Fitness/NonDominanceRankingParametric.cpp @@ -47,7 +47,7 @@ void NonDominanceRankingParametric::initialise() , TString("Number of bins used to partition the parameter " "space.\n" "The default value is 20.") - , typeid(int).hash_code()); + , getTType(int)); TP_defineNumberOfBins(Tigon::DefaultNumberBins); } diff --git a/src/libs/tigon/Operators/Initialisation/IInitialisation.cpp b/src/libs/tigon/Operators/Initialisation/IInitialisation.cpp index a884479..ab6cd40 100644 --- a/src/libs/tigon/Operators/Initialisation/IInitialisation.cpp +++ b/src/libs/tigon/Operators/Initialisation/IInitialisation.cpp @@ -42,7 +42,7 @@ void IInitialisation::initialise() { addProperty("OptimizationSetSize" , TString("Number of mappings to initialise. Default is one") - , typeid(int).hash_code()); + , getTType(int)); addOutputTag(Tigon::TMainOptimizationSet); addOutputTag(Tigon::TForEvaluation); diff --git a/src/libs/tigon/Operators/Perturbations/IPerturbation.cpp b/src/libs/tigon/Operators/Perturbations/IPerturbation.cpp index 75d6c84..be35945 100644 --- a/src/libs/tigon/Operators/Perturbations/IPerturbation.cpp +++ b/src/libs/tigon/Operators/Perturbations/IPerturbation.cpp @@ -40,14 +40,14 @@ void IPerturbation::initialise() { addProperty("SolutionMutationProbability" , TString("Probability of applying mutation to a solution. Default is 1.0.") - , typeid(double).hash_code()); + , getTType(double)); addProperty("VariableMutationProbability" , TString("Average number of mutations per " "decision vector.\nThe per-variable " "probability is this number, divided " "by the number of decision variables\n" "Default is 1.") - , typeid(double).hash_code()); + , getTType(double)); TP_defineSolutionMutationProbability(Tigon::DefaultMutationSolutionProbability); TP_defineVariableMutationProbability(Tigon::DefaultMutationVariableProbability); diff --git a/src/libs/tigon/Operators/Perturbations/PolynomialMutation.cpp b/src/libs/tigon/Operators/Perturbations/PolynomialMutation.cpp index eae0260..eef9964 100644 --- a/src/libs/tigon/Operators/Perturbations/PolynomialMutation.cpp +++ b/src/libs/tigon/Operators/Perturbations/PolynomialMutation.cpp @@ -38,11 +38,10 @@ PolynomialMutation::PolynomialMutation(Tigon::Representation::IPSet* ipset) void PolynomialMutation::initialise() { - addProperty("MutationDistributionIndex", - TString("Controls the remoteness of the children from " - "the parent (see reference). " - "Default is 20.0"), - typeid(double).hash_code()); + addProperty("MutationDistributionIndex" + , TString("Controls the remoteness of the children from " + "the parent (see reference). Default is 20.0.") + , getTType(double)); TP_defineMutationDistributionIndex(Tigon::DefaultMutationDistributionIndex); diff --git a/src/libs/tigon/Operators/Terminations/ITermination.cpp b/src/libs/tigon/Operators/Terminations/ITermination.cpp index bedc9c4..20cdabf 100644 --- a/src/libs/tigon/Operators/Terminations/ITermination.cpp +++ b/src/libs/tigon/Operators/Terminations/ITermination.cpp @@ -89,11 +89,11 @@ void ITermination::initialise() { addProperty("maxIter" , TString("Max number of iterations") - , typeid(int).hash_code()); + , getTType(int)); addProperty("budget" , TString("Maximum number of function evaluations") - , typeid(int).hash_code()); + , getTType(int)); } } // namespace Operators From b1b2dd2aa4c186772d70277f3e1d8cd10278e2a6 Mon Sep 17 00:00:00 2001 From: "Joao A. Duro" Date: Fri, 1 Jan 2021 23:58:24 +0000 Subject: [PATCH 6/7] clean up --- .../Filtrations/FitnessEliteSelection.cpp | 7 +++--- .../Filtrations/NeighbourhoodFiltration.cpp | 24 +------------------ .../test_tigon/test_sparego/tst_sparego.cpp | 2 +- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/libs/tigon/Operators/Filtrations/FitnessEliteSelection.cpp b/src/libs/tigon/Operators/Filtrations/FitnessEliteSelection.cpp index cd0dd7a..c737852 100644 --- a/src/libs/tigon/Operators/Filtrations/FitnessEliteSelection.cpp +++ b/src/libs/tigon/Operators/Filtrations/FitnessEliteSelection.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2021 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -45,8 +45,9 @@ FitnessEliteSelection::FitnessEliteSelection() FitnessEliteSelection::FitnessEliteSelection(Tigon::Representation::IPSet* ipset) : IFiltration(ipset) { - addProperty("EliteRatio", - TString("Proportion of the Elite solutions of the total population. Default is half.") + addProperty("EliteRatio" + , TString("Proportion of the Elite solutions of the total " + "population. Default is half.") , getTType(double)); m_name = TString("Fitness-Based Elite Selection"); diff --git a/src/libs/tigon/Operators/Filtrations/NeighbourhoodFiltration.cpp b/src/libs/tigon/Operators/Filtrations/NeighbourhoodFiltration.cpp index 483adff..8e5fb43 100644 --- a/src/libs/tigon/Operators/Filtrations/NeighbourhoodFiltration.cpp +++ b/src/libs/tigon/Operators/Filtrations/NeighbourhoodFiltration.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012-2018 The University of Sheffield (www.sheffield.ac.uk) +** Copyright (C) 2012-2021 The University of Sheffield (www.sheffield.ac.uk) ** ** This file is part of Liger. ** @@ -53,12 +53,6 @@ void NeighbourhoodFiltration::initialise() "within a predefined distance in normalised decision space.\n" "The distance is controlled by changing the neighbourhood radius property"); -// addProperty("NeighbourhoodCriterion" -// , TString("This is an enumeration property that " -// "selects the criterion used by this operator " -// "to determine a solution neighbourhood.\n" -// "The default is NeighbourhoodRadius.") -// , typeid(NeighbourhoodType).hash_code()); addProperty("NeighbourhoodRadius" , TString("Maximum distance between solutions to be " "considered as neighbours.\nTo account for " @@ -80,12 +74,6 @@ void NeighbourhoodFiltration::initialise() "Outputsets, otherwise the outputsets are not clear.\n" "The default is true.\n") , getTType(bool)); -// addProperty("DistanceMeasureSelection" -// , TString("Selects the distance measure used to determine the " -// "neighbourhoods. The available options are " -// "ManhattanDistance and EuclideanDistance.\n" -// "The default is EuclideanDistance.\n") -// , typeid(DistanceMeasure).hash_code()); TP_defineNeighbourhoodCriterion(Tigon::NeighbourhoodRadius); TP_defineNeighbourhoodRadius(0.1); @@ -100,7 +88,6 @@ void NeighbourhoodFiltration::initialise() void NeighbourhoodFiltration::evaluateNode() { - if(TP_isClearOutputSets()) { clearOutputSets(); //overrides the data from previous iteration } @@ -118,15 +105,6 @@ void NeighbourhoodFiltration::evaluateNode() { // Normalise the decision variables BoxConstraintsDataSPtr box = boxConstraints(); - // TVector > normalInputs; - // for (int i=0; i normVec(decisionVecSize()); - // for(int j=0; jat(i)->decisionVar(j)->clone(); - // } - // normaliseToUnitBox(normVec,box); - // normalInputs.push_back(normVec); - // } // Calculate the distance (e.g. Euclidean) of every solution from each other for(int i=0; i Date: Sat, 2 Jan 2021 12:06:43 +0000 Subject: [PATCH 7/7] clean up --- .../test_tigon/test_sparego/tst_sparego.cpp | 96 +------------------ 1 file changed, 4 insertions(+), 92 deletions(-) diff --git a/tests/auto/test_tigon/test_sparego/tst_sparego.cpp b/tests/auto/test_tigon/test_sparego/tst_sparego.cpp index 144a03e..06700a7 100644 --- a/tests/auto/test_tigon/test_sparego/tst_sparego.cpp +++ b/tests/auto/test_tigon/test_sparego/tst_sparego.cpp @@ -46,12 +46,11 @@ private slots: void test_sParEGO_workflow(); void test_sParEGO(); void test_LogDirectionVector(); - void test_sParEGOWithMonteCarloValidation(); }; inline void writeVector(QTextStream &st, TVector vec, QString sep = "\t", QString endLine = "\n") { - for(int i=0; i neighbourhoods = nFilt->outputSets(); TVector counts; - for(int i=0; isize(); + for(size_t i=0; isize(); if(counts.size() < s) { counts.resize(s); } @@ -882,7 +881,6 @@ void tst_sparego::test_sParEGO() double nRaduis = 0.2; int budget = 14; int maxSurrogateSize = 30; - int stallIterations = 10; PSetBase* base = new PSetBase(); IFormulation* prob = new IFormulation(base); @@ -938,7 +936,6 @@ void tst_sparego::test_LogDirectionVector() // the maximum distance for neighbourhood is 0.2*sqrt(8) ~= 0.56569 double nRaduis = 0.2; int maxSurrogateSize = 10; - int stallIterations = 10; /// sParEGO optimization workflow PSetBase* base = new PSetBase(); @@ -981,7 +978,7 @@ void tst_sparego::test_LogDirectionVector() TVector dv = sol->weightingVec(); - for(int i=0; iTP_defineNInputs(dVecSize); - func->TP_defineNOutputs(oVecSize); - form->appendFunction(func); - - init->TP_defineSetSize(popsize); - init->TP_defineNeighbourhoodRadius(nRaduis); - init->addOutputTag(Tigon::TValidation); - - dirs->TP_defineReferenceSetSize(nDirs); - - filt->TP_defineMaxSolutions(maxSurrogateSize); - - val->TP_defineOperateOnFinal(false); - val->TP_defineCountEvaluations(true); - val->TP_defineScalarisingFunction(Tigon::WeightedChebyshev); - val->TP_defineNEvaluations(N); - val->addAdditionalOutputTag(Tigon::TFitness); - - opt->defineBudget(budget); - opt->TP_defineNeighbourhoodRadius(nRaduis); - opt->TP_defineErrorMethod(Tigon::ErrConfidenceIntervalBased); - opt->TP_defineOptimizationSearchQuality(0); - - iVal->defineIndicator(ConfidenceType, confidenceLevel); - - while(opt->remainingBudget() > 0) { - opt->evaluate(); - opt->incrementIteration(); - - cout << "Iteration: " << opt->currentIteration() - << ", Used budget " << opt->usedBudget() - << ", Remaining budget " << opt->remainingBudget() << endl; - } - - delete opt; - delete filt; - delete iVal; - delete val; - delete dirs; - delete init; - delete form; - delete base; -} - QTEST_GUILESS_MAIN(tst_sparego) #include "tst_sparego.moc"