/// <summary> /// Generates a test file /// </summary> static void GenerateExamples() { FileStream fs = new FileStream("examples.hl", FileMode.Create); StreamWriter w = new StreamWriter(fs); Random rnd = new Random(2); // Dependencies w.WriteLine("needs \"test_explicit.hl\""); w.WriteLine("let test = ["); for (int k = 0; k < 300; k++) { List <decimal> cs = new List <decimal>(); List <string> vars = new List <string>(); int i = rnd.Next(100); while (i >= 0) { vars.Add('x'.ToString() + "_" + String.Format("{0:000}", i)); cs.Add(rnd.Next(1000000000)); i -= rnd.Next(10) + 1; } LinearFunction f = new LinearFunction(cs, vars); w.Write(f.ToHOLExplicit(5, null)); // w.Write("`" + f.ToHOLString(5) + "`"); w.WriteLine(";"); } w.WriteLine("];;"); w.Flush(); fs.Close(); }
/// <summary> /// Private constructor /// </summary> private Inequality(Label id, IneqType type, LinearFunction lhs, LpNumber rhs, bool negFlag) { this.Id = id; this.type = type; this.lhs = lhs; this.rhs = rhs; this.NegFlag = negFlag; }
/// <summary> /// Returns the equality 0 = 0 /// </summary> public static Inequality Zero() { Label id = new Label("ZERO", ""); LinearFunction lhs = new LinearFunction(new List <decimal>(), new List <string>()); LpNumber rhs = new LpNumber(0); Inequality ineq = new Inequality(id, IneqType.Eq, lhs, rhs, false); return(ineq); }
public static LinearFunction operator *(decimal n, LinearFunction f) { LinearFunction result = new LinearFunction(); foreach (var term in f.terms) { result.terms.Add(term * n); } return(result); }
/// <summary> /// Rounds down the linear function /// </summary> /// <param name="precision"></param> /// <returns></returns> public LinearFunction RoundDown(int precision) { LinearFunction f = new LinearFunction(); foreach (var term in terms) { f.terms.Add(term.RoundDown(precision)); } return(f); }
/// <summary> /// Addition /// </summary> /// <param name="f1"></param> /// <param name="f2"></param> /// <returns></returns> public static LinearFunction operator +(LinearFunction f1, LinearFunction f2) { f1.terms.Sort(); f2.terms.Sort(); LinearFunction f = new LinearFunction(); int n1 = f1.terms.Count; int n2 = f2.terms.Count; int index1 = 0, index2 = 0; while (index1 < n1 && index2 < n2) { Term t1 = f1.terms[index1]; Term t2 = f2.terms[index2]; int r = t1.CompareTo(t2); if (r == 0) { LpNumber n = t1.c + t2.c; if (n.value != 0) { f.terms.Add(new Term(n, t1.varName)); } index1++; index2++; } else if (r > 0) { f.terms.Add(t2); index2++; } else { f.terms.Add(t1); index1++; } } for (int i = index1; i < n1; i++) { f.terms.Add(f1.terms[i]); } for (int i = index2; i < n2; i++) { f.terms.Add(f2.terms[i]); } return(f); }
/// <summary> /// Parses an inequality /// </summary> /// <param name="scanner"></param> /// <returns></returns> public static Inequality ParseInequality(Scanner scanner) { Token t; // Identifier Label id = Label.ParseLabel(scanner); // : t = scanner.nextToken(); if (t.Type != TokenType.Colon) { throw new Exception(": expected: " + t); } // lhs LinearFunction lhs = LinearFunction.ParseFunction(scanner); // type t = scanner.nextToken(); IneqType type; switch (t.Type) { case TokenType.Le: type = IneqType.Le; break; case TokenType.Ge: type = IneqType.Ge; break; case TokenType.Eq: type = IneqType.Eq; break; default: throw new Exception("<=, =>, or = expected: " + t); } // rhs t = scanner.nextToken(); if (t.Type != TokenType.Integer && t.Type != TokenType.Double) { throw new Exception("A number is expected: " + t); } LpNumber rhs = new LpNumber(decimal.Parse(t.StringValue)); return(new Inequality(id, type, lhs, rhs, false)); }
/// <summary> /// Parses a linear function /// </summary> /// <param name="scanner"></param> /// <returns></returns> public static LinearFunction ParseFunction(Scanner scanner) { LinearFunction f = new LinearFunction(); Token t; while (true) { t = scanner.peekToken(); if (t.Type != TokenType.Plus && t.Type != TokenType.Minus) { break; } Term term = Term.ParseTerm(scanner); f.terms.Add(term); } return(f); }
/// <summary> /// Processes all inequalities based on the given solution /// </summary> /// <param name="sol"></param> /// <param name="precision"></param> /// <returns></returns> public bool SetSolution(LPSolution sol, int precision) { if (sol.NumberOfVariables != vars.Number) { throw new Exception("Inconsistent number of variables"); } if (sol.NumberOfConstraints != originalIneqs.Count) { throw new Exception("Inconsistent number of constraints"); } ineqs = new List <Inequality>(); // ineqMarginals = new List<LpNumber>(); // Constraints for (int i = 0; i < sol.NumberOfConstraints; i++) { LpNumber m = sol.ConstraintMarginals[i]; if (m.IsZero(precision)) { continue; } Inequality ineq = originalIneqs[i]; if (m.value < 0) { ineq = -ineq; m = -m; } ineq = ineq.Round(precision); ineq.Marginal = m; ineqs.Add(ineq); // ineqMarginals.Add(m); } // Variables List <Inequality> tmpIneqs = new List <Inequality>(); for (int i = 0; i < sol.NumberOfVariables; i++) { Variable var = vars[i]; LpNumber m = sol.VariableMarginals[i]; if (m.IsZero(precision)) { continue; } Inequality ineq; if (m.value < 0) { var.LMarginal = -m; ineq = -Inequality.FromLowerBound(var); ineq = ineq.Round(precision) * (-m.value); } else { var.UMarginal = m; ineq = Inequality.FromUpperBound(var); ineq = ineq.Round(precision) * m.value; } tmpIneqs.Add(ineq); } // Compute additional inequality // Inequality sum1 = ineqs[0] * ineqs[0].Marginal.value; //ineqMarginals[0].value; Inequality sum1 = Inequality.Zero(); for (int i = 0; i < ineqs.Count; i++) { sum1 += ineqs[i] * ineqs[i].Marginal.value; //ineqMarginals[i].value; } Inequality sum2 = sum1; for (int i = 0; i < tmpIneqs.Count; i++) { sum2 += tmpIneqs[i]; } // df LinearFunction df = objective - sum2.lhs; // Compute corrections for marginals foreach (var term in df.Terms) { LpNumber c = term.c; if (c.value < 0) { vars[term.varName].LMarginal -= c; } else { vars[term.varName].UMarginal += c; } } // Verification LpNumber sum = sum1.rhs; for (int i = 0; i < vars.Number; i++) { Variable var = vars[i]; if (!var.LMarginal.IsZero(precision)) { sum -= var.LMarginal * LpNumber.RoundDown(var.LBound, precision); } if (!var.UMarginal.IsZero(precision)) { sum += var.UMarginal * LpNumber.RoundUp(var.UBound, precision); } } LpNumber eps = sol.UpperBound - sum; Console.WriteLine("eps = {0}", eps); if (eps.value < 0) { return(false); } // Set the upper bound upperBound = sol.UpperBound; // Generate inequalities for variables Console.Write("Generating inequalities for variables..."); varIneqs = new List <Inequality>(); // varIneqMarginals = new List<LpNumber>(); for (int i = 0; i < vars.Number; i++) { Variable var = vars[i]; Inequality ineq; if (!var.LMarginal.IsZero(precision)) { ineq = -Inequality.FromLowerBound(var); ineq = ineq.Round(precision); ineq.Marginal = var.LMarginal; varIneqs.Add(ineq); // varIneqMarginals.Add(var.LMarginal); } if (!var.UMarginal.IsZero(precision)) { ineq = Inequality.FromUpperBound(var); ineq = ineq.Round(precision); ineq.Marginal = var.UMarginal; varIneqs.Add(ineq); // varIneqMarginals.Add(var.UMarginal); } } Console.WriteLine("done"); return(true); }
/// <summary> /// Parses a LP /// </summary> /// <param name="scanner"></param> /// <returns></returns> public static LP ParseLP(Scanner scanner) { LP lp = new LP(); // Maximize Token t = scanner.nextToken(); if (t.Type != TokenType.Identifier && t.StringValue != "Maximize") { throw new Exception("Maximize expected: " + t); } // objective t = scanner.nextToken(); if (t.Type != TokenType.Identifier) { throw new Exception("Identifier expected: " + t); } // : t = scanner.nextToken(); if (t.Type != TokenType.Colon) { throw new Exception(": expected: " + t); } // objective function lp.objective = LinearFunction.ParseFunction(scanner); // Subject To t = scanner.nextToken(); if (t.Type != TokenType.Identifier && t.StringValue != "Subject") { throw new Exception("Subject To expected: " + t); } t = scanner.nextToken(); if (t.Type != TokenType.Identifier && t.StringValue != "To") { throw new Exception("Subject To expected: " + t); } // Constraints while (true) { t = scanner.peekToken(); if (t.Type == TokenType.Identifier && t.StringValue == "Bounds") { break; } if (t.Type == TokenType.EOF) { break; } Inequality ineq = Inequality.ParseInequality(scanner); lp.originalIneqs.Add(ineq); } // Bounds t = scanner.nextToken(); if (t.Type != TokenType.Identifier && t.StringValue != "Bounds") { throw new Exception("Bounds expected: " + t); } // Bounds while (true) { t = scanner.peekToken(); if (t.Type == TokenType.Identifier && t.StringValue == "End") { break; } if (t.Type == TokenType.EOF) { break; } ParseBound(scanner, lp); } return(lp); }