/// <summary> /// Creates an upper bound inequality for a variable /// </summary> /// <param name="var"></param> /// <returns></returns> public static Inequality FromUpperBound(Variable var) { Inequality ineq = new Inequality(new Label(var.Name, var.Name.name + "_hi"), IneqType.Le, new LinearFunction(var), new LpNumber(var.UBound), false); return(ineq); }
// Adds an indexed inequality to a dictionary private void AddIndexedIneq(Inequality ineq, LpNumber marginal, ListHyp hypermap) { IndexedInequality newIneq = new IndexedInequality(ineq, marginal, hypermap); string name = ineq.Id.name; // Ad hoc treatment of sums over faces if (name == "sol_sum" || name == "tau_sum") { DartList face = hypermap.Manager.TranslateIneq(hypermap, ineq.Id) as DartList; if (face == null) { throw new Exception("A face is expected for the constraint " + name); } name += face.list.Count.ToString(); } if (ineq.type == Inequality.IneqType.Eq && ineq.NegFlag) { name += "_neg"; } if (dict.ContainsKey(name)) { dict[name].Add(newIneq); } else { var list = new List <IndexedInequality>(); list.Add(newIneq); dict.Add(name, list); ineqNames.Add(name); } }
/// <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); }
/// <summary> /// Computes the index automatically /// </summary> public IndexedInequality(Inequality ineq, LpNumber marginal, ListHyp hypermap) { this.ineq = ineq; this.marginal = marginal; if (ineq.Id.index == null || ineq.Id.index == "") { this.index = 0; } else { this.index = hypermap.Manager.FindIneqIndex(hypermap, ineq.Id); } }
/// <summary> /// Prints the given inequality into a stream /// </summary> private void WriteIneqText(Inequality ineq, LpNumber marginal, int precision, StreamWriter writer, ListHyp hypermap) { // Relabel HypermapElement element = hypermap.Manager.TranslateIneq(hypermap, ineq.Id); int index = hypermap.Manager.FindIneqIndex(hypermap, ineq.Id); // Write out if (ineq.NegFlag && ineq.type == Inequality.IneqType.Eq) { writer.Write("-"); } writer.Write(ineq.Id + " & "); writer.Write(index + " & "); writer.Write(element + ": "); writer.Write(ineq.ToHOLString(precision, vars)); writer.Write("\t ("); writer.Write(marginal.ToHOLString(precision)); writer.WriteLine(")"); }
// Adds an indexed inequality to a dictionary private void AddIndexedIneq(Inequality ineq, LpNumber marginal, ListHyp hypermap) { IndexedInequality newIneq = new IndexedInequality(ineq, marginal, hypermap); string name = ineq.Id.name; if (ineq.type == Inequality.IneqType.Eq && ineq.NegFlag) { name += "_neg"; } if (dict.ContainsKey(name)) { dict[name].Add(newIneq); } else { var list = new List <IndexedInequality>(); list.Add(newIneq); dict.Add(name, list); ineqNames.Add(name); } }
/// <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); }
/// <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; }
/// <summary> /// Creates an upper bound inequality for a variable /// </summary> /// <param name="var"></param> /// <returns></returns> public static Inequality FromUpperBound(Variable var) { Inequality ineq = new Inequality(new Label(var.Name, var.Name.name + "_hi"), IneqType.Le, new LinearFunction(var), new LpNumber(var.UBound), false); return ineq; }
/// <summary> /// Computes the index automatically /// </summary> public IndexedInequality(Inequality ineq, LpNumber marginal, ListHyp hypermap) { this.ineq = ineq; this.marginal = marginal; this.index = hypermap.Manager.FindIneqIndex(hypermap, ineq.Id); }
/// <summary> /// Converts the LP into HOL data /// </summary> /// <param name="writer"></param> public void ConvertToHOL(StreamWriter writer, int precision) { // Find target variables foreach (var term in objective.Terms) { vars[term.varName].TargetVariable = true; } // Compute the precision constant decimal mul = 1; for (int i = 0; i < precision; i++) { mul *= 10; } // Dependencies writer.WriteLine("module Lp = struct"); // writer.WriteLine("needs \"arith/prove_lp.hl\";;"); // writer.WriteLine("open Prove_lp;;"); // Target writer.WriteLine("let target = `" + objective.ToHOLString(precision, vars) + "`;;"); // Target bound writer.WriteLine("let target_bound = `" + upperBound.ToHOLString(100) + "`;;"); // Precision // LpNumber precision_constant = new LpNumber(mul * mul * mul); writer.Write("let precision_constant = "); writer.Write("Int " + mul); // writer.Write(precision_constant.ToHOLExplicit(0)); writer.WriteLine(";;"); // Constraints int counter = 0; writer.WriteLine("let ineqs = ["); vars.MakeSimpleNames(); for (int i = 0; i < ineqs.Count; i++) { Inequality ineq = ineqs[i]; LpNumber m = ineq.Marginal; //ineqMarginals[i]; if (ineq.Id.name == "lnsum_def") { throw new Exception("lnsum_def cannot be active"); } // Ignore zero values if (m.IsZero(precision)) { continue; } // m *= mul * mul; m *= mul; ineq = ineq * mul; writer.Write("ASSUME ("); writer.Write(ineq.ToHOLExplicit(precision, vars)); writer.Write("), "); writer.Write(m.ToHOLExplicit(precision)); writer.WriteLine(";"); counter++; } writer.WriteLine("];;"); int constraintIneqs = counter; // Variables // Sort variables varIneqs.Sort(new VarsComparer(vars)); // Save target variables first writer.WriteLine("let target_vars = ["); counter = 0; for (; counter < varIneqs.Count; counter++) { Inequality ineq = varIneqs[counter]; if (!vars[ineq.lhs.Terms.First().varName].TargetVariable) { break; } LpNumber m = ineq.Marginal; //varIneqMarginals[i]; m *= mul * mul; ineq = ineq * mul; writer.Write("ASSUME ("); writer.Write(ineq.ToHOLExplicit(precision, vars)); writer.Write("), "); writer.Write(m.ToHOLExplicit(precision)); writer.WriteLine(";"); } writer.WriteLine("];;\n\n"); writer.WriteLine("let var_ineqs = ["); // writer.WriteLine("let vars = ["); // counter = 0; for (int i = counter; i < varIneqs.Count; i++) { Inequality ineq = varIneqs[i]; LpNumber m = ineq.Marginal; //varIneqMarginals[i]; if (m.IsZero(precision)) { throw new Exception("Unexpected zero"); } if (i < varIneqs.Count - 1) { Inequality ineq2 = varIneqs[i + 1]; LpNumber m2 = ineq2.Marginal; if (m2.IsZero(precision)) { throw new Exception("Unexpected zero"); } if (ineq.lhs.Terms.First().varName == ineq2.lhs.Terms.First().varName) { m *= mul * mul; m2 *= mul * mul; ineq = ineq * mul; ineq2 = ineq2 * mul; writer.Write("var2_le_transform ("); writer.Write(ineq.ToHOLExplicit(precision, vars)); writer.Write(", "); writer.Write(m.ToHOLExplicit(precision)); writer.Write(") "); writer.Write("("); writer.Write(ineq2.ToHOLExplicit(precision, vars)); writer.Write(", "); writer.Write(m2.ToHOLExplicit(precision)); writer.WriteLine(");"); i++; continue; } } m *= mul * mul; ineq = ineq * mul; writer.Write("var1_le_transform ("); writer.Write(ineq.ToHOLExplicit(precision, vars)); writer.Write(", "); writer.Write(m.ToHOLExplicit(precision)); writer.WriteLine(");"); // writer.WriteLine(";"); } writer.WriteLine("];;"); Console.WriteLine("Inequalities for constraints: {0}", constraintIneqs); Console.WriteLine("Inequalities for variables: {0}", varIneqs.Count); Console.WriteLine("Number of variables: {0}", vars.Number); Console.WriteLine("Total constraints: {0}", constraintIneqs + varIneqs.Count); writer.WriteLine("let start = Sys.time();;"); writer.WriteLine("let result = prove_lp ineqs var_ineqs target_vars target_bound precision_constant;;"); // writer.WriteLine("let result = Prove_lp.prove_lp ineqs vars target_bound precision_constant;;"); writer.WriteLine("end;;"); writer.WriteLine("Sys.time() -. Lp.start;;"); // writer.WriteLine("let done_message = \"{0} done\";;", fname); writer.WriteLine("concl (Lp.result);;"); writer.Flush(); }
/// <summary> /// Prints all inequalities in a text file using HOL syntax /// </summary> /// <param name="writer"></param> /// <param name="precision"></param> public void PrintAllText(StreamWriter writer, int precision, ListHyp hypermap) { // Find target variables foreach (var term in objective.Terms) { vars[term.varName].TargetVariable = true; } // Compute the precision constant decimal mul = 1; for (int i = 0; i < precision; i++) { mul *= 10; } // Target writer.WriteLine("target: " + objective.ToHOLString(precision, vars)); // Precision writer.WriteLine("precision_constant: " + mul); // Constraints int counter = 0; vars.RelabelAllVariables(hypermap); for (int i = 0; i < ineqs.Count; i++) { Inequality ineq = ineqs[i]; LpNumber m = ineq.Marginal; if (ineq.Id.name == "lnsum_def") { throw new Exception("lnsum_def cannot be active"); } // Ignore zero values if (m.IsZero(precision)) { continue; } WriteIneqText(ineq * mul, m * mul, precision, writer, hypermap); counter++; } writer.WriteLine(); writer.WriteLine("Inequalities for constraints: {0}", counter); writer.WriteLine("-------------------------------------------------------"); writer.WriteLine(); // Variables // Sort variables varIneqs.Sort(new VarsComparer(vars)); // Target variables first writer.WriteLine("Target variables:"); counter = 0; for (; counter < varIneqs.Count; counter++) { Inequality ineq = varIneqs[counter]; if (!vars[ineq.lhs.Terms.First().varName].TargetVariable) { break; } LpNumber m = ineq.Marginal; //varIneqMarginals[i]; m *= mul * mul; ineq = ineq * mul; WriteIneqText(ineq, m, precision, writer, hypermap); } writer.WriteLine("-------------------------------------------------------"); writer.WriteLine(); // All other variables writer.WriteLine("Variables:"); for (int i = counter; i < varIneqs.Count; i++) { Inequality ineq = varIneqs[i]; LpNumber m = ineq.Marginal; //varIneqMarginals[i]; if (m.IsZero(precision)) { throw new Exception("Unexpected zero"); } /* if (i < varIneqs.Count - 1) * { * Inequality ineq2 = varIneqs[i + 1]; * LpNumber m2 = ineq2.Marginal; * * if (m2.IsZero(precision)) * throw new Exception("Unexpected zero"); * * if (ineq.lhs.Terms.First().varName == ineq2.lhs.Terms.First().varName) * { * m *= mul * mul; * m2 *= mul * mul; * ineq = ineq * mul; * ineq2 = ineq2 * mul; * * writer.Write("var2_le_transform ("); * writer.Write(ineq.ToHOLExplicit(precision, vars)); * writer.Write(", "); * writer.Write(m.ToHOLExplicit(precision)); * writer.Write(") "); * * writer.Write("("); * writer.Write(ineq2.ToHOLExplicit(precision, vars)); * writer.Write(", "); * writer.Write(m2.ToHOLExplicit(precision)); * writer.WriteLine(");"); * * i++; * continue; * } * } */ m *= mul * mul; ineq = ineq * mul; WriteIneqText(ineq, m, precision, writer, hypermap); } writer.WriteLine("Inequalities for variables: {0}", varIneqs.Count); writer.Flush(); }
/// <summary> /// Creates a HOL certificate /// </summary> public void PrintCertificate(StreamWriter writer, int precision, ListHyp hypermap, StreamWriter log) { // Find target variables foreach (var term in objective.Terms) { vars[term.varName].TargetVariable = true; } // Compute the precision constant decimal mul = 1; for (int i = 0; i < precision; i++) { mul *= 10; } // Head writer.WriteLine("needs \"nobranching_lp.hl\";;\n"); writer.WriteLine("module Test_case = struct"); // Parameters writer.WriteLine("let hypermap_string = \"" + hypermap.rawString + "\";;"); writer.WriteLine("let precision = " + precision + ";;"); dict.Clear(); ineqNames.Clear(); // Constraints int counter = 0; vars.RelabelAllVariables(hypermap); writer.WriteLine("(***************)"); writer.WriteLine("(* Constraints *)"); writer.WriteLine("(***************)"); for (int i = 0; i < ineqs.Count; i++) { Inequality ineq = ineqs[i]; LpNumber m = ineq.Marginal; if (ineq.Id.name == "lnsum_def") { throw new Exception("lnsum_def cannot be active"); } // Ignore zero values if (m.IsZero(precision)) { continue; } ineq *= mul; m *= mul; AddIndexedIneq(ineq, m, hypermap); } writer.WriteLine("let constraints = ["); SaveIndexedIneqs(writer, precision); writer.WriteLine("];;"); // Variables writer.WriteLine(); writer.WriteLine("(***************)"); writer.WriteLine("(* Variables *)"); writer.WriteLine("(***************)"); // Sort variables varIneqs.Sort(new VarsComparer(vars)); // Target variables first dict.Clear(); ineqNames.Clear(); counter = 0; for (; counter < varIneqs.Count; counter++) { Inequality ineq = varIneqs[counter]; if (!vars[ineq.lhs.Terms.First().varName].TargetVariable) { break; } LpNumber m = ineq.Marginal; m *= mul * mul; ineq = ineq * mul; AddIndexedIneq(ineq, m, hypermap); } writer.WriteLine("let target_variables = ["); SaveIndexedIneqs(writer, precision); writer.WriteLine("];;"); writer.WriteLine(); writer.WriteLine("(*************************)"); writer.WriteLine(); // All other variables dict.Clear(); ineqNames.Clear(); for (int i = counter; i < varIneqs.Count; i++) { Inequality ineq = varIneqs[i]; LpNumber m = ineq.Marginal; m *= mul * mul; ineq = ineq * mul; AddIndexedIneq(ineq, m, hypermap); } writer.WriteLine("let variable_bounds = ["); SaveIndexedIneqs(writer, precision); writer.WriteLine("];;"); // Tail writer.WriteLine("let result = prove_hypermap_lp hypermap_string precision constraints target_variables variable_bounds;;"); writer.WriteLine("end;;"); writer.WriteLine(); writer.WriteLine("concl (Test_case.result)"); writer.Flush(); log.WriteLine("{0}\t{1}\t{2}", hypermap.Id, ineqs.Count + varIneqs.Count, vars.Number); }