コード例 #1
0
        /// <summary>
        /// Remove the edit constraint previously added.
        /// <param name="v">Variable to which the edit constraint was added before.</param>
        /// </summary>
        private void RemoveEditVar(ClVariable v)
        {
            ClEditInfo   cei = _editVarMap[v];
            ClConstraint cn  = cei.Constraint;

            RemoveConstraint(cn);
        }
コード例 #2
0
        /// <summary>
        /// Protected convenience function to insert an error variable
        /// into the _errorVars set, creating the mapping with Add as necessary.
        /// </summary>
        protected void InsertErrorVar(ClConstraint cn, ClAbstractVariable var)
        {
            HashSet <ClAbstractVariable> cnset;

            if (!_errorVars.TryGetValue(cn, out cnset))
            {
                _errorVars.Add(cn, cnset = new HashSet <ClAbstractVariable>());
            }
            cnset.Add(var);
        }
コード例 #3
0
ファイル: ClEditInfo.cs プロジェクト: hur1can3/Cassowary.net
 public ClEditInfo(ClConstraint cn, ClSlackVariable eplus, 
                   ClSlackVariable eminus, double prevEditConstant,
                   int i)
 {
   _cn = cn;
   _clvEditPlus = eplus;
   _clvEditMinus = eminus;
   _prevEditConstant = prevEditConstant;
   _i = i;
 }
コード例 #4
0
 public ClEditInfo(ClConstraint cn, ClSlackVariable eplus,
                   ClSlackVariable eminus, double prevEditConstant,
                   int i)
 {
     _cn               = cn;
     _clvEditPlus      = eplus;
     _clvEditMinus     = eminus;
     _prevEditConstant = prevEditConstant;
     _i = i;
 }
コード例 #5
0
 /// <summary>
 /// Same as AddConstraint, throws no exceptions.
 /// <returns>
 /// False if the constraint resulted in an unsolvable system, otherwise true.
 /// </returns>
 /// </summary>
 public bool TryAddConstraint(ClConstraint cn)
 {
     try
     {
         AddConstraint(cn);
         return(true);
     }
     catch (CassowaryRequiredFailureException)
     {
         return(false);
     }
 }
コード例 #6
0
ファイル: ClParser.cs プロジェクト: hur1can3/Cassowary.net
    public void Parse()
    {
      UTF8Encoding ue = new UTF8Encoding();
      byte[] ruleBytes = ue.GetBytes(Rule);
      MemoryStream ms = new MemoryStream(ruleBytes);

      Scanner s = new Scanner(ms);
      Parser p = new Parser(s);
      p.Context = Context;

      p.Parse();
      
      _result = p.Value;
      
      if (p.errors.count > 0)
        throw new ExClParseError(Rule);
    }
コード例 #7
0
        /// <summary>
        /// Add a constraint to the solver.
        /// <param name="cn">
        /// The constraint to be added.
        /// </param>
        /// </summary>
        public ClSimplexSolver AddConstraint(ClConstraint cn)
        {
            List <ClAbstractVariable> eplusEminus = new List <ClAbstractVariable>(2);
            ClDouble           prevEConstant      = new ClDouble();
            ClLinearExpression expr = NewExpression(cn, /* output to: */
                                                    eplusEminus,
                                                    prevEConstant);

            bool cAddedOkDirectly = TryAddingDirectly(expr);

            if (!cAddedOkDirectly)
            {
                // could not add directly
                AddWithArtificialVariable(expr);
            }

            _cNeedsSolving = true;

            if (cn.IsEditConstraint)
            {
                int i = _editVarMap.Count;
                ClEditConstraint cnEdit    = (ClEditConstraint)cn;
                ClSlackVariable  clvEplus  = (ClSlackVariable)eplusEminus[0];
                ClSlackVariable  clvEminus = (ClSlackVariable)eplusEminus[1];
                _editVarMap.Add(cnEdit.Variable,
                                new ClEditInfo(cnEdit, clvEplus, clvEminus,
                                               prevEConstant.Value,
                                               i));
            }

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

            return(this);
        }
コード例 #8
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 */
    {
      if (Trace)
      {
        FnEnterPrint("RemoveConstraint: " + cn);
        TracePrint(this.ToString());
      }

      _cNeedsSolving = true;

      ResetStayConstants();

      ClLinearExpression zRow = RowExpression(_objective);

      Set eVars = (Set) _errorVars[cn];
      if (Trace)
        TracePrint("eVars == " + eVars);

      if (eVars != null)
      {
        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);
          }
        }
      }

      int markerVarsCount = _markerVars.Count;
      ClAbstractVariable marker = (ClAbstractVariable) _markerVars[cn];
      _markerVars.Remove(cn);
      
      if (markerVarsCount == _markerVars.Count) // key was not found
      {
        throw new ExClConstraintNotFound();
      }

      if (Trace)
        TracePrint("Looking to remove var " + marker);

      if (RowExpression(marker) == null)
      {
        // not in the basis, so need to do some more work
        Set col = (Set) _columns[marker];

        if (Trace)
          TracePrint("Must pivot -- columns are " + col);

        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 (Trace)
              TracePrint("Marker " + marker + "'s coefficient in " + expr + " is " + coeff);

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

        if (exitVar == null)
        {
          if (Trace)
            TracePrint("exitVar is still 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
            IEnumerator colEnum = col.GetEnumerator();
            colEnum.MoveNext();
            exitVar = (ClAbstractVariable) colEnum.Current; 
          }
        }

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

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

      if (eVars != null)
      {
        foreach (ClAbstractVariable v in eVars)
        {
          // FIXME: decide wether to use equals or !=
          if (v != marker)
          {
            RemoveColumn(v);
            // v = null; // is read-only, cannot be set to null
          }
        }
      }

      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 = (ClEditInfo) _editVarMap[clv];
        ClSlackVariable clvEditMinus = cei.ClvEditMinus;
        RemoveColumn(clvEditMinus);
        _editVarMap.Remove(clv);
      }

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

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

      return this;
    }
