FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Repairing infeasibility

Description
Demonstrates the repairinfeas utility, prints a relaxation summary and creates the relaxed subproblem.

repair_java.zip[download all files]

Source Files
By clicking on a file name, a preview is opened at the bottom of this page.
Repair.java[download]





Repair.java

/***********************************************************************
   Xpress Optimizer Examples
   =========================

   file repair.c
   `````````````
   Demonstrates the FICO repairinfeas utility.

   Prints a relaxation summary and creates the relaxed subproblem.

   (c) 2020-2024 Fair Isaac Corporation
***********************************************************************/

import com.dashoptimization.DefaultMessageListener;
import com.dashoptimization.XPRS;
import com.dashoptimization.XPRSprob;

import java.util.Arrays;

public final class Repair {

    public static void main(String[] args) {
        if ( args.length != 1 )
            throw new IllegalArgumentException("syntax: repair <filename>");
        String problem = args[0];

        // Initialize Optimizer
        try (XPRSprob prob = new XPRSprob(null)) {
            // Forward messages to screen
            prob.addMessageListener(DefaultMessageListener::console);

            // Load problem file and query dimensions
            prob.readProb(problem, "");
            int rows = prob.attributes().getRows();
            int cols = prob.attributes().getCols();

            // Allocate and set the preference arrays (we give the same
            // preference to all potential violations)
            double[] rowPref = new double[rows];   // row preferences
            double[] groupPref = new double[rows]; // group preferences
            double[] lbPref = new double[cols];    // lower bound preferences
            double[] ubPref = new double[cols];    // upper bound preferences
            Arrays.fill(rowPref, 1.0);
            Arrays.fill(groupPref, 1.0);
            Arrays.fill(lbPref, 1.0);
            Arrays.fill(ubPref, 1.0);

            // Allocate memory for the solution and the infeasibility breakers
            double[] x = new double[cols];
            double[] slacks = new double[rows];
            double[] boundviolations = new double[cols];
            double[] rowviolations = new double[rows];

            // Call repairinfeas
            int status = prob.repairWeightedInfeas(rowPref, groupPref, lbPref, ubPref,
                                                   'n', 0.001, "");
            System.out.printf("Repairinfeas return code (%d): ", status);
            switch (status) {
            case 0: System.out.printf("relaxed optimum found%n"); break;
            case 1: System.out.printf("relaxed problem is infeasible%n"); break;
            case 2: System.out.printf("relaxed problem is unbounded%n"); break;
            case 3: System.out.printf("solution of the relaxed problem regarding the original objective is nonoptimal%n"); break;
            case 4: System.out.printf("error%n"); break;
            case 5: System.out.printf("numerical instability%n"); break;
            }

            int nSets = prob.attributes().getSets();
            int nEnts = prob.attributes().getMIPEnts();

            // Get solution
            if ((nSets + nEnts) == 0) {
                prob.getLpSol(x, slacks, null, null);
            } else {
                // NOTE: for MIPs, use the getmipsolution function instead
                prob.getMipSol(x, slacks);
            }

            // Get the values of the breaker variables
            generateInfeasibilityBreakers(prob, x, slacks, rowviolations, boundviolations, 1.0e-6);

            // Print report
            generateInfeasilityReport(prob, rowviolations, boundviolations);

            // Repair and save problem
            applyRepairInfeasResult(prob, rowviolations, boundviolations);
            prob.writeProb("repaired.lp","lp");
            System.out.printf("Repaired problem is written as repaired.lp.%n");
            System.out.printf("(Please note that this matrix might show slightly different behaviour then the repairinfeas problem)%n%n");
        }
    }


    /** This function returns the lower bound for a row. */
    private static double getRowLB(XPRSprob prob, int i) {
        double rhs = prob.getRHS(i);
        double range = prob.getRHSrange(i);
        byte type = prob.getRowType(i);
        switch (type) {
        case 'L': return XPRS.MINUSINFINITY;
        case 'E': return rhs;
        case 'G': return rhs;
        case 'R': return rhs - range;
        default: return XPRS.MINUSINFINITY;
        }
    }

