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;
}
}
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;
}
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);
}
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;
}
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
*/
}
Aggregations