예제 #1
0
        /// <summary>
        /// Remove v from the tableau -- remove the column cross indices for v
        /// and remove v from every expression in rows in which v occurs
        /// </summary>
        protected /*sealed*/ void RemoveColumn(ClAbstractVariable var)
        {
            if (Trace)
            {
                FnEnterPrint(string.Format("RemoveColumn: {0}", var));
            }
            // remove the rows with the variables in varset

            Set rows = (Set)_columns[var];

            _columns.Remove(var);

            if (rows != null)
            {
                foreach (ClAbstractVariable clv in rows)
                {
                    ClLinearExpression expr = (ClLinearExpression)_rows[clv];
                    expr.Terms.Remove(var);
                }
            }
            else
            {
                if (Trace)
                {
                    DebugPrint(string.Format("Could not find var {0} in _columns", var));
                }
            }

            if (var.IsExternal)
            {
                _externalRows.Remove(var);
                _externalParametricVars.Remove(var);
            }
        }
예제 #2
0
 public ClLinearEquation(ClLinearExpression cle,
                         ClAbstractVariable clv,
                         ClStrength strength,
                         double weight) : base((ClLinearExpression) cle.Clone(), strength, weight)
 {
   _expression.AddVariable(clv, -1.0);
 }
예제 #3
0
 public ClLinearInequality(ClLinearExpression cle1,
                           byte op_enum,
                           ClLinearExpression cle2,
                           ClStrength strength) : this(cle1, op_enum, cle2, strength, 1.0)
     /* throws ExClInternalError */
 {
 }
예제 #4
0
    /// <remarks>
    /// Constructor initializes the fields, and creaties the objective row.
    /// </remarks>
    public ClSimplexSolver()
    { 
      _stayMinusErrorVars = new ArrayList();
      _stayPlusErrorVars = new ArrayList();
      _errorVars = new Hashtable();
      _markerVars = new Hashtable();

      _resolve_pair = new ArrayList(2);
      _resolve_pair.Add(new ClDouble(0));
      _resolve_pair.Add(new ClDouble(0));

      _objective = new ClObjectiveVariable("Z");

      _editVarMap = new Hashtable();

      _slackCounter = 0;
      _artificialCounter = 0;
      _dummyCounter = 0;
      _epsilon = 1e-8;

      _cOptimizeAutomatically = true;
      _cNeedsSolving = false;

      ClLinearExpression e = new ClLinearExpression();
      _rows.Add(_objective, e);
      _stkCedcns = new Stack();
      _stkCedcns.Push(0);

      if (Trace)
        TracePrint("objective expr == " + RowExpression(_objective));
    }
 public ClEditOrStayConstraint(ClVariable var, 
                               ClStrength strength, 
                               double weight) : base(strength, weight)
 {
   _variable = var;
   _expression = new ClLinearExpression(_variable, -1.0, _variable.Value);
 }
예제 #6
0
 public ClLinearInequality(ClLinearExpression cle,
                           byte op_enum,
                           ClAbstractVariable clv,
                           ClStrength strength) : this(cle, op_enum, clv, strength, 1.0)
     /* throws ExClInternalError */
 {
 }
예제 #7
0
 public ClLinearEquation(ClLinearExpression cle1,
                         ClLinearExpression cle2,
                         ClStrength strength,
                         double weight) : base((ClLinearExpression)cle1.Clone(), strength, weight)
 {
     _expression.AddExpression(cle2, -1.0);
 }
예제 #8
0
 public ClEditOrStayConstraint(ClVariable var,
                               ClStrength strength,
                               double weight) : base(strength, weight)
 {
     _variable   = var;
     _expression = new ClLinearExpression(_variable, -1.0, _variable.Value);
 }
예제 #9
0
 public ClLinearEquation(ClLinearExpression cle,
                         ClAbstractVariable clv,
                         ClStrength strength,
                         double weight) : base((ClLinearExpression)cle.Clone(), strength, weight)
 {
     _expression.AddVariable(clv, -1.0);
 }
예제 #10
0
        /// <summary>
        /// Replace all occurrences of oldVar with expr, and update column cross indices
        /// oldVar should now be a basic variable.
        /// </summary>
        protected /*sealed*/ void SubstituteOut(ClAbstractVariable oldVar, ClLinearExpression expr)
        {
            if (Trace)
            {
                FnEnterPrint(string.Format("SubstituteOut: {0}", oldVar, expr));
            }
            if (Trace)
            {
                TracePrint(this.ToString());
            }

            Set varset = (Set)_columns[oldVar];

            foreach (ClAbstractVariable v in varset)
            {
                ClLinearExpression row = (ClLinearExpression)_rows[v];
                row.SubstituteOut(oldVar, expr, v, this);
                if (v.IsRestricted && row.Constant < 0.0)
                {
                    _infeasibleRows.Add(v);
                }
            }

            if (oldVar.IsExternal)
            {
                _externalRows.Add(oldVar);
                _externalParametricVars.Remove(oldVar);
            }

            _columns.Remove(oldVar);
        }
