Skip to content

Commit

Permalink
wip gr4x6
Browse files Browse the repository at this point in the history
  • Loading branch information
apete committed Jul 21, 2024
1 parent 50dcf87 commit 1708805
Show file tree
Hide file tree
Showing 14 changed files with 1,441 additions and 146 deletions.
2 changes: 1 addition & 1 deletion ojAlgo Functionality Tests.launch
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<listEntry value="=ojAlgo/src\/main\/java=/optional=/true=/=/maven.pomderived=/true=/"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=ojAlgo"/>
<stringAttribute key="org.eclipse.jdt.junit.EXCLUDE_TAGS" value="slow,unstable"/>
<stringAttribute key="org.eclipse.jdt.junit.EXCLUDE_TAGS" value="slow,unstable,new_lp_problem"/>
<booleanAttribute key="org.eclipse.jdt.junit.HAS_EXCLUDE_TAGS" value="true"/>
<booleanAttribute key="org.eclipse.jdt.junit.HAS_INCLUDE_TAGS" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.INCLUDE_TAGS" value="new_lp_problem"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,8 @@ public ExpressionsBasedModel(final Optimisation.Options optimisationOptions) {

myShallowCopy = shallow || modelToCopy.isShallowCopy();
myRelaxed = modelToCopy.isRelaxed();
myKnownSolution = modelToCopy.getKnownSolution(); // TODO Should this be copied?
myValidationFailureHandler = modelToCopy.getValidationFailureHandler();
}

public Expression addExpression() {
Expand Down
20 changes: 10 additions & 10 deletions src/main/java/org/ojalgo/optimisation/integer/NodeSolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -283,22 +283,22 @@ boolean generateCuts(final ModelStrategy strategy, final ExpressionsBasedModel t
if (target.options.logger_detailed && target.options.logger_appender != null) {
target.options.logger_appender.println("{}: {} < {}", name, cut.getLowerLimit(), cut.getLinearEntrySet());
}

if (target.options.validate) {
if (!this.validate(target)) {
BasicLogger.error("Modified target model cuts off the optimal solution!");
}
if (target.validate(result)) {
BasicLogger.error("Result still valid, was NOT cut off!");
}
}
}
}
}

}

