Search in sources :

Example 6 with IntIndex

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();
}
Also used : IntIndex(org.ojalgo.access.Structure1D.IntIndex) BigDecimal(java.math.BigDecimal)

Example 7 with IntIndex

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;
    }
}
Also used : IntIndex(org.ojalgo.access.Structure1D.IntIndex) BigDecimal(java.math.BigDecimal)

Example 8 with IntIndex

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;
}
Also used : IntIndex(org.ojalgo.access.Structure1D.IntIndex)

Example 9 with IntIndex

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;
    }
}
Also used : IntRowColumn(org.ojalgo.access.Structure2D.IntRowColumn) BigDecimal(java.math.BigDecimal) IntIndex(org.ojalgo.access.Structure1D.IntIndex)

Example 10 with IntIndex

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);
    }
}
Also used : IntIndex(org.ojalgo.access.Structure1D.IntIndex) BigDecimal(java.math.BigDecimal)

Aggregations

IntIndex (org.ojalgo.access.Structure1D.IntIndex)15 BigDecimal (java.math.BigDecimal)9 IntRowColumn (org.ojalgo.access.Structure2D.IntRowColumn)6 Expression (org.ojalgo.optimisation.Expression)3 Variable (org.ojalgo.optimisation.Variable)3 PrimitiveDenseStore (org.ojalgo.matrix.store.PrimitiveDenseStore)2 ExpressionsBasedModel (org.ojalgo.optimisation.ExpressionsBasedModel)2 NumberContext (org.ojalgo.type.context.NumberContext)2 Arrays (java.util.Arrays)1 List (java.util.List)1 Set (java.util.Set)1 Collectors (java.util.stream.Collectors)1 OjAlgoUtils (org.ojalgo.OjAlgoUtils)1 Access1D (org.ojalgo.access.Access1D)1 Mutate1D (org.ojalgo.access.Mutate1D)1 Mutate2D (org.ojalgo.access.Mutate2D)1 Array1D (org.ojalgo.array.Array1D)1 SparseArray (org.ojalgo.array.SparseArray)1 PrimitiveMath (org.ojalgo.constant.PrimitiveMath)1 PrimitiveFunction (org.ojalgo.function.PrimitiveFunction)1