예제 #11
0
        /// <summary>
        /// Replace var with a symbolic expression expr that is equal to it.
        /// If a variable has been added to this expression that wasn't there
        /// before, or if a variable has been dropped from this expression
        /// because it now has a coefficient of 0, inform the solver.
        /// PRECONDITIONS:
        ///   var occurs with a non-zero coefficient in this expression.
        /// </summary>
        public void SubstituteOut(ClAbstractVariable var, ClLinearExpression expr, ClAbstractVariable subject, ClTableau solver)
        {
            double multiplier = (_terms[var]).Value;

            _terms.Remove(var);
            IncrementConstant(multiplier * expr.Constant);

            foreach (ClAbstractVariable clv in expr.Terms.Keys)
            {
                double   coeff = (expr.Terms[clv]).Value;
                ClDouble dOldCoeff;

                if (_terms.TryGetValue(clv, out dOldCoeff))
                {
                    double oldCoeff = dOldCoeff.Value;
                    double newCoeff = oldCoeff + multiplier * coeff;

                    if (Approx(newCoeff, 0.0))
                    {
                        solver.NoteRemovedVariable(clv, subject);
                        _terms.Remove(clv);
                    }
                    else
                    {
                        dOldCoeff.Value = newCoeff;
                    }
                }
                else
                {
                    // did not have that variable already
                    _terms.Add(clv, new ClDouble(multiplier * coeff));
                    solver.NoteAddedVariable(clv, subject);
                }
            }
        }
예제 #12
0
        // Add v=expr to the tableau, update column cross indices
        // v becomes a basic variable
        // expr is now owned by ClTableau class,
        // and ClTableau is responsible for deleting it
        // (also, expr better be allocated on the heap!).
        protected /*sealed*/ void AddRow(ClAbstractVariable var, ClLinearExpression expr)
        {
            if (Trace)
            {
                FnEnterPrint("AddRow: " + var + ", " + expr);
            }

            // for each variable in expr, add var to the set of rows which
            // have that variable in their expression
            _rows.Add(var, expr);

            // FIXME: check correctness!
            foreach (ClAbstractVariable clv in expr.Terms.Keys)
            {
                InsertColVar(clv, var);

                if (clv.IsExternal)
                {
                    _externalParametricVars.Add(clv);
                }
            }

            if (var.IsExternal)
            {
                _externalRows.Add(var);
            }

            if (Trace)
            {
                TracePrint(this.ToString());
            }
        }
예제 #13
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);
            }
        }
        public /*sealed*/ ClLinearExpression Divide(ClLinearExpression expr)
        /*throws ExCLNonlinearExpression*/
        {
            if (!expr.IsConstant)
            {
                throw new ExClNonlinearExpression();
            }

            return(Divide(expr._constant.Value));
        }
        public /*sealed*/ ClLinearExpression DivFrom(ClLinearExpression expr)
        /*throws ExCLNonlinearExpression*/
        {
            if (!IsConstant || Cl.Approx(_constant.Value, 0.0))
            {
                throw new ExClNonlinearExpression();
            }

            return(expr.Divide(_constant.Value));
        }
예제 #16
0
        public ClLinearExpression Divide(ClLinearExpression expr)
        /*throws ExCLNonlinearExpression*/
        {
            if (!expr.IsConstant)
            {
                throw new CassowaryNonlinearExpressionException();
            }

            return(Divide(expr._constant.Value));
        }
예제 #17
0
        public ClLinearExpression DivFrom(ClLinearExpression expr)
        /*throws ExCLNonlinearExpression*/
        {
            if (!IsConstant || Approx(_constant.Value, 0.0))
            {
                throw new CassowaryNonlinearExpressionException();
            }

            return(expr.Divide(_constant.Value));
        }