boolean didGenerate = nbConstr != target.constraints().count();
if (didGenerate && model.options.validate) {
if (!this.validate(target)) {
BasicLogger.error("Modified target model cuts off the optimal solution!");
}
if (target.validate(result)) {
BasicLogger.error("Result still valid, was NOT cut off!");
}
}
return didGenerate;
return nbConstr != target.constraints().count();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ public SimplexSolver build(final ExpressionsBasedModel model) {

Function<LinearStructure, SimplexStore> storeFactory = SimplexStore.newStoreFactory(options);

PhasedSimplexSolver solver = SimplexStore.build(model, storeFactory).newPhasedSimplexSolver(options);
PhasedSimplexSolver solver = SimplexSolver.build(model, storeFactory).newPhasedSimplexSolver(options);

if (options.validate) {
solver.setValidator(this.newValidator(model));
Expand Down
116 changes: 114 additions & 2 deletions src/main/java/org/ojalgo/optimisation/linear/SimplexSolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,27 @@
import static org.ojalgo.function.constant.PrimitiveMath.*;

import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Function;

import org.ojalgo.array.operation.IndexOf;
import org.ojalgo.equation.Equation;
import org.ojalgo.netio.BasicLogger;
import org.ojalgo.optimisation.ConstraintsMetaData;
import org.ojalgo.optimisation.Expression;
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.Optimisation;
import org.ojalgo.optimisation.Variable;
import org.ojalgo.optimisation.linear.SimplexStore.ColumnState;
import org.ojalgo.structure.Access1D;
import org.ojalgo.structure.Access2D;
import org.ojalgo.structure.Mutate1D;
import org.ojalgo.structure.Mutate2D;
import org.ojalgo.structure.Structure1D.IntIndex;
import org.ojalgo.type.PrimitiveNumber;
import org.ojalgo.type.context.NumberContext;
import org.ojalgo.type.keyvalue.EntryPair;
Expand Down Expand Up @@ -305,6 +315,106 @@ int row() {

private static final NumberContext ALGORITHM = NumberContext.of(8).withMode(RoundingMode.HALF_DOWN);

static <S extends SimplexStore> S build(final ExpressionsBasedModel model, final Function<LinearStructure, S> factory) {

Set<IntIndex> fixedVariables = model.getFixedVariables();
List<Variable> freeVariables = model.getFreeVariables();

List<Expression> equalityConstraints = new ArrayList<>();
List<Expression> lowerConstraints = new ArrayList<>();
List<Expression> upperConstraints = new ArrayList<>();

model.constraints().map(c -> c.compensate(fixedVariables)).forEach(constraint -> {
if (constraint.isEqualityConstraint()) {
equalityConstraints.add(constraint);
} else {
if (constraint.isLowerConstraint()) {
lowerConstraints.add(constraint);
}
if (constraint.isUpperConstraint()) {
upperConstraints.add(constraint);
}
}
});

Expression objective = model.objective().compensate(fixedVariables);

int nbUpConstr = upperConstraints.size();
int nbLoConstr = lowerConstraints.size();
int nbEqConstr = equalityConstraints.size();

int nbProbVars = freeVariables.size();
int nbSlckVars = nbUpConstr + nbLoConstr;

LinearStructure structure = new LinearStructure(true, nbUpConstr + nbLoConstr, nbEqConstr, nbProbVars, 0, 0, nbSlckVars);

S simplex = factory.apply(structure);
double[] lowerBounds = simplex.getLowerBounds();
double[] upperBounds = simplex.getUpperBounds();

Mutate2D mtrxA = simplex.constraintsBody();
Mutate1D mtrxB = simplex.constraintsRHS();
Mutate1D mtrxC = simplex.objective();

for (int i = 0; i < nbUpConstr; i++) {
Expression expression = upperConstraints.get(i);
for (IntIndex key : expression.getLinearKeySet()) {
int column = model.indexOfFreeVariable(key);
double factor = expression.doubleValue(key, true);
mtrxA.set(i, column, factor);
}
mtrxA.set(i, nbProbVars + i, ONE);
mtrxB.set(i, expression.getUpperLimit(true, POSITIVE_INFINITY));
lowerBounds[nbProbVars + i] = ZERO;
upperBounds[nbProbVars + i] = POSITIVE_INFINITY;
structure.setConstraintMap(i, expression, ConstraintType.UPPER, false);
}

for (int i = 0; i < nbLoConstr; i++) {
Expression expression = lowerConstraints.get(i);
for (IntIndex key : expression.getLinearKeySet()) {
int column = model.indexOfFreeVariable(key);
double factor = expression.doubleValue(key, true);
mtrxA.set(nbUpConstr + i, column, factor);
}
mtrxA.set(nbUpConstr + i, nbProbVars + nbUpConstr + i, ONE);
mtrxB.set(nbUpConstr + i, expression.getLowerLimit(true, NEGATIVE_INFINITY));
lowerBounds[nbProbVars + nbUpConstr + i] = NEGATIVE_INFINITY;
upperBounds[nbProbVars + nbUpConstr + i] = ZERO;
structure.setConstraintMap(nbUpConstr + i, expression, ConstraintType.LOWER, true);
}

for (int i = 0; i < nbEqConstr; i++) {
Expression expression = equalityConstraints.get(i);
for (IntIndex key : expression.getLinearKeySet()) {
int column = model.indexOfFreeVariable(key);
double factor = expression.doubleValue(key, true);
mtrxA.set(nbUpConstr + nbLoConstr + i, column, factor);
}
mtrxA.set(nbUpConstr + nbLoConstr + i, nbProbVars + nbSlckVars + i, ONE);
mtrxB.set(nbUpConstr + nbLoConstr + i, expression.getUpperLimit(true, ZERO));
lowerBounds[nbProbVars + nbSlckVars + i] = ZERO;
upperBounds[nbProbVars + nbSlckVars + i] = ZERO;
structure.setConstraintMap(nbUpConstr + nbLoConstr + i, expression, ConstraintType.EQUALITY, false);
}

for (int i = 0; i < nbProbVars; i++) {
Variable variable = freeVariables.get(i);
lowerBounds[i] = variable.getLowerLimit(false, NEGATIVE_INFINITY);
upperBounds[i] = variable.getUpperLimit(false, POSITIVE_INFINITY);
structure.positivePartVariables[i] = model.indexOf(variable);
}

structure.setObjectiveAdjustmentFactor(objective.getAdjustmentFactor());
boolean negate = model.getOptimisationSense() == Optimisation.Sense.MAX;
for (IntIndex key : objective.getLinearKeySet()) {
double weight = objective.doubleValue(key, true);
mtrxC.set(model.indexOfFreeVariable(key), negate ? -weight : weight);
}

return simplex;
}

private final SimplexStore mySimplex;
private final double[] mySolutionShift;
private double myValueShift = ZERO;
Expand Down Expand Up @@ -418,7 +528,8 @@ private boolean getDualExitCandidate(final IterDescr iteration) {

double largest = 1E-10;
int[] included = mySimplex.included;
for (int ji = 0, limit = included.length; ji < limit; ji++) {
// for (int ji = 0, limit = included.length; ji < limit; ji++) {
for (int ji = included.length - 1; ji >= 0; ji--) {
int j = included[ji];

double candidate = mySimplex.getInfeasibility(ji);
Expand Down Expand Up @@ -815,7 +926,8 @@ private boolean testPrimalExitRatio(final IterDescr iteration) {
iteration.ratioPrimal = range;

int[] included = mySimplex.included;
for (int ji = 0; ji < included.length; ji++) {
// for (int ji = 0; ji < included.length; ji++) {
for (int ji = included.length - 1; ji >= 0; ji--) {
int j = included[ji];

denom = mySimplex.getCurrentElement(ji, enter);
Expand Down
108 changes: 1 addition & 107 deletions src/main/java/org/ojalgo/optimisation/linear/SimplexStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,23 @@
*/
package org.ojalgo.optimisation.linear;

import static org.ojalgo.function.constant.PrimitiveMath.*;
import static org.ojalgo.function.constant.PrimitiveMath.ZERO;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Function;

import org.ojalgo.equation.Equation;
import org.ojalgo.netio.BasicLogger;
import org.ojalgo.optimisation.Expression;
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.Optimisation;
import org.ojalgo.optimisation.Optimisation.ConstraintType;
import org.ojalgo.optimisation.Optimisation.Options;
import org.ojalgo.optimisation.Variable;
import org.ojalgo.optimisation.linear.SimplexSolver.EnterInfo;
import org.ojalgo.optimisation.linear.SimplexSolver.ExitInfo;
import org.ojalgo.optimisation.linear.SimplexSolver.IterDescr;
import org.ojalgo.structure.Mutate1D;
import org.ojalgo.structure.Mutate2D;
import org.ojalgo.structure.Primitive1D;
import org.ojalgo.structure.Structure1D;
import org.ojalgo.structure.Structure1D.IntIndex;
import org.ojalgo.type.EnumPartition;
import org.ojalgo.type.context.NumberContext;

Expand Down Expand Up @@ -81,105 +74,6 @@ String key() {
}
}

static <S extends SimplexStore> S build(final ExpressionsBasedModel model, final Function<LinearStructure, S> factory) {

Set<IntIndex> fixedVariables = model.getFixedVariables();
List<Variable> freeVariables = model.getFreeVariables();

List<Expression> equalityConstraints = new ArrayList<>();
List<Expression> lowerConstraints = new ArrayList<>();
List<Expression> upperConstraints = new ArrayList<>();

model.constraints().map(c -> c.compensate(fixedVariables)).forEach(constraint -> {
if (constraint.isEqualityConstraint()) {
equalityConstraints.add(constraint);
} else {
if (constraint.isLowerConstraint()) {
lowerConstraints.add(constraint);
}
if (constraint.isUpperConstraint()) {
upperConstraints.add(constraint);
}
}
});

Expression objective = model.objective().compensate(fixedVariables);

int nbUpConstr = upperConstraints.size();
int nbLoConstr = lowerConstraints.size();
int nbEqConstr = equalityConstraints.size();

int nbProbVars = freeVariables.size();
int nbSlckVars = nbUpConstr + nbLoConstr;

LinearStructure structure = new LinearStructure(true, nbUpConstr + nbLoConstr, nbEqConstr, nbProbVars, 0, 0, nbSlckVars);

S simplex = factory.apply(structure);
double[] lowerBounds = simplex.getLowerBounds();
double[] upperBounds = simplex.getUpperBounds();

Mutate2D mtrxA = simplex.constraintsBody();
Mutate1D mtrxB = simplex.constraintsRHS();
Mutate1D mtrxC = simplex.objective();

for (int i = 0; i < nbUpConstr; i++) {
Expression expression = upperConstraints.get(i);
for (IntIndex key : expression.getLinearKeySet()) {
int column = model.indexOfFreeVariable(key);
double factor = expression.doubleValue(key, true);
mtrxA.set(i, column, factor);
}
mtrxA.set(i, nbProbVars + i, ONE);
mtrxB.set(i, expression.getUpperLimit(true, POSITIVE_INFINITY));
lowerBounds[nbProbVars + i] = ZERO;
upperBounds[nbProbVars + i] = POSITIVE_INFINITY;
structure.setConstraintMap(i, expression, ConstraintType.UPPER, false);
}

for (int i = 0; i < nbLoConstr; i++) {
Expression expression = lowerConstraints.get(i);
for (IntIndex key : expression.getLinearKeySet()) {
int column = model.indexOfFreeVariable(key);
double factor = expression.doubleValue(key, true);
mtrxA.set(nbUpConstr + i, column, factor);
}
mtrxA.set(nbUpConstr + i, nbProbVars + nbUpConstr + i, ONE);
mtrxB.set(nbUpConstr + i, expression.getLowerLimit(true, NEGATIVE_INFINITY));
lowerBounds[nbProbVars + nbUpConstr + i] = NEGATIVE_INFINITY;
upperBounds[nbProbVars + nbUpConstr + i] = ZERO;
structure.setConstraintMap(nbUpConstr + i, expression, ConstraintType.LOWER, true);
}

for (int i = 0; i < nbEqConstr; i++) {
Expression expression = equalityConstraints.get(i);
for (IntIndex key : expression.getLinearKeySet()) {
int column = model.indexOfFreeVariable(key);
double factor = expression.doubleValue(key, true);
mtrxA.set(nbUpConstr + nbLoConstr + i, column, factor);
}
mtrxA.set(nbUpConstr + nbLoConstr + i, nbProbVars + nbSlckVars + i, ONE);
mtrxB.set(nbUpConstr + nbLoConstr + i, expression.getUpperLimit(true, ZERO));
lowerBounds[nbProbVars + nbSlckVars + i] = ZERO;
upperBounds[nbProbVars + nbSlckVars + i] = ZERO;
structure.setConstraintMap(nbUpConstr + nbLoConstr + i, expression, ConstraintType.EQUALITY, false);
}

for (int i = 0; i < nbProbVars; i++) {
Variable variable = freeVariables.get(i);
lowerBounds[i] = variable.getLowerLimit(false, NEGATIVE_INFINITY);
upperBounds[i] = variable.getUpperLimit(false, POSITIVE_INFINITY);
structure.positivePartVariables[i] = model.indexOf(variable);
}

structure.setObjectiveAdjustmentFactor(objective.getAdjustmentFactor());
boolean negate = model.getOptimisationSense() == Optimisation.Sense.MAX;
for (IntIndex key : objective.getLinearKeySet()) {
double weight = objective.doubleValue(key, true);
mtrxC.set(model.indexOfFreeVariable(key), negate ? -weight : weight);
}

return simplex;
}

static Function<LinearStructure, SimplexStore> newStoreFactory(final Options options) {

Expand Down
Loading

0 comments on commit 1708805

Please sign in to comment.