Пример #1
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;
    }
Пример #2
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);
        }
Пример #3
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;
    }
Пример #4
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>
        private ClAbstractVariable ChooseSubject(ClLinearExpression expr)
        /* ExClRequiredFailure */
        {
            ClAbstractVariable subject = null; // the current best subject, if any

            bool foundUnrestricted  = false;
            bool foundNewRestricted = false;

            var terms = expr.Terms;

            foreach (ClAbstractVariable v in terms.Keys)
            {
                double c = (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)
                        {
                            HashSet <ClAbstractVariable> col;
                            if (!Columns.TryGetValue(v, out col) ||
                                (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 = (terms[v]).Value;

                if (!v.IsDummy)
                {
                    return(null); // nope, no luck
                }
                if (!ColumnsHasKey(v))
                {
                    subject = v;
                    coeff   = c;
                }
            }

            if (!Approx(expr.Constant, 0.0))
            {
                throw new CassowaryRequiredFailureException();
            }
            if (coeff > 0.0)
            {
                expr.MultiplyMe(-1);
            }

            return(subject);
        }