Search in sources :

Example 26 with Expression

use of org.ojalgo.optimisation.Expression in project ojAlgo by optimatika.

the class SimplexSolver method build.

static SimplexTableau build(final ExpressionsBasedModel model) {
    final List<Variable> tmpPosVariables = model.getPositiveVariables();
    final List<Variable> tmpNegVariables = model.getNegativeVariables();
    final Set<IntIndex> tmpFixVariables = model.getFixedVariables();
    final Expression tmpObjFunc = model.objective().compensate(tmpFixVariables);
    final List<Expression> tmpExprsEq = model.constraints().filter(c -> c.isEqualityConstraint() && !c.isAnyQuadraticFactorNonZero()).collect(Collectors.toList());
    final List<Expression> tmpExprsLo = model.constraints().filter(c -> c.isLowerConstraint() && !c.isAnyQuadraticFactorNonZero()).collect(Collectors.toList());
    final List<Expression> tmpExprsUp = model.constraints().filter(c -> c.isUpperConstraint() && !c.isAnyQuadraticFactorNonZero()).collect(Collectors.toList());
    final List<Variable> tmpVarsPosLo = model.bounds().filter(v -> v.isPositive() && v.isLowerConstraint() && (v.getLowerLimit().signum() > 0)).collect(Collectors.toList());
    final List<Variable> tmpVarsPosUp = model.bounds().filter(v -> v.isPositive() && v.isUpperConstraint() && (v.getUpperLimit().signum() > 0)).collect(Collectors.toList());
    final List<Variable> tmpVarsNegLo = model.bounds().filter(v -> v.isNegative() && v.isLowerConstraint() && (v.getLowerLimit().signum() < 0)).collect(Collectors.toList());
    final List<Variable> tmpVarsNegUp = model.bounds().filter(v -> v.isNegative() && v.isUpperConstraint() && (v.getUpperLimit().signum() < 0)).collect(Collectors.toList());
    final int tmpConstraiCount = tmpExprsEq.size() + tmpExprsLo.size() + tmpExprsUp.size() + tmpVarsPosLo.size() + tmpVarsPosUp.size() + tmpVarsNegLo.size() + tmpVarsNegUp.size();
    final int tmpProblVarCount = tmpPosVariables.size() + tmpNegVariables.size();
    final int tmpSlackVarCount = tmpExprsLo.size() + tmpExprsUp.size() + tmpVarsPosLo.size() + tmpVarsPosUp.size() + tmpVarsNegLo.size() + tmpVarsNegUp.size();
    final SimplexTableau retVal = SimplexTableau.make(tmpConstraiCount, tmpProblVarCount, tmpSlackVarCount);
    final int tmpPosVarsBaseIndex = 0;
    final int tmpNegVarsBaseIndex = tmpPosVarsBaseIndex + tmpPosVariables.size();
    final int tmpSlaVarsBaseIndex = tmpNegVarsBaseIndex + tmpNegVariables.size();
    for (final IntIndex tmpKey : tmpObjFunc.getLinearKeySet()) {
        final double tmpFactor = model.isMaximisation() ? -tmpObjFunc.getAdjustedLinearFactor(tmpKey) : tmpObjFunc.getAdjustedLinearFactor(tmpKey);
        final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
        if (tmpPosInd >= 0) {
            retVal.objective().set(tmpPosInd, tmpFactor);
        }
        final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
        if (tmpNegInd >= 0) {
            retVal.objective().set(tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
        }
    }
    int tmpConstrBaseIndex = 0;
    int tmpCurrentSlackVarIndex = tmpSlaVarsBaseIndex;
    final int tmpExprsEqLength = tmpExprsEq.size();
    for (int c = 0; c < tmpExprsEqLength; c++) {
        final Expression tmpExpr = tmpExprsEq.get(c).compensate(tmpFixVariables);
        final double tmpRHS = tmpExpr.getAdjustedLowerLimit();
        if (tmpRHS < ZERO) {
            retVal.constraintsRHS().set(tmpConstrBaseIndex + c, -tmpRHS);
            for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
                final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
                final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
                if (tmpPosInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, -tmpFactor);
                }
                final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
                if (tmpNegInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, tmpFactor);
                }
            }
        } else {
            retVal.constraintsRHS().set(tmpConstrBaseIndex + c, tmpRHS);
            for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
                final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
                final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
                if (tmpPosInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, tmpFactor);
                }
                final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
                if (tmpNegInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
                }
            }
        }
    }
    tmpConstrBaseIndex += tmpExprsEqLength;
    final int tmpExprsLoLength = tmpExprsLo.size();
    for (int c = 0; c < tmpExprsLoLength; c++) {
        final Expression tmpExpr = tmpExprsLo.get(c).compensate(tmpFixVariables);
        final double tmpRHS = tmpExpr.getAdjustedLowerLimit();
        if (tmpRHS < ZERO) {
            retVal.constraintsRHS().set(tmpConstrBaseIndex + c, -tmpRHS);
            for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
                final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
                final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
                if (tmpPosInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, -tmpFactor);
                }
                final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
                if (tmpNegInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, tmpFactor);
                }
            }
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, ONE);
        } else {
            retVal.constraintsRHS().set(tmpConstrBaseIndex + c, tmpRHS);
            for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
                final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
                final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
                if (tmpPosInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, tmpFactor);
                }
                final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
                if (tmpNegInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
                }
            }
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, NEG);
        }
    }
    tmpConstrBaseIndex += tmpExprsLoLength;
    final int tmpExprsUpLength = tmpExprsUp.size();
    for (int c = 0; c < tmpExprsUpLength; c++) {
        final Expression tmpExpr = tmpExprsUp.get(c).compensate(tmpFixVariables);
        final double tmpRHS = tmpExpr.getAdjustedUpperLimit();
        if (tmpRHS < ZERO) {
            retVal.constraintsRHS().set(tmpConstrBaseIndex + c, -tmpRHS);
            for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
                final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
                final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
                if (tmpPosInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, -tmpFactor);
                }
                final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
                if (tmpNegInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, tmpFactor);
                }
            }
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, NEG);
        } else {
            retVal.constraintsRHS().set(tmpConstrBaseIndex + c, tmpRHS);
            for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
                final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
                final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
                if (tmpPosInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, tmpFactor);
                }
                final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
                if (tmpNegInd >= 0) {
                    retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
                }
            }
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, ONE);
        }
    }
    tmpConstrBaseIndex += tmpExprsUpLength;
    final int tmpVarsPosLoLength = tmpVarsPosLo.size();
    for (int c = 0; c < tmpVarsPosLoLength; c++) {
        final Variable tmpVar = tmpVarsPosLo.get(c);
        retVal.constraintsRHS().set(tmpConstrBaseIndex + c, tmpVar.getAdjustedLowerLimit());
        final int tmpKey = model.indexOf(tmpVar);
        final double tmpFactor = tmpVar.getAdjustmentFactor();
        final int tmpPosInd = model.indexOfPositiveVariable(tmpKey);
        if (tmpPosInd >= 0) {
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, tmpFactor);
        }
        final int tmpNegInd = model.indexOfNegativeVariable(tmpKey);
        if (tmpNegInd >= 0) {
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
        }
        retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, NEG);
    }
    tmpConstrBaseIndex += tmpVarsPosLoLength;
    final int tmpVarsPosUpLength = tmpVarsPosUp.size();
    for (int c = 0; c < tmpVarsPosUpLength; c++) {
        final Variable tmpVar = tmpVarsPosUp.get(c);
        retVal.constraintsRHS().set(tmpConstrBaseIndex + c, tmpVar.getAdjustedUpperLimit());
        final int tmpKey = model.indexOf(tmpVar);
        final double tmpFactor = tmpVar.getAdjustmentFactor();
        final int tmpPosInd = model.indexOfPositiveVariable(tmpKey);
        if (tmpPosInd >= 0) {
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, tmpFactor);
        }
        final int tmpNegInd = model.indexOfNegativeVariable(tmpKey);
        if (tmpNegInd >= 0) {
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
        }
        retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, ONE);
    }
    tmpConstrBaseIndex += tmpVarsPosUpLength;
    final int tmpVarsNegLoLength = tmpVarsNegLo.size();
    for (int c = 0; c < tmpVarsNegLoLength; c++) {
        final Variable tmpVar = tmpVarsNegLo.get(c);
        retVal.constraintsRHS().set(tmpConstrBaseIndex + c, -tmpVar.getAdjustedLowerLimit());
        final int tmpKey = model.indexOf(tmpVar);
        final double tmpFactor = tmpVar.getAdjustmentFactor();
        final int tmpPosInd = model.indexOfPositiveVariable(tmpKey);
        if (tmpPosInd >= 0) {
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, -tmpFactor);
        }
        final int tmpNegInd = model.indexOfNegativeVariable(tmpKey);
        if (tmpNegInd >= 0) {
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, tmpFactor);
        }
        retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, ONE);
    }
    tmpConstrBaseIndex += tmpVarsNegLoLength;
    final int tmpVarsNegUpLength = tmpVarsNegUp.size();
    for (int c = 0; c < tmpVarsNegUpLength; c++) {
        final Variable tmpVar = tmpVarsNegUp.get(c);
        retVal.constraintsRHS().set(tmpConstrBaseIndex + c, -tmpVar.getAdjustedUpperLimit());
        final int tmpKey = model.indexOf(tmpVar);
        final double tmpFactor = tmpVar.getAdjustmentFactor();
        final int tmpPosInd = model.indexOfPositiveVariable(tmpKey);
        if (tmpPosInd >= 0) {
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, -tmpFactor);
        }
        final int tmpNegInd = model.indexOfNegativeVariable(tmpKey);
        if (tmpNegInd >= 0) {
            retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, tmpFactor);
        }
        retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, NEG);
    }
    tmpConstrBaseIndex += tmpVarsNegUpLength;
    if (retVal.getOvercapacity() <= OjAlgoUtils.ENVIRONMENT.getCacheElements(8L)) {
        return retVal.toDense();
    } else {
        return retVal;
    }
}
Also used : Arrays(java.util.Arrays) SparseArray(org.ojalgo.array.SparseArray) Variable(org.ojalgo.optimisation.Variable) ExpressionsBasedModel(org.ojalgo.optimisation.ExpressionsBasedModel) Optimisation(org.ojalgo.optimisation.Optimisation) PrimitiveMath(org.ojalgo.constant.PrimitiveMath) Mutate1D(org.ojalgo.access.Mutate1D) MatrixStore(org.ojalgo.matrix.store.MatrixStore) IntIndex(org.ojalgo.access.Structure1D.IntIndex) PrimitiveAggregator(org.ojalgo.function.aggregator.PrimitiveAggregator) ConvexSolver(org.ojalgo.optimisation.convex.ConvexSolver) PrimitiveFunction(org.ojalgo.function.PrimitiveFunction) Set(java.util.Set) AggregatorFunction(org.ojalgo.function.aggregator.AggregatorFunction) Collectors(java.util.stream.Collectors) PrimitiveDenseStore(org.ojalgo.matrix.store.PrimitiveDenseStore) OjAlgoUtils(org.ojalgo.OjAlgoUtils) RowsSupplier(org.ojalgo.matrix.store.RowsSupplier) PhysicalStore(org.ojalgo.matrix.store.PhysicalStore) Array1D(org.ojalgo.array.Array1D) List(java.util.List) Mutate2D(org.ojalgo.access.Mutate2D) IterationPoint(org.ojalgo.optimisation.linear.SimplexTableau.IterationPoint) Expression(org.ojalgo.optimisation.Expression) NumberContext(org.ojalgo.type.context.NumberContext) Access1D(org.ojalgo.access.Access1D) Variable(org.ojalgo.optimisation.Variable) Expression(org.ojalgo.optimisation.Expression) IntIndex(org.ojalgo.access.Structure1D.IntIndex) IterationPoint(org.ojalgo.optimisation.linear.SimplexTableau.IterationPoint)