コード例 #9
0
    /// <summary>
    /// Same as AddConstraint, throws no exceptions.
    /// <returns>
    /// False if the constraint resulted in an unsolvable system, otherwise true.
    /// </returns>
    /// </summary>
    public bool AddConstraintNoException(ClConstraint cn)
    {
      if (Trace)
        FnEnterPrint("AddConstraintNoException: " + cn);

      try
      {
        AddConstraint(cn);
        return true;
      } 
      catch (ExClRequiredFailure)
      {
        return false;
      }
    }
コード例 #10
0
    /// <summary>
    /// Protected convenience function to insert an error variable
    /// into the _errorVars set, creating the mapping with Add as necessary.
    /// </summary>
    protected void InsertErrorVar(ClConstraint cn, ClAbstractVariable var)
    {
      if (Trace)
        FnEnterPrint("InsertErrorVar: " + cn + ", " + var);

      Set cnset = (Set) _errorVars[cn];
      if (cnset == null)
        _errorVars.Add(cn, cnset = new Set());
      cnset.Add(var);
    }
コード例 #11
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;
    }
コード例 #12
0
    /// <summary>
    /// Add a constraint to the solver.
    /// <param name="cn">
    /// The constraint to be added.
    /// </param>
    /// </summary>
    public ClSimplexSolver AddConstraint(ClConstraint cn)
      /* throws ExClRequiredFailure, ExClInternalError */
    {
      if (Trace)
        FnEnterPrint("AddConstraint: " + cn);

      ArrayList eplus_eminus = new ArrayList(2);
      ClDouble prevEConstant = new ClDouble();
      ClLinearExpression expr = NewExpression(cn, /* output to: */
                                              eplus_eminus,
                                              prevEConstant);

      bool cAddedOkDirectly = false;

      try
      {
        cAddedOkDirectly = TryAddingDirectly(expr);
        if (!cAddedOkDirectly)
        {
          // could not add directly
          AddWithArtificialVariable(expr);
        }
      } 
      catch (ExClRequiredFailure rf)
      {
        throw rf;
      }

      _cNeedsSolving = true;

      if (cn.IsEditConstraint)
      {
        int i = _editVarMap.Count;
        ClEditConstraint cnEdit = (ClEditConstraint) cn;
        ClSlackVariable clvEplus = (ClSlackVariable) eplus_eminus[0];
        ClSlackVariable clvEminus = (ClSlackVariable) eplus_eminus[1];
        _editVarMap.Add(cnEdit.Variable,
                        new ClEditInfo(cnEdit, clvEplus, clvEminus,
                                       prevEConstant.Value,
                                       i));
      }

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

      return this;
    }
コード例 #13
0
        private ClLinearExpression NewExpression(ClConstraint cn,
                                                 ICollection <ClAbstractVariable> eplusEminus,
                                                 ClDouble prevEConstant)
        {
            ClLinearExpression cnExpr = cn.Expression;
            ClLinearExpression expr   = new ClLinearExpression(cnExpr.Constant);
            ClSlackVariable    eminus;
            var cnTerms = cnExpr.Terms;

            foreach (ClAbstractVariable v in cnTerms.Keys)
            {
                double             c = (cnTerms[v]).Value;
                ClLinearExpression e = RowExpression(v);
                if (e == null)
                {
                    expr.AddVariable(v, c);
                }
                else
                {
                    expr.AddExpression(e, c);
                }
            }

            if (cn.IsInequality)
            {
                ++_slackCounter;
                ClSlackVariable slackVar = new ClSlackVariable(_slackCounter, "s");
                expr.SetVariable(slackVar, -1);
                _markerVars.Add(cn, slackVar);
                if (!cn.Strength.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.Strength.IsRequired)
                {
                    ++_dummyCounter;
                    ClDummyVariable dummyVar = new ClDummyVariable(_dummyCounter, "d");
                    expr.SetVariable(dummyVar, 1.0);
                    _markerVars.Add(cn, dummyVar);
                }
                else
                {
                    ++_slackCounter;
                    ClSlackVariable 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();
                    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)
                    {
                        eplusEminus.Add(eplus);
                        eplusEminus.Add(eminus);
                        prevEConstant.Value = cnExpr.Constant;
                    }
                }
            }

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

            return(expr);
        }
コード例 #14
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);
        }
コード例 #15
0
ファイル: Parser.cs プロジェクト: hur1can3/Cassowary.net
	void Constraint() {
		ClLinearExpression e1, e2; bool eq = false, geq = false, leq = false; 
		Expression(out e1);
		if (la.kind == 3) {
			Get();
			eq = true; 
		} else if (la.kind == 2) {
			Get();
			geq = true; 
		} else if (la.kind == 5) {
			Get();
			geq = true; 
		} else if (la.kind == 1) {
			Get();
			leq = true; 
		} else if (la.kind == 4) {
			Get();
			leq = true; 
		} else SynErr(15);
		Expression(out e2);
		if (eq)
		 Value = new ClLinearEquation(e1, e2);
		else if (geq)
		  Value = new ClLinearInequality(e1, Cl.GEQ, e2);
		else if (leq)
		  Value = new ClLinearInequality(e1, Cl.LEQ, e2);
		
	}