use of org.ojalgo.access.Structure1D.IntIndex in project ojAlgo by optimatika.
the class Presolvers method doCase2.
/**
* Checks if bounds on either of the variables (together with the expressions's bounds) implies tighter
* bounds on the other variable.
*/
static boolean doCase2(final Expression expression, final BigDecimal fixedValue, final HashSet<IntIndex> remaining, final Function<IntIndex, Variable> variableResolver, final NumberContext precision) {
final Iterator<IntIndex> tmpIterator = remaining.iterator();
final Variable variableA = variableResolver.apply(tmpIterator.next());
final BigDecimal factorA = expression.get(variableA);
final BigDecimal oldLowerA = variableA.getLowerLimit();
final BigDecimal oldUpperA = variableA.getUpperLimit();
final BigDecimal varMaxContrA;
final BigDecimal varMinContrA;
if (factorA.signum() == 1) {
varMaxContrA = oldUpperA != null ? factorA.multiply(oldUpperA) : null;
varMinContrA = oldLowerA != null ? factorA.multiply(oldLowerA) : null;
} else {
varMinContrA = oldUpperA != null ? factorA.multiply(oldUpperA) : null;
varMaxContrA = oldLowerA != null ? factorA.multiply(oldLowerA) : null;
}
final Variable variableB = variableResolver.apply(tmpIterator.next());
final BigDecimal factorB = expression.get(variableB);
final BigDecimal oldLowerB = variableB.getLowerLimit();
final BigDecimal oldUpperB = variableB.getUpperLimit();
final BigDecimal varMaxContrB;
final BigDecimal varMinContrB;
if (factorB.signum() == 1) {
varMaxContrB = oldUpperB != null ? factorB.multiply(oldUpperB) : null;
varMinContrB = oldLowerB != null ? factorB.multiply(oldLowerB) : null;
} else {
varMinContrB = oldUpperB != null ? factorB.multiply(oldUpperB) : null;
varMaxContrB = oldLowerB != null ? factorB.multiply(oldLowerB) : null;
}
final BigDecimal exprLower = expression.getLowerLimit() != null ? expression.getLowerLimit().subtract(fixedValue) : null;
if ((exprLower != null) && (varMaxContrA != null) && (varMaxContrB != null) && precision.isLessThan(exprLower, varMaxContrA.add(varMaxContrB))) {
expression.setInfeasible();
return false;
}
final BigDecimal exprUpper = expression.getUpperLimit() != null ? expression.getUpperLimit().subtract(fixedValue) : null;
if ((exprUpper != null) && (varMinContrA != null) && (varMinContrB != null) && precision.isMoreThan(exprUpper, varMinContrA.add(varMinContrB))) {
expression.setInfeasible();
return false;
}
BigDecimal newLowerA = oldLowerA;
BigDecimal newUpperA = oldUpperA;
BigDecimal newLowerB = oldLowerB;
BigDecimal newUpperB = oldUpperB;
if (exprLower != null) {
if ((varMaxContrB != null) && (varMaxContrB.compareTo(exprLower) < 0)) {
BigDecimal newLimit = DIVIDE.invoke(exprLower.subtract(varMaxContrB), factorA);
newLimit = oldLowerA != null ? oldLowerA.max(newLimit) : newLimit;
newLimit = oldUpperA != null ? oldUpperA.min(newLimit) : newLimit;
if (factorA.signum() == 1) {
newLowerA = newLimit;
} else {
newUpperA = newLimit;
}
}
if ((varMaxContrA != null) && (varMaxContrA.compareTo(exprLower) < 0)) {
BigDecimal newLimit = DIVIDE.invoke(exprLower.subtract(varMaxContrA), factorB);
newLimit = oldLowerB != null ? oldLowerB.max(newLimit) : newLimit;
newLimit = oldUpperB != null ? oldUpperB.min(newLimit) : newLimit;
if (factorB.signum() == 1) {
newLowerB = newLimit;
} else {
newUpperB = newLimit;
}
}
}
if (exprUpper != null) {
if ((varMinContrB != null) && (varMinContrB.compareTo(exprUpper) > 0)) {
BigDecimal newLimit = DIVIDE.invoke(exprUpper.subtract(varMinContrB), factorA);
newLimit = oldLowerA != null ? oldLowerA.max(newLimit) : newLimit;
newLimit = oldUpperA != null ? oldUpperA.min(newLimit) : newLimit;
if (factorA.signum() == 1) {
newUpperA = newLimit;
} else {
newLowerA = newLimit;
}
}
if ((varMinContrA != null) && (varMinContrA.compareTo(exprUpper) > 0)) {
BigDecimal newLimit = DIVIDE.invoke(exprUpper.subtract(varMinContrA), factorB);
newLimit = oldLowerB != null ? oldLowerB.max(newLimit) : newLimit;
newLimit = oldUpperB != null ? oldUpperB.min(newLimit) : newLimit;
if (factorB.signum() == 1) {
newUpperB = newLimit;
} else {
newLowerB = newLimit;
}
}
}
if (variableA.isInteger()) {
if (newLowerA != null) {
newLowerA = newLowerA.setScale(0, RoundingMode.CEILING);
}
if (newUpperA != null) {
newUpperA = newUpperA.setScale(0, RoundingMode.FLOOR);
}
}
if (variableB.isInteger()) {
if (newLowerB != null) {
newLowerB = newLowerB.setScale(0, RoundingMode.CEILING);
}
if (newUpperB != null) {
newUpperB = newUpperB.setScale(0, RoundingMode.FLOOR);
}
}
variableA.lower(newLowerA).upper(newUpperA);
variableB.lower(newLowerB).upper(newUpperB);
return variableA.isEqualityConstraint() || variableB.isEqualityConstraint();
}
use of org.ojalgo.access.Structure1D.IntIndex in project ojAlgo by optimatika.
the class Presolvers method doCase1.
/**
* This constraint expression has 1 remaining free variable. The lower/upper limits can be transferred to
* that variable, and the expression marked as redundant.
*/
static boolean doCase1(final Expression expression, final BigDecimal fixedValue, final HashSet<IntIndex> remaining, final Function<IntIndex, Variable> variableResolver, final NumberContext precision) {
final IntIndex index = remaining.iterator().next();
final Variable variable = variableResolver.apply(index);
final BigDecimal factor = expression.get(index);
final BigDecimal oldLower = variable.getLowerLimit();
final BigDecimal oldUpper = variable.getUpperLimit();
final BigDecimal varMaxContr;
final BigDecimal varMinContr;
if (factor.signum() == 1) {
varMaxContr = oldUpper != null ? factor.multiply(oldUpper) : null;
varMinContr = oldLower != null ? factor.multiply(oldLower) : null;
} else {
varMinContr = oldUpper != null ? factor.multiply(oldUpper) : null;
varMaxContr = oldLower != null ? factor.multiply(oldLower) : null;
}
final BigDecimal exprLower = expression.getLowerLimit() != null ? expression.getLowerLimit().subtract(fixedValue) : null;
if ((exprLower != null) && (varMaxContr != null) && precision.isLessThan(exprLower, varMaxContr)) {
expression.setInfeasible();
return false;
}
final BigDecimal exprUpper = expression.getUpperLimit() != null ? expression.getUpperLimit().subtract(fixedValue) : null;
if ((exprUpper != null) && (varMinContr != null) && precision.isMoreThan(exprUpper, varMinContr)) {
expression.setInfeasible();
return false;
}
if (expression.isEqualityConstraint()) {
// Simple case with equality constraint
final BigDecimal solution = DIVIDE.invoke(exprUpper, factor);
if (variable.validate(solution, precision, null)) {
variable.setFixed(solution);
} else {
expression.setInfeasible();
}
} else {
// More general case
BigDecimal solutionLower = exprLower != null ? DIVIDE.invoke(exprLower, factor) : null;
BigDecimal solutionUpper = exprUpper != null ? DIVIDE.invoke(exprUpper, factor) : null;
if (factor.signum() < 0) {
final BigDecimal tmpVal = solutionLower;
solutionLower = solutionUpper;
solutionUpper = tmpVal;
}
final BigDecimal newLower;
if (solutionLower != null) {
solutionLower = oldLower != null ? oldLower.max(solutionLower) : solutionLower;
if (variable.isInteger()) {
solutionLower = solutionLower.setScale(0, RoundingMode.CEILING);
}
newLower = solutionLower;
} else {
newLower = oldLower;
}
final BigDecimal newUpper;
if (solutionUpper != null) {
solutionUpper = oldUpper != null ? oldUpper.min(solutionUpper) : solutionUpper;
if (variable.isInteger()) {
solutionUpper = solutionUpper.setScale(0, RoundingMode.FLOOR);
}
newUpper = solutionUpper;
} else {
newUpper = oldUpper;
}
variable.lower(newLower).upper(newUpper);
if (variable.isInfeasible()) {
expression.setInfeasible();
}
}
expression.setRedundant(true);
if (variable.isEqualityConstraint()) {
variable.setValue(variable.getLowerLimit());
return true;
} else {
return false;
}
}
use of org.ojalgo.access.Structure1D.IntIndex in project ojAlgo by optimatika.
the class SpecialOrderedSet method simplify.
/**
* The program logic here does not assume variables to be binary or even integer
*/
@Override
public boolean simplify(final Expression expression, final Set<IntIndex> fixedVariables, final BigDecimal fixedValue, final Function<IntIndex, Variable> variableResolver, NumberContext precision) {
if (!expression.equals(myExpression)) {
return false;
}
if (fixedVariables.size() == 0) {
return false;
}
int first = -1, limit = -1;
for (int i = 0; i < mySequence.length; i++) {
final IntIndex index = mySequence[1];
if (fixedVariables.contains(index) && (variableResolver.apply(index).getValue().signum() != 0)) {
if (first == -1) {
first = i;
}
limit = i + 1;
}
}
final int count = limit - first;
if (count > myType) {
expression.setInfeasible();
return false;
}
boolean didFixVariable = false;
for (int i = first + 1; i < limit; i++) {
final IntIndex index = mySequence[i];
final Variable variable = variableResolver.apply(index);
if (fixedVariables.contains(index)) {
if (variable.getValue().signum() == 0) {
expression.setInfeasible();
}
} else {
if (variable.isInteger()) {
variable.setFixed(BigDecimal.ONE);
didFixVariable = true;
}
}
}
final int remaining = myType - count;
if ((count > 0) && (remaining > 0)) {
for (int i = 0, lim = first - remaining; i < lim; i++) {
final IntIndex index = mySequence[i];
final Variable variable = variableResolver.apply(index);
if (fixedVariables.contains(index)) {
if (variable.getValue().signum() != 0) {
expression.setInfeasible();
}
} else {
variable.setFixed(BigDecimal.ZERO);
didFixVariable = true;
}
}
for (int i = limit + remaining, lim = mySequence.length; i < lim; i++) {
final IntIndex index = mySequence[i];
final Variable variable = variableResolver.apply(index);
if (fixedVariables.contains(index)) {
if (variable.getValue().signum() != 0) {
expression.setInfeasible();
}
} else {
variable.setFixed(BigDecimal.ZERO);
didFixVariable = true;
}
}
}
return didFixVariable;
}
use of org.ojalgo.access.Structure1D.IntIndex in project ojAlgo by optimatika.
the class Expression method compensate.
/**
* Will return an Expression with factors corresponding to fixed variables removed, and lower/upper limits
* compensated for the fixed part of the expression. Factors corresponding to bilinear variables, where
* one is fixed and the other is not, are linearized.
*
* @param fixedVariables A set of (by the presolver) fixed variable indices
* @return The reduced/modified expression
*/
public Expression compensate(final Set<IntIndex> fixedVariables) {
if ((fixedVariables.size() == 0) || (!this.isAnyQuadraticFactorNonZero() && Collections.disjoint(fixedVariables, this.getLinearKeySet()))) {
// No need to copy/compensate anything
return this;
} else {
final ExpressionsBasedModel tmpModel = this.getModel();
final Expression retVal = new Expression(this.getName(), tmpModel);
BigDecimal tmpFixedValue = BigMath.ZERO;
for (final Entry<IntIndex, BigDecimal> tmpEntry : myLinear.entrySet()) {
final IntIndex tmpKey = tmpEntry.getKey();
final BigDecimal tmpFactor = tmpEntry.getValue();
if (fixedVariables.contains(tmpKey)) {
// Fixed
final BigDecimal tmpValue = tmpModel.getVariable(tmpKey.index).getValue();
tmpFixedValue = tmpFixedValue.add(tmpFactor.multiply(tmpValue));
} else {
// Not fixed
retVal.set(tmpKey, tmpFactor);
}
}
for (final Entry<IntRowColumn, BigDecimal> tmpEntry : myQuadratic.entrySet()) {
final IntRowColumn tmpKey = tmpEntry.getKey();
final BigDecimal tmpFactor = tmpEntry.getValue();
final Variable tmpRowVariable = tmpModel.getVariable(tmpKey.row);
final Variable tmpColVariable = tmpModel.getVariable(tmpKey.column);
final IntIndex tmpRowKey = tmpRowVariable.getIndex();
final IntIndex tmpColKey = tmpColVariable.getIndex();
if (fixedVariables.contains(tmpRowKey)) {
final BigDecimal tmpRowValue = tmpRowVariable.getValue();
if (fixedVariables.contains(tmpColKey)) {
// Both fixed
final BigDecimal tmpColValue = tmpColVariable.getValue();
tmpFixedValue = tmpFixedValue.add(tmpFactor.multiply(tmpRowValue).multiply(tmpColValue));
} else {
// Row fixed
retVal.add(tmpColKey, tmpFactor.multiply(tmpRowValue));
}
} else {
if (fixedVariables.contains(tmpColKey)) {
// Column fixed
final BigDecimal tmpColValue = tmpColVariable.getValue();
retVal.add(tmpRowKey, tmpFactor.multiply(tmpColValue));
} else {
// Neither fixed
retVal.set(tmpKey, tmpFactor);
}
}
}
if (this.isLowerLimitSet()) {
retVal.lower(this.getLowerLimit().subtract(tmpFixedValue));
}
if (this.isUpperLimitSet()) {
retVal.upper(this.getUpperLimit().subtract(tmpFixedValue));
}
return retVal;
}
}
use of org.ojalgo.access.Structure1D.IntIndex in project ojAlgo by optimatika.
the class ExpressionsBasedModel method scanEntities.
private void scanEntities() {
final Set<IntIndex> fixedVariables = Collections.emptySet();
final BigDecimal fixedValue = BigMath.ZERO;
for (final Expression tmpExpression : myExpressions.values()) {
Presolvers.LINEAR_OBJECTIVE.simplify(tmpExpression, fixedVariables, fixedValue, this::getVariable, options.feasibility);
if (tmpExpression.isConstraint()) {
Presolvers.ZERO_ONE_TWO.simplify(tmpExpression, fixedVariables, fixedValue, this::getVariable, options.feasibility);
}
}
for (final Variable tmpVariable : myVariables) {
Presolvers.FIXED_OR_UNBOUNDED.simplify(tmpVariable, this);
}
}
Aggregations