Example 27 with Expression

use of org.ojalgo.optimisation.Expression in project ojAlgo by optimatika.

the class ConvexProblems method buildModel.

static ExpressionsBasedModel buildModel(final PrimitiveDenseStore[] matrices, final PrimitiveDenseStore expectedSolution) {
    final ExpressionsBasedModel retVal = new ExpressionsBasedModel();
    final int tmpNumberOfVariables = (int) matrices[3].count();
    for (int v = 0; v < tmpNumberOfVariables; v++) {
        final Variable tmpVariable = Variable.make("X" + v);
        tmpVariable.setValue(BigDecimal.valueOf(expectedSolution.doubleValue(v)));
        retVal.addVariable(tmpVariable);
    }
    if ((matrices[0] != null) && (matrices[1] != null)) {
        for (int e = 0; e < matrices[0].countRows(); e++) {
            final Expression tmpExpression = retVal.addExpression("E" + e);
            for (int v = 0; v < tmpNumberOfVariables; v++) {
                tmpExpression.set(v, matrices[0].get(e, v));
            }
            tmpExpression.level(matrices[1].doubleValue(e));
        }
    }
    if ((matrices[4] != null) && (matrices[5] != null)) {
        for (int i = 0; i < matrices[4].countRows(); i++) {
            final Expression tmpExpression = retVal.addExpression("I" + i);
            for (int v = 0; v < tmpNumberOfVariables; v++) {
                tmpExpression.set(v, matrices[4].get(i, v));
            }
            tmpExpression.upper(matrices[5].doubleValue(i));
        }
    }
    final Expression tmpObjQ = retVal.addExpression("Q");
    for (int r = 0; r < tmpNumberOfVariables; r++) {
        for (int v = 0; v < tmpNumberOfVariables; v++) {
            tmpObjQ.set(r, v, matrices[2].doubleValue(r, v));
        }
    }
    tmpObjQ.weight(HALF);
    final Expression tmpObjC = retVal.addExpression("C");
    for (int v = 0; v < tmpNumberOfVariables; v++) {
        tmpObjC.set(v, matrices[3].doubleValue(v));
    }
    tmpObjC.weight(NEG);
    return retVal;
}
Also used : Variable(org.ojalgo.optimisation.Variable) Expression(org.ojalgo.optimisation.Expression) ExpressionsBasedModel(org.ojalgo.optimisation.ExpressionsBasedModel)