예제 #18
0
        /// <summary>
        /// Add n*expr to this expression from another expression expr.
        /// </summary>
        public ClLinearExpression AddExpression(ClLinearExpression expr, double n = 1.0)
        {
            IncrementConstant(n * expr.Constant);

            foreach (ClAbstractVariable clv in expr.Terms.Keys)
            {
                double coeff = (expr.Terms[clv]).Value;
                AddVariable(clv, coeff * n);
            }

            return(this);
        }
        /// <summary>
        /// Add n*expr to this expression from another expression expr.
        /// Notify the solver if a variable is added or deleted from this
        /// expression.
        /// </summary>
        public /*sealed*/ ClLinearExpression AddExpression(ClLinearExpression expr, double n,
                                                           ClAbstractVariable subject, ClTableau solver)
        {
            IncrementConstant(n * expr.Constant);

            foreach (ClAbstractVariable clv in expr.Terms.Keys)
            {
                double coeff = ((ClDouble)expr.Terms[clv]).Value;
                AddVariable(clv, coeff * n, subject, solver);
            }

            return(this);
        }
예제 #20
0
        /// <summary>
        /// Do a pivot. Move entryVar into the basis and move exitVar
        /// out of the basis.
        /// </summary>
        /// <remarks>
        /// We could for example make entryVar a basic variable and
        /// make exitVar a parametric variable.
        /// </remarks>
        protected void Pivot(ClAbstractVariable entryVar, ClAbstractVariable exitVar)
        /* throws ExClInternalError */
        {
            // the entryVar might be non-pivotable if we're doing a
            // RemoveConstraint -- otherwise it should be a pivotable
            // variable -- enforced at call sites, hopefully

            ClLinearExpression pexpr = RemoveRow(exitVar);

            pexpr.ChangeSubject(exitVar, entryVar);
            SubstituteOut(entryVar, pexpr);
            AddRow(entryVar, pexpr);
        }
        /// <summary>
        /// Replace var with a symbolic expression expr that is equal to it.
        /// If a variable has been added to this expression that wasn't there
        /// before, or if a variable has been dropped from this expression
        /// because it now has a coefficient of 0, inform the solver.
        /// PRECONDITIONS:
        ///   var occurs with a non-zero coefficient in this expression.
        /// </summary>
        public /*sealed*/ void SubstituteOut(ClAbstractVariable var, ClLinearExpression expr,
                                             ClAbstractVariable subject, ClTableau solver)
        {
            if (Trace)
            {
                FnEnterPrint(string.Format("CLE:SubstituteOut: {0}, {1}, {2}, ...", var, expr, subject));
            }
            if (Trace)
            {
                TracePrint("this = " + this);
            }

            double multiplier = ((ClDouble)_terms[var]).Value;

            _terms.Remove(var);
            IncrementConstant(multiplier * expr.Constant);

            foreach (ClAbstractVariable clv in expr.Terms.Keys)
            {
                double   coeff       = ((ClDouble)expr.Terms[clv]).Value;
                ClDouble d_old_coeff = (ClDouble)_terms[clv];

                if (d_old_coeff != null)
                {
                    double old_coeff = d_old_coeff.Value;
                    double newCoeff  = old_coeff + multiplier * coeff;

                    if (Cl.Approx(newCoeff, 0.0))
                    {
                        solver.NoteRemovedVariable(clv, subject);
                        _terms.Remove(clv);
                    }
                    else
                    {
                        d_old_coeff.Value = newCoeff;
                    }
                }
                else
                {
                    // did not have that variable already
                    _terms.Add(clv, new ClDouble(multiplier * coeff));
                    solver.NoteAddedVariable(clv, subject);
                }
            }

            if (Trace)
            {
                TracePrint("Now this is " + this);
            }
        }
        public /*sealed*/ ClLinearExpression Times(ClLinearExpression expr)
        /*throws ExCLNonlinearExpression*/
        {
            if (IsConstant)
            {
                return(expr.Times(_constant.Value));
            }
            else if (!expr.IsConstant)
            {
                throw new ExClNonlinearExpression();
            }

            return(Times(expr._constant.Value));
        }
예제 #23
0
        public ClLinearExpression Times(ClLinearExpression expr)
        /*throws ExCLNonlinearExpression*/
        {
            if (IsConstant)
            {
                return(expr.Times(_constant.Value));
            }

            if (!expr.IsConstant)
            {
                throw new CassowaryNonlinearExpressionException();
            }

            return(Times(expr._constant.Value));
        }
