-
-
Notifications
You must be signed in to change notification settings - Fork 217
Description
Hello,
I encountered an issue where a feasible model containing quadratic expressions (with both quadratic and linear terms) is incorrectly marked as INFEASIBLE during the presolve phase. If I disable the presolver, the model is solved correctly.
Upon inspecting the source code, I believe the issue lies within the doCaseN method and its helper methods, specifically isNegativeOn and isPositiveOn.
Currently, the logic seems to be:
boolean isNegativeOn(final Set<IntIndex> subset) {
if (!this.isAnyQuadraticFactorNonZero()) {
// ... logic checking linear factors ...
}
// If there ARE quadratic factors, the loop is skipped and it returns TRUE
return true;
}
If an expression contains quadratic factors (e.g., x2), isAnyQuadraticFactorNonZero() returns true. Consequently, the method skips the linear checks and falls through to return true.
Here is a standalone test case demonstrating the issue. It solves a simple quadratic problem twice: first with the default presolvers (Result: INFEASIBLE), and then without them (Result: OPTIMAL).
package org.ojalgo.optimisation;
import java.math.BigDecimal;
import org.ojalgo.optimisation.solver.cplex.SolverCPLEX;
public class OJPresolveTest {
public static void main(String[] args) {
// Run with presolver
System.out.println("--- Run WITH Presolver ---");
caseN();
}
static void caseN() {
ExpressionsBasedModel model = getModel();
// 1. Solve with default settings (Presolver enabled)
Optimisation.Result result = model.minimise();
System.out.println("State with presolver: " + result.getState());
// 2. Clear presolvers and solve again
ExpressionsBasedModel.clearPresolvers();
// Re-create model to ensure clean state
model = getModel();
Optimisation.Result resultNoPre = model.minimise();
System.out.println("State without presolver: " + resultNoPre.getState());
}
private static ExpressionsBasedModel getModel() {
ExpressionsBasedModel model = new ExpressionsBasedModel();
Variable x1 = model.addVariable("x1");
Variable x2 = model.addVariable("x2");
Variable x3 = model.addVariable("x3");
x1.upper(1).lower(0);
x2.upper(1).lower(0);
x3.upper(1).lower(0);
// Create the quadratic expression
Expression quadExpr = model.addExpression("QuadraticExpression");
quadExpr.set(x1, x1, 0.1);
quadExpr.set(x2, x2, 0.1);
quadExpr.set(x3, x3, 0.1);
quadExpr.set(x1, -0.0649319296487038);
quadExpr.set(x2, -0.035049269354063314);
quadExpr.set(x3, -0.054569655903981634);
// This constraint causes the issue during presolve
quadExpr.upper(new BigDecimal("-0.02"));
return model;
}
}