Example 28 with Expression

use of org.ojalgo.optimisation.Expression in project ojAlgo by optimatika.

the class ConvexProblems method testInfeasibleCase.

/**
 * Just make sure an obviously infeasible problem is recognised as such - this has been a problem in the
 * past
 */
@Test
public void testInfeasibleCase() {
    final Variable[] tmpVariables = new Variable[] { new Variable("X1").lower(ONE).upper(TWO).weight(ONE), new Variable("X2").lower(ONE).upper(TWO).weight(TWO), new Variable("X3").lower(ONE).upper(TWO).weight(THREE) };
    final ExpressionsBasedModel tmpModel = new ExpressionsBasedModel(tmpVariables);
    final Expression tmpExprQ = tmpModel.addExpression("Q1");
    for (int i = 0; i < tmpModel.countVariables(); i++) {
        for (int j = 0; j < tmpModel.countVariables(); j++) {
            tmpExprQ.set(i, i, Math.random());
        }
    }
    // May not be positive definite, but infeasibillity should be realised before that becomes a problem
    tmpExprQ.weight(TEN);
    // tmpModel.options.debug(ConvexSolver.class);
    final Expression tmpExprC1 = tmpModel.addExpression("C1");
    for (int i = 0; i < tmpModel.countVariables(); i++) {
        tmpExprC1.set(i, ONE);
    }
    tmpExprC1.upper(TWO);
    Optimisation.Result tmpResult = tmpModel.maximise();
    TestUtils.assertFalse(tmpResult.getState().isFeasible());
    tmpExprC1.upper(null);
    tmpExprC1.lower(SEVEN);
    tmpResult = tmpModel.maximise();
    TestUtils.assertFalse(tmpResult.getState().isFeasible());
    OptimisationConvexTests.assertDirectAndIterativeEquals(tmpModel, null);
}
Also used : Variable(org.ojalgo.optimisation.Variable) Expression(org.ojalgo.optimisation.Expression) Result(org.ojalgo.optimisation.Optimisation.Result) Optimisation(org.ojalgo.optimisation.Optimisation) ExpressionsBasedModel(org.ojalgo.optimisation.ExpressionsBasedModel) Test(org.junit.jupiter.api.Test)