예제 #24
0
 /// <summary>
 /// Fix the constants in the equations representing the stays.
 /// </summary>
 /// <remarks>
 /// Each of the non-required stays will be represented by an equation
 /// of the form
 ///   v = c + eplus - eminus
 /// where v is the variable with the stay, c is the previous value
 /// of v, and eplus and eminus are slack variables that hold the error
 /// in satisfying the stay constraint. We are about to change something,
 /// and we want to fix the constants in the equations representing the
 /// stays. If both eplus and eminus are nonbasic they have value 0
 /// in the current solution, meaning the previous stay was exactly
 /// satisfied. In this case nothing needs to be changed. Otherwise one
 /// of them is basic, and the other must occur only in the expression
 /// for that basic error variable. Reset the constant of this
 /// expression to 0.
 /// </remarks>
 protected void ResetStayConstants()
 {
     for (int i = 0; i < _stayPlusErrorVars.Count; i++)
     {
         ClLinearExpression expr =
             RowExpression(_stayPlusErrorVars[i]);
         if (expr == null)
         {
             expr = RowExpression(_stayMinusErrorVars[i]);
         }
         if (expr != null)
         {
             expr.Constant = 0.0;
         }
     }
 }
예제 #25
0
        /// <summary>
        /// Try to add expr directly to the tableau without creating an
        /// artificial variable.
        /// </summary>
        /// <remarks>
        /// We are trying to add the constraint expr=0 to the appropriate
        /// tableau.
        /// </remarks>
        /// <returns>
        /// True if successful and false if not.
        /// </returns>
        private bool TryAddingDirectly(ClLinearExpression expr)
        /* throws ExClRequiredFailure */
        {
            ClAbstractVariable subject = ChooseSubject(expr);

            if (subject == null)
            {
                return(false);
            }
            expr.NewSubject(subject);
            if (ColumnsHasKey(subject))
            {
                SubstituteOut(subject, expr);
            }
            AddRow(subject, expr);
            return(true); // succesfully added directly
        }
예제 #26
0
        /// <summary>
        /// Remove the basic variable v from the tableau row v=expr
        /// Then update column cross indices.
        /// </summary>
        protected /*sealed*/ ClLinearExpression RemoveRow(ClAbstractVariable var)
        /*throws ExCLInternalError*/
        {
            if (Trace)
            {
                FnEnterPrint(string.Format("RemoveRow: {0}", var));
            }

            ClLinearExpression expr = (ClLinearExpression)_rows[var];

            Assert(expr != null);

            // For each variable in this expression, update
            // the column mapping and remove the variable from the list
            // of rows it is known to be in.
            foreach (ClAbstractVariable clv in expr.Terms.Keys)
            {
                Set varset = (Set)_columns[clv];

                if (varset != null)
                {
                    if (Trace)
                    {
                        DebugPrint(string.Format("removing from varset {0}", var));
                    }

                    varset.Remove(var);
                }
            }

            _infeasibleRows.Remove(var);

            if (var.IsExternal)
            {
                _externalRows.Remove(var);
            }

            _rows.Remove(var);
            if (Trace)
            {
                FnExitPrint(string.Format("returning {0}", expr));
            }

            return(expr);
        }
예제 #27
0
        public override string ToString()
        {
            string s = "Tableau:\n";

            foreach (ClAbstractVariable clv in _rows.Keys)
            {
                ClLinearExpression expr = _rows[clv];
                s += string.Format("{0} <==> {1}\n", clv, expr);
            }

            s += string.Format("\nColumns:\n{0}", _columns);
            s += string.Format("\nInfeasible rows: {0}", InfeasibleRows);

            s += string.Format("\nExternal basic variables: {0}", ExternalRows);
            s += string.Format("\nExternal parametric variables: {0}", ExternalParametricVars);

            return(s);
        }
예제 #28
0
        //// END PUBLIC INTERFACE ////

        /// <summary>
        /// Add the constraint expr=0 to the inequality tableau using an
        /// artificial variable.
        /// </summary>
        /// <remarks>
        /// To do this, create an artificial variable av and add av=expr
        /// to the inequality tableau, then make av be 0 (raise an exception
        /// if we can't attain av=0).
        /// </remarks>
        private void AddWithArtificialVariable(ClLinearExpression expr)
        /* throws ExClRequiredFailure, ExClInternalError */
        {
            ClSlackVariable     av    = new ClSlackVariable(++_artificialCounter, "a");
            ClObjectiveVariable az    = new ClObjectiveVariable("az");
            ClLinearExpression  azRow = expr.Clone();

            AddRow(az, azRow);
            AddRow(av, expr);

            Optimize(az);

            ClLinearExpression azTableauRow = RowExpression(az);

            if (!Approx(azTableauRow.Constant, 0.0))
            {
                RemoveRow(az);
                RemoveColumn(av);
                throw new CassowaryRequiredFailureException();
            }

            // see if av is a basic variable
            ClLinearExpression e = RowExpression(av);

            if (e != null)
            {
                // find another variable in this row and pivot,
                // so that av becomes parametric
                if (e.IsConstant)
                {
                    // if there isn't another variable in the row
                    // then the tableau contains the equation av=0 --
                    // just delete av's row
                    RemoveRow(av);
                    RemoveRow(az);
                    return;
                }
                ClAbstractVariable entryVar = e.AnyPivotableVariable();
                Pivot(entryVar, av);
            }
            Assert(RowExpression(av) == null, "RowExpression(av) == null)");
            RemoveColumn(av);
            RemoveRow(az);
        }
