Solving your first model in C++

Hexaly Optimizer is implemented in C++ language. A highly-portable C++ library is provided with object-oriented application programming interfaces (APIs), allowing a full integration of Hexaly Optimizer in your business applications. Hexaly Optimizer APIs are lightweight, with only a few classes to manipulate. Note that Hexaly Optimizer is a model-and-run math programming solver: having instantiated the model, no additional code has to be written in order to run the solver.

In this section, we show you how to model and solve your first problem in C++: the optimization of the shape of a bucket. With a limited surface of material (S=π), we try to build a bucket that holds the largest volume.

This small example is more precisely described in our example tour. Here our main goal is to learn how to write and launch a model.

Writing the model

Below is the C++ program which models this non linear problem (see examples/optimal_bucket).

#include "optimizer/hexalyoptimizer.h"
#include <fstream>
#include <iostream>
#include <vector>

using namespace hexaly;
using namespace std;

class OptimalBucket {
public:
    // Hexaly Optimizer
    HexalyOptimizer optimizer;

    // Hexaly Program variables
    HxExpression R;
    HxExpression r;
    HxExpression h;

    HxExpression surface;
    HxExpression volume;

    void solve(int limit) {
        hxdouble PI = 3.14159265359;

        // Declare the optimization model
        HxModel model = optimizer.getModel();

        // Numerical decisions
        R = model.floatVar(0.0, 1.0);
        r = model.floatVar(0.0, 1.0);
        h = model.floatVar(0.0, 1.0);

        // Surface must not exceed the surface of the plain disc
        surface = PI * model.pow(r, 2) + PI * (R + r) * model.sqrt(model.pow(R - r, 2) + model.pow(h, 2));
        model.constraint(model.leq(surface, PI));

        // Maximize the volume
        volume = PI * h / 3 * (model.pow(R, 2) + R * r + model.pow(r, 2));
        model.maximize(volume);

        model.close();

        // Parametrize the optimizer
        optimizer.getParam().setTimeLimit(limit);

        optimizer.solve();
    }

    /* Write the solution in a file with the following format:
     *  - surface and volume of the bucket
     *  - values of R, r and h */
    void writeSolution(const string& fileName) {
        ofstream outfile;
        outfile.exceptions(ofstream::failbit | ofstream::badbit);
        outfile.open(fileName.c_str());

        outfile << surface.getDoubleValue() << " " << volume.getDoubleValue() << endl;
        outfile << R.getDoubleValue() << " " << r.getDoubleValue() << " " << h.getDoubleValue() << endl;
    }
};

int main(int argc, char** argv) {
    const char* solFile = argc > 1 ? argv[1] : NULL;
    const char* strTimeLimit = argc > 2 ? argv[2] : "2";

    try {
        OptimalBucket model;
        model.solve(atoi(strTimeLimit));
        if (solFile != NULL)
            model.writeSolution(solFile);
        return 0;
    } catch (const exception& e) {
        cerr << "An error occurred:" << e.what() << endl;
        return 1;
    }
}

After creating the Hexaly Optimizer environment with HexalyOptimizer(), all the decision variables of the model, are declared with function floatVar() (or also boolVar(), intVar(), setVar(), listVar()). Intermediate expressions can be built upon these decision variables by using other operators or functions. For example, in the model above: power (pow), square root (sqrt), less than or equal to (leq). Many other mathematical operators are available, allowing you to model and solve highly-nonlinear combinatorial optimization problems. The functions constraint or maximize are used for tagging expressions as constrained or maximized.

Compiling and running the C++ program

On Windows, the above program is compiled and launched using the following lines in Visual Studio Command Prompt x64:

cl /EHsc optimal_bucket.cpp -I%HX_HOME%\include /link %HX_HOME%\bin\hexaly130.lib
optimal_bucket

Note that on Windows, in a PowerShell window you would use the following lines:

cl /EHsc optimal_bucket.cpp -I"$env:HX_HOME\include" /link "$env:HX_HOME\bin\hexaly130.lib"
optimal_bucket

On Linux or Mac OS, the same program is compiled and launched using the following lines:

g++ optimal_bucket.cpp -I/opt/hexaly_13_0/include -lhexaly130 -lpthread -o optimal_bucket
./optimal_bucket

Then, the following trace will appear in your console:

Model:  expressions = 26, decisions = 3, constraints = 1, objectives = 1
Param:  time limit = 2 sec, no iteration limit

[objective direction ]:     maximize

[  0 sec,       0 itr]:            0
[ optimality gap     ]:         100%
[  0 sec,   42898 itr]:      0.68709
[ optimality gap     ]:      < 0.01%

42898 iterations performed in 0 seconds

Optimal solution:
    obj    =      0.68709
    gap    =      < 0.01%
    bounds =     0.687189

If no time limit is set, the search will continue until optimality is proven (Optimal solution message) or until you force the stop of the program by pressing Ctrl+C. The trace in console starts with the key figures of the model: number of expressions, decisions, constraints and objectives.

Once the search is finished, the total number of iterations and the elapsed time are displayed, as well as the status and the value of the best solution found. The solution status can be Inconsistent, Infeasible, Feasible or Optimal.

If you have trouble compiling or launching the program, please have a look at the Installation & licensing. We invite users willing to go further with APIs to consult the C++ API Reference.