Example 29 with Expression

use of org.ojalgo.optimisation.Expression in project ojAlgo by optimatika.

the class FinancePortfolioProblem method buildModel.

private static ExpressionsBasedModel buildModel(final BasicMatrix covariances, final BasicMatrix returns, final BigDecimal riskAversion) {
    ProgrammingError.throwIfNotSquare(covariances);
    ProgrammingError.throwIfNotEqualRowDimensions(covariances, returns);
    final int numberOfVariables = (int) returns.countRows();
    final Variable[] tmpVariables = new Variable[numberOfVariables];
    for (int i = 0; i < numberOfVariables; i++) {
        tmpVariables[i] = Variable.make("Asset_" + Integer.toString(i)).lower(ZERO).upper(ONE).weight(-returns.doubleValue(i));
    }
    final ExpressionsBasedModel retVal = new ExpressionsBasedModel(tmpVariables);
    final Expression tmp100P = retVal.addExpression("Balance");
    for (int i = 0; i < numberOfVariables; i++) {
        tmp100P.set(i, ONE);
    }
    tmp100P.level(ONE);
    final Expression tmpVar = retVal.addExpression("Variance");
    for (int i = 0; i < numberOfVariables; i++) {
        for (int j = 0; j < numberOfVariables; j++) {
            tmpVar.set(i, j, covariances.doubleValue(i, j));
        }
    }
    tmpVar.weight(BigFunction.DIVIDE.invoke(riskAversion, TWO));
    return retVal;
}
Also used : Variable(org.ojalgo.optimisation.Variable) Expression(org.ojalgo.optimisation.Expression) ExpressionsBasedModel(org.ojalgo.optimisation.ExpressionsBasedModel)

Example 30 with Expression

use of org.ojalgo.optimisation.Expression in project ojAlgo by optimatika.

the class OJAlgoTest3 method main.

/**
 * @param args the command line arguments Objective: allocate the maximum qty, and try to keep
 *        proportionality between customer.
 */
