public LPSolution Solve() { LinearProgram.VerifyVariables(); Tableau previousTableau = new Tableau(); ConstraintRow[] constraints = new ConstraintRow[LinearProgram.Constraints.Length]; for (int i = 0; i < constraints.Length; i++) { constraints[i] = new ConstraintRow(i, constraints.Length, LinearProgram.Constraints[i].GetVars(), LinearProgram.Constraints[i].Constant); } previousTableau.Constraints = constraints; previousTableau.ObjectiveRow = new ObjectiveRow(constraints.Length, LinearProgram.ObjectiveFunction.GetVars()); Variable[] emptyVars = previousTableau.ObjectiveRow.Vars.Where(var => !var.IsSlack).Select(var => var.Empty).ToArray(); Tableau currentTableau = Tableau.EmptyTableau(previousTableau.Constraints.Length, emptyVars); while (MostNegitive(previousTableau, out Variable mostNegitive)) { int index = 0; double leastPositive = previousTableau.Constraints.Length > 0 ? previousTableau.Constraints[index].RatioTest(mostNegitive) : -1; for (int i = 0; i < previousTableau.Constraints.Length; i++) { double rt = previousTableau.Constraints[i].RatioTest(mostNegitive); if (rt > 0 && rt < leastPositive) { leastPositive = rt; index = i; } } if (leastPositive == 0) { throw new Exception("Least Positive is Unchanged"); } currentTableau.Constraints[index] = previousTableau.Constraints[index].PivotRow(mostNegitive.Index); currentTableau.ObjectiveRow = previousTableau.ObjectiveRow.Normalize(mostNegitive.Index, currentTableau.Constraints[index].Vars, currentTableau.Constraints[index].RHS); for (int i = 0; i < currentTableau.Constraints.Length; i++) { if (i != index) { currentTableau.Constraints[i] = previousTableau.Constraints[i].Normalize(mostNegitive.Index, currentTableau.Constraints[index].Vars, currentTableau.Constraints[index].RHS); } } previousTableau = currentTableau.Copy(); currentTableau = Tableau.EmptyTableau(previousTableau.Constraints.Length, emptyVars); } Console.WriteLine(previousTableau); return(new LPSolution(previousTableau)); }
public Tableau Copy() { ConstraintRow[] constraintRow = new ConstraintRow[Constraints.Length]; Constraints.CopyTo(constraintRow, 0); return(new Tableau() { Constraints = constraintRow, ObjectiveRow = new ObjectiveRow() { Vars = new List <Variable>(ObjectiveRow.Vars).ToArray(), RHS = ObjectiveRow.RHS } }); }
public static Tableau EmptyTableau(int constraintCount, Variable[] emptyVariables) { ConstraintRow[] constraints = new ConstraintRow[constraintCount]; for (int i = 0; i < constraints.Length; i++) { constraints[i] = new ConstraintRow(i, constraintCount, new List <Variable>(emptyVariables).ToArray(), 0); } return(new Tableau() { Constraints = constraints, ObjectiveRow = new ObjectiveRow(constraints.Length, new List <Variable>(emptyVariables).ToArray()) }); }
public static ConstraintRowParser Create(Constraint constraint) { if (constraint == null || constraint.ElementaryConstraints.Length == 0) { return(null); } ConstraintRowParser constraintRowParser = new ConstraintRowParser(); System.Action <ConstraintRow[], ElementaryConstraint, int, int> AssignRow = (rows, ec, constraintRow, localRow) => { if (rows[constraintRow] != null) { throw new Exception("Row index " + constraintRow + " already assigned: " + rows[constraintRow].ElementaryConstraint.NativeName); } rows[constraintRow] = new ConstraintRow(ec, localRow); }; ElementaryConstraint[] ordinaryElementaryConstraints = constraint.GetOrdinaryElementaryConstraints(); foreach (ElementaryConstraint ec in ordinaryElementaryConstraints) { if (ec.NumRows > 1) { // Only rotational QuatLock ("QL") and translational SphericalRel ("SR") with three rows. ConstraintRow[] rows = ec.NativeName == "QL" ? constraintRowParser.RotationalRows : ec.NativeName == "SW" ? constraintRowParser.RotationalRows : ec.NativeName == "SR" ? constraintRowParser.TranslationalRows : null; if (rows == null) { throw new Exception("Unknown elementary constraint with name: " + ec.NativeName); } // For Swing we should assign rows 0 and 1. for (int row = 0; row < ec.NumRows; ++row) { AssignRow(rows, ec, row, row); } } else if (ec.NumRows == 1) { // Dot2 for single translational row ("D2_U" along U and "D2_V" along V). int translationalRow = ec.NativeName == "D2_U" ? 0 : ec.NativeName == "D2_V" ? 1 : ec.NativeName == "D2_N" ? 2 : ec.NativeName == "CN" ? 2 : -1; // Dot1 for single rotational row ("D1_VN" about U and "D1_UN" about V ). int rotationalRow = ec.NativeName == "D1_VN" ? 0 : ec.NativeName == "D1_UN" ? 1 : ec.NativeName == "D1_UV" ? 2 : -1; if (translationalRow < 0 && rotationalRow < 0) { throw new Exception("Unknown single row elementary constraint with name: " + ec.NativeName); } if (translationalRow >= 0) { AssignRow(constraintRowParser.TranslationalRows, ec, translationalRow, 0); } else { AssignRow(constraintRowParser.RotationalRows, ec, rotationalRow, 0); } } } return(constraintRowParser); }