Closed jdh8 closed 1 year ago
Hello,
unfortunately this is not possible yet for a number of reasons. The only way to run Couenne is through AMPL, due to Ipopt using the AMPL interface to obtain nonlinear information (gradient, Hessian, etc.). Some recent developments sidestep this for specific heuristics, but these are not available yet for the use you showed.
Regards,
Pietro
Sent: Monday, December 13, 2021 at 12:05 PM From: "Chen-Pang He" @.> To: "coin-or/Couenne" @.> Cc: "Subscribed" @.***> Subject: [coin-or/Couenne] How to solve a CouenneProblem when using Couenne as a C++ library (Issue #59)
I am using Couenne as a C++ library to solve MINLP programmatically. I have constructed a CouenneProblem with the following code:
int main() { const Couenne::CouNumber xs[] = { 1, 5, 5, 1 }; const Couenne::CouNumber lbs[] = { 1, 1, 1, 1 }; const Couenne::CouNumber ubs[] = { 5, 5, 5, 5 };
Couenne::Domain domain; domain.push(Couenne::DomainPoint(4, xs, lbs, ubs, false), false);
Couenne::CouenneProblem problem;
Couenne::expression x0 = problem.addVariable(/isint=/false, &domain); Couenne::expression x1 = problem.addVariable(/isint=/false, &domain); Couenne::expression x2 = problem.addVariable(/isint=/true, &domain); Couenne::expression x3 = problem.addVariable(/isint=/true, &domain);
problem.addObjective(new Couenne::exprSum( new Couenne::exprMul(new Couenne::expression [3]{ x0->clone(), x3->clone(), new Couenne::exprSum(new Couenne::expression [3]{ x0->clone(), x1->clone(), x2->clone() }, 3) }, 3), x2->clone())); }
However, I don't know how to solve the problem. I tried Bonmin::BonminSetup, but it seemed to lack a Bonmin::TMINLP for initialization.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.
The AMPL and various other interfaces to Couenne implement the problem twice, as CouenneProblem and as TMINLP. So this would need to be done here, too.
I am working on computing gradients/Jacobians/Hessians with autodiff. I am still unsure about which function whose Hessian Bonmin::TMINLP
wants. Does it want the Hessian of the objective function? I think so because we are finding extrema as zeros of the first derivative (gradient) with help from the second derivative (Hessian).
It wants the Hessian of the Lagrangian function. It may be best to look at the Ipopt and Bonmin docus. A Bonmin::TMINLP is an Ipopt::TNLP plus some extras.
The files Couenne/src/heuristics/CouenneF* implement a feasibility pump and interface Ipopt with the problem through a native, non-AMPL interface. Maybe you want to take a look at that for your example, but I haven't generalized yet to Couenne as such.
Sent: Wednesday, December 15, 2021 at 10:50 AM From: "Stefan Vigerske" @.> To: "coin-or/Couenne" @.> Cc: "Pietro Belotti" @.>, "Comment" @.> Subject: Re: [coin-or/Couenne] How to solve a CouenneProblem when using Couenne as a C++ library (Issue #59)
It wants the Hessian of the Lagrangian function. It may be best to look at the Ipopt and Bonmin docus. A Bonmin::TMINLP is an Ipopt::TNLP plus some extras.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.
@jdh8 If I'm not mistaken, Optimization Services provides an interface for doing what you want to do. I couldn't find a very good succinct set of instructions that explain the basics (although there surely is something), but you can get the idea starting around Slide 28 of this deck. @merraksh please correct me if I'm wrong.
@tkralphs thanks, I forgot about OS. Slide 30 of the deck mentions methods for constructing general nonlinear constraints, so that must be the way to go. OS provides Hessian/Jacobian/gradient interfaces too, so this seems possible indeed.
Thanks! I've built an OSInstance
of my problem. Now I'm going to find out where its solving API is.
#include <coin/OSInstance.h>
namespace {
struct Expression : std::unique_ptr<OSnLNode>
{
using std::unique_ptr<OSnLNode>::unique_ptr;
Expression(OSnLNodeVariable &);
Expression(double);
};
} // namespace
Expression::Expression(OSnLNodeVariable &var)
: std::unique_ptr<OSnLNode>(var.cloneExprNode())
{}
Expression::Expression(double value)
: std::unique_ptr<OSnLNode>([](double v)
{
OSnLNodeNumber *raw = new OSnLNodeNumber;
raw->value = v;
return raw;
}(value))
{}
Expression operator+(Expression &&x, Expression &&y)
{
Expression expr(new OSnLNodePlus);
expr->m_mChildren[0] = x.release();
expr->m_mChildren[1] = y.release();
return expr;
}
Expression operator*(Expression &&x, Expression &&y)
{
Expression expr(new OSnLNodeTimes);
expr->m_mChildren[0] = x.release();
expr->m_mChildren[1] = y.release();
return expr;
}
Expression square(Expression &&x)
{
Expression expr(new OSnLNodeSquare);
expr->m_mChildren[0] = x.release();
return expr;
}
Nl make_nl(int index, Expression &&expr)
{
Nl nl;
ScalarExpressionTree *tree = new ScalarExpressionTree;
tree->m_treeRoot = expr.release();
nl.idx = index;
nl.osExpressionTree = tree;
return nl;
}
int main()
{
OSInstance instance;
instance.setInstanceSource("An example of MINLP");
instance.setInstanceDescription("A hard nonlinear program from "
"https://apmonitor.com/online/view_pass.php?f=minlp.apm");
instance.setVariableNumber(4);
instance.addVariable(0, "x0", 1, 5, 'C');
instance.addVariable(1, "x1", 1, 5, 'C');
instance.addVariable(2, "x2", 1, 5, 'I');
instance.addVariable(3, "x3", 1, 5, 'I');
SparseVector objcoeffs;
instance.setObjectiveNumber(1);
// Indices of objective functions go -1, -2, -3, ....
// This convention is how OS tells objectives from constraints.
instance.addObjective(-1, "", "min", 0, 1, &objcoeffs);
instance.setConstraintNumber(2);
instance.addConstraint(0, "", 25, OSDBL_MAX, 0);
instance.addConstraint(1, "", 40, 40, 0);
OSnLNodeVariable x0, x1, x2, x3;
x0.idx = 0;
x1.idx = 1;
x2.idx = 2;
x3.idx = 3;
Nl exprs[] = {
make_nl(-1, x0 * x3 * (x0 + x1 + x2) + x2),
make_nl(0, x0 * x1 * x2 * x3),
make_nl(1, square(x0) + square(x1) + square(x2) + square(x3)),
};
Nl *root[] = { exprs, exprs + 1, exprs + 2 };
instance.setNonlinearExpressions(3, root);
// From this point, `instance` has all data of my problem
}
I found the solver API. We can solve the instance with CouenneSolver
OSInstance instance /*= Somehow make an instance */;
CouenneSolver solver;
solver.osinstance = &instance;
solver.solve();
I am using Couenne as a C++ library to solve MINLP programmatically. I have constructed a
CouenneProblem
with the following code:However, I don't know how to solve the
problem
. I triedBonmin::BonminSetup
, but it seemed to lack aBonmin::TMINLP
for initialization.