    /** This function returns the upper bound for a row. */
    private static double getRowUB(XPRSprob prob, int i) {
        double rhs = prob.getRHS(i);
        double range = prob.getRHSrange(i);
        byte type = prob.getRowType(i);
        switch (type) {
        case 'L': return rhs;
        case 'E': return rhs;
        case 'G': return XPRS.PLUSINFINITY;
        case 'R': return rhs;
        default: return XPRS.PLUSINFINITY;
        }
    }

    /** This function sets new lower and upper bounds for a row. */
    private static void setRowBounds(XPRSprob prob, int i, double rowLB, double rowUB) {
        double lb, ub;

        // Normalize bounds for range constraints (we assume that we
        // do not attempt to set contradictory bounds).
        if (rowLB <= rowUB) {
            lb = rowLB;
            ub = rowUB;
        } else {
            lb = rowUB;
            ub = rowLB;
        }

        // determine row type and set bounds
        if (lb <= XPRS.MINUSINFINITY && ub >= XPRS.PLUSINFINITY) {
            prob.chgRowType(i, (byte)'N');
        }
        else if (lb <= XPRS.MINUSINFINITY) {
            prob.chgRowType(i, (byte)'L');
            prob.chgRHS(i, ub);
        }
        else if (ub >= XPRS.PLUSINFINITY) {
            prob.chgRowType(i, (byte)'G');
            prob.chgRHS(i, lb);
        }
        else if (lb == ub) {
            prob.chgRowType(i, (byte)'E');
            prob.chgRHS(i, ub);
        }
        else {
            prob.chgRowType(i, (byte)'R');
            prob.chgRHS(i, ub);
            prob.chgRHSrange(i, ub - lb);
        }
    }

    /** This function calculates the infeasibilities of a solution
     * (i.e. the values of the feasibility breakers after a repairinfeas
     * call)
     */
    private static void generateInfeasibilityBreakers(XPRSprob prob, double[] x, double[] slacks, double[] constraints, double[] bounds, double tolarence) {
        // Get problem dimensions
        int rows = prob.attributes().getOriginalRows();
        int cols = prob.attributes().getOriginalCols();

        // Check constraints
        for (int i = 0; i < rows; i++) {
            double rhs = prob.getRHS(i);
            double activity = rhs - slacks[i];
            double lb = getRowLB(prob, i);
            double ub = getRowUB(prob, i);

            if (activity < lb - tolarence) {
                // a negative value indicates that the lower bound is relaxed
                constraints[i] = activity - lb;
            }
            else if (activity > ub+tolarence) {
                // a positive value indicates that the upper bound is relaxed
                constraints[i] = activity - ub;
            }
            else {
                constraints[i] = 0.0;
            }
        }

        // Check bounds
        for (int j = 0; j < cols; j++) {
            double lb = prob.getLB(j);
            double ub = prob.getUB(j);

            if (x[j] < lb - tolarence) {
                // a negative value indicates that the lower bound is relaxed
                bounds[j] = x[j] - lb;
            }
            else if (x[j] > ub + tolarence) {
                // a positive value indicates that the upper bound is relaxed
                bounds[j] = x[j] - ub;
            }
            else {
                bounds[j] = 0.0;
            }
        }
    }

    /** This function just converts a double to a string for reporting,
     * converting infinity values as "NONE"
     */
    private static String boundToString(double bound) {
        if (bound > XPRS.MINUSINFINITY && bound < XPRS.PLUSINFINITY) {
            if (bound >= 0)
                return String.format(" %.5e", bound);
            else
                return String.format("%.5e", bound);
        }
        else
            return "    NONE     ";
    }