예제 #29
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);
                }
            }
        }
예제 #30
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);
                    }
                }
            }
        }
예제 #31
0
        /// <summary>
        /// Replace all occurrences of oldVar with expr, and update column cross indices
        /// oldVar should now be a basic variable.
        /// </summary>
        protected void SubstituteOut(ClAbstractVariable oldVar, ClLinearExpression expr)
        {
            var varset = _columns[oldVar];

            foreach (var v in varset)
            {
                var row = _rows[v];
                row.SubstituteOut(oldVar, expr, v, this);
                if (v.IsRestricted && row.Constant < 0.0)
                {
                    InfeasibleRows.Add(v);
                }
            }

            if (oldVar.IsExternal)
            {
                ExternalRows.Add((ClVariable)oldVar);
                ExternalParametricVars.Remove((ClVariable)oldVar);
            }

            _columns.Remove(oldVar);
        }
예제 #32
0
        // Add v=expr to the tableau, update column cross indices
        // v becomes a basic variable
        // expr is now owned by ClTableau class,
        // and ClTableau is responsible for deleting it
        // (also, expr better be allocated on the heap!).
        protected void AddRow(ClAbstractVariable var, ClLinearExpression expr)
        {
            // for each variable in expr, add var to the set of rows which
            // have that variable in their expression
            _rows.Add(var, expr);

            // FIXME: check correctness!
            foreach (var clv in expr.Terms.Keys)
            {
                InsertColVar(clv, var);

                if (clv.IsExternal)
                {
                    ExternalParametricVars.Add((ClVariable)clv);
                }
            }

            if (var.IsExternal)
            {
                ExternalRows.Add((ClVariable)var);
            }
        }
예제 #33
0
        /// <summary>
        /// Set the external variables known to this solver to their appropriate values.
        /// </summary>
        /// <remarks>
        /// Set each external basic variable to its value, and set each external parametric
        /// variable to 0. (It isn't clear that we will ever have external parametric
        /// variables -- every external variable should either have a stay on it, or have an
        /// equation that defines it in terms of other external variables that do have stays.
        /// For the moment I'll put this in though.) Variables that are internal to the solver
        /// don't actually store values -- their values are just implicit in the tableau -- so
        /// we don't need to set them.
        /// </remarks>
        protected void SetExternalVariables()
        {
            foreach (var v in ExternalParametricVars)
            {
                if (RowExpression(v) != null)
                {
                    Console.Error.WriteLine(string.Format("Error: variable {0} in _externalParametricVars is basic", v));
                }
                else
                {
                    v.Value = 0.0;
                }
            }

            foreach (var v in ExternalRows)
            {
                ClLinearExpression expr = RowExpression(v);
                v.Value = expr.Constant;
            }

            _cNeedsSolving = false;
        }
예제 #34
0
		public static ClLinearExpression Plus(ClVariable e1, ClLinearExpression e2)
		{
		  return (new ClLinearExpression(e1)).Plus(e2);
		}
예제 #35
0
		public static ClLinearExpression Plus(ClLinearExpression e1, ClLinearExpression e2)
		{
		  return e1.Plus(e2);
		}
예제 #36
0
		public static ClLinearExpression Divide(ClLinearExpression e1, ClLinearExpression e2) 
		  /*throws ExCLNonlinearExpression*/
		{
			return e1.Divide(e2); 
		}
예제 #37
0
 public ClLinearEquation(ClLinearExpression cle, ClAbstractVariable clv) : this(cle, clv, ClStrength.Required, 1.0)
 {}
예제 #38
0
 public ClLinearEquation(ClLinearExpression cle1,
                         ClLinearExpression cle2,
                         ClStrength strength,
                         double weight) : base((ClLinearExpression) cle1.Clone(), strength, weight)
 {
   _expression.AddExpression(cle2, -1.0);
 }
예제 #39
0
 public ClLinearEquation(ClLinearExpression cle) : base(cle)
 {}
예제 #40
0
 public ClLinearEquation(ClLinearExpression cle1, 
                         ClLinearExpression cle2) : this(cle1, cle2, ClStrength.Required, 1.0)
 {}
예제 #41
0
 public ClLinearInequality(ClLinearExpression cle) : base(cle)
 {}
