Skip to content

Presolver incorrectly marks feasible Quadratic constraints as INFEASIBLE due to logic in doCaseN #647

@leorm2002

Description

@leorm2002

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;
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions