Пример #1
0
        /// <summary>
        /// Minimize the value of the objective.
        /// </summary>
        /// <remarks>
        /// The tableau should already be feasible.
        /// </remarks>
        private void Optimize(ClObjectiveVariable zVar)
        /* throws ExClInternalError */
        {
            ClLinearExpression zRow = RowExpression(zVar);

            if (zRow == null)
            {
                throw new CassowaryInternalException("Assertion failed: zRow != null");
            }

            ClAbstractVariable entryVar = null;
            ClAbstractVariable exitVar  = null;

            while (true)
            {
                double objectiveCoeff = 0;
                foreach (var kvp in zRow.Terms)
                {
                    if (kvp.Key.IsPivotable && kvp.Value.Value < objectiveCoeff)
                    {
                        objectiveCoeff = kvp.Value.Value;
                        entryVar       = kvp.Key;
                    }
                }

                if (objectiveCoeff >= -EPSILON || entryVar == null)
                {
                    return;
                }

                double minRatio = Double.MaxValue;
                foreach (ClAbstractVariable v in Columns[entryVar])
                {
                    if (v.IsPivotable)
                    {
                        ClLinearExpression expr  = RowExpression(v);
                        double             coeff = expr.CoefficientFor(entryVar);
                        if (coeff < 0.0)
                        {
                            double r = -expr.Constant / coeff;
                            if (r < minRatio)
                            {
                                minRatio = r;
                                exitVar  = v;
                            }
                        }
                    }
                }
// ReSharper disable CompareOfFloatsByEqualityOperator
                if (minRatio == Double.MaxValue)
// ReSharper restore CompareOfFloatsByEqualityOperator
                {
                    throw new CassowaryInternalException("Objective function is unbounded in Optimize");
                }
                Pivot(entryVar, exitVar);
            }
        }