public static void main(final String[] args) {
    /*
         * 5 Products with associated Qty.
         */
    final Map<String, Integer> constraintsProduct = new HashMap<>();
    constraintsProduct.put("PRODUCT_1", 296_000);
    constraintsProduct.put("PRODUCT_2", 888_000);
    constraintsProduct.put("PRODUCT_3", 636_000);
    constraintsProduct.put("PRODUCT_4", 220_000);
    constraintsProduct.put("PRODUCT_5", 0);
    final double stockTotal = constraintsProduct.values().stream().mapToDouble(e -> e.doubleValue()).sum();
    BasicLogger.debug("STOCK_TOTAL " + stockTotal);
    /*
         * Demand of each Customers
         */
    final Map<String, Integer> constraintsCustomer = new LinkedHashMap<>();
    constraintsCustomer.put("CUSTOMER_A_1", 72_000);
    constraintsCustomer.put("CUSTOMER_A_2", 44_000);
    constraintsCustomer.put("CUSTOMER_A_3", 12_000);
    constraintsCustomer.put("CUSTOMER_A_4", 36_000);
    constraintsCustomer.put("CUSTOMER_A_5", 0);
    constraintsCustomer.put("CUSTOMER_A_6", 36_000);
    constraintsCustomer.put("CUSTOMER_A_7", 12_000);
    constraintsCustomer.put("CUSTOMER_A_8", 0);
    constraintsCustomer.put("CUSTOMER_A_9", 0);
    constraintsCustomer.put("CUSTOMER_A_10", 12_000);
    constraintsCustomer.put("CUSTOMER_A_11", 12_000);
    constraintsCustomer.put("CUSTOMER_A_12", 0);
    constraintsCustomer.put("CUSTOMER_A_13", 0);
    constraintsCustomer.put("CUSTOMER_A_14", 0);
    constraintsCustomer.put("CUSTOMER_B_1", 24_000);
    constraintsCustomer.put("CUSTOMER_B_2", 12_000);
    constraintsCustomer.put("CUSTOMER_B_3", 300);
    constraintsCustomer.put("CUSTOMER_C_1", 24_000);
    constraintsCustomer.put("CUSTOMER_D_1", 20_000);
    constraintsCustomer.put("CUSTOMER_E_1", 12_000);
    constraintsCustomer.put("CUSTOMER_F_1", 12_000);
    constraintsCustomer.put("CUSTOMER_G_1", 72_000);
    constraintsCustomer.put("CUSTOMER_H_1", 28_000);
    constraintsCustomer.put("CUSTOMER_I_1", 24_000);
    constraintsCustomer.put("CUSTOMER_J_1", 16_000);
    constraintsCustomer.put("CUSTOMER_K_1", 24_000);
    constraintsCustomer.put("CUSTOMER_L_1", 56_000);
    final double demandTotal = constraintsCustomer.values().stream().mapToDouble(e -> e.doubleValue()).sum();
    BasicLogger.debug("DEMAND_TOTAL " + demandTotal);
    /*
         * User constraint. In this case, user want to allocate 236_000 Qty on Customer_A_*
         */
    final double userConstraintQty = 236_000;
    final List<String> userConstraint = new ArrayList<>();
    userConstraint.add("CUSTOMER_A_1|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_2|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_3|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_4|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_5|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_6|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_7|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_8|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_9|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_10|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_11|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_12|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_13|PRODUCT_2");
    userConstraint.add("CUSTOMER_A_14|PRODUCT_2");
    // List of Variable Names
    final List<String> variablesName = new ArrayList<>();
    variablesName.add("CUSTOMER_A_1|PRODUCT_2");
    variablesName.add("CUSTOMER_A_2|PRODUCT_2");
    variablesName.add("CUSTOMER_A_3|PRODUCT_2");
    variablesName.add("CUSTOMER_A_4|PRODUCT_2");
    variablesName.add("CUSTOMER_A_5|PRODUCT_2");
    variablesName.add("CUSTOMER_A_6|PRODUCT_2");
    variablesName.add("CUSTOMER_A_7|PRODUCT_2");
    variablesName.add("CUSTOMER_A_8|PRODUCT_2");
    variablesName.add("CUSTOMER_A_9|PRODUCT_2");
    variablesName.add("CUSTOMER_A_10|PRODUCT_2");
    variablesName.add("CUSTOMER_A_11|PRODUCT_2");
    variablesName.add("CUSTOMER_A_12|PRODUCT_2");
    variablesName.add("CUSTOMER_A_13|PRODUCT_2");
    variablesName.add("CUSTOMER_A_14|PRODUCT_2");
    variablesName.add("CUSTOMER_B_1|PRODUCT_2");
    variablesName.add("CUSTOMER_B_1|PRODUCT_3");
    variablesName.add("CUSTOMER_B_2|PRODUCT_2");
    variablesName.add("CUSTOMER_B_2|PRODUCT_3");
    variablesName.add("CUSTOMER_B_3|PRODUCT_2");
    variablesName.add("CUSTOMER_B_3|PRODUCT_3");
    variablesName.add("CUSTOMER_C_1|PRODUCT_2");
    variablesName.add("CUSTOMER_C_1|PRODUCT_3");
    variablesName.add("CUSTOMER_D_1|PRODUCT_4");
    variablesName.add("CUSTOMER_D_1|PRODUCT_5");
    variablesName.add("CUSTOMER_D_1|PRODUCT_2");
    variablesName.add("CUSTOMER_D_1|PRODUCT_3");
    variablesName.add("CUSTOMER_E_1|PRODUCT_1");
    variablesName.add("CUSTOMER_F_1|PRODUCT_4");
    variablesName.add("CUSTOMER_F_1|PRODUCT_5");
    variablesName.add("CUSTOMER_F_1|PRODUCT_2");
    variablesName.add("CUSTOMER_F_1|PRODUCT_3");
    variablesName.add("CUSTOMER_G_1|PRODUCT_4");
    variablesName.add("CUSTOMER_G_1|PRODUCT_5");
    variablesName.add("CUSTOMER_G_1|PRODUCT_2");
    variablesName.add("CUSTOMER_G_1|PRODUCT_3");
    variablesName.add("CUSTOMER_H_1|PRODUCT_4");
    variablesName.add("CUSTOMER_H_1|PRODUCT_5");
    variablesName.add("CUSTOMER_H_1|PRODUCT_2");
    variablesName.add("CUSTOMER_H_1|PRODUCT_3");
    variablesName.add("CUSTOMER_I_1|PRODUCT_4");
    variablesName.add("CUSTOMER_I_1|PRODUCT_5");
    variablesName.add("CUSTOMER_I_1|PRODUCT_2");
    variablesName.add("CUSTOMER_I_1|PRODUCT_3");
    variablesName.add("CUSTOMER_J_1|PRODUCT_4");
    variablesName.add("CUSTOMER_J_1|PRODUCT_5");
    variablesName.add("CUSTOMER_J_1|PRODUCT_2");
    variablesName.add("CUSTOMER_J_1|PRODUCT_3");
    variablesName.add("CUSTOMER_K_1|PRODUCT_4");
    variablesName.add("CUSTOMER_K_1|PRODUCT_5");
    variablesName.add("CUSTOMER_K_1|PRODUCT_2");
    variablesName.add("CUSTOMER_K_1|PRODUCT_3");
    variablesName.add("CUSTOMER_L_1|PRODUCT_1");
    /*
         *
         */
    final ExpressionsBasedModel model = new ExpressionsBasedModel();
    final List<Variable> variables = new ArrayList<>();
    /*
         * Create All Variables:
         */
    BasicLogger.debug("---- Variable creation ------");
    variablesName.forEach(name -> {
        final Variable var = Variable.make(name).lower(0.0).weight(1.0);
        model.addVariable(var);
        variables.add(var);
        BasicLogger.debug(var);
    });
    BasicLogger.debug("---- Constraints customers ------");
    // Apply Customers constraints.
    // CUSTOMER_A of Demand constraint because managed by user constraints.
    constraintsCustomer.entrySet().stream().filter(e -> !e.getKey().startsWith("CUSTOMER_A")).forEach(entry -> {
        final List<Variable> linked = variables.stream().filter(v -> v.getName().startsWith(entry.getKey())).collect(Collectors.toList());
        final Expression constraint = model.addExpression("CONSTRAINTS_" + entry.getKey());
        constraint.upper(entry.getValue().doubleValue());
        constraint.setLinearFactorsSimple(linked);
        BasicLogger.debug(constraint);
    });
    BasicLogger.debug("---- User Constraints Customers ------");
    // Apply Product Type constraints.
    final List<Variable> userLinked = variables.stream().filter(v -> userConstraint.contains(v.getName())).collect(Collectors.toList());
    final Expression constraintUser = model.addExpression("CONSTRAINTS_USER_CUSTOMER_A");
    constraintUser.level(userConstraintQty);
    constraintUser.setLinearFactorsSimple(userLinked);
    BasicLogger.debug(constraintUser);
    BasicLogger.debug("---- Constraints Product ------");
    // Apply Product Type constraints.
    constraintsProduct.entrySet().forEach(entry -> {
        final List<Variable> linked = variables.stream().filter(v -> v.getName().endsWith(entry.getKey())).collect(Collectors.toList());
        final Expression constraint = model.addExpression("CONSTRAINTS_" + entry.getKey());
        constraint.upper(entry.getValue().doubleValue());
        constraint.setLinearFactorsSimple(linked);
        BasicLogger.debug(constraint);
    });
    /*
         * Objective expression. - Maximize the Sum of all variables - Minimize the Sum of square error vs
         * proportionality.
         */
    BasicLogger.debug("---- Objective  ------");
    final Expression objective = model.addExpression("OBJECTIVE").weight(-1.0);
    // - Maximize the Sum of all variables
    // objective.setLinearFactorsSimple(variables);
    BasicLogger.debug("---- Error formula ------");
    /*
         * Example: x1, x2, x3 linked variables for Customer X Error = ( (x1+x2+x3) / Target - 1 )^2 * ratio
         */
    constraintsCustomer.entrySet().forEach(entry -> {
        final List<Variable> linked = variables.stream().filter(v -> v.getName().startsWith(entry.getKey())).collect(Collectors.toList());
        if (!linked.isEmpty() && (entry.getValue().doubleValue() > 0)) {
            final double demand = entry.getValue();
            final double ratio = demand / demandTotal;
            final double target = stockTotal * ratio;
            linked.forEach(v1 -> {
                linked.forEach(v2 -> {
                    objective.set(v1, v2, ratio / (target * target));
                });
                objective.set(v1, (-2.0 * ratio) / target);
            });
        }
    });
    // - Maximise
    // model.options.validate = true;
    final Result result = model.maximise();
    BasicLogger.debug(result);
    // GOOD  OPTIMAL 560300.4702803734
    // WRONG OPTIMAL 560300.4015031556
    BasicLogger.debug("");
    BasicLogger.debug("");
    variables.forEach(v -> BasicLogger.debug(v.getName() + " = " + v.getValue().doubleValue()));
/*
         * WRONG ALLOCATION CUSTOMER_A_1|PRODUCT_2 = 236000.0 CUSTOMER_A_2|PRODUCT_2 = 0.0
         * CUSTOMER_A_3|PRODUCT_2 = 0.0 CUSTOMER_A_4|PRODUCT_2 = 0.0 CUSTOMER_A_5|PRODUCT_2 = 0.0
         * CUSTOMER_A_6|PRODUCT_2 = 0.0 CUSTOMER_A_7|PRODUCT_2 = 0.0 CUSTOMER_A_8|PRODUCT_2 = 0.0
         * CUSTOMER_A_9|PRODUCT_2 = 0.0 CUSTOMER_A_10|PRODUCT_2 = 0.0 CUSTOMER_A_11|PRODUCT_2 = 0.0
         * CUSTOMER_A_12|PRODUCT_2 = 0.0 CUSTOMER_A_13|PRODUCT_2 = 0.0 CUSTOMER_A_14|PRODUCT_2 = 0.0
         * CUSTOMER_B_1|PRODUCT_2 = 24000.0 CUSTOMER_B_1|PRODUCT_3 = 0.0 CUSTOMER_B_2|PRODUCT_2 = 12000.0
         * CUSTOMER_B_2|PRODUCT_3 = 0.0 CUSTOMER_B_3|PRODUCT_2 = 0.0 CUSTOMER_B_3|PRODUCT_3 = 300.0
         * CUSTOMER_C_1|PRODUCT_2 = 24000.0 CUSTOMER_C_1|PRODUCT_3 = 0.0 CUSTOMER_D_1|PRODUCT_4 = 20000.0
         * CUSTOMER_D_1|PRODUCT_5 = 0.0 CUSTOMER_D_1|PRODUCT_2 = 0.0 CUSTOMER_D_1|PRODUCT_3 = 0.0
         * CUSTOMER_E_1|PRODUCT_1 = 12000.0 CUSTOMER_F_1|PRODUCT_4 = 12000.0 CUSTOMER_F_1|PRODUCT_5 = 0.0
         * CUSTOMER_F_1|PRODUCT_2 = 0.0 CUSTOMER_F_1|PRODUCT_3 = 0.0 CUSTOMER_G_1|PRODUCT_4 = 72000.0
         * CUSTOMER_G_1|PRODUCT_5 = 0.0 CUSTOMER_G_1|PRODUCT_2 = 0.0 CUSTOMER_G_1|PRODUCT_3 = 0.0
         * CUSTOMER_H_1|PRODUCT_4 = 28000.0 CUSTOMER_H_1|PRODUCT_5 = 0.0 CUSTOMER_H_1|PRODUCT_2 = 0.0
         * CUSTOMER_H_1|PRODUCT_3 = 0.0 CUSTOMER_I_1|PRODUCT_4 = 24000.0 CUSTOMER_I_1|PRODUCT_5 = 0.0
         * CUSTOMER_I_1|PRODUCT_2 = 0.0 CUSTOMER_I_1|PRODUCT_3 = 0.0 CUSTOMER_J_1|PRODUCT_4 = 16000.0
         * CUSTOMER_J_1|PRODUCT_5 = 0.0 CUSTOMER_J_1|PRODUCT_2 = 0.0 CUSTOMER_J_1|PRODUCT_3 = 0.0
         * CUSTOMER_K_1|PRODUCT_4 = 24000.0 CUSTOMER_K_1|PRODUCT_5 = 0.0 CUSTOMER_K_1|PRODUCT_2 = 0.0
         * CUSTOMER_K_1|PRODUCT_3 = 0.0 CUSTOMER_L_1|PRODUCT_1 = 56000.0
         */
/*
         * GOOD ALLOCATION CUSTOMER_A_1|PRODUCT_2 = 80150.9434796 CUSTOMER_A_2|PRODUCT_2 = 48981.1320493
         * CUSTOMER_A_3|PRODUCT_2 = 13358.4905589 CUSTOMER_A_4|PRODUCT_2 = 40075.4716767
         * CUSTOMER_A_5|PRODUCT_2 = 0.0 CUSTOMER_A_6|PRODUCT_2 = 40075.4716767 CUSTOMER_A_7|PRODUCT_2 =
         * 13358.4905589 CUSTOMER_A_8|PRODUCT_2 = 0.0 CUSTOMER_A_9|PRODUCT_2 = 0.0 CUSTOMER_A_10|PRODUCT_2 =
         * 0.0 CUSTOMER_A_11|PRODUCT_2 = 0.0 CUSTOMER_A_12|PRODUCT_2 = 0.0 CUSTOMER_A_13|PRODUCT_2 = 0.0
         * CUSTOMER_A_14|PRODUCT_2 = 0.0 CUSTOMER_B_1|PRODUCT_2 = 24000.0 CUSTOMER_B_1|PRODUCT_3 = 0.0
         * CUSTOMER_B_2|PRODUCT_2 = 12000.0 CUSTOMER_B_2|PRODUCT_3 = 0.0 CUSTOMER_B_3|PRODUCT_2 = 0.0
         * CUSTOMER_B_3|PRODUCT_3 = 300.0 CUSTOMER_C_1|PRODUCT_2 = 24000.0 CUSTOMER_C_1|PRODUCT_3 = 0.0
         * CUSTOMER_D_1|PRODUCT_4 = 20000.0 CUSTOMER_D_1|PRODUCT_5 = 0.0 CUSTOMER_D_1|PRODUCT_2 = 0.0
         * CUSTOMER_D_1|PRODUCT_3 = 0.0 CUSTOMER_E_1|PRODUCT_1 = 12000.0 CUSTOMER_F_1|PRODUCT_4 = 12000.0
         * CUSTOMER_F_1|PRODUCT_5 = 0.0 CUSTOMER_F_1|PRODUCT_2 = 0.0 CUSTOMER_F_1|PRODUCT_3 = 0.0
         * CUSTOMER_G_1|PRODUCT_4 = 72000.0 CUSTOMER_G_1|PRODUCT_5 = 0.0 CUSTOMER_G_1|PRODUCT_2 = 0.0
         * CUSTOMER_G_1|PRODUCT_3 = 0.0 CUSTOMER_H_1|PRODUCT_4 = 28000.0 CUSTOMER_H_1|PRODUCT_5 = 0.0
         * CUSTOMER_H_1|PRODUCT_2 = 0.0 CUSTOMER_H_1|PRODUCT_3 = 0.0 CUSTOMER_I_1|PRODUCT_4 = 24000.0
         * CUSTOMER_I_1|PRODUCT_5 = 0.0 CUSTOMER_I_1|PRODUCT_2 = 0.0 CUSTOMER_I_1|PRODUCT_3 = 0.0
         * CUSTOMER_J_1|PRODUCT_4 = 16000.0 CUSTOMER_J_1|PRODUCT_5 = 0.0 CUSTOMER_J_1|PRODUCT_2 = 0.0
         * CUSTOMER_J_1|PRODUCT_3 = 0.0 CUSTOMER_K_1|PRODUCT_4 = 24000.0 CUSTOMER_K_1|PRODUCT_5 = 0.0
         * CUSTOMER_K_1|PRODUCT_2 = 0.0 CUSTOMER_K_1|PRODUCT_3 = 0.0 CUSTOMER_L_1|PRODUCT_1 = 56000.0
         */
}
Also used : LinkedHashMap(java.util.LinkedHashMap) List(java.util.List) Result(org.ojalgo.optimisation.Optimisation.Result) Expression(org.ojalgo.optimisation.Expression) Map(java.util.Map) BasicLogger(org.ojalgo.netio.BasicLogger) Variable(org.ojalgo.optimisation.Variable) HashMap(java.util.HashMap) ExpressionsBasedModel(org.ojalgo.optimisation.ExpressionsBasedModel) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) Variable(org.ojalgo.optimisation.Variable) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ExpressionsBasedModel(org.ojalgo.optimisation.ExpressionsBasedModel) LinkedHashMap(java.util.LinkedHashMap) Result(org.ojalgo.optimisation.Optimisation.Result) Expression(org.ojalgo.optimisation.Expression)

Aggregations

Expression (org.ojalgo.optimisation.Expression)49 ExpressionsBasedModel (org.ojalgo.optimisation.ExpressionsBasedModel)45 Variable (org.ojalgo.optimisation.Variable)44 Result (org.ojalgo.optimisation.Optimisation.Result)27 Test (org.junit.jupiter.api.Test)23 BigDecimal (java.math.BigDecimal)18 Optimisation (org.ojalgo.optimisation.Optimisation)18 ArrayList (java.util.ArrayList)9 BasicMatrix (org.ojalgo.matrix.BasicMatrix)9 NumberContext (org.ojalgo.type.context.NumberContext)9 List (java.util.List)5 Map (java.util.Map)5 Collectors (java.util.stream.Collectors)5 HashMap (java.util.HashMap)4 LinkedHashMap (java.util.LinkedHashMap)4 BasicLogger (org.ojalgo.netio.BasicLogger)4 IntIndex (org.ojalgo.access.Structure1D.IntIndex)3 BigArray (org.ojalgo.array.BigArray)3 BigDenseStore (org.ojalgo.matrix.store.BigDenseStore)3 File (java.io.File)1