    /** Prints a summary of the infeasibily breakers using the already
     * calculated infeasibities
     */
    private static void generateInfeasilityReport(XPRSprob prob, double[] constraintviolations, double []boundviolations) {
        double suminf = 0;   // Sum if infeasibility
        int    ninf = 0;     // Number of violateed rows and columns

        int rows = prob.attributes().getOriginalRows();
        int cols = prob.attributes().getOriginalCols();

        System.out.printf("%n");
        System.out.printf("%n");
        System.out.printf("XPRESS-MP FEASIBILITY REPAIR REPORT.%n");
        System.out.printf("%n");
        System.out.printf("The following constraints were repaired.%n");
        System.out.printf("%n");

        System.out.printf("Index     Name%4s  Lower bound    Repaired        Upper bound    Repaired %n", "");

        for (int i = 0; i < rows; i++) {
            if (constraintviolations[i] != 0) {

                // Get constraint name
                String name = prob.getRowName(i);
                double lb = getRowLB(prob, i);
                double ub = getRowUB(prob, i);

                suminf += Math.abs(constraintviolations[i]);
                ninf++;

                String lbShift, ubShift;
                if (constraintviolations[i] < 0) {
                    lbShift = boundToString(lb + constraintviolations[i]);
                    ubShift = boundToString(ub);
                } else {
                    lbShift = boundToString(lb);
                    ubShift = boundToString(ub + constraintviolations[i]);
                }

                System.out.printf("%5d  %8s    %7s  %7s   %7s  %7s%n", i, name, boundToString(lb), lbShift, boundToString(ub), ubShift);
            }
        }

        System.out.printf("%n");
        System.out.printf("The following bound constraints were repaired.%n");
        System.out.printf("%n");

        System.out.printf("Index   Name%4s   Lower bound      Repaired     Upper bound      Repaired %n", "");

        for (int j = 0; j < cols; j++) {
            if (boundviolations[j] != 0) {
                // Get column name
                String name = prob.getColumnName(j);
                double lb = prob.getLB(j);
                double ub = prob.getUB(j);

                suminf += Math.abs(boundviolations[j]);
                ninf++;

                String lbShift, ubShift;
                if (constraintviolations[j] < 0) {
                    lbShift = boundToString(boundviolations[j]);
                    ubShift = boundToString(ub);
                }
                else {
                    lbShift = boundToString(lb);
                    ubShift = boundToString(boundviolations[j]);
                }

                System.out.printf("%5d  %8s    %7s  %7s   %7s  %7s%n", j, name, boundToString(lb), lbShift, boundToString(ub), ubShift);
            }
        }

        System.out.printf("%n");
        System.out.printf("Sum of Violations %f%n", suminf);
        System.out.printf("Number of corrections: %d%n", ninf);
        System.out.printf("%n");
    }

    /** Relaxes the problem given the values of the feasibility breakers.
     */
    private static void applyRepairInfeasResult(XPRSprob prob, double[] constraintviolations, double[] boundviolations) {
        int rows = prob.attributes().getOriginalRows();
        int cols = prob.attributes().getOriginalCols();

        // Apply changes to rows
        for (int i = 0; i < rows; i++) {
            if (constraintviolations[i] != 0) {
                double lb = getRowLB(prob, i);
                double ub = getRowUB(prob, i);
                // Apply relaxation
                if (constraintviolations[i] > 0)
                    ub += constraintviolations[i];
                else
                    lb += constraintviolations[i];
                setRowBounds(prob, i, lb, ub);
            }
        }

        // Apply changes to columns
        for (int j = 0; j < cols; j++) {
            if (boundviolations[j] != 0) {
                double lb = prob.getLB(j);
                double ub = prob.getUB(j);
                if (boundviolations[j] > 0)
                    prob.chgUB(j, ub + boundviolations[j]);
                else
                    prob.chgLB(j, lb + boundviolations[j]);
            }
        }

        System.out.printf("%n");
        System.out.printf("Problem repaired.");
        System.out.printf("%n");
    }
}

Back to examples browserPrevious exampleNext example