예제 #42
0
    /// <summary>
    /// Try to add expr directly to the tableau without creating an
    /// artificial variable.
    /// </summary>
    /// <remarks>
    /// We are trying to add the constraint expr=0 to the appropriate
    /// tableau.
    /// </remarks>
    /// <returns>
    /// True if successful and false if not.
    /// </returns>
    protected bool TryAddingDirectly(ClLinearExpression expr)
      /* throws ExClRequiredFailure */
    {
      if (Trace)
        FnEnterPrint("TryAddingDirectly: " + expr);

      ClAbstractVariable subject = ChooseSubject(expr);
      if (subject == null)
      {
        if (Trace)
          FnExitPrint("returning false");
        return false;
      }
      expr.NewSubject(subject);
      if (ColumnsHasKey(subject))
      {
        SubstituteOut(subject, expr);
      }
      AddRow(subject, expr);
      if (Trace)
        FnExitPrint("returning true");
      return true; // succesfully added directly
    }
예제 #43
0
 public ClLinearEquation(ClLinearExpression cle1,
                         ClLinearExpression cle2,
                         ClStrength strength) : this(cle1, cle2, strength, 1.0)
 {}
예제 #44
0
 public ClLinearEquation(ClLinearExpression cle,
                         ClStrength strength,
                         double weight) : base(cle, strength, weight)
 {}
예제 #45
0
 public ClLinearEquation(ClLinearExpression cle,
                         ClStrength strength) : base(cle, strength)
 {}
예제 #46
0
		public static ClLinearExpression Plus(ClLinearExpression e1, ClVariable e2)
		{
		  return e1.Plus(new ClLinearExpression(e2));
		}
예제 #47
0
    protected ClLinearExpression NewExpression(ClConstraint cn,
                                               ArrayList eplus_eminus,
                                               ClDouble prevEConstant)
    {
      if (Trace)
      {
        FnEnterPrint("NewExpression: " + cn);
        TracePrint("cn.IsInequality == " + cn.IsInequality);
        TracePrint("cn.IsRequired == " + cn.IsRequired);
      }

      ClLinearExpression cnExpr = cn.Expression;
      ClLinearExpression expr = new ClLinearExpression(cnExpr.Constant);
      ClSlackVariable slackVar = new ClSlackVariable();
      ClDummyVariable dummyVar = new ClDummyVariable();
      ClSlackVariable eminus = new ClSlackVariable();
      ClSlackVariable eplus = new ClSlackVariable();
      Hashtable cnTerms = cnExpr.Terms;
      foreach(ClAbstractVariable v in cnTerms.Keys)
      {
        double c = ((ClDouble) cnTerms[v]).Value;
        ClLinearExpression e = RowExpression(v);
        if (e == null)
          expr.AddVariable(v, c);
        else
          expr.AddExpression(e, c);
      }

      if (cn.IsInequality)
      {
        ++_slackCounter;
        slackVar = new ClSlackVariable (_slackCounter, "s");
        expr.SetVariable(slackVar, -1);
        _markerVars.Add(cn, slackVar);
        if (!cn.IsRequired)
        {
          ++_slackCounter;
          eminus = new ClSlackVariable(_slackCounter, "em");
          expr.SetVariable(eminus, 1.0);
          ClLinearExpression zRow = RowExpression(_objective);
          ClSymbolicWeight sw = cn.Strength.SymbolicWeight.Times(cn.Weight);
          zRow.SetVariable(eminus, sw.AsDouble());
          InsertErrorVar(cn, eminus);
          NoteAddedVariable(eminus, _objective);
        }
      }
      else
      {
        // cn is an equality
        if (cn.IsRequired)
        {
          ++_dummyCounter;
          dummyVar = new ClDummyVariable(_dummyCounter, "d");
          expr.SetVariable(dummyVar, 1.0);
          _markerVars.Add(cn, dummyVar);
          if (Trace)
            TracePrint("Adding dummyVar == d" + _dummyCounter);
        }
        else
        {
          ++_slackCounter;
          eplus = new ClSlackVariable(_slackCounter, "ep");
          eminus = new ClSlackVariable(_slackCounter, "em");

          expr.SetVariable(eplus, -1.0);
          expr.SetVariable(eminus, 1.0);
          _markerVars.Add(cn, eplus);
          ClLinearExpression zRow = RowExpression(_objective);
          ClSymbolicWeight sw = cn.Strength.SymbolicWeight.Times(cn.Weight);
          double swCoeff = sw.AsDouble();
          if (swCoeff == 0)
          {
            if (Trace)
            {
              TracePrint("sw == " + sw);
              TracePrint("cn == " + cn);
              TracePrint("adding " + eplus + " and " + eminus + " with swCoeff == " + swCoeff);
            }
          }
          zRow.SetVariable(eplus, swCoeff);
          NoteAddedVariable(eplus, _objective);
          zRow.SetVariable(eminus, swCoeff);
          NoteAddedVariable(eminus, _objective);
          InsertErrorVar(cn, eminus);
          InsertErrorVar(cn, eplus);
          if (cn.IsStayConstraint)
          {
            _stayPlusErrorVars.Add(eplus);
            _stayMinusErrorVars.Add(eminus);
          }
          else if (cn.IsEditConstraint)
          {
            eplus_eminus.Add(eplus);
            eplus_eminus.Add(eminus);
            prevEConstant.Value = cnExpr.Constant;
          }
        }
      }

      if (expr.Constant < 0)
        expr.MultiplyMe(-1);

      if (Trace)
        FnExitPrint("returning " + expr);

      return expr;
    }