Пример #2
0
        /// <summary>
        /// Re-optimize using the dual simplex algorithm.
        /// </summary>
        /// <remarks>
        /// We have set new values for the constants in the edit constraints.
        /// </remarks>
        protected void DualOptimize()
        /* throws ExClInternalError */
        {
            ClLinearExpression zRow = RowExpression(_objective);

            while (InfeasibleRows.Count > 0)
            {
                ClAbstractVariable exitVar = InfeasibleRows.First();

                InfeasibleRows.Remove(exitVar);
                ClAbstractVariable entryVar = null;
                ClLinearExpression expr     = RowExpression(exitVar);
                if (expr != null)
                {
                    if (expr.Constant < 0.0)
                    {
                        double ratio = Double.MaxValue;
                        var    terms = expr.Terms;
                        foreach (ClAbstractVariable v in terms.Keys)
                        {
                            double c = (terms[v]).Value;
                            if (c > 0.0 && v.IsPivotable)
                            {
                                double zc = zRow.CoefficientFor(v);
                                double r  = zc / c;
                                if (r < ratio)
                                {
                                    entryVar = v;
                                    ratio    = r;
                                }
                            }
                        }
// ReSharper disable CompareOfFloatsByEqualityOperator
                        if (ratio == Double.MaxValue)
// ReSharper restore CompareOfFloatsByEqualityOperator
                        {
                            throw new CassowaryInternalException("ratio == nil (Double.MaxValue) in DualOptimize");
                        }
                        Pivot(entryVar, exitVar);
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Fix the constants in the equations representing the edit constraints.
        /// </summary>
        /// <remarks>
        /// Each of the non-required edits will be represented by an equation
        /// of the form:
        ///   v = c + eplus - eminus
        /// where v is the variable with the edit, c is the previous edit value,
        /// and eplus and eminus are slack variables that hold the error in
        /// satisfying the edit constraint. We are about to change something,
        /// and we want to fix the constants in the equations representing
        /// the edit constraints. If one of eplus and eminus is basic, the other
        /// must occur only in the expression for that basic error variable.
        /// (They can't both be basic.) Fix the constant in this expression.
        /// Otherwise they are both non-basic. Find all of the expressions
        /// in which they occur, and fix the constants in those. See the
        /// UIST paper for details.
        /// (This comment was for ResetEditConstants(), but that is now
        /// gone since it was part of the screwey vector-based interface
        /// to resolveing. --02/16/99 gjb)
        /// </remarks>
        protected void DeltaEditConstant(double delta,
                                         ClAbstractVariable plusErrorVar,
                                         ClAbstractVariable minusErrorVar)
        {
            ClLinearExpression exprPlus = RowExpression(plusErrorVar);

            if (exprPlus != null)
            {
                exprPlus.IncrementConstant(delta);

                if (exprPlus.Constant < 0.0)
                {
                    InfeasibleRows.Add(plusErrorVar);
                }
                return;
            }

            ClLinearExpression exprMinus = RowExpression(minusErrorVar);

            if (exprMinus != null)
            {
                exprMinus.IncrementConstant(-delta);
                if (exprMinus.Constant < 0.0)
                {
                    InfeasibleRows.Add(minusErrorVar);
                }
                return;
            }

            var columnVars = Columns[minusErrorVar];

            foreach (ClAbstractVariable basicVar in columnVars)
            {
                ClLinearExpression expr = RowExpression(basicVar);
                //Assert(expr != null, "expr != null");
                double c = expr.CoefficientFor(minusErrorVar);
                expr.IncrementConstant(c * delta);
                if (basicVar.IsRestricted && expr.Constant < 0.0)
                {
                    InfeasibleRows.Add(basicVar);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Remove a constraint from the tableau.
        /// Also remove any error variable associated with it.
        /// </summary>
        public ClSimplexSolver RemoveConstraint(ClConstraint cn)
        /* throws ExClRequiredFailure, ExClInternalError */
        {
            _cNeedsSolving = true;

            ResetStayConstants();

            ClLinearExpression zRow = RowExpression(_objective);

            HashSet <ClAbstractVariable> eVars;

            if (_errorVars.TryGetValue(cn, out eVars))
            {
                foreach (ClAbstractVariable clv in eVars)
                {
                    ClLinearExpression expr = RowExpression(clv);
                    if (expr == null)
                    {
                        zRow.AddVariable(clv, -cn.Weight *
                                         cn.Strength.SymbolicWeight.AsDouble(),
                                         _objective, this);
                    }
                    else // the error variable was in the basis
                    {
                        zRow.AddExpression(expr, -cn.Weight *
                                           cn.Strength.SymbolicWeight.AsDouble(),
                                           _objective, this);
                    }
                }
            }

            ClAbstractVariable marker;

            if (!_markerVars.TryGetValue(cn, out marker))
            {
                throw new CassowaryConstraintNotFoundException();
            }

            _markerVars.Remove(cn);
            if (RowExpression(marker) == null)
            {
                // not in the basis, so need to do some more work
                var col = Columns[marker];

                ClAbstractVariable exitVar  = null;
                double             minRatio = 0.0;
                foreach (ClAbstractVariable v in col)
                {
                    if (v.IsRestricted)
                    {
                        ClLinearExpression expr  = RowExpression(v);
                        double             coeff = expr.CoefficientFor(marker);

                        if (coeff < 0.0)
                        {
                            double r = -expr.Constant / coeff;
                            if (exitVar == null || r < minRatio)
                            {
                                minRatio = r;
                                exitVar  = v;
                            }
                        }
                    }
                }

                if (exitVar == null)
                {
                    foreach (ClAbstractVariable v in col)
                    {
                        if (v.IsRestricted)
                        {
                            ClLinearExpression expr  = RowExpression(v);
                            double             coeff = expr.CoefficientFor(marker);
                            double             r     = expr.Constant / coeff;
                            if (exitVar == null || r < minRatio)
                            {
                                minRatio = r;
                                exitVar  = v;
                            }
                        }
                    }
                }

                if (exitVar == null)
                {
                    // exitVar is still null
                    if (col.Count == 0)
                    {
                        RemoveColumn(marker);
                    }
                    else
                    {
                        // put first element in exitVar
                        var colEnum = col.GetEnumerator();
                        colEnum.MoveNext();
                        exitVar = colEnum.Current;
                    }
                }

                if (exitVar != null)
                {
                    Pivot(marker, exitVar);
                }
            }

            if (RowExpression(marker) != null)
            {
                RemoveRow(marker);
            }

            if (eVars != null)
            {
                foreach (ClAbstractVariable v in eVars.Where(a => a != marker))
                {
                    RemoveColumn(v);
                }
            }

            if (cn.IsStayConstraint)
            {
                if (eVars != null)
                {
                    for (int i = 0; i < _stayPlusErrorVars.Count; i++)
                    {
                        eVars.Remove(_stayPlusErrorVars[i]);
                        eVars.Remove(_stayMinusErrorVars[i]);
                    }
                }
            }
            else if (cn.IsEditConstraint)
            {
                Assert(eVars != null, "eVars != null");
                ClEditConstraint cnEdit       = (ClEditConstraint)cn;
                ClVariable       clv          = cnEdit.Variable;
                ClEditInfo       cei          = _editVarMap[clv];
                ClSlackVariable  clvEditMinus = cei.ClvEditMinus;
                RemoveColumn(clvEditMinus);
                _editVarMap.Remove(clv);
            }

            // FIXME: do the remove at top
            if (eVars != null)
            {
                //_errorVars.Remove(eVars);
                _errorVars.Remove(cn);
            }

            if (_cOptimizeAutomatically)
            {
                Optimize(_objective);
                SetExternalVariables();
            }

            return(this);
        }