Hosaki Function¶
Note
This problem can be resolved without the surrogate modeling functionality (see branin function). Indeed, this functionality is useful when the objective function is computationally expensive. The purpose of this example is only to illustrate the use of surrogate modeling on a simple and computationally inexpensive problem.
Principles learned¶
Create an external function
Enable the surrogate modeling on an external function
Set an evaluation limit to the function
Problem¶
Hosaki function is defined by
This is a box-constrained problem.
For more details, see: hosaki_function.html
Download the exampleProgram¶
The objective function is defined by an external function. It receives the
argument values via the LSExternalArgumentValues
, and returns
the value of the function at this point.
Two floating decision variables x1
and x2
are declared. The domains of
these variables are respectively [0,5]
and [0,6]
. To calculate the value
returned by the external function, an O_Call
expression is created. This
expression is then minimized.
To use the surrogate modeling feature, the method enableSurrogateModeling
available on the LSExternalContext
of the function is called. This method
returns the LSSurrogateParameters
, on which the maximum number of calls to
the function can be set, as the function is usually computationally expensive.
- Execution:
- localsolver hosaki.lsp [evaluationLimit=] [solFileName=]
use io;
/* External function */
function hosaki(x1, x2) {
return (1 - 8*x1 + 7*pow(x1, 2) - 7*pow(x1, 3)/3 + pow(x1, 4)/4) * pow(x2, 2)
* exp(-x2);
}
/* Declare the optimization model */
function model() {
// Numerical decisions
x1 <- float(0, 5);
x2 <- float(0, 6);
// Create and call the function
f <- doubleExternalFunction(hosaki);
funcCall <- call(f, x1, x2);
// Enable surrogate modeling
surrogateParams = f.context.enableSurrogateModeling();
// Minimize function call
minimize(funcCall);
}
/* Parameterize the solver */
function param() {
if (evaluationLimit == nil) surrogateParams.evaluationLimit = 30;
else surrogateParams.evaluationLimit = evaluationLimit;
}
/* Write the solution in a file */
function output() {
if (solFileName != nil) {
local solFile = io.openWrite(solFileName);
solFile.println("obj=", funcCall.value);
solFile.println("x1=", x1.value);
solFile.println("x2=", x2.value);
}
}
- Execution (Windows)
- set PYTHONPATH=%LS_HOME%\bin\pythonpython hosaki.py
- Execution (Linux)
- export PYTHONPATH=/opt/localsolver_12_0/bin/pythonpython hosaki.py
import localsolver
import sys
import math
#
# External function
#
def hosaki_function(argument_values):
x1 = argument_values[0]
x2 = argument_values[1]
return ((1 - 8 * x1 + 7 * pow(x1, 2) - 7 * pow(x1, 3) / 3 + pow(x1, 4) / 4)
* pow(x2, 2) * math.exp(-x2))
def main(evaluation_limit, output_file):
with localsolver.LocalSolver() as ls:
#
# Declare the optimization model
#
model = ls.model
# Numerical decisions
x1 = model.float(0, 5)
x2 = model.float(0, 6)
# Create and call the function
f = model.create_double_external_function(hosaki_function)
func_call = model.call(f, x1, x2)
# Enable surrogate modeling
surrogate_params = f.external_context.enable_surrogate_modeling()
# Minimize function call
model.minimize(func_call)
model.close()
# Parameterize the solver
surrogate_params.evaluation_limit = evaluation_limit
ls.solve()
# Write the solution in a file
if output_file is not None:
with open(output_file, 'w') as f:
f.write("obj=%f\n" % func_call.value)
f.write("x1=%f\n" % x1.value)
f.write("x2=%f\n" % x2.value)
if __name__ == '__main__':
output_file = sys.argv[1] if len(sys.argv) > 1 else None
evaluation_limit = int(sys.argv[2]) if len(sys.argv) > 2 else 30
main(evaluation_limit, output_file)
- Compilation / Execution (Windows)
- cl /EHsc hosaki.cpp -I%LS_HOME%\include /link %LS_HOME%\bin\localsolver120.libhosaki
- Compilation / Execution (Linux)
- g++ hosaki.cpp -I/opt/localsolver_12_0/include -llocalsolver120 -lpthread -o hosakihosaki
#include "localsolver.h"
#include <cmath>
#include <fstream>
#include <iostream>
using namespace localsolver;
using namespace std;
/* External function */
class HosakiFunction : public LSExternalFunction<lsdouble> {
lsdouble call(const LSExternalArgumentValues& argumentValues) override {
lsdouble x1 = argumentValues.getDoubleValue(0);
lsdouble x2 = argumentValues.getDoubleValue(1);
return (1 - 8 * x1 + 7 * pow(x1, 2) - 7 * pow(x1, 3) / 3 + pow(x1, 4) / 4) * pow(x2, 2) * exp(-x2);
}
};
class Hosaki {
public:
// LocalSolver
LocalSolver localsolver;
// LS Program variables
LSExpression x1;
LSExpression x2;
LSExpression funcCall;
void solve(int evaluationLimit) {
// Declare the optimization model
LSModel model = localsolver.getModel();
// Numerical decisions
x1 = model.floatVar(0, 5);
x2 = model.floatVar(0, 6);
// Create and call the function
HosakiFunction funcClass;
LSExpression func = model.createExternalFunction(&funcClass);
funcCall = model.call(func, x1, x2);
// Enable surrogate modeling
LSExternalContext context = func.getExternalContext();
LSSurrogateParameters surrogateParams = context.enableSurrogateModeling();
// Minimize function call
model.minimize(funcCall);
model.close();
// Parameterize the solver
surrogateParams.setEvaluationLimit(evaluationLimit);
localsolver.solve();
}
/* Write the solution in a file */
void writeSolution(const string& fileName) {
ofstream outfile;
outfile.exceptions(ofstream::failbit | ofstream::badbit);
outfile.open(fileName.c_str());
outfile << "obj=" << funcCall.getDoubleValue() << endl;
outfile << "x1=" << x1.getDoubleValue() << endl;
outfile << "x2=" << x2.getDoubleValue() << endl;
}
};
int main(int argc, char** argv) {
const char* solFile = argc > 1 ? argv[1] : NULL;
const char* strEvaluationLimit = argc > 2 ? argv[2] : "30";
try {
Hosaki model;
model.solve(atoi(strEvaluationLimit));
if (solFile != NULL)
model.writeSolution(solFile);
} catch (const exception& e) {
cerr << "An error occurred: " << e.what() << endl;
return 1;
}
return 0;
}
- Compilation / Execution (Windows)
- copy %LS_HOME%\bin\localsolvernet.dll .csc Hosaki.cs /reference:localsolvernet.dllHosaki
using System;
using System.IO;
using localsolver;
public class Hosaki : IDisposable
{
/* External function */
public class HosakiFunction
{
public double Call(LSExternalArgumentValues argumentValues)
{
double x1 = argumentValues.GetDoubleValue(0);
double x2 = argumentValues.GetDoubleValue(1);
return (1 - 8 * x1 + 7 * Math.Pow(x1, 2) - 7 * Math.Pow(x1, 3) / 3 + Math.Pow(x1, 4) / 4)
* Math.Pow(x2, 2)
* Math.Exp(-x2);
}
}
// LocalSolver
private LocalSolver localsolver;
// LS Program variables
private LSExpression x1;
private LSExpression x2;
private LSExpression funcCall;
public Hosaki()
{
localsolver = new LocalSolver();
}
public void Dispose()
{
if (localsolver != null)
localsolver.Dispose();
}
public void Solve(int evaluationLimit)
{
// Declare the optimization model
LSModel model = localsolver.GetModel();
// Numerical decisions
x1 = model.Float(0, 5);
x2 = model.Float(0, 6);
// Create and call the function
HosakiFunction hosakiFunction = new HosakiFunction();
LSDoubleExternalFunction func = new LSDoubleExternalFunction(hosakiFunction.Call);
LSExpression funcExpr = model.DoubleExternalFunction(func);
funcCall = model.Call(funcExpr, x1, x2);
// Enable surrogate modeling
LSExternalContext context = funcExpr.GetExternalContext();
LSSurrogateParameters surrogateParams = context.EnableSurrogateModeling();
// Minimize function call
model.Minimize(funcCall);
model.Close();
// Parameterize the solver
surrogateParams.SetEvaluationLimit(evaluationLimit);
localsolver.Solve();
}
/* Write the solution in a file */
public void WriteSolution(string fileName)
{
using (StreamWriter output = new StreamWriter(fileName))
{
output.WriteLine("obj=" + funcCall.GetDoubleValue());
output.WriteLine("x1=" + x1.GetDoubleValue());
output.WriteLine("x2=" + x2.GetDoubleValue());
}
}
public static void Main(string[] args)
{
string outputFile = args.Length > 0 ? args[0] : null;
string strEvaluationLimit = args.Length > 1 ? args[1] : "30";
using (Hosaki model = new Hosaki())
{
model.Solve(int.Parse(strEvaluationLimit));
if (outputFile != null)
model.WriteSolution(outputFile);
}
}
}
- Compilation / Execution (Windows)
- javac Hosaki.java -cp %LS_HOME%\bin\localsolver.jarjava -cp %LS_HOME%\bin\localsolver.jar;. Hosaki
- Compilation / Execution (Linux)
- javac Hosaki.java -cp /opt/localsolver_12_0/bin/localsolver.jarjava -cp /opt/localsolver_12_0/bin/localsolver.jar:. Hosaki
import java.io.*;
import java.lang.Math;
import localsolver.*;
public class Hosaki {
/* External function */
private static class HosakiFunction implements LSDoubleExternalFunction {
@Override
public double call(LSExternalArgumentValues argumentValues) {
double x1 = argumentValues.getDoubleValue(0);
double x2 = argumentValues.getDoubleValue(1);
return (1 - 8 * x1 + 7 * Math.pow(x1, 2) - 7 * Math.pow(x1, 3) / 3 + Math.pow(x1, 4) / 4) * Math.pow(x2, 2) * Math.exp(-x2);
}
}
// LocalSolver
private final LocalSolver localsolver;
// LS Program variables
private LSExpression x1;
private LSExpression x2;
private LSExpression funcCall;
private Hosaki(LocalSolver localsolver) {
this.localsolver = localsolver;
}
private void solve(int evaluationLimit) {
// Declare the optimization model
LSModel model = localsolver.getModel();
// Numerical decisions
x1 = model.floatVar(0, 5);
x2 = model.floatVar(0, 6);
// Create and call the function
HosakiFunction function = new HosakiFunction();
LSExpression func = model.doubleExternalFunction(function);
funcCall = model.call(func, x1, x2);
// Enable surrogate modeling
LSExternalContext context = func.getExternalContext();
LSSurrogateParameters surrogateParams = context.enableSurrogateModeling();
// Minimize function call
model.minimize(funcCall);
model.close();
// Parameterize the solver
surrogateParams.setEvaluationLimit(evaluationLimit);
localsolver.solve();
}
/* Write the solution in a file */
private void writeSolution(String fileName) throws IOException {
try (PrintWriter output = new PrintWriter(fileName)) {
output.println("obj=" + funcCall.getDoubleValue());
output.println("x1=" + x1.getDoubleValue());
output.println("x2=" + x2.getDoubleValue());
}
}
public static void main(String[] args) {
String outputFile = args.length > 0 ? args[0] : null;
String strEvaluationLimit = args.length > 1 ? args[1] : "30";
try (LocalSolver localsolver = new LocalSolver()) {
Hosaki model = new Hosaki(localsolver);
model.solve(Integer.parseInt(strEvaluationLimit));
if (outputFile != null) {
model.writeSolution(outputFile);
}
} catch (Exception ex) {
System.err.println(ex);
ex.printStackTrace();
System.exit(1);
}
}
}