예제 #48
0
 public ClLinearInequality(ClLinearExpression cle,
                           ClStrength strength,
                           double weight) : base(cle, strength, weight)
 {}
예제 #49
0
    //// END PUBLIC INTERFACE ////
    
    /// <summary>
    /// Add the constraint expr=0 to the inequality tableau using an
    /// artificial variable.
    /// </summary>
    /// <remarks>
    /// To do this, create an artificial variable av and add av=expr
    /// to the inequality tableau, then make av be 0 (raise an exception
    /// if we can't attain av=0).
    /// </remarks>
    protected void AddWithArtificialVariable(ClLinearExpression expr)
      /* throws ExClRequiredFailure, ExClInternalError */
    {
      if (Trace)
        FnEnterPrint("AddWithArtificialVariable: " + expr);

      ClSlackVariable av = new ClSlackVariable(++_artificialCounter, "a");
      ClObjectiveVariable az = new ClObjectiveVariable("az");
      ClLinearExpression azRow = (ClLinearExpression) expr.Clone();
      
      if (Trace)
        TracePrint("before AddRows:\n" + this);

      AddRow(az, azRow);
      AddRow(av, expr);

      if (Trace)
        TracePrint("after AddRows:\n" + this);
      
      Optimize(az);

      ClLinearExpression azTableauRow = RowExpression(az);

      if (Trace)
        TracePrint("azTableauRow.Constant == " + azTableauRow.Constant);

      if (!Cl.Approx(azTableauRow.Constant, 0.0))
      {
        RemoveRow(az);
        RemoveColumn(av);
        throw new ExClRequiredFailure();
      }

      // see if av is a basic variable
      ClLinearExpression e = RowExpression(av);

      if (e != null)
      {
        // find another variable in this row and pivot,
        // so that av becomes parametric
        if (e.IsConstant)
        {
          // if there isn't another variable in the row
          // then the tableau contains the equation av=0 --
          // just delete av's row
          RemoveRow(av);
          RemoveRow(az);
          return;
        }
        ClAbstractVariable entryVar = e.AnyPivotableVariable();
        Pivot(entryVar, av);
      }
      Assert(RowExpression(av) == null, "RowExpression(av) == null)");
      RemoveColumn(av);
      RemoveRow(az);
    }
예제 #50
0
    // Add v=expr to the tableau, update column cross indices
    // v becomes a basic variable
    // expr is now owned by ClTableau class, 
    // and ClTableau is responsible for deleting it
    // (also, expr better be allocated on the heap!).
    protected /*sealed*/ void AddRow(ClAbstractVariable var, ClLinearExpression expr)
    {
      if (Trace) 
        FnEnterPrint("AddRow: " + var + ", " + expr);

      // for each variable in expr, add var to the set of rows which
      // have that variable in their expression
      _rows.Add(var, expr);
        
      // FIXME: check correctness!
      foreach (ClAbstractVariable clv in expr.Terms.Keys)
      {
        InsertColVar(clv, var);
        
        if (clv.IsExternal)
        {
          _externalParametricVars.Add(clv);
        }
      }

      if (var.IsExternal) {
        _externalRows.Add(var);
      }

      if (Trace) 
        TracePrint(this.ToString());
    }
