public static Expression reduce( Expression expr) { Dictionary<Variable,double> vars=new Dictionary<Variable, double>(); foreach(Term t in expr.terms()) { if(vars.ContainsKey(t.variable())) { vars[t.variable()]+=t.coefficient(); } else { vars[t.variable()]=t.coefficient(); } } List<Term> terms=new List<Term>(); foreach(KeyValuePair<Variable,double> kv in vars ) { terms.Add(new Term(kv.Key,kv.Value)); } return new Expression(terms, expr.constant()); }
/* Create a new Row object for the given constraint. The terms in the constraint will be converted to cells in the row. Any term in the constraint with a coefficient of zero is ignored. This method uses the `getVarSymbol` method to get the symbol for the variables added to the row. If the symbol for a given cell variable is basic, the cell variable will be substituted with the basic row. The necessary slack and error variables will be added to the row. If the constant for the row is negative, the sign for the row will be inverted so the constant becomes positive. The tag will be updated with the marker and error symbols to use for tracking the movement of the constraint in the tableau. */ Row createRow( Constraint constraint, Tag tag ) { Expression expr= constraint.expression(); Row row = new Row( expr.constant() ); // Substitute the current basic variables into the row. foreach(Term t in expr.terms() ) { if( !Util.nearZero( t.coefficient() ) ) { Symbol symbol=new Symbol ( getVarSymbol( t.variable() ) ); Row tr; if(m_rows.TryGetValue(symbol,out tr)) { row.insert(tr,t.coefficient()); } else { row.insert(symbol,t.coefficient()); } } } // Add the necessary slack, error, and dummy variables. switch( constraint.op() ) { case RelationalOperator.OP_LE: case RelationalOperator.OP_GE: { double coeff = constraint.op() == RelationalOperator.OP_LE ? 1.0 : -1.0; Symbol slack=new Symbol( Symbol.Type.Slack, m_id_tick++ ); tag.marker = slack; row.insert( slack, coeff ); if( constraint.strength() < Strength.required ) { Symbol error=new Symbol( Symbol.Type.Error, m_id_tick++ ); tag.other = error; row.insert( error, -coeff ); m_objective.insert( error, constraint.strength() ); } break; } case RelationalOperator.OP_EQ: { if( constraint.strength() < Strength.required ) { Symbol errplus=new Symbol( Symbol.Type.Error, m_id_tick++ ); Symbol errminus=new Symbol ( Symbol.Type.Error, m_id_tick++ ); tag.marker = errplus; tag.other = errminus; row.insert( errplus, -1.0 ); // v = eplus - eminus row.insert( errminus, 1.0 ); // v - eplus + eminus = 0 m_objective.insert( errplus, constraint.strength() ); m_objective.insert( errminus, constraint.strength() ); } else { Symbol dummy=new Symbol( Symbol.Type.Dummy, m_id_tick++ ); tag.marker = dummy; row.insert( dummy ); } break; } } // Ensure the row as a positive constant. if( row.constant() < 0.0 ) row.reverseSign(); return row; }