예제 #51
0
    /// <summary>
    /// Try to choose a subject (a variable to become basic) from
    /// among the current variables in expr.
    /// </summary>
    /// <remarks>
    /// We are trying to add the constraint expr=0 to the tableaux.
    /// If expr constains any unrestricted variables, then we must choose
    /// an unrestricted variable as the subject. Also if the subject is
    /// new to the solver, we won't have to do any substitutions, so we
    /// prefer new variables to ones that are currently noted as parametric.
    /// If expr contains only restricted variables, if there is a restricted
    /// variable with a negative coefficient that is new to the solver we can
    /// make that the subject. Otherwise we can't find a subject, so return nil.
    /// (In this last case we have to add an artificial variable and use that
    /// variable as the subject -- this is done outside this method though.)
    /// </remarks>
    protected ClAbstractVariable ChooseSubject(ClLinearExpression expr)
      /* ExClRequiredFailure */
    {
      if (Trace)
        FnEnterPrint("ChooseSubject: " + expr);

      ClAbstractVariable subject = null; // the current best subject, if any

      bool foundUnrestricted = false;
      bool foundNewRestricted = false;

      Hashtable terms = expr.Terms;

      foreach (ClAbstractVariable v in terms.Keys)
      {
        double c = ((ClDouble) terms[v]).Value;

        if (foundUnrestricted)
        {
          if (!v.IsRestricted)
          {
            if (!ColumnsHasKey(v))
              return v;
          }
        }
        else
        {
          // we haven't found an restricted variable yet
          if (v.IsRestricted)
          {
            if (!foundNewRestricted && !v.IsDummy && c < 0.0)
            {
              Set col = (Set) _columns[v];

              if ( col == null ||
                   (col.Count == 1 && ColumnsHasKey(_objective)) ) 
              {
                subject = v;
                foundNewRestricted = true;
              }
            }
          }
          else
          {
            subject = v;
            foundUnrestricted = true;
          }
        }
      }

      if (subject != null)
        return subject;

      double coeff = 0.0;

      foreach (ClAbstractVariable v in terms.Keys)
      {
        double c = ((ClDouble) terms[v]).Value;
        
        if (!v.IsDummy)
          return null; // nope, no luck
        if (!ColumnsHasKey(v))
        {
          subject = v;
          coeff = c;
        }
      }

      if (!Cl.Approx(expr.Constant, 0.0))
      {
        throw new ExClRequiredFailure();
      }
      if (coeff > 0.0)
      {
        expr.MultiplyMe(-1);
      }
      
      return subject;
    }
예제 #52
0
		public static ClLinearExpression Minus(double e1, ClLinearExpression e2)
		{ 
			return (new ClLinearExpression(e1)).Minus(e2); 
		}
예제 #53
0
 public ClLinearInequality(ClLinearExpression cle,
                           ClStrength strength) : base(cle, strength)
 {}
예제 #54
0
		public static ClLinearExpression Minus(ClLinearExpression e1, double e2)
		{ 
			return e1.Minus(new ClLinearExpression(e2)); 
		}
예제 #55
0
 /// <summary> 
 /// Replace all occurrences of oldVar with expr, and update column cross indices
 /// oldVar should now be a basic variable.
 /// </summary> 
 protected /*sealed*/ void SubstituteOut(ClAbstractVariable oldVar, ClLinearExpression expr)
 {
   if (Trace)
     FnEnterPrint(string.Format("SubstituteOut: {0}", oldVar, expr));
   if (Trace) 
     TracePrint(this.ToString());
       
   Set varset = (Set) _columns[oldVar];
   
   foreach(ClAbstractVariable v in varset)
   {
     ClLinearExpression row = (ClLinearExpression) _rows[v];
     row.SubstituteOut(oldVar, expr, v, this);
     if (v.IsRestricted && row.Constant < 0.0) 
     {
       _infeasibleRows.Add(v);
     }
   }
   
   if (oldVar.IsExternal) {
     _externalRows.Add(oldVar);
     _externalParametricVars.Remove(oldVar);
   }
 
   _columns.Remove(oldVar);
 }
예제 #56
0
		public static ClLinearExpression Times(ClLinearExpression e1, ClLinearExpression e2) 
		  /*throws ExCLNonlinearExpression*/
		{ 
			return e1.Times(e2); 
		}
예제 #57
0
		public static ClLinearExpression Times(ClLinearExpression e1, double e2) 
		  /*throws ExCLNonlinearExpression*/
		{		
			return e1.Times(new ClLinearExpression(e2)); 
		}
예제 #58
0
		public static ClLinearExpression Times(double e1, ClLinearExpression e2) 
		  /*throws ExCLNonlinearExpression*/
		{ 
			return (new ClLinearExpression(e1)).Times(e2); 
		}
예제 #59
0
		public static ClLinearExpression Minus(ClLinearExpression e1, ClLinearExpression e2)
		{ 
			return e1.Minus(e2); 
		}
예제 #60
0
 public ClLinearEquation(ClLinearExpression cle,
                         ClAbstractVariable clv,
                         ClStrength strength) : this(cle, clv, strength, 1.0)
 {}