diff --git a/.gitignore b/.gitignore index 65a69bf51..2158b8633 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ ocamlz3 # Emacs temp files \#*\# # Directories with generated code and documentation +release/* build/* build-dist/* dist/* diff --git a/RELEASE_NOTES b/RELEASE_NOTES index fa4857e32..ad2dcaf00 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,5 +1,10 @@ RELEASE NOTES +Version 4.3.3 +============= + +- Fixed bug in floating point models + Version 4.3.2 ============= diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index b348e7d36..ba706a769 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -21,6 +21,7 @@ void demorgan() { // adding the negation of the conjecture as a constraint. s.add(!conjecture); std::cout << s << "\n"; + std::cout << s.to_smt2() << "\n"; switch (s.check()) { case unsat: std::cout << "de-Morgan is valid\n"; break; case sat: std::cout << "de-Morgan is not valid\n"; break; @@ -974,6 +975,30 @@ void substitute_example() { std::cout << new_f << std::endl; } +void opt_example() { + context c; + optimize opt(c); + params p(c); + p.set("priority",c.str_symbol("pareto")); + opt.set(p); + expr x = c.int_const("x"); + expr y = c.int_const("y"); + opt.add(10 >= x && x >= 0); + opt.add(10 >= y && y >= 0); + opt.add(x + y <= 11); + optimize::handle h1 = opt.maximize(x); + optimize::handle h2 = opt.maximize(y); + check_result r = sat; + while (true) { + if (sat == opt.check()) { + std::cout << x << ": " << opt.lower(h1) << " " << y << ": " << opt.lower(h2) << "\n"; + } + else { + break; + } + } +} + int main() { try { demorgan(); std::cout << "\n"; @@ -1012,6 +1037,7 @@ int main() { expr_vector_example(); std::cout << "\n"; exists_expr_vector_example(); std::cout << "\n"; substitute_example(); std::cout << "\n"; + opt_example(); std::cout << "\n"; std::cout << "done\n"; } catch (exception & ex) { diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index 4361cab96..a20978d62 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -759,7 +759,7 @@ namespace test_mapi foreach (BoolExpr a in g.Formulas) solver.Assert(a); - if (solver.Check() != Status.SATISFIABLE) + if (solver.Check() != Status.SATISFIABLE) throw new TestFailedException(); ApplyResult ar = ApplyTactic(ctx, ctx.MkTactic("simplify"), g); diff --git a/examples/msf/README b/examples/msf/README new file mode 100644 index 000000000..d6e56f72f --- /dev/null +++ b/examples/msf/README @@ -0,0 +1,20 @@ +In order to use Z3 MSF plugin, follow the following steps: +1. Compile latest Z3 .NET API (from any branch consisting of opt features) and copy 'libz3.dll' and 'Microsoft.Z3.dll' to the folder of 'Z3MSFPlugin.sln'. +2. Retrieve 'Microsoft.Solver.Foundation.dll' from http://archive.msdn.microsoft.com/solverfoundation/Release/ProjectReleases.aspx?ReleaseId=1799, + preferably using DLL only version. Copy 'Microsoft.Solver.Foundation.dll' to the folder of 'Z3MSFPlugin.sln' +3. Build 'Z3MSFPlugin.sln'. Note that you have to compile using x86 target for Microsoft.Z3.dll 32-bit and x64 target for Microsoft.Z3.dll 64-bit. + +The solution consists of a plugin project, a test project with a few simple test cases and a command line projects for external OML, MPS and SMPS models. +To retrieve SMT2 models which are native to Z3, set the logging file in corresponding directives or solver params e.g. + + var p = new Z3MILPParams(); + p.SMT2LogFile = "model.smt2"; + +For more details, check out the commands in 'Validator\Program.cs'. + +Enjoy! + + + + + \ No newline at end of file diff --git a/examples/msf/SolverFoundation.Plugin.Z3.Tests/App.config b/examples/msf/SolverFoundation.Plugin.Z3.Tests/App.config new file mode 100644 index 000000000..75e2872f1 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3.Tests/App.config @@ -0,0 +1,60 @@ + + + +
+ + + + + + + + + + + + + + + + diff --git a/examples/msf/SolverFoundation.Plugin.Z3.Tests/Properties/AssemblyInfo.cs b/examples/msf/SolverFoundation.Plugin.Z3.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..b58f97eda --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SolverFoundation.Plugin.Z3.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SolverFoundation.Plugin.Z3.Tests")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("27657eee-ca7b-4996-a905-86a3f4584988")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/examples/msf/SolverFoundation.Plugin.Z3.Tests/ServiceTests.cs b/examples/msf/SolverFoundation.Plugin.Z3.Tests/ServiceTests.cs new file mode 100644 index 000000000..25a8e2d26 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3.Tests/ServiceTests.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SolverFoundation.Common; +using Microsoft.SolverFoundation.Solvers; +using Microsoft.SolverFoundation.Services; +using Microsoft.SolverFoundation.Plugin.Z3; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.SolverFoundation.Plugin.Z3.Tests +{ + [TestClass] + public class ServiceTests + { + [TestInitialize] + public void SetUp() + { + SolverContext context = SolverContext.GetContext(); + context.ClearModel(); + } + + private void TestService1(Directive directive) + { + SolverContext context = SolverContext.GetContext(); + Model model = context.CreateModel(); + + Decision x1 = new Decision(Domain.RealRange(0, 2), "x1"); + Decision x2 = new Decision(Domain.RealRange(0, 2), "x2"); + + Decision z = new Decision(Domain.IntegerRange(0, 1), "z"); + + model.AddDecisions(x1, x2, z); + + model.AddConstraint("Row0", x1 - z <= 1); + model.AddConstraint("Row1", x2 + z <= 2); + + Goal goal = model.AddGoal("Goal0", GoalKind.Maximize, x1 + x2); + + Solution solution = context.Solve(directive); + Assert.IsTrue(goal.ToInt32() == 3); + context.ClearModel(); + } + + private void TestService2(Directive directive) + { + SolverContext context = SolverContext.GetContext(); + Model model = context.CreateModel(); + + Decision x1 = new Decision(Domain.RealNonnegative, "x1"); + Decision x2 = new Decision(Domain.RealNonnegative, "x2"); + + Decision z = new Decision(Domain.IntegerRange(0, 1), "z"); + + Rational M = 100; + + model.AddDecisions(x1, x2, z); + + model.AddConstraint("Row0", x1 + x2 >= 1); + model.AddConstraint("Row1", x1 - z * 100 <= 0); + model.AddConstraint("Row2", x2 + z * 100 <= 100); + + Goal goal = model.AddGoal("Goal0", GoalKind.Maximize, x1 + x2); + + Solution solution = context.Solve(directive); + Assert.IsTrue(goal.ToInt32() == 100); + context.ClearModel(); + } + + [TestMethod] + public void TestService1() + { + TestService1(new Z3MILPDirective()); + TestService1(new Z3TermDirective()); + } + + [TestMethod] + public void TestService2() + { + TestService2(new Z3MILPDirective()); + TestService2(new Z3TermDirective()); + } + + } +} diff --git a/examples/msf/SolverFoundation.Plugin.Z3.Tests/SolverFoundation.Plugin.Z3.Tests.csproj b/examples/msf/SolverFoundation.Plugin.Z3.Tests/SolverFoundation.Plugin.Z3.Tests.csproj new file mode 100644 index 000000000..24cecfa10 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3.Tests/SolverFoundation.Plugin.Z3.Tests.csproj @@ -0,0 +1,70 @@ + + + + + Debug + AnyCPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B} + Library + Properties + Microsoft.SolverFoundation.Plugin.Z3.Tests + SolverFoundation.Plugin.Z3.Tests + v4.0 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + x86 + + + + ..\Microsoft.Solver.Foundation.dll + + + + + + + + + + + + + + + + + + + + + {7340e664-f648-4ff7-89b2-f4da424996d3} + SolverFoundation.Plugin.Z3 + + + + + \ No newline at end of file diff --git a/examples/msf/SolverFoundation.Plugin.Z3.Tests/SolverTests.cs b/examples/msf/SolverFoundation.Plugin.Z3.Tests/SolverTests.cs new file mode 100644 index 000000000..c2cd0c270 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3.Tests/SolverTests.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SolverFoundation.Common; +using Microsoft.SolverFoundation.Solvers; +using Microsoft.SolverFoundation.Services; +using Microsoft.SolverFoundation.Plugin.Z3; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.SolverFoundation.Plugin.Z3.Tests +{ + [TestClass] + public class SolverTests + { + [TestMethod] + public void TestMILPSolver1() + { + var solver = new Z3MILPSolver(); + int goal; + + solver.AddRow("goal", out goal); + int x1, x2, z; + + // 0 <= x1 <= 2 + solver.AddVariable("x1", out x1); + solver.SetBounds(x1, 0, 2); + + // 0 <= x2 <= 2 + solver.AddVariable("x2", out x2); + solver.SetBounds(x2, 0, 2); + + // z is an integer in [0,1] + solver.AddVariable("z", out z); + solver.SetIntegrality(z, true); + solver.SetBounds(z, 0, 1); + + //max x1 + x2 + solver.SetCoefficient(goal, x1, 1); + solver.SetCoefficient(goal, x2, 1); + solver.AddGoal(goal, 1, false); + + // 0 <= x1 -z <= 1 + int row1; + solver.AddRow("rowI1", out row1); + solver.SetBounds(row1, 0, 1); + solver.SetCoefficient(row1, x1, 1); + solver.SetCoefficient(row1, z, -1); + + // 0 <= x2 + z <= 2 + int row2; + solver.AddRow("rowI2", out row2); + solver.SetBounds(row2, 0, 2); + solver.SetCoefficient(row2, x2, 1); + solver.SetCoefficient(row2, z, 1); + + var p = new Z3MILPParams(); + solver.Solve(p); + + Assert.IsTrue(solver.Result == LinearResult.Optimal); + Assert.AreEqual(solver.GetValue(x1), 2 * Rational.One); + Assert.AreEqual(solver.GetValue(x2), Rational.One); + Assert.AreEqual(solver.GetValue(z), Rational.One); + Assert.AreEqual(solver.GetValue(goal), 3 * Rational.One); + } + + [TestMethod] + public void TestMILPSolver2() + { + var solver = new Z3MILPSolver(); + int goal, extraGoal; + + Rational M = 100; + solver.AddRow("goal", out goal); + int x1, x2, z; + + // 0 <= x1 <= 100 + solver.AddVariable("x1", out x1); + solver.SetBounds(x1, 0, M); + + // 0 <= x2 <= 100 + solver.AddVariable("x2", out x2); + solver.SetBounds(x2, 0, M); + + // z is an integer in [0,1] + solver.AddVariable("z", out z); + solver.SetIntegrality(z, true); + solver.SetBounds(z, 0, 1); + + solver.SetCoefficient(goal, x1, 1); + solver.SetCoefficient(goal, x2, 2); + solver.AddGoal(goal, 1, false); + + solver.AddRow("extraGoal", out extraGoal); + + solver.SetCoefficient(extraGoal, x1, 2); + solver.SetCoefficient(extraGoal, x2, 1); + solver.AddGoal(extraGoal, 2, false); + + // x1 + x2 >= 1 + int row; + solver.AddRow("row", out row); + solver.SetBounds(row, 1, Rational.PositiveInfinity); + solver.SetCoefficient(row, x1, 1); + solver.SetCoefficient(row, x2, 1); + + + // x1 - M*z <= 0 + int row1; + solver.AddRow("rowI1", out row1); + solver.SetBounds(row1, Rational.NegativeInfinity, 0); + solver.SetCoefficient(row1, x1, 1); + solver.SetCoefficient(row1, z, -M); + + // x2 - M* (1-z) <= 0 + int row2; + solver.AddRow("rowI2", out row2); + solver.SetBounds(row2, Rational.NegativeInfinity, M); + solver.SetCoefficient(row2, x2, 1); + solver.SetCoefficient(row2, z, M); + + var p = new Z3MILPParams(); + p.OptKind = OptimizationKind.BoundingBox; + + solver.Solve(p); + Assert.IsTrue(solver.Result == LinearResult.Optimal); + Assert.AreEqual(solver.GetValue(goal), 200 * Rational.One); + Assert.AreEqual(solver.GetValue(extraGoal), 200 * Rational.One); + } + } +} diff --git a/examples/msf/SolverFoundation.Plugin.Z3/AbortWorker.cs b/examples/msf/SolverFoundation.Plugin.Z3/AbortWorker.cs new file mode 100644 index 000000000..99d6fe17a --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/AbortWorker.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using Microsoft.Z3; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + /// + /// Thread that will wait until the query abort function returns true or + /// the stop method is called. If the abort function returns true at some + /// point it will issue a softCancel() call to Z3. + /// + internal class AbortWorker + { + #region Private Members + + /// The Z3 solver + private Microsoft.Z3.Context _context; + /// The abort function to use to check if we are aborted + private Func _QueryAbortFunction; + /// Flag indicating that worker should stop + private bool _stop = false; + /// Flag indicating that we have been sent an abort signal + private bool _aborted = false; + + #endregion Private Members + + #region Construction + + /// + /// Worker constructor taking a Z3 instance and a function to periodically + /// check for aborts. + /// + /// Z3 instance + /// method to call to check for aborts + public AbortWorker(Context context, Func queryAbortFunction) + { + _context = context; + _QueryAbortFunction = queryAbortFunction; + } + + #endregion Construction + + #region Public Methods + + /// + /// Stop the abort worker. + /// + public void Stop() + { + _stop = true; + } + + /// + /// Is true if we have been aborted. + /// + public bool Aborted + { + get + { + return _aborted; + } + } + + /// + /// Starts the abort worker. The worker checks the abort method + /// periodically until either it is stopped by a call to the Stop() + /// method or it gets an abort signal. In the latter case it will + /// issue a soft abort signal to Z3. + /// + public void Start() + { + // We go until someone stops us + _stop = false; + while (!_stop && !_QueryAbortFunction()) + { + // Wait for a while + Thread.Sleep(10); + } + // If we were stopped on abort, cancel z3 + if (!_stop) + { + _context.Interrupt(); + _aborted = true; + } + } + + #endregion Public Methods + } +} diff --git a/examples/msf/SolverFoundation.Plugin.Z3/App.config b/examples/msf/SolverFoundation.Plugin.Z3/App.config new file mode 100644 index 000000000..75e2872f1 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/App.config @@ -0,0 +1,60 @@ + + + +
+ + + + + + + + + + + + + + + + diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Properties/AssemblyInfo.cs b/examples/msf/SolverFoundation.Plugin.Z3/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..b30c01ab4 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SolverFoundation.Plugin.Z3")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("SolverFoundation.Plugin.Z3")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ed1476c0-96de-4d2c-983d-3888b140c3ad")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/examples/msf/SolverFoundation.Plugin.Z3/SolverFoundation.Plugin.Z3.csproj b/examples/msf/SolverFoundation.Plugin.Z3/SolverFoundation.Plugin.Z3.csproj new file mode 100644 index 000000000..0b30e1677 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/SolverFoundation.Plugin.Z3.csproj @@ -0,0 +1,149 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {7340E664-F648-4FF7-89B2-F4DA424996D3} + Library + Properties + Microsoft.SolverFoundation.Plugin.Z3 + SolverFoundation.Plugin.Z3 + v4.0 + 512 + false + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + bin\commercial\ + TRACE + true + pdbonly + AnyCPU + prompt + + + bin\commercial_64\ + TRACE + true + pdbonly + AnyCPU + prompt + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + AllRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + AllRules.ruleset + + + bin\x86\commercial\ + TRACE + true + pdbonly + x86 + prompt + AllRules.ruleset + + + bin\x86\commercial_64\ + TRACE + true + pdbonly + x86 + prompt + + + + ..\Microsoft.Solver.Foundation.dll + + + False + ..\Microsoft.Z3.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Utils.cs b/examples/msf/SolverFoundation.Plugin.Z3/Utils.cs new file mode 100644 index 000000000..71c8647a1 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Utils.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; +using Microsoft.Z3; +using Microsoft.SolverFoundation.Common; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + public class Utils + { + /// + /// Returns the Z3 term corresponding to the MSF rational number. + /// + /// The MSF rational + /// The Z3 term + public static ArithExpr GetNumeral(Context context, Rational rational, Sort sort = null) + { + try + { + sort = rational.IsInteger() ? ((Sort)context.IntSort) : (sort == null ? (Sort)context.RealSort : sort); + return (ArithExpr)context.MkNumeral(rational.ToString(), sort); + } + catch (Z3Exception e) + { + Console.Error.WriteLine("Conversion of {0} failed:\n {1}", rational, e); + throw new NotSupportedException(); + } + } + + private static long BASE = 10 ^ 18; + + private static Rational ToRational(System.Numerics.BigInteger bi) + { + if (System.Numerics.BigInteger.Abs(bi) <= BASE) + { + return (Rational)((long)bi); + } + return BASE * ToRational(bi / BASE) + ToRational(bi % BASE); + } + + public static Rational ToRational(IntNum i) + { + return ToRational(i.BigInteger); + } + + public static Rational ToRational(RatNum r) + { + return ToRational(r.BigIntNumerator) / ToRational(r.BigIntDenominator); + } + + public static Rational ToRational(Expr expr) + { + Debug.Assert(expr is ArithExpr, "Only accept ArithExpr for now."); + var e = expr as ArithExpr; + + if (e is IntNum) + { + Debug.Assert(expr.IsIntNum, "Number should be an integer."); + return ToRational(expr as IntNum); + } + + if (e is RatNum) + { + Debug.Assert(expr.IsRatNum, "Number should be a rational."); + return ToRational(expr as RatNum); + } + + if (e.IsAdd) + { + Rational r = Rational.Zero; + foreach (var arg in e.Args) + { + r += ToRational(arg); + } + return r; + } + + if (e.IsMul) + { + Rational r = Rational.One; + foreach (var arg in e.Args) + { + r *= ToRational(arg); + } + return r; + } + + if (e.IsUMinus) + { + return -ToRational(e.Args[0]); + } + + if (e.IsDiv) + { + return ToRational(e.Args[0]) / ToRational(e.Args[1]); + } + + if (e.IsSub) + { + Rational r = ToRational(e.Args[0]); + for (int i = 1; i < e.Args.Length; ++i) + { + r -= ToRational(e.Args[i]); + } + return r; + } + + if (e.IsConst && e.FuncDecl.Name.ToString() == "oo") + { + return Rational.PositiveInfinity; + } + + if (e.IsConst && e.FuncDecl.Name.ToString() == "epsilon") + { + return Rational.One/Rational.PositiveInfinity; + } + + Debug.Assert(false, "Should not happen"); + return Rational.One; + } + } +} diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Z3BaseDirective.cs b/examples/msf/SolverFoundation.Plugin.Z3/Z3BaseDirective.cs new file mode 100644 index 000000000..e1403f698 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Z3BaseDirective.cs @@ -0,0 +1,101 @@ +using System; +using System.Text; +using Microsoft.SolverFoundation.Services; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + /// + /// Combining objective functions + /// + public enum OptimizationKind + { + Lexicographic, + BoundingBox, + ParetoOptimal + }; + + /// + /// Algorithm for solving cardinality constraints + /// + public enum CardinalityAlgorithm + { + FuMalik, + CoreMaxSAT + } + + /// + /// Algorithm for solving pseudo-boolean constraints + /// + public enum PseudoBooleanAlgorithm + { + WeightedMaxSAT, + IterativeWeightedMaxSAT, + BisectionWeightedMaxSAT, + WeightedPartialMaxSAT2 + } + + /// + /// Strategy for solving arithmetic optimization + /// + public enum ArithmeticStrategy + { + Basic, + Farkas + } + + public abstract class Z3BaseDirective : Directive + { + protected OptimizationKind _optKind; + protected CardinalityAlgorithm _cardAlgorithm; + protected PseudoBooleanAlgorithm _pboAlgorithm; + protected ArithmeticStrategy _arithStrategy; + + protected string _smt2LogFile; + + public Z3BaseDirective() + { + Arithmetic = Arithmetic.Exact; + } + + public OptimizationKind OptKind + { + get { return _optKind; } + set { _optKind = value; } + } + + public CardinalityAlgorithm CardinalityAlgorithm + { + get { return _cardAlgorithm; } + set { _cardAlgorithm = value; } + } + + public PseudoBooleanAlgorithm PseudoBooleanAlgorithm + { + get { return _pboAlgorithm; } + set { _pboAlgorithm = value; } + } + + public ArithmeticStrategy ArithmeticStrategy + { + get { return _arithStrategy; } + set { _arithStrategy = value; } + } + + public string SMT2LogFile + { + get { return _smt2LogFile; } + set { _smt2LogFile = value; } + } + + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append(this.GetType().Name); + sb.Append("("); + sb.AppendFormat("OptKind: {0}, ", _optKind); + sb.AppendFormat("SMT2LogFile: {0}", _smt2LogFile); + sb.Append(")"); + return sb.ToString(); + } + } +} diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Z3BaseParams.cs b/examples/msf/SolverFoundation.Plugin.Z3/Z3BaseParams.cs new file mode 100644 index 000000000..6585181ec --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Z3BaseParams.cs @@ -0,0 +1,103 @@ +using Microsoft.SolverFoundation.Services; +using System; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + /// + /// Implementation of the solver parameters for Z3 + /// + public class Z3BaseParams : ISolverParameters + { + #region Private Members + + /// The abort method we can call (defaults to always false) + protected Func _queryAbortFunction = delegate() { return false; }; + + /// The directive to use + protected Directive _directive = null; + + protected OptimizationKind _optKind; + protected CardinalityAlgorithm _cardAlgorithm; + protected PseudoBooleanAlgorithm _pboAlgorithm; + protected ArithmeticStrategy _arithStrategy; + + protected string _smt2LogFile; + + #endregion Private Members + + #region Construction + + public Z3BaseParams() { } + + public Z3BaseParams(Directive directive) + { + _directive = directive; + + var z3Directive = directive as Z3BaseDirective; + if (z3Directive != null) + { + _optKind = z3Directive.OptKind; + _cardAlgorithm = z3Directive.CardinalityAlgorithm; + _pboAlgorithm = z3Directive.PseudoBooleanAlgorithm; + _arithStrategy = z3Directive.ArithmeticStrategy; + _smt2LogFile = z3Directive.SMT2LogFile; + } + } + + public Z3BaseParams(Func queryAbortFunction) + { + _queryAbortFunction = queryAbortFunction; + } + + public Z3BaseParams(Z3BaseParams z3Parameters) + { + _queryAbortFunction = z3Parameters._queryAbortFunction; + } + + #endregion Construction + + #region ISolverParameters Members + + /// + /// Getter for the abort method + /// + public Func QueryAbort + { + get { return _queryAbortFunction; } + set { _queryAbortFunction = value; } + } + + public OptimizationKind OptKind + { + get { return _optKind; } + set { _optKind = value; } + } + + public CardinalityAlgorithm CardinalityAlgorithm + { + get { return _cardAlgorithm; } + set { _cardAlgorithm = value; } + } + + public PseudoBooleanAlgorithm PseudoBooleanAlgorithm + { + get { return _pboAlgorithm; } + set { _pboAlgorithm = value; } + } + + public ArithmeticStrategy ArithmeticStrategy + { + get { return _arithStrategy; } + set { _arithStrategy = value; } + } + + public string SMT2LogFile + { + get { return _smt2LogFile; } + set { _smt2LogFile = value; } + } + + #endregion + } + +} \ No newline at end of file diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Z3BaseSolver.cs b/examples/msf/SolverFoundation.Plugin.Z3/Z3BaseSolver.cs new file mode 100644 index 000000000..54e3893f0 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Z3BaseSolver.cs @@ -0,0 +1,381 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.IO; +using System.Linq; +using System.Text; +using System.Diagnostics; +using Microsoft.Z3; +using Microsoft.SolverFoundation.Common; +using Microsoft.SolverFoundation.Services; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + internal enum Z3Result + { + Optimal, + LocalOptimal, + Feasible, + Interrupted, + Infeasible + } + + /// + /// The basic solver class to take care of transformation from an MSF instance to an Z3 instance + /// + internal class Z3BaseSolver + { + /// Representing MSF model + private IRowVariableModel _model; + + /// The Z3 solver we are currently using + private Context _context = null; + + /// Default optimization solver + private Optimize _optSolver = null; + + /// Marks when we are inside the Solve() method + private bool _isSolving = false; + + /// A map from MSF variable ids to Z3 variables + private Dictionary _variables = new Dictionary(); + + /// A map from MSF variable ids to Z3 goal ids + private Dictionary _goals = new Dictionary(); + + internal Z3BaseSolver(IRowVariableModel model) + { + _model = model; + } + + internal Context Context + { + get { return _context; } + } + + internal Dictionary Variables + { + get { return _variables; } + } + + internal Dictionary Goals + { + get { return _goals; } + } + + /// + /// Destructs a currently active Z3 solver and the associated data. + /// + internal void DestructSolver(bool checkInSolve) + { + if (_context != null) + { + if (checkInSolve && !_isSolving) + { + _variables.Clear(); + if (!_isSolving) + { + _optSolver.Dispose(); + _context.Dispose(); + } + } + else + { + Console.Error.WriteLine("Z3 destruction is invoked while in Solving phase."); + } + } + } + + /// + /// Constructs a Z3 solver to be used. + /// + internal void ConstructSolver(Z3BaseParams parameters) + { + // If Z3 is there already, kill it + if (_context != null) + { + DestructSolver(false); + } + + _context = new Context(); + _optSolver = _context.MkOptimize(); + var p = _context.MkParams(); + + switch (parameters.OptKind) + { + case OptimizationKind.BoundingBox: + p.Add("priority", _context.MkSymbol("box")); + break; + case OptimizationKind.Lexicographic: + p.Add("priority", _context.MkSymbol("lex")); + break; + case OptimizationKind.ParetoOptimal: + p.Add("priority", _context.MkSymbol("pareto")); + break; + default: + Debug.Assert(false, String.Format("Unknown optimization option {0}", parameters.OptKind)); + break; + } + + switch (parameters.CardinalityAlgorithm) + { + case CardinalityAlgorithm.FuMalik: + p.Add("maxsat_engine", _context.MkSymbol("fu_malik")); + break; + case CardinalityAlgorithm.CoreMaxSAT: + p.Add("maxsat_engine", _context.MkSymbol("core_maxsat")); + break; + default: + Debug.Assert(false, String.Format("Unknown cardinality algorithm option {0}", parameters.CardinalityAlgorithm)); + break; + } + + switch (parameters.PseudoBooleanAlgorithm) + { + case PseudoBooleanAlgorithm.WeightedMaxSAT: + p.Add("wmaxsat_engine", _context.MkSymbol("wmax")); + break; + case PseudoBooleanAlgorithm.IterativeWeightedMaxSAT: + p.Add("wmaxsat_engine", _context.MkSymbol("iwmax")); + break; + case PseudoBooleanAlgorithm.BisectionWeightedMaxSAT: + p.Add("wmaxsat_engine", _context.MkSymbol("bwmax")); + break; + case PseudoBooleanAlgorithm.WeightedPartialMaxSAT2: + p.Add("wmaxsat_engine", _context.MkSymbol("wpm2")); + break; + default: + Debug.Assert(false, String.Format("Unknown pseudo-boolean algorithm option {0}", parameters.PseudoBooleanAlgorithm)); + break; + } + + switch (parameters.ArithmeticStrategy) + { + case ArithmeticStrategy.Basic: + p.Add("engine", _context.MkSymbol("basic")); + break; + case ArithmeticStrategy.Farkas: + p.Add("engine", _context.MkSymbol("farkas")); + break; + default: + Debug.Assert(false, String.Format("Unknown arithmetic strategy option {0}", parameters.ArithmeticStrategy)); + break; + } + + _optSolver.Parameters = p; + } + + internal ArithExpr GetVariable(int vid) + { + Expr variable; + if (!_variables.TryGetValue(vid, out variable)) + { + AddVariable(vid); + variable = _variables[vid]; + } + return (ArithExpr)variable; + } + + internal void AssertBool(BoolExpr row) + { + _optSolver.Assert(row); + } + + internal void AssertArith(int vid, ArithExpr variable) + { + // Get the bounds on the row + Rational lower, upper; + _model.GetBounds(vid, out lower, out upper); + + // Case of equality + if (lower == upper) + { + // Create the equality term + Expr eqConst = GetNumeral(lower, variable.Sort); + BoolExpr constraint = _context.MkEq(eqConst, variable); + // Assert the constraint + _optSolver.Assert(constraint); + } + else + { + // If upper bound is finite assert the upper bound constraint + if (lower.IsFinite) + { + // Create the lower Bound constraint + ArithExpr lowerTerm = GetNumeral(lower, variable.Sort); + BoolExpr constraint = _context.MkLe(lowerTerm, variable); + // Assert the constraint + _optSolver.Assert(constraint); + } + // If lower bound is finite assert the lower bound constraint + if (upper.IsFinite) + { + // Create the upper bound constraint + ArithExpr upperTerm = GetNumeral(upper, variable.Sort); + BoolExpr constraint = _context.MkGe(upperTerm, variable); + // Assert the constraint + _optSolver.Assert(constraint); + } + } + } + + /// + /// Adds a MSF variable with the coresponding assertion to the Z3 variables. + /// + /// The MSF id of the variable + internal void AddVariable(int vid) + { + // Is the variable an integer + bool isInteger = _model.GetIntegrality(vid); + + // Construct the sort we will be using + Sort sort = isInteger ? (Sort)_context.IntSort : (Sort)_context.RealSort; + + // Get the variable key + object key = _model.GetKeyFromIndex(vid); + + // Try to construct the name + string name; + if (key != null) name = String.Format("x_{0}_{1}", key, vid); + else name = String.Format("x_{0}", vid); + ArithExpr variable = (ArithExpr)_context.MkConst(name, sort); + + // Create the variable and add it to the map + Debug.Assert(!_variables.ContainsKey(vid), "Variable names should be unique."); + _variables.Add(vid, variable); + + AssertArith(vid, variable); + } + + internal ArithExpr GetNumeral(Rational rational, Sort sort = null) + { + return Utils.GetNumeral(_context, rational, sort); + } + + internal void Solve(Z3BaseParams parameters, IEnumerable modelGoals, + Action addRow, Func mkGoalRow, Action setResult) + { + _variables.Clear(); + _goals.Clear(); + + try + { + // Mark that we are in solving phase + _isSolving = true; + + // Construct Z3 + ConstructSolver(parameters); + + // Add all the variables + foreach (int vid in _model.VariableIndices) + { + AddVariable(vid); + } + + // Add all the rows + foreach (int rid in _model.RowIndices) + { + addRow(rid); + } + + // Add enabled goals to optimization problem + foreach (IGoal g in modelGoals) + { + if (!g.Enabled) continue; + + ArithExpr gr = mkGoalRow(g.Index); + if (g.Minimize) + _goals.Add(g, _optSolver.MkMinimize(gr)); + else + _goals.Add(g, _optSolver.MkMaximize(gr)); + } + + if (_goals.Any() && parameters.SMT2LogFile != null) + { + Debug.WriteLine("Dumping SMT2 benchmark to log file..."); + File.WriteAllText(parameters.SMT2LogFile, _optSolver.ToString()); + } + + bool aborted = parameters.QueryAbort(); + + if (!aborted) + { + // Start the abort thread + AbortWorker abortWorker = new AbortWorker(_context, parameters.QueryAbort); + Thread abortThread = new Thread(abortWorker.Start); + abortThread.Start(); + + // Now solve the problem + Status status = _optSolver.Check(); + + // Stop the abort thread + abortWorker.Stop(); + abortThread.Join(); + + switch (status) + { + case Status.SATISFIABLE: + Microsoft.Z3.Model model = _optSolver.Model; + Debug.Assert(model != null, "Should be able to get Z3 model."); + // Remember the solution values + foreach (KeyValuePair pair in _variables) + { + var value = Utils.ToRational(model.Eval(pair.Value, true)); + _model.SetValue(pair.Key, value); + } + // Remember all objective values + foreach (var pair in _goals) + { + var optimalValue = Utils.ToRational(_optSolver.GetUpper(pair.Value)); + _model.SetValue(pair.Key.Index, optimalValue); + } + model.Dispose(); + setResult(_goals.Any() ? Z3Result.Optimal : Z3Result.Feasible); + break; + case Status.UNSATISFIABLE: + setResult(Z3Result.Infeasible); + break; + case Status.UNKNOWN: + if (abortWorker.Aborted) + { + Microsoft.Z3.Model subOptimalModel = _optSolver.Model; + if (subOptimalModel != null && subOptimalModel.NumConsts != 0) + { + // Remember the solution values + foreach (KeyValuePair pair in _variables) + { + var value = Utils.ToRational(subOptimalModel.Eval(pair.Value, true)); + _model.SetValue(pair.Key, value); + } + // Remember all objective values + foreach (var pair in _goals) + { + var optimalValue = Utils.ToRational(_optSolver.GetUpper(pair.Value)); + _model.SetValue(pair.Key.Index, optimalValue); + } + subOptimalModel.Dispose(); + + setResult(Z3Result.LocalOptimal); + } + else + setResult(Z3Result.Infeasible); + } + else + setResult(Z3Result.Interrupted); + break; + default: + Debug.Assert(false, "Unrecognized Z3 Status"); + break; + } + } + } + finally + { + _isSolving = false; + } + + // Now kill Z3 + DestructSolver(true); + } + } +} diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Z3MILPDirective.cs b/examples/msf/SolverFoundation.Plugin.Z3/Z3MILPDirective.cs new file mode 100644 index 000000000..69f9ff6c1 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Z3MILPDirective.cs @@ -0,0 +1,9 @@ +using Microsoft.SolverFoundation.Services; +using System; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + public class Z3MILPDirective : Z3BaseDirective + { + } +} diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Z3MILPParams.cs b/examples/msf/SolverFoundation.Plugin.Z3/Z3MILPParams.cs new file mode 100644 index 000000000..38bd9040a --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Z3MILPParams.cs @@ -0,0 +1,19 @@ +using Microsoft.SolverFoundation.Services; +using System; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + public class Z3MILPParams : Z3BaseParams + { + // Need these constructors for reflection done by plugin model + + public Z3MILPParams() : base() { } + + public Z3MILPParams(Directive directive) : base(directive) { } + + public Z3MILPParams(Func queryAbortFunction) : base(queryAbortFunction) { } + + public Z3MILPParams(Z3BaseParams z3Parameters) : base (z3Parameters) { } + } + +} \ No newline at end of file diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Z3MILPSolver.cs b/examples/msf/SolverFoundation.Plugin.Z3/Z3MILPSolver.cs new file mode 100644 index 000000000..b31f6de97 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Z3MILPSolver.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.IO; + +using Microsoft.Z3; +using Microsoft.SolverFoundation.Common; +using Microsoft.SolverFoundation.Services; +using Microsoft.SolverFoundation.Plugin; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + /// + /// The class is implementation of the MSF mixed linear programming solver + /// using the Microsoft Z3 solver as the backend. + /// + public class Z3MILPSolver : LinearModel, ILinearSolver, ILinearSolution, IReportProvider + { + #region Private members + + private LinearResult _result; + private LinearSolutionQuality _solutionQuality; + private Z3BaseSolver _solver; + + #endregion Private members + + #region Solver construction and destruction + + /// Constructor that initializes the base clases + public Z3MILPSolver() : base(null) + { + _result = LinearResult.Feasible; + _solver = new Z3BaseSolver(this); + } + + /// Constructor that initializes the base clases + public Z3MILPSolver(ISolverEnvironment context) : this() { } + + /// + /// Shutdown can be called when when the solver is not active, i.e. + /// when it is done with Solve() or it has gracefully returns from Solve() + /// after an abort. + /// + public void Shutdown() { _solver.DestructSolver(true); } + + #endregion Solver construction and destruction + + #region Obtaining information about the solution + + public ILinearSolverReport GetReport(LinearSolverReportType reportType) + { + // We don't support sensitivity report + return null; + } + + #endregion Obtaining information about the solution + + #region Construction of the problem + + /// + /// Get corresponding Z3 formula of a MSF row. + /// + /// The MSF row id + private ArithExpr MkGoalRow(int rid) + { + // Start with the 0 term + List row = new List(); + + // Now, add all the entries of this row + foreach (LinearEntry entry in GetRowEntries(rid)) + { + // Get the variable and constant in the row + ArithExpr e = _solver.GetVariable(entry.Index); + if (!entry.Value.IsOne) + { + e = _solver.Context.MkMul(_solver.GetNumeral(entry.Value, e.Sort), e); + } + row.Add(e); + } + switch (row.Count) + { + case 0: return _solver.GetNumeral(new Rational()); + case 1: return row[0]; + default: return _solver.Context.MkAdd(row.ToArray()); + } + } + + /// + /// Adds a MSF row to the Z3 assertions. + /// + /// The MSF row id + private void AddRow(int rid) + { + // Start with the 0 term + ArithExpr row = MkGoalRow(rid); + _solver.AssertArith(rid, row); + } + + /// + /// Set results based on internal solver status + /// + private void SetResult(Z3Result status) + { + switch (status) + { + case Z3Result.Optimal: + _result = LinearResult.Optimal; + _solutionQuality = LinearSolutionQuality.Exact; + break; + case Z3Result.LocalOptimal: + _result = LinearResult.Feasible; + _solutionQuality = LinearSolutionQuality.Approximate; + break; + case Z3Result.Feasible: + _result = LinearResult.Feasible; + _solutionQuality = LinearSolutionQuality.Exact; + break; + case Z3Result.Infeasible: + _result = LinearResult.InfeasiblePrimal; + _solutionQuality = LinearSolutionQuality.None; + break; + case Z3Result.Interrupted: + _result = LinearResult.Interrupted; + _solutionQuality = LinearSolutionQuality.None; + break; + default: + Debug.Assert(false, "Unrecognized Z3 Result"); + break; + } + } + + #endregion Construction of the problem + + #region Solving the problem + + /// + /// Starts solving the problem using the Z3 solver. + /// + /// Parameters to the solver + /// The solution to the problem + public ILinearSolution Solve(ISolverParameters parameters) + { + // Get the Z3 parameters + var z3Params = parameters as Z3BaseParams; + Debug.Assert(z3Params != null, "Parameters should be an instance of Z3BaseParams."); + + _solver.Solve(z3Params, Goals, AddRow, MkGoalRow, SetResult); + + return this; + } + + #endregion Solving the problem + + #region ILinearSolution Members + + public Rational GetSolutionValue(int goalIndex) + { + var goal = Goals.ElementAt(goalIndex); + Debug.Assert(goal != null, "Goal should be an element of the goal list."); + return GetValue(goal.Index); + } + + public void GetSolvedGoal(int goalIndex, out object key, out int vid, out bool minimize, out bool optimal) + { + var goal = Goals.ElementAt(goalIndex); + Debug.Assert(goal != null, "Goal should be an element of the goal list."); + key = goal.Key; + vid = goal.Index; + minimize = goal.Minimize; + optimal = _result == LinearResult.Optimal; + } + + // LpResult is LP relaxation assignment. + + public LinearResult LpResult + { + get { return _result; } + } + + public Rational MipBestBound + { + get + { + Debug.Assert(GoalCount > 0, "MipBestBound is only applicable for optimization instances."); + return GetSolutionValue(0); + } + } + + public LinearResult MipResult + { + get { return _result; } + } + + public LinearResult Result + { + get { return _result; } + } + + public LinearSolutionQuality SolutionQuality + { + get { return _solutionQuality; } + } + + public int SolvedGoalCount + { + get { return GoalCount; } + } + + #endregion + + public Report GetReport(SolverContext context, Solution solution, SolutionMapping solutionMapping) + { + LinearSolutionMapping lpSolutionMapping = solutionMapping as LinearSolutionMapping; + if (lpSolutionMapping == null && solutionMapping != null) + throw new ArgumentException("solutionMapping is not a LinearSolutionMapping", "solutionMapping"); + return new Z3LinearSolverReport(context, this, solution, lpSolutionMapping); + } + } + + /// + /// Class implementing the LinearReport. + /// + public class Z3LinearSolverReport : LinearReport + { + public Z3LinearSolverReport(SolverContext context, ISolver solver, Solution solution, LinearSolutionMapping solutionMapping) + : base(context, solver, solution, solutionMapping) { + } + } +} diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Z3TermDirective.cs b/examples/msf/SolverFoundation.Plugin.Z3/Z3TermDirective.cs new file mode 100644 index 000000000..12dcb6e84 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Z3TermDirective.cs @@ -0,0 +1,9 @@ +using Microsoft.SolverFoundation.Services; +using System; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + public class Z3TermDirective : Z3BaseDirective + { + } +} diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Z3TermParams.cs b/examples/msf/SolverFoundation.Plugin.Z3/Z3TermParams.cs new file mode 100644 index 000000000..48a90afe1 --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Z3TermParams.cs @@ -0,0 +1,17 @@ +using Microsoft.SolverFoundation.Services; +using System; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + public class Z3TermParams : Z3BaseParams + { + public Z3TermParams() : base() { } + + public Z3TermParams(Directive directive) : base(directive) { } + + public Z3TermParams(Func queryAbortFunction) : base(queryAbortFunction) { } + + public Z3TermParams(Z3BaseParams z3Parameters) : base(z3Parameters) { } + } + +} \ No newline at end of file diff --git a/examples/msf/SolverFoundation.Plugin.Z3/Z3TermSolver.cs b/examples/msf/SolverFoundation.Plugin.Z3/Z3TermSolver.cs new file mode 100644 index 000000000..3317b9a4d --- /dev/null +++ b/examples/msf/SolverFoundation.Plugin.Z3/Z3TermSolver.cs @@ -0,0 +1,382 @@ +using System; +using System.Threading; +using System.Globalization; +using System.Collections.Generic; +using Microsoft.SolverFoundation.Common; +using Microsoft.SolverFoundation.Properties; +using Microsoft.SolverFoundation.Solvers; +using Microsoft.SolverFoundation.Services; +using Microsoft.Z3; +using System.Linq; +using System.Diagnostics; +using System.IO; + +namespace Microsoft.SolverFoundation.Plugin.Z3 +{ + /// + /// The class is implementation of the MSF constraint solver + /// using the Microsoft Z3 solver as the backend. + /// This solver supports Int, Real constraints and their arbitrary boolean combinations. + /// + public class Z3TermSolver : TermModel, ITermSolver, INonlinearSolution, IReportProvider + { + private NonlinearResult _result; + private Z3BaseSolver _solver; + + /// Constructor that initializes the base clases + public Z3TermSolver() : base(null) + { + _solver = new Z3BaseSolver(this); + } + + /// Constructor that initializes the base clases + public Z3TermSolver(ISolverEnvironment context) : this() { } + + /// + /// Shutdown can be called when when the solver is not active, i.e. + /// when it is done with Solve() or it has gracefully returns from Solve() + /// after an abort. + /// + public void Shutdown() { _solver.DestructSolver(true); } + + private BoolExpr MkBool(int rid) + { + var context = _solver.Context; + + if (IsConstant(rid)) + { + Rational lower, upper; + GetBounds(rid, out lower, out upper); + Debug.Assert(lower == upper); + if (lower.IsZero) return context.MkFalse(); + return context.MkTrue(); + } + if (IsOperation(rid)) + { + BoolExpr[] children; + ArithExpr[] operands; + TermModelOperation op = GetOperation(rid); + switch(op) { + case TermModelOperation.And: + Debug.Assert(GetOperandCount(rid) >= 2, "Conjunction requires at least two operands."); + children = (GetOperands(rid)).Select(x => MkBool(x)).ToArray(); + return context.MkAnd(children); + case TermModelOperation.Or: + Debug.Assert(GetOperandCount(rid) >= 2, "Disjunction requires at least two operands."); + children = (GetOperands(rid)).Select(x => MkBool(x)).ToArray(); + return context.MkOr(children); + case TermModelOperation.Not: + Debug.Assert(GetOperandCount(rid) == 1, "Negation is unary."); + return context.MkNot(MkBool(GetOperand(rid, 0))); + case TermModelOperation.If: + Debug.Assert(GetOperandCount(rid) == 3, "If is ternary."); + BoolExpr b = MkBool(GetOperand(rid, 0)); + Expr x1 = MkBool(GetOperand(rid, 1)); + Expr x2 = MkBool(GetOperand(rid, 2)); + return (BoolExpr)context.MkITE(b, x1, x2); + case TermModelOperation.Unequal: + Debug.Assert(GetOperandCount(rid) >= 2, "Distinct should have at least two operands."); + return context.MkDistinct((GetOperands(rid)).Select(x => MkTerm(x)).ToArray()); + case TermModelOperation.Greater: + case TermModelOperation.Less: + case TermModelOperation.GreaterEqual: + case TermModelOperation.LessEqual: + case TermModelOperation.Equal: + Debug.Assert(GetOperandCount(rid) >= 2, "Comparison should have at least two operands."); + operands = (GetOperands(rid)).Select(x => MkTerm(x)).ToArray(); + return ReduceComparison(GetOperation(rid), operands); + case TermModelOperation.Identity: + Debug.Assert(GetOperandCount(rid) == 1, "Identity takes exactly one operand."); + return MkBool(GetOperand(rid, 0)); + default: + return context.MkEq(MkTerm(rid), _solver.GetNumeral(Rational.One)); + } + } + return context.MkEq(MkTerm(rid), _solver.GetNumeral(Rational.One)); + } + + private ArithExpr MkBoolToArith(BoolExpr e) + { + var context = _solver.Context; + return (ArithExpr)context.MkITE(e, _solver.GetNumeral(Rational.One), _solver.GetNumeral(Rational.Zero)); + } + + private ArithExpr MkTerm(int rid) + { + var context = _solver.Context; + + if (IsConstant(rid)) + { + Rational lower, upper; + GetBounds(rid, out lower, out upper); + Debug.Assert(lower == upper); + return _solver.GetNumeral(lower); + } + else if (IsOperation(rid)) + { + ArithExpr[] operands; + TermModelOperation op = GetOperation(rid); + switch(op) + { + case TermModelOperation.And: + case TermModelOperation.Or: + case TermModelOperation.Not: + case TermModelOperation.Unequal: + case TermModelOperation.Greater: + case TermModelOperation.Less: + case TermModelOperation.GreaterEqual: + case TermModelOperation.LessEqual: + case TermModelOperation.Equal: + return MkBoolToArith(MkBool(rid)); + case TermModelOperation.If: + Debug.Assert(GetOperandCount(rid) == 3, "If is ternary."); + BoolExpr b = MkBool(GetOperand(rid, 0)); + Expr x1 = MkTerm(GetOperand(rid, 1)); + Expr x2 = MkTerm(GetOperand(rid, 2)); + return (ArithExpr)context.MkITE(b, x1, x2); + case TermModelOperation.Plus: + Debug.Assert(GetOperandCount(rid) >= 2, "Plus takes at least two operands."); + operands = (GetOperands(rid)).Select(x => MkTerm(x)).ToArray(); + return context.MkAdd(operands); + case TermModelOperation.Minus: + Debug.Assert(GetOperandCount(rid) == 1, "Minus takes exactly one operand."); + return context.MkUnaryMinus(MkTerm(GetOperand(rid, 0))); + case TermModelOperation.Times: + Debug.Assert(GetOperandCount(rid) >= 2, "Times requires at least two operands."); + operands = (GetOperands(rid)).Select(x => MkTerm(x)).ToArray(); + return context.MkMul(operands); + case TermModelOperation.Identity: + Debug.Assert(GetOperandCount(rid) == 1, "Identity takes exactly one operand."); + return MkTerm(GetOperand(rid, 0)); + case TermModelOperation.Abs: + Debug.Assert(GetOperandCount(rid) == 1, "Abs takes exactly one operand."); + ArithExpr e = MkTerm(GetOperand(rid, 0)); + ArithExpr minusE = context.MkUnaryMinus(e); + ArithExpr zero = _solver.GetNumeral(Rational.Zero); + return (ArithExpr)context.MkITE(context.MkGe(e, zero), e, minusE); + default: + Console.Error.WriteLine("{0} operation isn't supported.", op); + throw new NotSupportedException(); + } + } + else + { + return _solver.GetVariable(rid); + } + } + + private BoolExpr ReduceComparison(TermModelOperation type, ArithExpr[] operands) + { + var context = _solver.Context; + Debug.Assert(operands.Length >= 2); + Func mkComparison; + switch (type) + { + case TermModelOperation.Greater: + mkComparison = (x, y) => context.MkGt(x, y); + break; + case TermModelOperation.Less: + mkComparison = (x, y) => context.MkLt(x, y); + break; + case TermModelOperation.GreaterEqual: + mkComparison = (x, y) => context.MkGe(x, y); + break; + case TermModelOperation.LessEqual: + mkComparison = (x, y) => context.MkLe(x, y); + break; + case TermModelOperation.Equal: + mkComparison = (x, y) => context.MkEq(x, y); + break; + default: + throw new NotSupportedException(); + } + + BoolExpr current = mkComparison(operands[0], operands[1]); + for (int i = 1; i < operands.Length - 1; ++i) + current = context.MkAnd(current, mkComparison(operands[i], operands[i + 1])); + return current; + } + + private bool IsBoolRow(int rid) + { + Rational lower, upper; + GetBounds(rid, out lower, out upper); + + return lower == upper && lower.IsOne && IsBoolTerm(rid); + } + + private bool IsBoolTerm(int rid) + { + if (IsConstant(rid)) + { + Rational lower, upper; + GetBounds(rid, out lower, out upper); + Debug.Assert(lower == upper); + return lower.IsOne || lower.IsZero; + } + if (IsOperation(rid)) + { + TermModelOperation op = GetOperation(rid); + switch (op) + { + case TermModelOperation.And: + case TermModelOperation.Or: + case TermModelOperation.Not: + case TermModelOperation.LessEqual: + case TermModelOperation.Less: + case TermModelOperation.Greater: + case TermModelOperation.GreaterEqual: + case TermModelOperation.Unequal: + case TermModelOperation.Equal: + return true; + case TermModelOperation.If: + return IsBoolTerm(GetOperand(rid, 1)) && + IsBoolTerm(GetOperand(rid, 2)); + case TermModelOperation.Identity: + return IsBoolTerm(GetOperand(rid, 0)); + default: + return false; + } + } + return false; + } + + /// + /// Adds a MSF row to the Z3 assertions. + /// + /// The MSF row id + private void AddRow(int rid) + { + if (IsConstant(rid)) + return; + + if (IsBoolRow(rid)) + { + _solver.AssertBool(MkBool(rid)); + return; + } + // Start with the 0 term + ArithExpr row = MkTerm(rid); + _solver.AssertArith(rid, row); + } + + private TermModelOperation[] _supportedOperations = + { TermModelOperation.And, + TermModelOperation.Or, + TermModelOperation.Not, + TermModelOperation.Unequal, + TermModelOperation.Greater, + TermModelOperation.Less, + TermModelOperation.GreaterEqual, + TermModelOperation.LessEqual, + TermModelOperation.Equal, + TermModelOperation.If, + TermModelOperation.Plus, + TermModelOperation.Minus, + TermModelOperation.Times, + TermModelOperation.Identity, + TermModelOperation.Abs }; + + /// + /// Gets the operations supported by the solver. + /// + /// All the TermModelOperations supported by the solver. + public IEnumerable SupportedOperations + { + get { return _supportedOperations; } + } + + /// + /// Set results based on internal solver status + /// + private void SetResult(Z3Result status) + { + switch (status) + { + case Z3Result.Optimal: + _result = NonlinearResult.Optimal; + break; + case Z3Result.LocalOptimal: + _result = NonlinearResult.LocalOptimal; + break; + case Z3Result.Feasible: + _result = NonlinearResult.Feasible; + break; + case Z3Result.Infeasible: + _result = NonlinearResult.Infeasible; + break; + case Z3Result.Interrupted: + _result = NonlinearResult.Interrupted; + break; + default: + Debug.Assert(false, "Unrecognized Z3 Result"); + break; + } + } + + /// + /// Starts solving the problem using the Z3 solver. + /// + /// Parameters to the solver + /// The solution to the problem + public INonlinearSolution Solve(ISolverParameters parameters) + { + // Get the Z3 parameters + var z3Params = parameters as Z3BaseParams; + Debug.Assert(z3Params != null, "Parameters should be an instance of Z3BaseParams."); + + _solver.Solve(z3Params, Goals, AddRow, MkTerm, SetResult); + + return this; + } + + double INonlinearSolution.GetValue(int vid) + { + Debug.Assert(_solver.Variables.ContainsKey(vid), "This index should correspond to a variable."); + return GetValue(vid).ToDouble(); + } + + public int SolvedGoalCount + { + get { return GoalCount; } + } + + public double GetSolutionValue(int goalIndex) + { + var goal = Goals.ElementAt(goalIndex); + Debug.Assert(goal != null, "Goal should be an element of the goal list."); + return GetValue(goal.Index).ToDouble(); + } + + public void GetSolvedGoal(int goalIndex, out object key, out int vid, out bool minimize, out bool optimal) + { + var goal = Goals.ElementAt(goalIndex); + Debug.Assert(goal != null, "Goal should be an element of the goal list."); + key = goal.Key; + vid = goal.Index; + minimize = goal.Minimize; + optimal = _result == NonlinearResult.Optimal; + } + + public NonlinearResult Result + { + get { return _result; } + } + + public Report GetReport(SolverContext context, Solution solution, SolutionMapping solutionMapping) + { + PluginSolutionMapping pluginSolutionMapping = solutionMapping as PluginSolutionMapping; + if (pluginSolutionMapping == null && solutionMapping != null) + throw new ArgumentException("solutionMapping is not a LinearSolutionMapping", "solutionMapping"); + return new Z3TermSolverReport(context, this, solution, pluginSolutionMapping); + } + } + + public class Z3TermSolverReport : Report + { + public Z3TermSolverReport(SolverContext context, ISolver solver, Solution solution, PluginSolutionMapping pluginSolutionMapping) + : base(context, solver, solution, pluginSolutionMapping) + { + } + } +} diff --git a/examples/msf/Validator/App.config b/examples/msf/Validator/App.config new file mode 100644 index 000000000..75e2872f1 --- /dev/null +++ b/examples/msf/Validator/App.config @@ -0,0 +1,60 @@ + + + +
+ + + + + + + + + + + + + + + + diff --git a/examples/msf/Validator/MicrosoftSolverFoundationForExcel.dll.config b/examples/msf/Validator/MicrosoftSolverFoundationForExcel.dll.config new file mode 100644 index 000000000..cd9dcad25 --- /dev/null +++ b/examples/msf/Validator/MicrosoftSolverFoundationForExcel.dll.config @@ -0,0 +1,58 @@ + + + +
+ + + + + + + + + + + + + diff --git a/examples/msf/Validator/Program.cs b/examples/msf/Validator/Program.cs new file mode 100644 index 000000000..758c65c78 --- /dev/null +++ b/examples/msf/Validator/Program.cs @@ -0,0 +1,194 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections.Generic; +using Microsoft.SolverFoundation.Common; +using Microsoft.SolverFoundation.Solvers; +using Microsoft.SolverFoundation.Plugin.Z3; +using Microsoft.SolverFoundation.Services; +using System.Text; + +namespace Validator +{ + class Program + { + static void LoadModel(SolverContext context, string fileName) + { + string ext = Path.GetExtension(fileName).ToLower(); + + if (ext == ".mps") + { + context.LoadModel(FileFormat.MPS, Path.GetFullPath(fileName)); + } + else if (ext == ".smps") + { + context.LoadModel(FileFormat.SMPS, Path.GetFullPath(fileName)); + } + else if (ext == ".oml") + { + context.LoadModel(FileFormat.OML, Path.GetFullPath(fileName)); + } + else + { + throw new NotSupportedException("This file format hasn't been supported."); + } + } + + static void ExecuteZ3(string fileName, Z3BaseDirective directive) + { + SolverContext context = SolverContext.GetContext(); + try + { + LoadModel(context, fileName); + + Solution solution = context.Solve(directive); + Report report = solution.GetReport(); + Console.Write("{0}", report); + } + catch (Exception e) + { + Console.WriteLine("Skipping unsolvable instance in {0} with error message '{1}'.", fileName, e.Message); + } + finally + { + context.ClearModel(); + } + } + + static void ConvertToSMT2(string fileName, Z3BaseDirective directive) + { + SolverContext context = SolverContext.GetContext(); + try + { + LoadModel(context, fileName); + + if (context.CurrentModel.Goals.Any()) + { + directive.SMT2LogFile = Path.ChangeExtension(fileName, ".smt2"); + context.Solve(() => true, directive); + } + } + catch (Exception e) + { + Console.WriteLine("Skipping unconvertable instance in {0} with error message '{1}'.", fileName, e.Message); + } + finally + { + context.ClearModel(); + } + } + + static void ValidateZ3(string fileName, Z3BaseDirective directive) + { + SolverContext context = SolverContext.GetContext(); + try + { + LoadModel(context, fileName); + + if (context.CurrentModel.Goals.Any()) + { + var msfDirective = (directive is Z3MILPDirective) ? (Directive)new MixedIntegerProgrammingDirective() { TimeLimit = 10000 } + : (Directive)new Directive() { TimeLimit = 10000 }; + var sol1 = context.Solve(msfDirective); + + Console.WriteLine("Solved the model using MSF."); + Console.Write("{0}", sol1.GetReport()); + var expectedGoals = sol1.Goals.Select(x => x.ToDouble()); + context.ClearModel(); + + context.LoadModel(FileFormat.OML, Path.GetFullPath(fileName)); + directive.SMT2LogFile = Path.ChangeExtension(fileName, ".smt2"); + var sol2 = context.Solve(directive); + //Console.Write("{0}", sol2.GetReport()); + var actualGoals = sol2.Goals.Select(x => x.ToDouble()); + + Console.WriteLine("Solved the model using Z3."); + var goalPairs = expectedGoals.Zip(actualGoals, (expected, actual) => new { expected, actual }).ToArray(); + bool validated = goalPairs.All(p => Math.Abs(p.expected - p.actual) <= 0.0001); + if (validated) + { + Console.WriteLine("INFO: Two solvers give approximately the same results."); + } + else + { + Console.Error.WriteLine("ERROR: Discrepancy found between results."); + if (!validated && File.Exists(directive.SMT2LogFile)) + { + var sb = new StringBuilder(); + for(int i = 0; i < goalPairs.Length; i++) + { + sb.AppendFormat("\n(echo \"Goal {0}: actual |-> {1:0.0000}, expected |-> {2:0.0000}\")", + i + 1, goalPairs[i].actual, goalPairs[i].expected); + } + Console.Error.WriteLine(sb.ToString()); + File.AppendAllText(directive.SMT2LogFile, sb.ToString()); + } + } + } + else + { + Console.WriteLine("Ignoring this instance without having any goal."); + } + } + catch (Exception e) + { + Console.WriteLine("Skipping unsolvable instance in {0} with error message '{1}'.", + fileName, e.Message); + } + finally + { + context.ClearModel(); + } + } + + static void Main(string[] args) + { + Z3BaseDirective directive = new Z3MILPDirective(); + + for (int i = 0; i < args.Length; ++i) { + if (args[i] == "-s" || args[i] == "-solve") + { + ExecuteZ3(args[i + 1], directive); + return; + } + if (args[i] == "-c" || args[i] == "-convert") + { + ConvertToSMT2(args[i + 1], directive); + return; + } + if (args[i] == "-v" || args[i] == "-validate") + { + ValidateZ3(args[i + 1], directive); + return; + } + if (args[i] == "-t" || args[i] == "-term") + { + directive = new Z3TermDirective(); + } + } + + if (args.Length > 0) + { + ExecuteZ3(args[0], directive); + return; + } + + Console.WriteLine(@" +Validator is a simple command line to migrate benchmarks from OML, MPS and SMPS to SMT2 formats. + +Commands: + -solve : solving the model using Z3 + -convert : converting the model into SMT2 format + -validate : validating by comparing results between Z3 and MSF solvers + -term : change the default Z3 MILP solver to Z3 Term solver + + where is any file with OML, MPS or SMPS extension. + +Examples: + Validator.exe -convert model.mps + Validator.exe -term -solve model.oml + +"); + } + } +} diff --git a/examples/msf/Validator/Properties/AssemblyInfo.cs b/examples/msf/Validator/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..eb2f8ed71 --- /dev/null +++ b/examples/msf/Validator/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("testSolver")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("testSolver")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c03c1084-d119-483f-80fe-c639eae75959")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/examples/msf/Validator/Validator.csproj b/examples/msf/Validator/Validator.csproj new file mode 100644 index 000000000..cfea3c80b --- /dev/null +++ b/examples/msf/Validator/Validator.csproj @@ -0,0 +1,123 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {54835857-129F-44C9-B529-A42158647B36} + Exe + Properties + Validator + Validator + v4.0 + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x86 + true + GlobalSuppressions.cs + prompt + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + true + GlobalSuppressions.cs + prompt + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\Microsoft.Solver.Foundation.dll + + + + + + + + + + + + + + + + + + + + + + {7340e664-f648-4ff7-89b2-f4da424996d3} + SolverFoundation.Plugin.Z3 + + + + + \ No newline at end of file diff --git a/examples/msf/Z3MSFPlugin.sln b/examples/msf/Z3MSFPlugin.sln new file mode 100644 index 000000000..c3af1dc22 --- /dev/null +++ b/examples/msf/Z3MSFPlugin.sln @@ -0,0 +1,125 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SolverFoundation.Plugin.Z3", "SolverFoundation.Plugin.Z3\SolverFoundation.Plugin.Z3.csproj", "{7340E664-F648-4FF7-89B2-F4DA424996D3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SolverFoundation.Plugin.Z3.Tests", "SolverFoundation.Plugin.Z3.Tests\SolverFoundation.Plugin.Z3.Tests.csproj", "{280AEE2F-1FDB-4A27-BE37-14DC154C873B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Validator", "Validator\Validator.csproj", "{54835857-129F-44C9-B529-A42158647B36}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F1E99540-BA5E-46DF-9E29-6146A309CD18}" + ProjectSection(SolutionItems) = preProject + README = README + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + commercial_64|Any CPU = commercial_64|Any CPU + commercial_64|Mixed Platforms = commercial_64|Mixed Platforms + commercial_64|x64 = commercial_64|x64 + commercial_64|x86 = commercial_64|x86 + commercial|Any CPU = commercial|Any CPU + commercial|Mixed Platforms = commercial|Mixed Platforms + commercial|x64 = commercial|x64 + commercial|x86 = commercial|x86 + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|Any CPU.ActiveCfg = commercial_64|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|Any CPU.Build.0 = commercial_64|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|Mixed Platforms.ActiveCfg = commercial_64|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|Mixed Platforms.Build.0 = commercial_64|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|x64.ActiveCfg = commercial_64|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|x86.ActiveCfg = commercial_64|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|x86.Build.0 = commercial_64|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|Any CPU.ActiveCfg = commercial|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|Any CPU.Build.0 = commercial|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|Mixed Platforms.ActiveCfg = commercial|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|Mixed Platforms.Build.0 = commercial|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|x64.ActiveCfg = commercial|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|x86.ActiveCfg = commercial|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|x86.Build.0 = commercial|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|x64.ActiveCfg = Debug|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|x86.ActiveCfg = Debug|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|x86.Build.0 = Debug|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|Any CPU.Build.0 = Release|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|Mixed Platforms.Build.0 = Release|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|x64.ActiveCfg = Release|Any CPU + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|x86.ActiveCfg = Release|x86 + {7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|x86.Build.0 = Release|x86 + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|Any CPU.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|Any CPU.Build.0 = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|Mixed Platforms.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|Mixed Platforms.Build.0 = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|x64.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|x86.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|Any CPU.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|Any CPU.Build.0 = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|Mixed Platforms.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|Mixed Platforms.Build.0 = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|x64.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|x86.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|x64.ActiveCfg = Debug|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|x86.ActiveCfg = Debug|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|x86.Build.0 = Debug|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|Any CPU.Build.0 = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|x64.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|x86.ActiveCfg = Release|Any CPU + {280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|x86.Build.0 = Release|Any CPU + {54835857-129F-44C9-B529-A42158647B36}.commercial_64|Any CPU.ActiveCfg = Release|Any CPU + {54835857-129F-44C9-B529-A42158647B36}.commercial_64|Any CPU.Build.0 = Release|Any CPU + {54835857-129F-44C9-B529-A42158647B36}.commercial_64|Mixed Platforms.ActiveCfg = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.commercial_64|Mixed Platforms.Build.0 = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.commercial_64|x64.ActiveCfg = Release|x64 + {54835857-129F-44C9-B529-A42158647B36}.commercial_64|x64.Build.0 = Release|x64 + {54835857-129F-44C9-B529-A42158647B36}.commercial_64|x86.ActiveCfg = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.commercial_64|x86.Build.0 = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.commercial|Any CPU.ActiveCfg = Release|Any CPU + {54835857-129F-44C9-B529-A42158647B36}.commercial|Any CPU.Build.0 = Release|Any CPU + {54835857-129F-44C9-B529-A42158647B36}.commercial|Mixed Platforms.ActiveCfg = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.commercial|Mixed Platforms.Build.0 = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.commercial|x64.ActiveCfg = Release|x64 + {54835857-129F-44C9-B529-A42158647B36}.commercial|x64.Build.0 = Release|x64 + {54835857-129F-44C9-B529-A42158647B36}.commercial|x86.ActiveCfg = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.commercial|x86.Build.0 = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54835857-129F-44C9-B529-A42158647B36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54835857-129F-44C9-B529-A42158647B36}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {54835857-129F-44C9-B529-A42158647B36}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {54835857-129F-44C9-B529-A42158647B36}.Debug|x64.ActiveCfg = Debug|x64 + {54835857-129F-44C9-B529-A42158647B36}.Debug|x64.Build.0 = Debug|x64 + {54835857-129F-44C9-B529-A42158647B36}.Debug|x86.ActiveCfg = Debug|x86 + {54835857-129F-44C9-B529-A42158647B36}.Debug|x86.Build.0 = Debug|x86 + {54835857-129F-44C9-B529-A42158647B36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54835857-129F-44C9-B529-A42158647B36}.Release|Any CPU.Build.0 = Release|Any CPU + {54835857-129F-44C9-B529-A42158647B36}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.Release|Mixed Platforms.Build.0 = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.Release|x64.ActiveCfg = Release|x64 + {54835857-129F-44C9-B529-A42158647B36}.Release|x64.Build.0 = Release|x64 + {54835857-129F-44C9-B529-A42158647B36}.Release|x86.ActiveCfg = Release|x86 + {54835857-129F-44C9-B529-A42158647B36}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 170124bd8..2e620b46b 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -9,12 +9,13 @@ from mk_util import * # Z3 Project definition def init_project_def(): - set_version(4, 3, 2, 0) + set_version(4, 3, 3, 0) add_lib('util', []) add_lib('polynomial', ['util'], 'math/polynomial') add_lib('sat', ['util']) add_lib('nlsat', ['polynomial', 'sat']) add_lib('hilbert', ['util'], 'math/hilbert') + add_lib('simplex', ['util'], 'math/simplex') add_lib('interval', ['util'], 'math/interval') add_lib('realclosure', ['interval'], 'math/realclosure') add_lib('subpaving', ['interval'], 'math/subpaving') @@ -49,7 +50,7 @@ def init_project_def(): add_lib('smt_params', ['ast', 'simplifier', 'pattern', 'bit_blaster'], 'smt/params') add_lib('proto_model', ['model', 'simplifier', 'smt_params'], 'smt/proto_model') add_lib('smt', ['bit_blaster', 'macros', 'normal_forms', 'cmd_context', 'proto_model', - 'substitution', 'grobner', 'euclid', 'proof_checker', 'pattern', 'parser_util', 'fpa']) + 'substitution', 'grobner', 'euclid', 'simplex', 'proof_checker', 'pattern', 'parser_util', 'fpa']) add_lib('user_plugin', ['smt'], 'smt/user_plugin') add_lib('bv_tactics', ['tactic', 'bit_blaster'], 'tactic/bv') add_lib('fuzzing', ['ast'], 'test/fuzzing') @@ -61,25 +62,27 @@ def init_project_def(): add_lib('muz', ['smt', 'sat', 'smt2parser', 'aig_tactic', 'qe'], 'muz/base') add_lib('transforms', ['muz', 'hilbert'], 'muz/transforms') add_lib('rel', ['muz', 'transforms'], 'muz/rel') - add_lib('pdr', ['muz', 'transforms', 'arith_tactics', 'smt_tactic'], 'muz/pdr') + add_lib('pdr', ['muz', 'transforms', 'arith_tactics', 'core_tactics', 'smt_tactic'], 'muz/pdr') add_lib('clp', ['muz', 'transforms'], 'muz/clp') add_lib('tab', ['muz', 'transforms'], 'muz/tab') add_lib('bmc', ['muz', 'transforms'], 'muz/bmc') + add_lib('ddnf', ['muz', 'transforms', 'rel'], 'muz/ddnf') add_lib('duality_intf', ['muz', 'transforms', 'duality'], 'muz/duality') - add_lib('fp', ['muz', 'pdr', 'clp', 'tab', 'rel', 'bmc', 'duality_intf'], 'muz/fp') + add_lib('fp', ['muz', 'pdr', 'clp', 'tab', 'rel', 'bmc', 'duality_intf', 'ddnf'], 'muz/fp') add_lib('smtlogic_tactics', ['arith_tactics', 'bv_tactics', 'nlsat_tactic', 'smt_tactic', 'aig_tactic', 'fp', 'muz','qe'], 'tactic/smtlogics') add_lib('ufbv_tactic', ['normal_forms', 'core_tactics', 'macros', 'smt_tactic', 'rewriter'], 'tactic/ufbv') add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa_tactics', 'aig_tactic', 'fp', 'qe','sls_tactic', 'subpaving_tactic'], 'tactic/portfolio') add_lib('smtparser', ['portfolio'], 'parsers/smt') + add_lib('opt', ['smt', 'smtlogic_tactics', 'sls_tactic'], 'opt') # add_dll('foci2', ['util'], 'interp/foci2stub', # dll_name='foci2', # export_files=['foci2stub.cpp']) # add_lib('interp', ['solver','foci2']) API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h', 'z3_interp.h'] - add_lib('api', ['portfolio', 'user_plugin', 'smtparser', 'realclosure', 'interp'], + add_lib('api', ['portfolio', 'user_plugin', 'smtparser', 'realclosure', 'interp', 'opt'], includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files) - add_exe('shell', ['api', 'sat', 'extra_cmds'], exe_name='z3') - add_exe('test', ['api', 'fuzzing'], exe_name='test-z3', install=False) + add_exe('shell', ['api', 'sat', 'extra_cmds','opt'], exe_name='z3') + add_exe('test', ['api', 'fuzzing', 'simplex'], exe_name='test-z3', install=False) add_dll('api_dll', ['api', 'sat', 'extra_cmds'], 'api/dll', reexports=['api'], dll_name='libz3', diff --git a/scripts/update_api.py b/scripts/update_api.py index 2fbf42cca..e10a2aa75 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -979,6 +979,11 @@ def def_API(name, result, params): log_c.write(" }\n") log_c.write(" Au(a%s);\n" % sz) exe_c.write("in.get_uint_array(%s)" % i) + elif ty == INT: + log_c.write("U(a%s[i]);" % i) + log_c.write(" }\n") + log_c.write(" Au(a%s);\n" % sz) + exe_c.write("in.get_int_array(%s)" % i) else: error ("unsupported parameter for %s, %s" % (ty, name, p)) elif kind == OUT_ARRAY: diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index c2864ca2d..0ab027f69 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -24,6 +24,7 @@ Revision History: #include"bv_decl_plugin.h" #include"datatype_decl_plugin.h" #include"array_decl_plugin.h" +#include"pb_decl_plugin.h" #include"ast_translation.h" #include"ast_pp.h" #include"ast_ll_pp.h" @@ -1075,7 +1076,6 @@ extern "C" { case OP_BSREM_I: case OP_BUREM_I: case OP_BSMOD_I: - return Z3_OP_UNINTERPRETED; default: UNREACHABLE(); @@ -1084,9 +1084,10 @@ extern "C" { } if (mk_c(c)->get_dt_fid() == _d->get_family_id()) { switch(_d->get_decl_kind()) { - case OP_DT_CONSTRUCTOR: return Z3_OP_DT_CONSTRUCTOR; - case OP_DT_RECOGNISER: return Z3_OP_DT_RECOGNISER; - case OP_DT_ACCESSOR: return Z3_OP_DT_ACCESSOR; + case OP_DT_CONSTRUCTOR: return Z3_OP_DT_CONSTRUCTOR; + case OP_DT_RECOGNISER: return Z3_OP_DT_RECOGNISER; + case OP_DT_ACCESSOR: return Z3_OP_DT_ACCESSOR; + case OP_DT_UPDATE_FIELD: return Z3_OP_DT_UPDATE_FIELD; default: UNREACHABLE(); return Z3_OP_UNINTERPRETED; @@ -1124,6 +1125,15 @@ extern "C" { } } + if (mk_c(c)->get_pb_fid() == _d->get_family_id()) { + switch(_d->get_decl_kind()) { + case OP_PB_LE: return Z3_OP_PB_LE; + case OP_PB_GE: return Z3_OP_PB_GE; + case OP_AT_MOST_K: return Z3_OP_PB_AT_MOST; + default: UNREACHABLE(); + } + } + return Z3_OP_UNINTERPRETED; Z3_CATCH_RETURN(Z3_OP_UNINTERPRETED); } diff --git a/src/api/api_config_params.cpp b/src/api/api_config_params.cpp index c46e7363d..5b385a872 100644 --- a/src/api/api_config_params.cpp +++ b/src/api/api_config_params.cpp @@ -37,9 +37,7 @@ extern "C" { catch (z3_exception & ex) { // The error handler is only available for contexts // Just throw a warning. - std::ostringstream buffer; - buffer << "Error setting " << param_id << ", " << ex.msg(); - warning_msg(buffer.str().c_str()); + warning_msg(ex.msg()); } } @@ -64,9 +62,7 @@ extern "C" { catch (z3_exception & ex) { // The error handler is only available for contexts // Just throw a warning. - std::ostringstream buffer; - buffer << "Error setting " << param_id << ": " << ex.msg(); - warning_msg(buffer.str().c_str()); + warning_msg(ex.msg()); return Z3_FALSE; } } @@ -92,9 +88,7 @@ extern "C" { catch (z3_exception & ex) { // The error handler is only available for contexts // Just throw a warning. - std::ostringstream buffer; - buffer << "Error setting " << param_id << ": " << ex.msg(); - warning_msg(buffer.str().c_str()); + warning_msg(ex.msg()); } } diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index b10621d43..b8470839f 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -109,6 +109,7 @@ namespace api { m_basic_fid = m().get_basic_family_id(); m_arith_fid = m().mk_family_id("arith"); m_bv_fid = m().mk_family_id("bv"); + m_pb_fid = m().mk_family_id("pb"); m_array_fid = m().mk_family_id("array"); m_dt_fid = m().mk_family_id("datatype"); m_datalog_fid = m().mk_family_id("datalog_relation"); diff --git a/src/api/api_context.h b/src/api/api_context.h index e0c95b07b..8b4418c9a 100644 --- a/src/api/api_context.h +++ b/src/api/api_context.h @@ -75,6 +75,7 @@ namespace api { family_id m_bv_fid; family_id m_dt_fid; family_id m_datalog_fid; + family_id m_pb_fid; datatype_decl_plugin * m_dt_plugin; std::string m_string_buffer; // temporary buffer used to cache strings sent to the "external" world. @@ -121,6 +122,7 @@ namespace api { family_id get_bv_fid() const { return m_bv_fid; } family_id get_dt_fid() const { return m_dt_fid; } family_id get_datalog_fid() const { return m_datalog_fid; } + family_id get_pb_fid() const { return m_pb_fid; } datatype_decl_plugin * get_dt_plugin() const { return m_dt_plugin; } Z3_error_code get_error_code() const { return m_error_code; } diff --git a/src/api/api_datalog.cpp b/src/api/api_datalog.cpp index ad6b5ad69..2d2b50f3d 100644 --- a/src/api/api_datalog.cpp +++ b/src/api/api_datalog.cpp @@ -125,7 +125,7 @@ namespace api { return "unknown"; } } - std::string to_string(unsigned num_queries, expr*const* queries) { + std::string to_string(unsigned num_queries, expr* const* queries) { std::stringstream str; m_context.display_smt2(num_queries, queries, str); return str.str(); @@ -466,13 +466,16 @@ extern "C" { ast_manager& m = mk_c(c)->m(); Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, m); mk_c(c)->save_object(v); - expr_ref_vector rules(m); + expr_ref_vector rules(m), queries(m); svector names; - to_fixedpoint_ref(d)->ctx().get_rules_as_formulas(rules, names); + to_fixedpoint_ref(d)->ctx().get_rules_as_formulas(rules, queries, names); for (unsigned i = 0; i < rules.size(); ++i) { v->m_ast_vector.push_back(rules[i].get()); } + for (unsigned i = 0; i < queries.size(); ++i) { + v->m_ast_vector.push_back(m.mk_not(queries[i].get())); + } RETURN_Z3(of_ast_vector(v)); Z3_CATCH_RETURN(0); } diff --git a/src/api/api_datatype.cpp b/src/api/api_datatype.cpp index f3a275508..fae8a21bc 100644 --- a/src/api/api_datatype.cpp +++ b/src/api/api_datatype.cpp @@ -618,4 +618,25 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_datatype_update_field( + __in Z3_context c, __in Z3_func_decl f, __in Z3_ast t, __in Z3_ast v) { + Z3_TRY; + LOG_Z3_datatype_update_field(c, f, t, v); + RESET_ERROR_CODE(); + ast_manager & m = mk_c(c)->m(); + func_decl* _f = to_func_decl(f); + expr* _t = to_expr(t); + expr* _v = to_expr(v); + expr* args[2] = { _t, _v }; + sort* domain[2] = { m.get_sort(_t), m.get_sort(_v) }; + parameter param(_f); + func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_DT_UPDATE_FIELD, 1, ¶m, 2, domain); + app* r = m.mk_app(d, 2, args); + mk_c(c)->save_ast_trail(r); + check_sorts(c, r); + RETURN_Z3(of_ast(r)); + Z3_CATCH_RETURN(0); + } + + }; diff --git a/src/api/api_opt.cpp b/src/api/api_opt.cpp new file mode 100644 index 000000000..d9369092a --- /dev/null +++ b/src/api/api_opt.cpp @@ -0,0 +1,243 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + api_opt.cpp + +Abstract: + API for optimization + +Author: + + Nikolaj Bjorner (nbjorner) 2013-12-3. + +Revision History: + +--*/ +#include +#include"z3.h" +#include"api_log_macros.h" +#include"api_stats.h" +#include"api_context.h" +#include"api_util.h" +#include"api_model.h" +#include"opt_context.h" +#include"cancel_eh.h" +#include"scoped_timer.h" + + +extern "C" { + + struct Z3_optimize_ref : public api::object { + opt::context* m_opt; + Z3_optimize_ref():m_opt(0) {} + virtual ~Z3_optimize_ref() { dealloc(m_opt); } + }; + inline Z3_optimize_ref * to_optimize(Z3_optimize o) { return reinterpret_cast(o); } + inline Z3_optimize of_optimize(Z3_optimize_ref * o) { return reinterpret_cast(o); } + inline opt::context* to_optimize_ptr(Z3_optimize o) { return to_optimize(o)->m_opt; } + + Z3_optimize Z3_API Z3_mk_optimize(Z3_context c) { + Z3_TRY; + LOG_Z3_mk_optimize(c); + RESET_ERROR_CODE(); + Z3_optimize_ref * o = alloc(Z3_optimize_ref); + o->m_opt = alloc(opt::context,mk_c(c)->m()); + mk_c(c)->save_object(o); + RETURN_Z3(of_optimize(o)); + Z3_CATCH_RETURN(0); + } + + void Z3_API Z3_optimize_inc_ref(Z3_context c, Z3_optimize o) { + Z3_TRY; + LOG_Z3_optimize_inc_ref(c, o); + RESET_ERROR_CODE(); + to_optimize(o)->inc_ref(); + Z3_CATCH; + } + + void Z3_API Z3_optimize_dec_ref(Z3_context c, Z3_optimize o) { + Z3_TRY; + LOG_Z3_optimize_dec_ref(c, o); + RESET_ERROR_CODE(); + to_optimize(o)->dec_ref(); + Z3_CATCH; + } + + void Z3_API Z3_optimize_assert(Z3_context c, Z3_optimize o, Z3_ast a) { + Z3_TRY; + LOG_Z3_optimize_assert(c, o, a); + RESET_ERROR_CODE(); + CHECK_FORMULA(a,); + to_optimize_ptr(o)->add_hard_constraint(to_expr(a)); + Z3_CATCH; + } + + unsigned Z3_API Z3_optimize_assert_soft(Z3_context c, Z3_optimize o, Z3_ast a, Z3_string weight, Z3_symbol id) { + Z3_TRY; + LOG_Z3_optimize_assert_soft(c, o, a, weight, id); + RESET_ERROR_CODE(); + CHECK_FORMULA(a,0); + rational w(weight); + return to_optimize_ptr(o)->add_soft_constraint(to_expr(a), w, to_symbol(id)); + Z3_CATCH_RETURN(0); + } + + unsigned Z3_API Z3_optimize_maximize(Z3_context c, Z3_optimize o, Z3_ast t) { + Z3_TRY; + LOG_Z3_optimize_maximize(c, o, t); + RESET_ERROR_CODE(); + CHECK_VALID_AST(t,0); + return to_optimize_ptr(o)->add_objective(to_app(t), true); + Z3_CATCH_RETURN(0); + } + + unsigned Z3_API Z3_optimize_minimize(Z3_context c, Z3_optimize o, Z3_ast t) { + Z3_TRY; + LOG_Z3_optimize_minimize(c, o, t); + RESET_ERROR_CODE(); + CHECK_VALID_AST(t,0); + return to_optimize_ptr(o)->add_objective(to_app(t), false); + Z3_CATCH_RETURN(0); + } + + void Z3_API Z3_optimize_push(Z3_context c,Z3_optimize d) { + Z3_TRY; + LOG_Z3_optimize_push(c, d); + RESET_ERROR_CODE(); + to_optimize_ptr(d)->push(); + Z3_CATCH; + } + + void Z3_API Z3_optimize_pop(Z3_context c,Z3_optimize d) { + Z3_TRY; + LOG_Z3_optimize_pop(c, d); + RESET_ERROR_CODE(); + to_optimize_ptr(d)->pop(1); + Z3_CATCH; + } + + + Z3_lbool Z3_API Z3_optimize_check(Z3_context c, Z3_optimize o) { + Z3_TRY; + LOG_Z3_optimize_check(c, o); + RESET_ERROR_CODE(); + lbool r = l_undef; + cancel_eh eh(*to_optimize_ptr(o)); + unsigned timeout = to_optimize_ptr(o)->get_params().get_uint("timeout", mk_c(c)->get_timeout()); + api::context::set_interruptable si(*(mk_c(c)), eh); + { + scoped_timer timer(timeout, &eh); + try { + r = to_optimize_ptr(o)->optimize(); + } + catch (z3_exception& ex) { + mk_c(c)->handle_exception(ex); + r = l_undef; + } + // to_optimize_ref(d).cleanup(); + } + return of_lbool(r); + Z3_CATCH_RETURN(Z3_L_UNDEF); + } + + Z3_model Z3_API Z3_optimize_get_model(Z3_context c, Z3_optimize o) { + Z3_TRY; + LOG_Z3_optimize_get_model(c, o); + RESET_ERROR_CODE(); + model_ref _m; + to_optimize_ptr(o)->get_model(_m); + Z3_model_ref * m_ref = alloc(Z3_model_ref); + if (_m) { + m_ref->m_model = _m; + } + else { + m_ref->m_model = alloc(model, mk_c(c)->m()); + } + mk_c(c)->save_object(m_ref); + RETURN_Z3(of_model(m_ref)); + Z3_CATCH_RETURN(0); + } + + void Z3_API Z3_optimize_set_params(Z3_context c, Z3_optimize o, Z3_params p) { + Z3_TRY; + LOG_Z3_optimize_set_params(c, o, p); + RESET_ERROR_CODE(); + param_descrs descrs; + to_optimize_ptr(o)->collect_param_descrs(descrs); + to_params(p)->m_params.validate(descrs); + params_ref pr = to_param_ref(p); + to_optimize_ptr(o)->updt_params(pr); + Z3_CATCH; + } + + Z3_param_descrs Z3_API Z3_optimize_get_param_descrs(Z3_context c, Z3_optimize o) { + Z3_TRY; + LOG_Z3_optimize_get_param_descrs(c, o); + RESET_ERROR_CODE(); + Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref); + mk_c(c)->save_object(d); + to_optimize_ptr(o)->collect_param_descrs(d->m_descrs); + Z3_param_descrs r = of_param_descrs(d); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + // get lower value or current approximation + Z3_ast Z3_API Z3_optimize_get_lower(Z3_context c, Z3_optimize o, unsigned idx) { + Z3_TRY; + LOG_Z3_optimize_get_lower(c, o, idx); + RESET_ERROR_CODE(); + expr_ref e = to_optimize_ptr(o)->get_lower(idx); + mk_c(c)->save_ast_trail(e); + RETURN_Z3(of_expr(e)); + Z3_CATCH_RETURN(0); + } + + // get upper or current approximation + Z3_ast Z3_API Z3_optimize_get_upper(Z3_context c, Z3_optimize o, unsigned idx) { + Z3_TRY; + LOG_Z3_optimize_get_upper(c, o, idx); + RESET_ERROR_CODE(); + expr_ref e = to_optimize_ptr(o)->get_upper(idx); + mk_c(c)->save_ast_trail(e); + RETURN_Z3(of_expr(e)); + Z3_CATCH_RETURN(0); + } + + Z3_string Z3_API Z3_optimize_to_string(Z3_context c, Z3_optimize o) { + Z3_TRY; + LOG_Z3_optimize_to_string(c, o); + RESET_ERROR_CODE(); + return mk_c(c)->mk_external_string(to_optimize_ptr(o)->to_string()); + Z3_CATCH_RETURN(""); + } + + Z3_string Z3_API Z3_optimize_get_help(Z3_context c, Z3_optimize d) { + Z3_TRY; + LOG_Z3_optimize_get_help(c, d); + RESET_ERROR_CODE(); + std::ostringstream buffer; + param_descrs descrs; + to_optimize_ptr(d)->collect_param_descrs(descrs); + descrs.display(buffer); + return mk_c(c)->mk_external_string(buffer.str()); + Z3_CATCH_RETURN(""); + } + + Z3_stats Z3_API Z3_optimize_get_statistics(Z3_context c,Z3_optimize d) { + Z3_TRY; + LOG_Z3_optimize_get_statistics(c, d); + RESET_ERROR_CODE(); + Z3_stats_ref * st = alloc(Z3_stats_ref); + to_optimize_ptr(d)->collect_statistics(st->m_stats); + mk_c(c)->save_object(st); + Z3_stats r = of_stats(st); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + + +}; diff --git a/src/api/api_pb.cpp b/src/api/api_pb.cpp new file mode 100644 index 000000000..6d5a56d2c --- /dev/null +++ b/src/api/api_pb.cpp @@ -0,0 +1,61 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + api_pb.cpp + +Abstract: + API for pb theory + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-13. + +Revision History: + +--*/ +#include +#include"z3.h" +#include"api_log_macros.h" +#include"api_context.h" +#include"api_util.h" +#include"pb_decl_plugin.h" + +extern "C" { + + Z3_ast Z3_API Z3_mk_atmost(Z3_context c, unsigned num_args, + Z3_ast const args[], unsigned k) { + Z3_TRY; + LOG_Z3_mk_atmost(c, num_args, args, k); + RESET_ERROR_CODE(); + parameter param(k); + pb_util util(mk_c(c)->m()); + ast* a = util.mk_at_most_k(num_args, to_exprs(args), k); + mk_c(c)->save_ast_trail(a); + check_sorts(c, a); + RETURN_Z3(of_ast(a)); + Z3_CATCH_RETURN(0); + } + + + Z3_ast Z3_API Z3_mk_pble(Z3_context c, unsigned num_args, + Z3_ast const args[], int _coeffs[], + int k) { + Z3_TRY; + LOG_Z3_mk_pble(c, num_args, args, _coeffs, k); + RESET_ERROR_CODE(); + pb_util util(mk_c(c)->m()); + vector coeffs; + for (unsigned i = 0; i < num_args; ++i) { + coeffs.push_back(rational(_coeffs[i])); + } + ast* a = util.mk_le(num_args, coeffs.c_ptr(), to_exprs(args), rational(k)); + mk_c(c)->save_ast_trail(a); + check_sorts(c, a); + RETURN_Z3(of_ast(a)); + Z3_CATCH_RETURN(0); + } + + +}; diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index c35208d86..a180bdabe 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -1314,6 +1314,26 @@ namespace z3 { expr_vector assertions() const { Z3_ast_vector r = Z3_solver_get_assertions(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); } expr proof() const { Z3_ast r = Z3_solver_get_proof(ctx(), m_solver); check_error(); return expr(ctx(), r); } friend std::ostream & operator<<(std::ostream & out, solver const & s) { out << Z3_solver_to_string(s.ctx(), s); return out; } + + std::string to_smt2(char const* status = "unknown") { + array es(assertions()); + Z3_ast const* fmls = es.ptr(); + Z3_ast fml = 0; + unsigned sz = es.size(); + if (sz > 0) { + --sz; + fml = fmls[sz]; + } + else { + fml = ctx().bool_val(true); + } + return std::string(Z3_benchmark_to_smtlib_string( + ctx(), + "", "", status, "", + sz, + fmls, + fml)); + } }; class goal : public object { @@ -1513,6 +1533,62 @@ namespace z3 { } }; + class optimize : public object { + Z3_optimize m_opt; + public: + class handle { + unsigned m_h; + public: + handle(unsigned h): m_h(h) {} + unsigned h() const { return m_h; } + }; + optimize(context& c):object(c) { m_opt = Z3_mk_optimize(c); Z3_optimize_inc_ref(c, m_opt); } + ~optimize() { Z3_optimize_dec_ref(ctx(), m_opt); } + operator Z3_optimize() const { return m_opt; } + void add(expr const& e) { + assert(e.is_bool()); + Z3_optimize_assert(ctx(), m_opt, e); + } + handle add(expr const& e, unsigned weight) { + assert(e.is_bool()); + std::stringstream strm; + strm << weight; + return handle(Z3_optimize_assert_soft(ctx(), m_opt, e, strm.str().c_str(), 0)); + } + handle add(expr const& e, char const* weight) { + assert(e.is_bool()); + return handle(Z3_optimize_assert_soft(ctx(), m_opt, e, weight, 0)); + } + handle maximize(expr const& e) { + return handle(Z3_optimize_maximize(ctx(), m_opt, e)); + } + handle minimize(expr const& e) { + return handle(Z3_optimize_minimize(ctx(), m_opt, e)); + } + void push() { + Z3_optimize_push(ctx(), m_opt); + } + void pop() { + Z3_optimize_pop(ctx(), m_opt); + } + check_result check() { Z3_lbool r = Z3_optimize_check(ctx(), m_opt); check_error(); return to_check_result(r); } + model get_model() const { Z3_model m = Z3_optimize_get_model(ctx(), m_opt); check_error(); return model(ctx(), m); } + void set(params const & p) { Z3_optimize_set_params(ctx(), m_opt, p); check_error(); } + expr lower(handle const& h) { + Z3_ast r = Z3_optimize_get_lower(ctx(), m_opt, h.h()); + check_error(); + return expr(ctx(), r); + } + expr upper(handle const& h) { + Z3_ast r = Z3_optimize_get_upper(ctx(), m_opt, h.h()); + check_error(); + return expr(ctx(), r); + } + stats statistics() const { Z3_stats r = Z3_optimize_get_statistics(ctx(), m_opt); check_error(); return stats(ctx(), r); } + friend std::ostream & operator<<(std::ostream & out, optimize const & s) { out << Z3_optimize_to_string(s.ctx(), s.m_opt); return out; } + std::string help() const { char const * r = Z3_optimize_get_help(ctx(), m_opt); check_error(); return r; } + }; + inline tactic fail_if(probe const & p) { Z3_tactic r = Z3_tactic_fail_if(p.ctx(), p); p.check_error(); diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 1c03d76b6..13e78e495 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -449,6 +449,19 @@ namespace Microsoft.Z3 return MkDatatypeSorts(MkSymbols(names), c); } + /// + /// Update a datatype field at expression t with value v. + /// The function performs a record update at t. The field + /// that is passed in as argument is updated with value v, + /// the remainig fields of t are unchanged. + /// + public Expr MkUpdateField(FuncDecl field, Expr t, Expr v) + { + return Expr.Create(this, Native.Z3_datatype_update_field( + nCtx, field.NativeObject, + t.NativeObject, v.NativeObject)); + } + #endregion #endregion @@ -2251,6 +2264,36 @@ namespace Microsoft.Z3 } #endregion + #region Pseudo-Boolean constraints + + /// + /// Create an at-most-k constraint. + /// + public BoolExpr MkAtMost(BoolExpr[] args, uint k) + { + Contract.Requires(args != null); + Contract.Requires(Contract.Result() != null); + CheckContextMatch(args); + return new BoolExpr(this, Native.Z3_mk_atmost(nCtx, (uint) args.Length, + AST.ArrayToNative(args), k)); + } + + /// + /// Create a pseudo-Boolean less-or-equal constraint. + /// + public BoolExpr MkPBLe(int[] coeffs, BoolExpr[] args, int k) + { + Contract.Requires(args != null); + Contract.Requires(coeffs != null); + Contract.Requires(args.Length == coeffs.Length); + Contract.Requires(Contract.Result() != null); + CheckContextMatch(args); + return new BoolExpr(this, Native.Z3_mk_pble(nCtx, (uint) args.Length, + AST.ArrayToNative(args), + coeffs, k)); + } + #endregion + #region Numerals #region General Numerals @@ -3438,6 +3481,18 @@ namespace Microsoft.Z3 } #endregion + #region Optimization + /// + /// Create an Optimization context. + /// + public Optimize MkOptimize() + { + Contract.Ensures(Contract.Result() != null); + + return new Optimize(this); + } + #endregion + #region Miscellaneous /// @@ -3594,6 +3649,7 @@ namespace Microsoft.Z3 Contract.Invariant(m_Statistics_DRQ != null); Contract.Invariant(m_Tactic_DRQ != null); Contract.Invariant(m_Fixedpoint_DRQ != null); + Contract.Invariant(m_Optimize_DRQ != null); } readonly private AST.DecRefQueue m_AST_DRQ = new AST.DecRefQueue(); @@ -3611,6 +3667,7 @@ namespace Microsoft.Z3 readonly private Statistics.DecRefQueue m_Statistics_DRQ = new Statistics.DecRefQueue(); readonly private Tactic.DecRefQueue m_Tactic_DRQ = new Tactic.DecRefQueue(); readonly private Fixedpoint.DecRefQueue m_Fixedpoint_DRQ = new Fixedpoint.DecRefQueue(); + readonly private Optimize.DecRefQueue m_Optimize_DRQ = new Optimize.DecRefQueue(); internal AST.DecRefQueue AST_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_AST_DRQ; } } internal ASTMap.DecRefQueue ASTMap_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_ASTMap_DRQ; } } @@ -3627,6 +3684,7 @@ namespace Microsoft.Z3 internal Statistics.DecRefQueue Statistics_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Statistics_DRQ; } } internal Tactic.DecRefQueue Tactic_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Tactic_DRQ; } } internal Fixedpoint.DecRefQueue Fixedpoint_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Fixedpoint_DRQ; } } + internal Optimize.DecRefQueue Optimize_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Optimize_DRQ; } } internal long refCount = 0; @@ -3670,6 +3728,7 @@ namespace Microsoft.Z3 Statistics_DRQ.Clear(this); Tactic_DRQ.Clear(this); Fixedpoint_DRQ.Clear(this); + Optimize_DRQ.Clear(this); m_boolSort = null; m_intSort = null; diff --git a/src/api/dotnet/Deprecated.cs b/src/api/dotnet/Deprecated.cs new file mode 100644 index 000000000..aa6dffb45 --- /dev/null +++ b/src/api/dotnet/Deprecated.cs @@ -0,0 +1,111 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + Deprecated.cs + +Abstract: + + Expose deprecated features for use from the managed API + those who use them for experiments. + +Author: + + Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +--*/ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Diagnostics.Contracts; + +namespace Microsoft.Z3 +{ + /// + /// The main interaction with Z3 happens via the Context. + /// + [ContractVerification(true)] + public class Deprecated + { + + /// + /// Creates a backtracking point. + /// + /// + public static void Push(Context ctx) { + Native.Z3_push(ctx.nCtx); + } + + /// + /// Backtracks backtracking points. + /// + /// Note that an exception is thrown if is not smaller than NumScopes + /// + public static void Pop(Context ctx, uint n = 1) { + Native.Z3_pop(ctx.nCtx, n); + } + + /// + /// Assert a constraint (or multiple) into the solver. + /// + public static void Assert(Context ctx, params BoolExpr[] constraints) + { + Contract.Requires(constraints != null); + Contract.Requires(Contract.ForAll(constraints, c => c != null)); + + ctx.CheckContextMatch(constraints); + foreach (BoolExpr a in constraints) + { + Native.Z3_assert_cnstr(ctx.nCtx, a.NativeObject); + } + } + /// + /// Checks whether the assertions in the context are consistent or not. + /// + public static Status Check(Context ctx, List core, ref Model model, ref Expr proof, params Expr[] assumptions) + { + Z3_lbool r; + model = null; + proof = null; + if (assumptions == null || assumptions.Length == 0) + r = (Z3_lbool)Native.Z3_check(ctx.nCtx); + else { + IntPtr mdl = IntPtr.Zero, prf = IntPtr.Zero; + uint core_size = 0; + IntPtr[] native_core = new IntPtr[assumptions.Length]; + r = (Z3_lbool)Native.Z3_check_assumptions(ctx.nCtx, + (uint)assumptions.Length, AST.ArrayToNative(assumptions), + ref mdl, ref prf, ref core_size, native_core); + + for (uint i = 0; i < core_size; i++) + core.Add((BoolExpr)Expr.Create(ctx, native_core[i])); + if (mdl != IntPtr.Zero) { + model = new Model(ctx, mdl); + } + if (prf != IntPtr.Zero) { + proof = Expr.Create(ctx, prf); + } + + } + switch (r) + { + case Z3_lbool.Z3_L_TRUE: return Status.SATISFIABLE; + case Z3_lbool.Z3_L_FALSE: return Status.UNSATISFIABLE; + default: return Status.UNKNOWN; + } + } + + /// + /// Retrieves an assignment to atomic propositions for a satisfiable context. + /// + public static BoolExpr GetAssignment(Context ctx) + { + IntPtr x = Native.Z3_get_context_assignment(ctx.nCtx); + return (BoolExpr)Expr.Create(ctx, x); + } + + } +} \ No newline at end of file diff --git a/src/api/dotnet/Fixedpoint.cs b/src/api/dotnet/Fixedpoint.cs index 3f40b220b..6d75235c6 100644 --- a/src/api/dotnet/Fixedpoint.cs +++ b/src/api/dotnet/Fixedpoint.cs @@ -304,6 +304,19 @@ namespace Microsoft.Z3 } /// + /// Fixedpoint statistics. + /// + public Statistics Statistics + { + get + { + Contract.Ensures(Contract.Result() != null); + + return new Statistics(Context, Native.Z3_fixedpoint_get_statistics(Context.nCtx, NativeObject)); + } + } + + /// /// Parse an SMT-LIB2 file with fixedpoint rules. /// Add the rules to the current fixedpoint context. /// Return the set of queries in the file. diff --git a/src/api/dotnet/Microsoft.Z3.csproj b/src/api/dotnet/Microsoft.Z3.csproj index cc7d3c0c5..36bd6ad02 100644 --- a/src/api/dotnet/Microsoft.Z3.csproj +++ b/src/api/dotnet/Microsoft.Z3.csproj @@ -19,12 +19,12 @@ true full false - ..\..\..\..\..\cwinter\bugs\z3bugs\Debug\ + ..\Debug\ DEBUG;TRACE prompt 4 true - C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML + ..\Debug\Microsoft.Z3.XML False False True @@ -254,7 +254,7 @@ true - ..\..\..\..\..\cwinter\bugs\z3bugs\Debug\ + ..\x86\Debug\ DEBUG;TRACE true full @@ -266,7 +266,7 @@ MinimumRecommendedRules.ruleset ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML + ..\x86\Debug\Microsoft.Z3.XML bin\x86\Release\ diff --git a/src/api/dotnet/Optimize.cs b/src/api/dotnet/Optimize.cs new file mode 100644 index 000000000..ed7d1d60a --- /dev/null +++ b/src/api/dotnet/Optimize.cs @@ -0,0 +1,296 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + Optimize.cs + +Abstract: + + Z3 Managed API: Optimizes + +Author: + + Nikolaj Bjorner (nbjorner) 2013-12-03 + +Notes: + +--*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace Microsoft.Z3 +{ + /// + /// Object for managing optimizization context + /// + [ContractVerification(true)] + public class Optimize : Z3Object + { + /// + /// A string that describes all available optimize solver parameters. + /// + public string Help + { + get + { + Contract.Ensures(Contract.Result() != null); + return Native.Z3_optimize_get_help(Context.nCtx, NativeObject); + } + } + + /// + /// Sets the optimize solver parameters. + /// + public Params Parameters + { + set + { + Contract.Requires(value != null); + Context.CheckContextMatch(value); + Native.Z3_optimize_set_params(Context.nCtx, NativeObject, value.NativeObject); + } + } + + /// + /// Retrieves parameter descriptions for Optimize solver. + /// + public ParamDescrs ParameterDescriptions + { + get { return new ParamDescrs(Context, Native.Z3_optimize_get_param_descrs(Context.nCtx, NativeObject)); } + } + + /// + /// Assert a constraint (or multiple) into the optimize solver. + /// + public void Assert(params BoolExpr[] constraints) + { + Contract.Requires(constraints != null); + Contract.Requires(Contract.ForAll(constraints, c => c != null)); + + Context.CheckContextMatch(constraints); + foreach (BoolExpr a in constraints) + { + Native.Z3_optimize_assert(Context.nCtx, NativeObject, a.NativeObject); + } + } + + /// + /// Alias for Assert. + /// + public void Add(params BoolExpr[] constraints) + { + Assert(constraints); + } + + /// + /// Handle to objectives returned by objective functions. + /// + public class Handle + { + Optimize opt; + uint handle; + internal Handle(Optimize opt, uint h) + { + this.opt = opt; + this.handle = h; + } + + /// + /// Retrieve a lower bound for the objective handle. + /// + public ArithExpr Lower + { + get { return opt.GetLower(handle); } + } + + /// + /// Retrieve an upper bound for the objective handle. + /// + public ArithExpr Upper + { + get { return opt.GetUpper(handle); } + } + + /// + /// Retrieve the value of an objective. + /// + public ArithExpr Value + { + get { return Lower; } + } + } + + /// + /// Assert soft constraint + /// + /// + /// Return an objective which associates with the group of constraints. + /// + public Handle AssertSoft(BoolExpr constraint, uint weight, string group) + { + Context.CheckContextMatch(constraint); + Symbol s = Context.MkSymbol(group); + return new Handle(this, Native.Z3_optimize_assert_soft(Context.nCtx, NativeObject, constraint.NativeObject, weight.ToString(), s.NativeObject)); + } + + + /// + /// + /// Check satisfiability of asserted constraints. + /// Produce a model that (when the objectives are bounded and + /// don't use strict inequalities) meets the objectives. + /// + /// + public Status Check() { + Z3_lbool r = (Z3_lbool)Native.Z3_optimize_check(Context.nCtx, NativeObject); + switch (r) + { + case Z3_lbool.Z3_L_TRUE: + return Status.SATISFIABLE; + case Z3_lbool.Z3_L_FALSE: + return Status.UNSATISFIABLE; + default: + return Status.UNKNOWN; + } + } + + /// + /// Creates a backtracking point. + /// + /// + public void Push() + { + Native.Z3_optimize_push(Context.nCtx, NativeObject); + } + + /// + /// Backtrack one backtracking point. + /// + /// Note that an exception is thrown if Pop is called without a corresponding Push + /// + public void Pop() + { + Native.Z3_optimize_pop(Context.nCtx, NativeObject); + } + + + /// + /// The model of the last Check. + /// + /// + /// The result is null if Check was not invoked before, + /// if its results was not SATISFIABLE, or if model production is not enabled. + /// + public Model Model + { + get + { + IntPtr x = Native.Z3_optimize_get_model(Context.nCtx, NativeObject); + if (x == IntPtr.Zero) + return null; + else + return new Model(Context, x); + } + } + + /// + /// Declare an arithmetical maximization objective. + /// Return a handle to the objective. The handle is used as + /// to retrieve the values of objectives after calling Check. + /// + public Handle MkMaximize(ArithExpr e) + { + return new Handle(this, Native.Z3_optimize_maximize(Context.nCtx, NativeObject, e.NativeObject)); + } + + /// + /// Declare an arithmetical minimization objective. + /// Similar to MkMaximize. + /// + public Handle MkMinimize(ArithExpr e) + { + return new Handle(this, Native.Z3_optimize_minimize(Context.nCtx, NativeObject, e.NativeObject)); + } + + /// + /// Retrieve a lower bound for the objective handle. + /// + private ArithExpr GetLower(uint index) + { + return (ArithExpr)Expr.Create(Context, Native.Z3_optimize_get_lower(Context.nCtx, NativeObject, index)); + } + + + /// + /// Retrieve an upper bound for the objective handle. + /// + private ArithExpr GetUpper(uint index) + { + return (ArithExpr)Expr.Create(Context, Native.Z3_optimize_get_upper(Context.nCtx, NativeObject, index)); + } + + + /// + /// Print the context to a string (SMT-LIB parseable benchmark). + /// + public override string ToString() + { + return Native.Z3_optimize_to_string(Context.nCtx, NativeObject); + } + + /// + /// Optimize statistics. + /// + public Statistics Statistics + { + get + { + Contract.Ensures(Contract.Result() != null); + + return new Statistics(Context, Native.Z3_optimize_get_statistics(Context.nCtx, NativeObject)); + } + } + + + #region Internal + internal Optimize(Context ctx, IntPtr obj) + : base(ctx, obj) + { + Contract.Requires(ctx != null); + } + internal Optimize(Context ctx) + : base(ctx, Native.Z3_mk_optimize(ctx.nCtx)) + { + Contract.Requires(ctx != null); + } + + internal class DecRefQueue : IDecRefQueue + { + public override void IncRef(Context ctx, IntPtr obj) + { + Native.Z3_optimize_inc_ref(ctx.nCtx, obj); + } + + public override void DecRef(Context ctx, IntPtr obj) + { + Native.Z3_optimize_dec_ref(ctx.nCtx, obj); + } + }; + + internal override void IncRef(IntPtr o) + { + Context.Optimize_DRQ.IncAndClear(Context, o); + base.IncRef(o); + } + + internal override void DecRef(IntPtr o) + { + Context.Optimize_DRQ.Add(o); + base.DecRef(o); + } + #endregion + } +} diff --git a/src/api/dotnet/Params.cs b/src/api/dotnet/Params.cs index c33728491..cd6ac248d 100644 --- a/src/api/dotnet/Params.cs +++ b/src/api/dotnet/Params.cs @@ -79,6 +79,7 @@ namespace Microsoft.Z3 Native.Z3_params_set_symbol(Context.nCtx, NativeObject, name.NativeObject, value.NativeObject); } + /// /// Adds a parameter setting. /// @@ -118,6 +119,7 @@ namespace Microsoft.Z3 /// public void Add(string name, string value) { + Contract.Requires(name != null); Contract.Requires(value != null); Native.Z3_params_set_symbol(Context.nCtx, NativeObject, Context.MkSymbol(name).NativeObject, Context.MkSymbol(value).NativeObject); diff --git a/src/api/dotnet/Readme.NET35 b/src/api/dotnet/Readme.NET35 new file mode 100644 index 000000000..73743fd15 --- /dev/null +++ b/src/api/dotnet/Readme.NET35 @@ -0,0 +1,9 @@ +The default Z3 bindings for .NET are built for the .NET framework version 4. +Should the need arise, it is also possible to build them for .NET 3.5; the +instructions are as follows: + +In the project properties of Microsoft.Z3.csproj: +- Under 'Application': Change Target framework to .NET Framework 3.5 +- Under 'Build': Add FRAMEWORK_LT_4 to the condidional compilation symbols +- Remove the reference to System.Numerics +- Install the NuGet Package "Microsoft Code Contracts for Net3.5" diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 4fbd79be2..5de82026f 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -375,6 +375,23 @@ public class Context extends IDisposable return mkDatatypeSorts(MkSymbols(names), c); } + /** + * Update a datatype field at expression t with value v. + * The function performs a record update at t. The field + * that is passed in as argument is updated with value v, + * the remainig fields of t are unchanged. + **/ + public Expr MkUpdateField(FuncDecl field, Expr t, Expr v) + throws Z3Exception + { + return Expr.create + (this, + Native.datatypeUpdateField + (nCtx(), field.getNativeObject(), + t.getNativeObject(), v.getNativeObject())); + } + + /** * Creates a new function declaration. **/ diff --git a/src/api/java/Fixedpoint.java b/src/api/java/Fixedpoint.java index 57e1e105a..f7d2bc7b7 100644 --- a/src/api/java/Fixedpoint.java +++ b/src/api/java/Fixedpoint.java @@ -319,6 +319,18 @@ public class Fixedpoint extends Z3Object return res; } + /** + * Fixedpoint statistics. + * + * @throws Z3Exception + **/ + public Statistics getStatistics() throws Z3Exception + { + return new Statistics(getContext(), Native.fixedpointGetStatistics( + getContext().nCtx(), getNativeObject())); + } + + Fixedpoint(Context ctx, long obj) throws Z3Exception { super(ctx, obj); diff --git a/src/api/python/z3.py b/src/api/python/z3.py index e58e47640..ca04c419b 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -298,9 +298,8 @@ class AstRef(Z3PPObject): return self.ast def get_id(self): - """Return unique identifier for object. It can be used for hash-tables and maps.""" - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) - + """Return unique identifier for object. It can be used for hash-tables and maps.""" + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def ctx_ref(self): """Return a reference to the C context where this AST node is stored.""" @@ -453,8 +452,7 @@ class SortRef(AstRef): return Z3_sort_to_ast(self.ctx_ref(), self.ast) def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) - + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def kind(self): """Return the Z3 internal kind of a sort. This method can be used to test if `self` is one of the Z3 builtin sorts. @@ -555,6 +553,8 @@ def _to_sort_ref(s, ctx): return ArraySortRef(s, ctx) elif k == Z3_DATATYPE_SORT: return DatatypeSortRef(s, ctx) + elif k == Z3_FINITE_DOMAIN_SORT: + return FiniteDomainSortRef(s, ctx) return SortRef(s, ctx) def _sort(ctx, a): @@ -595,7 +595,7 @@ class FuncDeclRef(AstRef): return Z3_func_decl_to_ast(self.ctx_ref(), self.ast) def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def as_func_decl(self): return self.ast @@ -743,7 +743,7 @@ class ExprRef(AstRef): return self.ast def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def sort(self): """Return the sort of expression `self`. @@ -1540,7 +1540,7 @@ class PatternRef(ExprRef): return Z3_pattern_to_ast(self.ctx_ref(), self.ast) def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def is_pattern(a): """Return `True` if `a` is a Z3 pattern (hint for quantifier instantiation. @@ -1605,7 +1605,7 @@ class QuantifierRef(BoolRef): return self.ast def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def sort(self): """Return the Boolean sort.""" @@ -6033,22 +6033,20 @@ class Solver(Z3PPObject): return Z3_solver_to_string(self.ctx.ref(), self.solver) def to_smt2(self): - """return SMTLIB2 formatted benchmark for solver's assertions""" - es = self.assertions() - sz = len(es) - sz1 = sz - if sz1 > 0: - sz1 -= 1 - v = (Ast * sz1)() - for i in range(sz1): - v[i] = es[i].as_ast() - if sz > 0: - e = es[sz1].as_ast() - else: - e = BoolVal(True, self.ctx).as_ast() - return Z3_benchmark_to_smtlib_string(self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e) - - + """return SMTLIB2 formatted benchmark for solver's assertions""" + es = self.assertions() + sz = len(es) + sz1 = sz + if sz1 > 0: + sz1 -= 1 + v = (Ast * sz1)() + for i in range(sz1): + v[i] = es[i].as_ast() + if sz > 0: + e = es[sz1].as_ast() + else: + e = BoolVal(True, self.ctx).as_ast() + return Z3_benchmark_to_smtlib_string(self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e) def SolverFor(logic, ctx=None): """Create a solver customized for the given logic. @@ -6166,7 +6164,7 @@ class Fixedpoint(Z3PPObject): Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, head.as_ast(), name) else: body = _get_args(body) - f = self.abstract(Implies(And(body),head)) + f = self.abstract(Implies(And(body, self.ctx),head)) Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) def rule(self, head, body = None, name = None): @@ -6183,7 +6181,7 @@ class Fixedpoint(Z3PPObject): """ query = _get_args(query) sz = len(query) - if sz >= 1 and isinstance(query[0], FuncDecl): + if sz >= 1 and isinstance(query[0], FuncDeclRef): _decls = (FuncDecl * sz)() i = 0 for q in query: @@ -6194,7 +6192,7 @@ class Fixedpoint(Z3PPObject): if sz == 1: query = query[0] else: - query = And(query) + query = And(query, self.ctx) query = self.abstract(query, False) r = Z3_fixedpoint_query(self.ctx.ref(), self.fixedpoint, query.as_ast()) return CheckSatResult(r) @@ -6213,7 +6211,7 @@ class Fixedpoint(Z3PPObject): name = "" name = to_symbol(name, self.ctx) body = _get_args(body) - f = self.abstract(Implies(And(body),head)) + f = self.abstract(Implies(And(body, self.ctx),head)) Z3_fixedpoint_update_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) def get_answer(self): @@ -6310,6 +6308,166 @@ class Fixedpoint(Z3PPObject): else: return Exists(self.vars, fml) + +######################################### +# +# Finite domain sorts +# +######################################### + +class FiniteDomainSortRef(SortRef): + """Finite domain sort.""" + + def size(self): + """Return the size of the finite domain sort""" + r = (ctype.c_ulonglong * 1)() + if Z3_get_finite_domain_sort_size(self.ctx_ref(), self.ast(), r): + return r[0] + else: + raise Z3Exception("Failed to retrieve finite domain sort size") + +def FiniteDomainSort(name, sz, ctx=None): + """Create a named finite domain sort of a given size sz""" + ctx = _get_ctx(ctx) + return FiniteDomainSortRef(Z3_mk_finite_domain_sort(ctx.ref(), name, sz), ctx) + +######################################### +# +# Optimize +# +######################################### + +class OptimizeObjective: + def __init__(self, opt, value, is_max): + self._opt = opt + self._value = value + self._is_max = is_max + + def lower(self): + opt = self._opt + return _to_expr_ref(Z3_optimize_get_lower(opt.ctx.ref(), opt.optimize, self._value), opt.ctx) + + def upper(self): + opt = self._opt + return _to_expr_ref(Z3_optimize_get_upper(opt.ctx.ref(), opt.optimize, self._value), opt.ctx) + + def value(self): + if self._is_max: + return self.upper() + else: + return self.lower() + +class Optimize(Z3PPObject): + """Optimize API provides methods for solving using objective functions and weighted soft constraints""" + + def __init__(self, ctx=None): + self.ctx = _get_ctx(ctx) + self.optimize = Z3_mk_optimize(self.ctx.ref()) + Z3_optimize_inc_ref(self.ctx.ref(), self.optimize) + + def __del__(self): + if self.optimize != None: + Z3_optimize_dec_ref(self.ctx.ref(), self.optimize) + + def set(self, *args, **keys): + """Set a configuration option. The method `help()` return a string containing all available options. + """ + p = args2params(args, keys, self.ctx) + Z3_optimize_set_params(self.ctx.ref(), self.optimize, p.params) + + def help(self): + """Display a string describing all available options.""" + print(Z3_optimize_get_help(self.ctx.ref(), self.optimize)) + + def param_descrs(self): + """Return the parameter description set.""" + return ParamDescrsRef(Z3_optimize_get_param_descrs(self.ctx.ref(), self.optimize), self.ctx) + + def assert_exprs(self, *args): + """Assert constraints as background axioms for the optimize solver.""" + args = _get_args(args) + for arg in args: + if isinstance(arg, Goal) or isinstance(arg, AstVector): + for f in arg: + Z3_optimize_assert(self.ctx.ref(), self.optimize, f.as_ast()) + else: + Z3_optimize_assert(self.ctx.ref(), self.optimize, arg.as_ast()) + + def add(self, *args): + """Assert constraints as background axioms for the optimize solver. Alias for assert_expr.""" + self.assert_exprs(*args) + + def add_soft(self, arg, weight = "1", id = None): + """Add soft constraint with optional weight and optional identifier. + If no weight is supplied, then the penalty for violating the soft constraint + is 1. + Soft constraints are grouped by identifiers. Soft constraints that are + added without identifiers are grouped by default. + """ + if _is_int(weight): + weight = "%d" % weight + if not isinstance(weight, str): + raise Z3Exception("weight should be a string or an integer") + if id == None: + id = "" + id = to_symbol(id, self.ctx) + v = Z3_optimize_assert_soft(self.ctx.ref(), self.optimize, arg.as_ast(), weight, id) + return OptimizeObjective(self, v, False) + + def maximize(self, arg): + """Add objective function to maximize.""" + return OptimizeObjective(self, Z3_optimize_maximize(self.ctx.ref(), self.optimize, arg.as_ast()), True) + + def minimize(self, arg): + """Add objective function to minimize.""" + return OptimizeObjective(self, Z3_optimize_minimize(self.ctx.ref(), self.optimize, arg.as_ast()), False) + + def push(self): + """create a backtracking point for added rules, facts and assertions""" + Z3_optimize_push(self.ctx.ref(), self.optimize) + + def pop(self): + """restore to previously created backtracking point""" + Z3_optimize_pop(self.ctx.ref(), self.optimize) + + def check(self): + """Check satisfiability while optimizing objective functions.""" + return CheckSatResult(Z3_optimize_check(self.ctx.ref(), self.optimize)) + + def model(self): + """Return a model for the last check().""" + try: + return ModelRef(Z3_optimize_get_model(self.ctx.ref(), self.optimize), self.ctx) + except Z3Exception: + raise Z3Exception("model is not available") + + def lower(self, obj): + if not isinstance(obj, OptimizeObjective): + raise Z3Exception("Expecting objective handle returned by maximize/minimize") + return obj.lower() + + def upper(self, obj): + if not isinstance(obj, OptimizeObjective): + raise Z3Exception("Expecting objective handle returned by maximize/minimize") + return obj.upper() + + def __repr__(self): + """Return a formatted string with all added rules and constraints.""" + return self.sexpr() + + def sexpr(self): + """Return a formatted string (in Lisp-like format) with all added constraints. We say the string is in s-expression format. + """ + return Z3_optimize_to_string(self.ctx.ref(), self.optimize) + + def statistics(self): + """Return statistics for the last `query()`. + """ + return Statistics(Z3_optimize_get_statistics(self.ctx.ref(), self.optimize), self.ctx) + + + + ######################################### # # ApplyResult diff --git a/src/api/python/z3printer.py b/src/api/python/z3printer.py index d1d85d30e..bd4c72477 100644 --- a/src/api/python/z3printer.py +++ b/src/api/python/z3printer.py @@ -842,6 +842,8 @@ class Formatter: return self.pp_seq(a.assertions(), 0, []) elif isinstance(a, z3.Fixedpoint): return a.sexpr() + elif isinstance(a, z3.Optimize): + return a.sexpr() elif isinstance(a, z3.ApplyResult): return self.pp_seq_seq(a, 0, []) elif isinstance(a, z3.ModelRef): diff --git a/src/api/python/z3types.py b/src/api/python/z3types.py index 5d59368ff..e01b78238 100644 --- a/src/api/python/z3types.py +++ b/src/api/python/z3types.py @@ -78,6 +78,10 @@ class FixedpointObj(ctypes.c_void_p): def __init__(self, fixedpoint): self._as_parameter_ = fixedpoint def from_param(obj): return obj +class OptimizeObj(ctypes.c_void_p): + def __init__(self, optimize): self._as_parameter_ = optimize + def from_param(obj): return obj + class ModelObj(ctypes.c_void_p): def __init__(self, model): self._as_parameter_ = model def from_param(obj): return obj diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 4dcca078d..d21c979e8 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -47,6 +47,7 @@ DEFINE_TYPE(Z3_func_interp); #define Z3_func_interp_opt Z3_func_interp DEFINE_TYPE(Z3_func_entry); DEFINE_TYPE(Z3_fixedpoint); +DEFINE_TYPE(Z3_optimize); DEFINE_TYPE(Z3_rcf_num); DEFINE_VOID(Z3_theory_data); #endif @@ -85,6 +86,7 @@ DEFINE_VOID(Z3_theory_data); - \c Z3_func_interp: interpretation of a function in a model. - \c Z3_func_entry: representation of the value of a \c Z3_func_interp at a particular point. - \c Z3_fixedpoint: context for the recursive predicate solver. + - \c Z3_optimize: context for solving optimization queries. - \c Z3_ast_vector: vector of \c Z3_ast objects. - \c Z3_ast_map: mapping from \c Z3_ast to \c Z3_ast objects. - \c Z3_goal: set of formulas that can be solved and/or transformed using tactics and solvers. @@ -875,6 +877,17 @@ typedef enum - Z3_OP_DT_ACCESSOR: datatype accessor. + - Z3_OP_DT_UPDATE_FIELD: datatype field update. + + - Z3_OP_PB_AT_MOST: Cardinality constraint. + E.g., x + y + z <= 2 + + - Z3_OP_PB_LE: Generalized Pseudo-Boolean cardinality constraint. + Example 2*x + 3*y <= 4 + + - Z3_OP_PB_GE: Generalized Pseudo-Boolean cardinality constraint. + Example 2*x + 3*y + 2*z >= 4 + - Z3_OP_UNINTERPRETED: kind used for uninterpreted symbols. */ typedef enum { @@ -1055,6 +1068,12 @@ typedef enum { Z3_OP_DT_CONSTRUCTOR=0x800, Z3_OP_DT_RECOGNISER, Z3_OP_DT_ACCESSOR, + Z3_OP_DT_UPDATE_FIELD, + + // Pseudo Booleans + Z3_OP_PB_AT_MOST=0x900, + Z3_OP_PB_LE, + Z3_OP_PB_GE, Z3_OP_UNINTERPRETED } Z3_decl_kind; @@ -1192,6 +1211,7 @@ typedef enum def_Type('FUNC_INTERP', 'Z3_func_interp', 'FuncInterpObj') def_Type('FUNC_ENTRY', 'Z3_func_entry', 'FuncEntryObj') def_Type('FIXEDPOINT', 'Z3_fixedpoint', 'FixedpointObj') + def_Type('OPTIMIZE', 'Z3_optimize', 'OptimizeObj') def_Type('PARAM_DESCRS', 'Z3_param_descrs', 'ParamDescrs') def_Type('RCF_NUM', 'Z3_rcf_num', 'RCFNumObj') */ @@ -3734,6 +3754,28 @@ END_MLAPI_EXCLUDE Z3_func_decl Z3_API Z3_get_datatype_sort_constructor_accessor( __in Z3_context c, __in Z3_sort t, unsigned idx_c, unsigned idx_a); + /** + \brief Update record field with a value. + + This corresponds to the 'with' construct in OCaml. + It has the effect of updating a record field with a given value. + The remaining fields are left unchanged. It is the record + equivalent of an array store (see \sa Z3_mk_store). + If the datatype has more than one constructor, then the update function + behaves as identity if there is a miss-match between the accessor and + constructor. For example ((_ update-field car) nil 1) is nil, + while ((_ update-field car) (cons 2 nil) 1) is (cons 1 nil). + + + \pre Z3_get_sort_kind(Z3_get_sort(c, t)) == Z3_get_domain(c, field_access, 1) == Z3_DATATYPE_SORT + \pre Z3_get_sort(c, value) == Z3_get_range(c, field_access) + + + def_API('Z3_datatype_update_field', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(AST), _in(AST))) + */ + Z3_ast Z3_API Z3_datatype_update_field( + __in Z3_context c, __in Z3_func_decl field_access, + __in Z3_ast t, __in Z3_ast value); /** \brief Return arity of relation. @@ -3759,6 +3801,29 @@ END_MLAPI_EXCLUDE Z3_sort Z3_API Z3_get_relation_column(__in Z3_context c, __in Z3_sort s, unsigned col); + /** + \brief Pseudo-Boolean relations. + + Encode p1 + p2 + ... + pn <= k + + def_API('Z3_mk_atmost', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in(UINT))) + */ + + Z3_ast Z3_API Z3_mk_atmost(__in Z3_context c, __in unsigned num_args, + __in_ecount(num_args) Z3_ast const args[], __in unsigned k); + + /** + \brief Pseudo-Boolean relations. + + Encode k1*p1 + k2*p2 + ... + kn*pn <= k + + def_API('Z3_mk_pble', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in_array(1,INT), _in(INT))) + */ + + Z3_ast Z3_API Z3_mk_pble(__in Z3_context c, __in unsigned num_args, + __in_ecount(num_args) Z3_ast const args[], __in_ecount(num_args) int coeffs[], + __in int k); + /** \mlonly {3 {L Function Declarations}} \endmlonly */ @@ -3988,6 +4053,12 @@ END_MLAPI_EXCLUDE /** \brief Return a unique identifier for \c t. + The identifier is unique up to structural equality. Thus, two ast nodes + created by the same context and having the same children and same function symbols + have the same identifiers. Ast nodes created in the same context, but having + different children or different functions have different identifiers. + Variables and quantifiers are also assigned different identifiers according to + their structure. \mlonly \remark Implicitly used by [Pervasives.compare] for values of type [ast], [app], [sort], [func_decl], and [pattern]. \endmlonly def_API('Z3_get_ast_id', UINT, (_in(CONTEXT), _in(AST))) @@ -3996,6 +4067,8 @@ END_MLAPI_EXCLUDE /** \brief Return a hash code for the given AST. + The hash code is structural. You can use Z3_get_ast_id interchangably with + this function. \mlonly \remark Implicitly used by [Hashtbl.hash] for values of type [ast], [app], [sort], [func_decl], and [pattern]. \endmlonly def_API('Z3_get_ast_hash', UINT, (_in(CONTEXT), _in(AST))) @@ -5904,6 +5977,197 @@ END_MLAPI_EXCLUDE #endif #endif + + +#ifdef CorML4 + /** + @name Optimize facilities + */ + /*@{*/ + + /** + \brief Create a new optimize context. + + \conly \remark User must use #Z3_optimize_inc_ref and #Z3_optimize_dec_ref to manage optimize objects. + \conly Even if the context was created using #Z3_mk_context instead of #Z3_mk_context_rc. + + def_API('Z3_mk_optimize', OPTIMIZE, (_in(CONTEXT), )) + */ + Z3_optimize Z3_API Z3_mk_optimize(__in Z3_context c); + +#ifdef Conly + /** + \brief Increment the reference counter of the given optimize context + + def_API('Z3_optimize_inc_ref', VOID, (_in(CONTEXT), _in(OPTIMIZE))) + */ + void Z3_API Z3_optimize_inc_ref(__in Z3_context c,__in Z3_optimize d); + + /** + \brief Decrement the reference counter of the given optimize context. + + def_API('Z3_optimize_dec_ref', VOID, (_in(CONTEXT), _in(OPTIMIZE))) + */ + void Z3_API Z3_optimize_dec_ref(__in Z3_context c,__in Z3_optimize d); +#endif + + /** + \brief Assert hard constraint to the optimization context. + + def_API('Z3_optimize_assert', VOID, (_in(CONTEXT), _in(OPTIMIZE), _in(AST))) + */ + void Z3_API Z3_optimize_assert(Z3_context c, Z3_optimize o, Z3_ast a); + + + /** + \brief Assert soft constraint to the optimization context. + \param c - context + \param o - optimization context + \param a - formula + \param weight - a positive weight, penalty for violating soft constraint + \param id - optional identifier to group soft constraints + + def_API('Z3_optimize_assert_soft', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST), _in(STRING), _in(SYMBOL))) + */ + unsigned Z3_API Z3_optimize_assert_soft(Z3_context c, Z3_optimize o, Z3_ast a, Z3_string weight, Z3_symbol id); + + + /** + \brief Add a maximization constraint. + \param c - context + \param o - optimization context + \param a - arithmetical term + def_API('Z3_optimize_maximize', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST))) + */ + unsigned Z3_API Z3_optimize_maximize(Z3_context c, Z3_optimize o, Z3_ast t); + + /** + \brief Add a minimization constraint. + \param c - context + \param o - optimization context + \param a - arithmetical term + + def_API('Z3_optimize_minimize', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST))) + */ + unsigned Z3_API Z3_optimize_minimize(Z3_context c, Z3_optimize o, Z3_ast t); + + + /** + \brief Create a backtracking point. + + The optimize solver contains a set of rules, added facts and assertions. + The set of rules, facts and assertions are restored upon calling #Z3_optimize_pop. + + \sa Z3_optimize_pop + + def_API('Z3_optimize_push', VOID, (_in(CONTEXT), _in(OPTIMIZE))) + */ + void Z3_API Z3_optimize_push(Z3_context c,Z3_optimize d); + + /** + \brief Backtrack one level. + + \sa Z3_optimize_push + + \pre The number of calls to pop cannot exceed calls to push. + + def_API('Z3_optimize_pop', VOID, (_in(CONTEXT), _in(OPTIMIZE))) + */ + void Z3_API Z3_optimize_pop(Z3_context c,Z3_optimize d); + + /** + \brief Check consistency and produce optimal values. + \param c - context + \param o - optimization context + + def_API('Z3_optimize_check', INT, (_in(CONTEXT), _in(OPTIMIZE))) + */ + Z3_lbool Z3_API Z3_optimize_check(Z3_context c, Z3_optimize o); + + + /** + \brief Retrieve the model for the last #Z3_optimize_check + + The error handler is invoked if a model is not available because + the commands above were not invoked for the given optimization + solver, or if the result was \c Z3_L_FALSE. + + def_API('Z3_optimize_get_model', MODEL, (_in(CONTEXT), _in(OPTIMIZE))) + */ + Z3_model Z3_API Z3_optimize_get_model(Z3_context c, Z3_optimize o); + + /** + \brief Set parameters on optimization context. + + \param c - context + \param o - optimization context + \param p - parameters + + def_API('Z3_optimize_set_params', VOID, (_in(CONTEXT), _in(OPTIMIZE), _in(PARAMS))) + */ + void Z3_API Z3_optimize_set_params(Z3_context c, Z3_optimize o, Z3_params p); + + /** + \brief Return the parameter description set for the given optimize object. + + \param c - context + \param o - optimization context + + def_API('Z3_optimize_get_param_descrs', PARAM_DESCRS, (_in(CONTEXT), _in(OPTIMIZE))) + */ + Z3_param_descrs Z3_API Z3_optimize_get_param_descrs(Z3_context c, Z3_optimize o); + + /** + \brief Retrieve lower bound value or approximation for the i'th optimization objective. + + \param c - context + \param o - optimization context + \param idx - index of optimization objective + + def_API('Z3_optimize_get_lower', AST, (_in(CONTEXT), _in(OPTIMIZE), _in(UINT))) + */ + Z3_ast Z3_API Z3_optimize_get_lower(Z3_context c, Z3_optimize o, unsigned idx); + + /** + \brief Retrieve upper bound value or approximation for the i'th optimization objective. + + \param c - context + \param o - optimization context + \param idx - index of optimization objective + + def_API('Z3_optimize_get_upper', AST, (_in(CONTEXT), _in(OPTIMIZE), _in(UINT))) + */ + Z3_ast Z3_API Z3_optimize_get_upper(Z3_context c, Z3_optimize o, unsigned idx); + + /** + \brief Print the current context as a string. + \param c - context. + \param o - optimization context. + + def_API('Z3_optimize_to_string', STRING, (_in(CONTEXT), _in(OPTIMIZE))) + */ + Z3_string Z3_API Z3_optimize_to_string( + __in Z3_context c, + __in Z3_optimize o); + + + /** + \brief Return a string containing a description of parameters accepted by optimize. + + def_API('Z3_optimize_get_help', STRING, (_in(CONTEXT), _in(OPTIMIZE))) + */ + Z3_string Z3_API Z3_optimize_get_help(__in Z3_context c, __in Z3_optimize t); + + /** + \brief Retrieve statistics information from the last call to #Z3_optimize_check + + def_API('Z3_optimize_get_statistics', STATS, (_in(CONTEXT), _in(OPTIMIZE))) + */ + Z3_stats Z3_API Z3_optimize_get_statistics(__in Z3_context c,__in Z3_optimize d); + + +#endif + #ifdef CorML4 /*@}*/ diff --git a/src/api/z3_replayer.cpp b/src/api/z3_replayer.cpp index acdb10bf6..dd18f865c 100644 --- a/src/api/z3_replayer.cpp +++ b/src/api/z3_replayer.cpp @@ -22,12 +22,14 @@ Notes: #include"stream_buffer.h" #include"symbol.h" #include"trace.h" +#include void register_z3_replayer_cmds(z3_replayer & in); + void throw_invalid_reference() { TRACE("z3_replayer", tout << "invalid argument reference\n";); - throw z3_replayer_exception("invalid argument reference"); + throw z3_replayer_exception("invalid argument reference1"); } struct z3_replayer::imp { @@ -44,7 +46,37 @@ struct z3_replayer::imp { size_t_map m_heap; svector m_cmds; - enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY }; + enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, INT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY }; + + char const* kind2string(value_kind k) const { + switch (k) { + case INT64: return "int64"; + case UINT64: return "uint64"; + case DOUBLE: return "double"; + case STRING: return "string"; + case SYMBOL: return "symbol"; + case OBJECT: return "object"; + case UINT_ARRAY: return "uint_array"; + case INT_ARRAY: return "int_array"; + case SYMBOL_ARRAY: return "symbol_array"; + case OBJECT_ARRAY: return "object_array"; + default: UNREACHABLE(); return "unknown"; + } + } + + + void check_arg(unsigned pos, value_kind k) const { + if (pos >= m_args.size()) { + TRACE("z3_replayer", tout << "too few arguments " << m_args.size() << " expecting " << kind2string(k) << "\n";); + throw z3_replayer_exception("invalid argument reference2"); + } + if (m_args[pos].m_kind != k) { + std::stringstream strm; + strm << "expecting " << kind2string(k) << " at position " + << pos << " but got " << kind2string(m_args[pos].m_kind); + throw z3_replayer_exception(strm.str().c_str()); + } + } struct value { value_kind m_kind; @@ -68,6 +100,7 @@ struct z3_replayer::imp { vector > m_obj_arrays; vector > m_sym_arrays; vector m_unsigned_arrays; + vector > m_int_arrays; imp(z3_replayer & o, std::istream & in): m_owner(o), @@ -295,6 +328,15 @@ struct z3_replayer::imp { v.push_back(static_cast(m_args[i].m_uint)); } } + if (k == INT64) { + aidx = m_int_arrays.size(); + nk = INT_ARRAY; + m_int_arrays.push_back(svector()); + svector & v = m_int_arrays.back(); + for (unsigned i = asz - sz; i < asz; i++) { + v.push_back(static_cast(m_args[i].m_int)); + } + } else if (k == SYMBOL) { aidx = m_sym_arrays.size(); nk = SYMBOL_ARRAY; @@ -457,8 +499,7 @@ struct z3_replayer::imp { next(); skip_blank(); read_ptr(); skip_blank(); read_uint64(); unsigned pos = static_cast(m_uint64); TRACE("z3_replayer", tout << "[" << m_line << "] " << "* " << m_ptr << " " << pos << "\n";); - if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT) - throw_invalid_reference(); + check_arg(pos, OBJECT); m_heap.insert(m_ptr, m_args[pos].m_obj); break; } @@ -467,8 +508,7 @@ struct z3_replayer::imp { // @ obj_id array_pos idx next(); skip_blank(); read_ptr(); skip_blank(); read_uint64(); unsigned pos = static_cast(m_uint64); - if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT_ARRAY) - throw_invalid_reference(); + check_arg(pos, OBJECT_ARRAY); unsigned aidx = static_cast(m_args[pos].m_uint); ptr_vector & v = m_obj_arrays[aidx]; skip_blank(); read_uint64(); @@ -493,70 +533,65 @@ struct z3_replayer::imp { } int get_int(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != INT64) - throw_invalid_reference(); + check_arg(pos, INT64); return static_cast(m_args[pos].m_int); } __int64 get_int64(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != INT64) - throw_invalid_reference(); + check_arg(pos, INT64); return m_args[pos].m_int; } unsigned get_uint(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != UINT64) - throw_invalid_reference(); + check_arg(pos, UINT64); return static_cast(m_args[pos].m_uint); } __uint64 get_uint64(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != UINT64) - throw_invalid_reference(); + check_arg(pos, UINT64); return m_args[pos].m_uint; } double get_double(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != DOUBLE) - throw_invalid_reference(); + check_arg(pos, DOUBLE); return m_args[pos].m_double; } Z3_string get_str(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != STRING) - throw_invalid_reference(); + check_arg(pos, STRING); return m_args[pos].m_str; } Z3_symbol get_symbol(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != SYMBOL) - throw_invalid_reference(); + check_arg(pos, SYMBOL); return reinterpret_cast(const_cast(m_args[pos].m_str)); } void * get_obj(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT) - throw_invalid_reference(); + check_arg(pos, OBJECT); return m_args[pos].m_obj; } unsigned * get_uint_array(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != UINT_ARRAY) - throw_invalid_reference(); + check_arg(pos, UINT_ARRAY); unsigned idx = static_cast(m_args[pos].m_uint); return m_unsigned_arrays[idx].c_ptr(); } + int * get_int_array(unsigned pos) const { + check_arg(pos, INT_ARRAY); + unsigned idx = static_cast(m_args[pos].m_uint); + return m_int_arrays[idx].c_ptr(); + } + Z3_symbol * get_symbol_array(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != SYMBOL_ARRAY) - throw_invalid_reference(); + check_arg(pos, SYMBOL_ARRAY); unsigned idx = static_cast(m_args[pos].m_uint); return m_sym_arrays[idx].c_ptr(); } void ** get_obj_array(unsigned pos) const { - if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT_ARRAY) - throw_invalid_reference(); + check_arg(pos, OBJECT_ARRAY); unsigned idx = static_cast(m_args[pos].m_uint); ptr_vector const & v = m_obj_arrays[idx]; TRACE("z3_replayer_bug", tout << "pos: " << pos << ", idx: " << idx << " size(): " << v.size() << "\n"; @@ -565,38 +600,32 @@ struct z3_replayer::imp { } int * get_int_addr(unsigned pos) { - if (pos >= m_args.size() || m_args[pos].m_kind != INT64) - throw_invalid_reference(); + check_arg(pos, INT64); return reinterpret_cast(&(m_args[pos].m_int)); } __int64 * get_int64_addr(unsigned pos) { - if (pos >= m_args.size() || m_args[pos].m_kind != INT64) - throw_invalid_reference(); + check_arg(pos, INT64); return &(m_args[pos].m_int); } unsigned * get_uint_addr(unsigned pos) { - if (pos >= m_args.size() || m_args[pos].m_kind != UINT64) - throw_invalid_reference(); + check_arg(pos, UINT64); return reinterpret_cast(&(m_args[pos].m_uint)); } __uint64 * get_uint64_addr(unsigned pos) { - if (pos >= m_args.size() || m_args[pos].m_kind != UINT64) - throw_invalid_reference(); + check_arg(pos, UINT64); return &(m_args[pos].m_uint); } Z3_string * get_str_addr(unsigned pos) { - if (pos >= m_args.size() || m_args[pos].m_kind != STRING) - throw_invalid_reference(); + check_arg(pos, STRING); return &(m_args[pos].m_str); } void ** get_obj_addr(unsigned pos) { - if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT) - throw_invalid_reference(); + check_arg(pos, OBJECT); return &(m_args[pos].m_obj); } @@ -615,6 +644,7 @@ struct z3_replayer::imp { m_obj_arrays.reset(); m_sym_arrays.reset(); m_unsigned_arrays.reset(); + m_int_arrays.reset(); } @@ -673,6 +703,10 @@ unsigned * z3_replayer::get_uint_array(unsigned pos) const { return m_imp->get_uint_array(pos); } +int * z3_replayer::get_int_array(unsigned pos) const { + return m_imp->get_int_array(pos); +} + Z3_symbol * z3_replayer::get_symbol_array(unsigned pos) const { return m_imp->get_symbol_array(pos); } diff --git a/src/api/z3_replayer.h b/src/api/z3_replayer.h index 6de4bdb39..412032eb7 100644 --- a/src/api/z3_replayer.h +++ b/src/api/z3_replayer.h @@ -49,6 +49,7 @@ public: void * get_obj(unsigned pos) const; unsigned * get_uint_array(unsigned pos) const; + int * get_int_array(unsigned pos) const; Z3_symbol * get_symbol_array(unsigned pos) const; void ** get_obj_array(unsigned pos) const; diff --git a/src/ast/arith_decl_plugin.cpp b/src/ast/arith_decl_plugin.cpp index 9d1f4343f..5245b9685 100644 --- a/src/ast/arith_decl_plugin.cpp +++ b/src/ast/arith_decl_plugin.cpp @@ -417,6 +417,7 @@ inline decl_kind arith_decl_plugin::fix_kind(decl_kind k, unsigned arity) { app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) { if (is_int && !val.is_int()) { + SASSERT(false); m_manager->raise_exception("invalid rational value passed as an integer"); } if (val.is_unsigned()) { diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 68f7596ee..47079f4c6 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -1013,6 +1013,17 @@ func_decl * basic_decl_plugin::mk_ite_decl(sort * s) { return m_ite_decls[id]; } +sort* basic_decl_plugin::join(sort* s1, sort* s2) { + if (s1 == s2) return s1; + if (s1->get_family_id() == m_manager->m_arith_family_id && + s2->get_family_id() == m_manager->m_arith_family_id) { + if (s1->get_decl_kind() == REAL_SORT) { + return s1; + } + } + return s2; +} + func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { switch (static_cast(k)) { @@ -1025,10 +1036,10 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters case OP_IFF: return m_iff_decl; case OP_IMPLIES: return m_implies_decl; case OP_XOR: return m_xor_decl; - case OP_ITE: return arity == 3 ? mk_ite_decl(domain[1]) : 0; + case OP_ITE: return arity == 3 ? mk_ite_decl(join(domain[1], domain[2])) : 0; // eq and oeq must have at least two arguments, they can have more since they are chainable - case OP_EQ: return arity >= 2 ? mk_eq_decl_core("=", OP_EQ, domain[0], m_eq_decls) : 0; - case OP_OEQ: return arity >= 2 ? mk_eq_decl_core("~", OP_OEQ, domain[0], m_oeq_decls) : 0; + case OP_EQ: return arity >= 2 ? mk_eq_decl_core("=", OP_EQ, join(domain[0],domain[1]), m_eq_decls) : 0; + case OP_OEQ: return arity >= 2 ? mk_eq_decl_core("~", OP_OEQ, join(domain[0],domain[1]), m_oeq_decls) : 0; case OP_DISTINCT: { func_decl_info info(m_family_id, OP_DISTINCT); info.set_pairwise(); @@ -1061,10 +1072,12 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters case OP_IFF: return m_iff_decl; case OP_IMPLIES: return m_implies_decl; case OP_XOR: return m_xor_decl; - case OP_ITE: return num_args == 3 ? mk_ite_decl(m_manager->get_sort(args[1])): 0; + case OP_ITE: return num_args == 3 ? mk_ite_decl(join(m_manager->get_sort(args[1]), m_manager->get_sort(args[2]))): 0; // eq and oeq must have at least two arguments, they can have more since they are chainable - case OP_EQ: return num_args >= 2 ? mk_eq_decl_core("=", OP_EQ, m_manager->get_sort(args[0]), m_eq_decls) : 0; - case OP_OEQ: return num_args >= 2 ? mk_eq_decl_core("~", OP_OEQ, m_manager->get_sort(args[0]), m_oeq_decls) : 0; + case OP_EQ: return num_args >= 2 ? mk_eq_decl_core("=", OP_EQ, join(m_manager->get_sort(args[0]), + m_manager->get_sort(args[1])), m_eq_decls) : 0; + case OP_OEQ: return num_args >= 2 ? mk_eq_decl_core("~", OP_OEQ, join(m_manager->get_sort(args[0]), + m_manager->get_sort(args[1])), m_oeq_decls) : 0; case OP_DISTINCT: return decl_plugin::mk_func_decl(k, num_parameters, parameters, num_args, args, range); default: @@ -2058,6 +2071,8 @@ app * ast_manager::mk_app(func_decl * decl, unsigned num_args, expr * const * ar return r; } + + func_decl * ast_manager::mk_fresh_func_decl(symbol const & prefix, symbol const & suffix, unsigned arity, sort * const * domain, sort * range) { func_decl_info info(null_family_id, null_decl_kind); diff --git a/src/ast/ast.h b/src/ast/ast.h index 68f08e1ac..c336174f5 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -1100,6 +1100,7 @@ protected: virtual void set_manager(ast_manager * m, family_id id); func_decl * mk_eq_decl_core(char const * name, decl_kind k, sort * s, ptr_vector & cache); func_decl * mk_ite_decl(sort * s); + sort* join(sort* s1, sort* s2); public: basic_decl_plugin(); @@ -1378,7 +1379,7 @@ enum proof_gen_mode { // ----------------------------------- class ast_manager { -protected: + friend class basic_decl_plugin; protected: struct config { typedef ast_manager value_manager; @@ -2005,6 +2006,7 @@ public: app * mk_false() { return m_false; } app * mk_interp(expr * arg) { return mk_app(m_basic_family_id, OP_INTERP, arg); } + func_decl* mk_and_decl() { sort* domain[2] = { m_bool_sort, m_bool_sort }; return mk_func_decl(m_basic_family_id, OP_AND, 0, 0, 2, domain); diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index 77c8ac58f..cf2c0478f 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -77,6 +77,8 @@ bool smt2_pp_environment::is_indexed_fdecl(func_decl * f) const { for (i = 0; i < num; i++) { if (f->get_parameter(i).is_int()) continue; + if (f->get_parameter(i).is_rational()) + continue; if (f->get_parameter(i).is_ast() && is_func_decl(f->get_parameter(i).get_ast())) continue; break; @@ -105,9 +107,13 @@ format * smt2_pp_environment::pp_fdecl_params(format * fname, func_decl * f) { ptr_buffer fs; fs.push_back(fname); for (unsigned i = 0; i < num; i++) { - SASSERT(f->get_parameter(i).is_int() || (f->get_parameter(i).is_ast() && is_func_decl(f->get_parameter(i).get_ast()))); + SASSERT(f->get_parameter(i).is_int() || + f->get_parameter(i).is_rational() || + (f->get_parameter(i).is_ast() && is_func_decl(f->get_parameter(i).get_ast()))); if (f->get_parameter(i).is_int()) fs.push_back(mk_int(get_manager(), f->get_parameter(i).get_int())); + else if (f->get_parameter(i).is_rational()) + fs.push_back(mk_string(get_manager(), f->get_parameter(i).get_rational().to_string().c_str())); else fs.push_back(pp_fdecl_ref(to_func_decl(f->get_parameter(i).get_ast()))); } @@ -1126,6 +1132,26 @@ std::ostream& operator<<(std::ostream& out, mk_ismt2_pp const & p) { return out; } +std::ostream& operator<<(std::ostream& out, expr_ref const& e) { + return out << mk_ismt2_pp(e.get(), e.get_manager()); +} + +std::ostream& operator<<(std::ostream& out, app_ref const& e) { + return out << mk_ismt2_pp(e.get(), e.get_manager()); +} + +std::ostream& operator<<(std::ostream& out, expr_ref_vector const& e) { + for (unsigned i = 0; i < e.size(); ++i) + out << mk_ismt2_pp(e[i], e.get_manager()) << "\n"; + return out; +} + +std::ostream& operator<<(std::ostream& out, app_ref_vector const& e) { + for (unsigned i = 0; i < e.size(); ++i) + out << mk_ismt2_pp(e[i], e.get_manager()) << "\n"; + return out; +} + #ifdef Z3DEBUG void pp(expr const * n, ast_manager & m) { std::cout << mk_ismt2_pp(const_cast(n), m) << std::endl; diff --git a/src/ast/ast_smt2_pp.h b/src/ast/ast_smt2_pp.h index aa84d6e03..68d669a5e 100644 --- a/src/ast/ast_smt2_pp.h +++ b/src/ast/ast_smt2_pp.h @@ -110,4 +110,10 @@ struct mk_ismt2_pp { std::ostream& operator<<(std::ostream& out, mk_ismt2_pp const & p); +std::ostream& operator<<(std::ostream& out, expr_ref const& e); +std::ostream& operator<<(std::ostream& out, app_ref const& e); + +std::ostream& operator<<(std::ostream& out, expr_ref_vector const& e); +std::ostream& operator<<(std::ostream& out, app_ref_vector const& e); + #endif diff --git a/src/ast/ast_smt_pp.cpp b/src/ast/ast_smt_pp.cpp index 59e5c04b9..0484753c5 100644 --- a/src/ast/ast_smt_pp.cpp +++ b/src/ast/ast_smt_pp.cpp @@ -1058,7 +1058,8 @@ void ast_smt_pp::display_ast_smt2(std::ostream& strm, ast* a, unsigned indent, u void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) { ptr_vector ql; - decl_collector decls(m_manager); + ast_manager& m = m_manager; + decl_collector decls(m); smt_renaming rn; for (unsigned i = 0; i < m_assumptions.size(); ++i) { @@ -1069,7 +1070,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) { } decls.visit(n); - if (m_manager.is_proof(n)) { + if (m.is_proof(n)) { strm << "("; } if (m_benchmark_name != symbol::null) { @@ -1078,7 +1079,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) { if (m_source_info != symbol::null && m_source_info != symbol("")) { strm << "; :source { " << m_source_info << " }\n"; } - if (m_manager.is_bool(n)) { + if (m.is_bool(n)) { strm << "(set-info :status " << m_status << ")\n"; } if (m_category != symbol::null && m_category != symbol("")) { @@ -1095,7 +1096,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) { for (unsigned i = 0; i < decls.get_num_sorts(); ++i) { sort* s = decls.get_sorts()[i]; if (!(*m_is_declared)(s)) { - smt_printer p(strm, m_manager, ql, rn, m_logic, true, true, m_simplify_implies, 0); + smt_printer p(strm, m, ql, rn, m_logic, true, true, m_simplify_implies, 0); p.pp_sort_decl(sort_mark, s); } } @@ -1103,7 +1104,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) { for (unsigned i = 0; i < decls.get_num_decls(); ++i) { func_decl* d = decls.get_func_decls()[i]; if (!(*m_is_declared)(d)) { - smt_printer p(strm, m_manager, ql, rn, m_logic, true, true, m_simplify_implies, 0); + smt_printer p(strm, m, ql, rn, m_logic, true, true, m_simplify_implies, 0); p(d); strm << "\n"; } @@ -1112,34 +1113,36 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) { for (unsigned i = 0; i < decls.get_num_preds(); ++i) { func_decl* d = decls.get_pred_decls()[i]; if (!(*m_is_declared)(d)) { - smt_printer p(strm, m_manager, ql, rn, m_logic, true, true, m_simplify_implies, 0); + smt_printer p(strm, m, ql, rn, m_logic, true, true, m_simplify_implies, 0); p(d); strm << "\n"; } } for (unsigned i = 0; i < m_assumptions.size(); ++i) { - strm << "(assert\n"; - smt_printer p(strm, m_manager, ql, rn, m_logic, false, true, m_simplify_implies, 0); - p(m_assumptions[i].get()); - strm << ")\n"; + smt_printer p(strm, m, ql, rn, m_logic, false, true, m_simplify_implies, 1); + strm << "(assert\n "; + p(m_assumptions[i].get()); + strm << ")\n"; } for (unsigned i = 0; i < m_assumptions_star.size(); ++i) { - strm << "(assert\n"; - smt_printer p(strm, m_manager, ql, rn, m_logic, false, true, m_simplify_implies, 0); - p(m_assumptions_star[i].get()); + smt_printer p(strm, m, ql, rn, m_logic, false, true, m_simplify_implies, 1); + strm << "(assert\n "; + p(m_assumptions_star[i].get()); strm << ")\n"; } - smt_printer p(strm, m_manager, ql, rn, m_logic, false, true, m_simplify_implies, 0); - if (m_manager.is_bool(n)) { - strm << "(assert\n"; - p(n); - strm << ")\n"; + smt_printer p(strm, m, ql, rn, m_logic, false, true, m_simplify_implies, 0); + if (m.is_bool(n)) { + if (!m.is_true(n)) { + strm << "(assert\n "; + p(n); + strm << ")\n"; + } strm << "(check-sat)\n"; } - else if (m_manager.is_proof(n)) { + else if (m.is_proof(n)) { strm << "(proof\n"; p(n); strm << "))\n"; diff --git a/src/ast/ast_trail.h b/src/ast/ast_trail.h new file mode 100644 index 000000000..94039875e --- /dev/null +++ b/src/ast/ast_trail.h @@ -0,0 +1,76 @@ +/*++ +Copyright (c) 2006 Microsoft Corporation + +Module Name: + + ast_trail.h + +Abstract: + + + +Author: + + Leonardo de Moura (leonardo) 2008-06-02. + +Revision History: + + Extracted AST specific features from trail.h + nbjorner 2014-9-28 + +--*/ +#ifndef _AST_TRAIL_H_ +#define _AST_TRAIL_H_ + +#include"ast.h" +#include"trail.h" + + +template +class ast2ast_trailmap { + ref_vector m_domain; + ref_vector m_range; + obj_map m_map; +public: + ast2ast_trailmap(ast_manager& m): + m_domain(m), + m_range(m), + m_map() + {} + + bool find(S* s, T*& t) { + return m_map.find(s,t); + } + + void insert(S* s, T* t) { + SASSERT(!m_map.contains(s)); + m_domain.push_back(s); + m_range.push_back(t); + m_map.insert(s,t); + } + + void pop() { + SASSERT(!m_domain.empty()); + m_map.remove(m_domain.back()); + m_domain.pop_back(); + m_range.pop_back(); + } +}; + +template +class ast2ast_trail : public trail { + ast2ast_trailmap& m_map; +public: + ast2ast_trail(ast2ast_trailmap& m, S* s, T* t) : + m_map(m) { + m.insert(s,t); + } + + virtual void undo(Ctx& ctx) { + m_map.pop(); + } +}; + + +#endif /* _AST_TRAIL_H_ */ + diff --git a/src/ast/datatype_decl_plugin.cpp b/src/ast/datatype_decl_plugin.cpp index ee3271b9b..d707f0178 100644 --- a/src/ast/datatype_decl_plugin.cpp +++ b/src/ast/datatype_decl_plugin.cpp @@ -422,8 +422,55 @@ static sort * get_type(ast_manager & m, family_id datatype_fid, sort * source_da } } +func_decl * datatype_decl_plugin::mk_update_field( + unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { + decl_kind k = OP_DT_UPDATE_FIELD; + ast_manager& m = *m_manager; + + if (num_parameters != 1 || !parameters[0].is_ast()) { + m.raise_exception("invalid parameters for datatype field update"); + return 0; + } + if (arity != 2) { + m.raise_exception("invalid number of arguments for datatype field update"); + return 0; + } + func_decl* acc = 0; + if (is_func_decl(parameters[0].get_ast())) { + acc = to_func_decl(parameters[0].get_ast()); + } + if (acc && !get_util().is_accessor(acc)) { + acc = 0; + } + if (!acc) { + m.raise_exception("datatype field update requires a datatype accessor as the second argument"); + return 0; + } + sort* dom = acc->get_domain(0); + sort* rng = acc->get_range(); + if (dom != domain[0]) { + m.raise_exception("first argument to field update should be a data-type"); + return 0; + } + if (rng != domain[1]) { + std::ostringstream buffer; + buffer << "second argument to field update should be " << mk_ismt2_pp(rng, m) + << " instead of " << mk_ismt2_pp(domain[1], m); + m.raise_exception(buffer.str().c_str()); + return 0; + } + range = domain[0]; + func_decl_info info(m_family_id, k, num_parameters, parameters); + return m.mk_func_decl(symbol("update_field"), arity, domain, range, info); +} + func_decl * datatype_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { + + if (k == OP_DT_UPDATE_FIELD) { + return mk_update_field(num_parameters, parameters, arity, domain, range); + } if (num_parameters < 2 || !parameters[0].is_ast() || !is_sort(parameters[0].get_ast())) { m_manager->raise_exception("invalid parameters for datatype operator"); return 0; @@ -521,6 +568,9 @@ func_decl * datatype_decl_plugin::mk_func_decl(decl_kind k, unsigned num_paramet return m_manager->mk_func_decl(a_name, arity, domain, a_type, info); } break; + case OP_DT_UPDATE_FIELD: + UNREACHABLE(); + return 0; default: m_manager->raise_exception("invalid datatype operator kind"); return 0; @@ -672,6 +722,13 @@ bool datatype_decl_plugin::is_value(app * e) const { return true; } +void datatype_decl_plugin::get_op_names(svector & op_names, symbol const & logic) { + if (logic == symbol::null) { + op_names.push_back(builtin_name("update-field", OP_DT_UPDATE_FIELD)); + } +} + + datatype_util::datatype_util(ast_manager & m): m_manager(m), m_family_id(m.mk_family_id("datatype")), @@ -919,9 +976,9 @@ void datatype_util::display_datatype(sort *s0, std::ostream& strm) { todo.push_back(s0); mark.mark(s0, true); while (!todo.empty()) { - sort* s = todo.back(); + sort* s = todo.back(); todo.pop_back(); - strm << s->get_name() << " =\n"; + strm << s->get_name() << " =\n"; ptr_vector const * cnstrs = get_datatype_constructors(s); for (unsigned i = 0; i < cnstrs->size(); ++i) { @@ -931,14 +988,14 @@ void datatype_util::display_datatype(sort *s0, std::ostream& strm) { ptr_vector const * accs = get_constructor_accessors(cns); for (unsigned j = 0; j < accs->size(); ++j) { func_decl* acc = (*accs)[j]; - sort* s1 = acc->get_range(); + sort* s1 = acc->get_range(); strm << "(" << acc->get_name() << ": " << s1->get_name() << ") "; if (is_datatype(s1) && are_siblings(s1, s0) && !mark.is_marked(s1)) { mark.mark(s1, true); todo.push_back(s1); } } - strm << "\n"; + strm << "\n"; } } diff --git a/src/ast/datatype_decl_plugin.h b/src/ast/datatype_decl_plugin.h index 96b678fb2..2218963c3 100644 --- a/src/ast/datatype_decl_plugin.h +++ b/src/ast/datatype_decl_plugin.h @@ -32,6 +32,7 @@ enum datatype_op_kind { OP_DT_CONSTRUCTOR, OP_DT_RECOGNISER, OP_DT_ACCESSOR, + OP_DT_UPDATE_FIELD, LAST_DT_OP }; @@ -149,8 +150,14 @@ public: virtual bool is_unique_value(app * e) const { return is_value(e); } + virtual void get_op_names(svector & op_names, symbol const & logic); + private: bool is_value_visit(expr * arg, ptr_buffer & todo) const; + + func_decl * mk_update_field( + unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); }; class datatype_util { @@ -181,9 +188,11 @@ public: bool is_constructor(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_CONSTRUCTOR); } bool is_recognizer(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_RECOGNISER); } bool is_accessor(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_ACCESSOR); } + bool is_update_field(func_decl * f) const { return is_decl_of(f, m_family_id, OP_DT_UPDATE_FIELD); } bool is_constructor(app * f) const { return is_app_of(f, m_family_id, OP_DT_CONSTRUCTOR); } bool is_recognizer(app * f) const { return is_app_of(f, m_family_id, OP_DT_RECOGNISER); } bool is_accessor(app * f) const { return is_app_of(f, m_family_id, OP_DT_ACCESSOR); } + bool is_update_field(app * f) const { return is_app_of(f, m_family_id, OP_DT_UPDATE_FIELD); } ptr_vector const * get_datatype_constructors(sort * ty); unsigned get_datatype_num_constructors(sort * ty) { return get_datatype_constructors(ty)->size(); } unsigned get_constructor_idx(func_decl * f) const { SASSERT(is_constructor(f)); return f->get_parameter(1).get_int(); } diff --git a/src/ast/expr_map.h b/src/ast/expr_map.h index 5ab6545f8..3e6f71e86 100644 --- a/src/ast/expr_map.h +++ b/src/ast/expr_map.h @@ -44,6 +44,10 @@ public: void erase(expr * k); void reset(); void flush(); + void set_store_proofs(bool f) { + if (m_store_proofs != f) flush(); + m_store_proofs = f; + } }; #endif diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 5f92b4d94..c23de3bfa 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2155,15 +2155,15 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg SASSERT(f->get_num_parameters() == 1); SASSERT(f->get_parameter(0).is_int()); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - int width = f->get_parameter(0).get_int(); + //unsigned ebits = m_util.get_ebits(f->get_range()); + //unsigned sbits = m_util.get_sbits(f->get_range()); + //int width = f->get_parameter(0).get_int(); - expr * rm = args[0]; - expr * x = args[1]; + //expr * rm = args[0]; + //expr * x = args[1]; - expr * sgn, *s, *e; - split(x, sgn, s, e); + //expr * sgn, *s, *e; + //split(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } @@ -2173,15 +2173,15 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg SASSERT(f->get_num_parameters() == 1); SASSERT(f->get_parameter(0).is_int()); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - int width = f->get_parameter(0).get_int(); + //unsigned ebits = m_util.get_ebits(f->get_range()); + //unsigned sbits = m_util.get_sbits(f->get_range()); + //int width = f->get_parameter(0).get_int(); - expr * rm = args[0]; - expr * x = args[1]; + //expr * rm = args[0]; + //expr * x = args[1]; - expr * sgn, *s, *e; - split(x, sgn, s, e); + //expr * sgn, *s, *e; + //split(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } @@ -2189,15 +2189,15 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - int width = f->get_parameter(0).get_int(); + //unsigned ebits = m_util.get_ebits(f->get_range()); + //unsigned sbits = m_util.get_sbits(f->get_range()); + //int width = f->get_parameter(0).get_int(); - expr * rm = args[0]; - expr * x = args[1]; + //expr * rm = args[0]; + //expr * x = args[1]; - expr * sgn, *s, *e; - split(x, sgn, s, e); + //expr * sgn, *s, *e; + //split(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } diff --git a/src/ast/macros/macro_manager.cpp b/src/ast/macros/macro_manager.cpp index abcc97882..75b4e55f4 100644 --- a/src/ast/macros/macro_manager.cpp +++ b/src/ast/macros/macro_manager.cpp @@ -255,9 +255,9 @@ bool macro_manager::macro_expander::get_subst(expr * _n, expr_ref & r, proof_ref app * n = to_app(_n); quantifier * q = 0; func_decl * d = n->get_decl(); - TRACE("macro_manager_bug", tout << "trying to expand:\n" << mk_pp(n, m_manager) << "\nd:\n" << d->get_name() << "\n";); + TRACE("macro_manager_bug", tout << "trying to expand:\n" << mk_pp(n, m) << "\nd:\n" << d->get_name() << "\n";); if (m_macro_manager.m_decl2macro.find(d, q)) { - TRACE("macro_manager", tout << "expanding: " << mk_pp(n, m_manager) << "\n";); + TRACE("macro_manager", tout << "expanding: " << mk_pp(n, m) << "\n";); app * head = 0; expr * def = 0; m_macro_manager.get_head_def(q, d, head, def); @@ -272,17 +272,17 @@ bool macro_manager::macro_expander::get_subst(expr * _n, expr_ref & r, proof_ref SASSERT(subst_args[nidx] == 0); subst_args[nidx] = n->get_arg(i); } - var_subst s(m_manager); + var_subst s(m); s(def, num, subst_args.c_ptr(), r); - if (m_manager.proofs_enabled()) { - expr_ref instance(m_manager); + if (m.proofs_enabled()) { + expr_ref instance(m); s(q->get_expr(), num, subst_args.c_ptr(), instance); - proof * qi_pr = m_manager.mk_quant_inst(m_manager.mk_or(m_manager.mk_not(q), instance), num, subst_args.c_ptr()); + proof * qi_pr = m.mk_quant_inst(m.mk_or(m.mk_not(q), instance), num, subst_args.c_ptr()); proof * q_pr = 0; m_macro_manager.m_decl2macro_pr.find(d, q_pr); SASSERT(q_pr != 0); proof * prs[2] = { qi_pr, q_pr }; - p = m_manager.mk_unit_resolution(2, prs); + p = m.mk_unit_resolution(2, prs); } else { p = 0; diff --git a/src/ast/pattern/pattern_inference.cpp b/src/ast/pattern/pattern_inference.cpp index 83362f5b3..b93dd7657 100644 --- a/src/ast/pattern/pattern_inference.cpp +++ b/src/ast/pattern/pattern_inference.cpp @@ -116,7 +116,7 @@ void pattern_inference::collect::operator()(expr * n, unsigned num_bindings) { n = e.m_node; unsigned delta = e.m_delta; TRACE("collect", tout << "processing: " << n->get_id() << " " << delta << " kind: " << n->get_kind() << "\n";); - TRACE("collect_info", tout << mk_pp(n, m_manager) << "\n";); + TRACE("collect_info", tout << mk_pp(n, m) << "\n";); if (visit_children(n, delta)) { m_todo.pop_back(); save_candidate(n, delta); @@ -170,9 +170,9 @@ void pattern_inference::collect::save_candidate(expr * n, unsigned delta) { free_vars.insert(idx); info * i = 0; if (delta == 0) - i = alloc(info, m_manager, n, free_vars, 1); + i = alloc(info, m, n, free_vars, 1); else - i = alloc(info, m_manager, m_manager.mk_var(idx, to_var(n)->get_sort()), free_vars, 1); + i = alloc(info, m, m.mk_var(idx, to_var(n)->get_sort()), free_vars, 1); save(n, delta, i); } else { @@ -189,7 +189,7 @@ void pattern_inference::collect::save_candidate(expr * n, unsigned delta) { } if (c->get_num_args() == 0) { - save(n, delta, alloc(info, m_manager, n, uint_set(), 1)); + save(n, delta, alloc(info, m, n, uint_set(), 1)); return; } @@ -219,10 +219,10 @@ void pattern_inference::collect::save_candidate(expr * n, unsigned delta) { app * new_node = 0; if (changed) - new_node = m_manager.mk_app(decl, buffer.size(), buffer.c_ptr()); + new_node = m.mk_app(decl, buffer.size(), buffer.c_ptr()); else new_node = to_app(n); - save(n, delta, alloc(info, m_manager, new_node, free_vars, size)); + save(n, delta, alloc(info, m, new_node, free_vars, size)); // Remark: arithmetic patterns are only used if they are nested inside other terms. // That is, we never consider x + 1 as pattern. On the other hand, f(x+1) can be a pattern // if arithmetic is not in the forbidden list. @@ -235,7 +235,7 @@ void pattern_inference::collect::save_candidate(expr * n, unsigned delta) { decl_kind k = c->get_decl_kind(); if (!free_vars.empty() && (fid != m_afid || (fid == m_afid && !m_owner.m_nested_arith_only && (k == OP_DIV || k == OP_IDIV || k == OP_MOD || k == OP_REM || k == OP_MUL)))) { - TRACE("pattern_inference", tout << "potential candidate: \n" << mk_pp(new_node, m_manager) << "\n";); + TRACE("pattern_inference", tout << "potential candidate: \n" << mk_pp(new_node, m) << "\n";); m_owner.add_candidate(new_node, free_vars, size); } return; @@ -338,7 +338,7 @@ bool pattern_inference::contains_subpattern::operator()(expr * n) { uint_set const & s2 = e->get_data().m_value.m_free_vars; SASSERT(s2.subset_of(s1)); if (s1 == s2) { - TRACE("pattern_inference", tout << mk_pp(n, m_owner.m_manager) << "\nis bigger than\n" << mk_pp(to_app(curr), m_owner.m_manager) << "\n";); + TRACE("pattern_inference", tout << mk_pp(n, m_owner.m) << "\nis bigger than\n" << mk_pp(to_app(curr), m_owner.m) << "\n";); return true; } } @@ -411,7 +411,7 @@ void pattern_inference::candidates2unary_patterns(ptr_vector const & candid expr2info::obj_map_entry * e = m_candidates_info.find_core(candidate); info const & i = e->get_data().m_value; if (i.m_free_vars.num_elems() == m_num_bindings) { - app * new_pattern = m_manager.mk_pattern(candidate); + app * new_pattern = m.mk_pattern(candidate); result.push_back(new_pattern); } else { @@ -435,7 +435,7 @@ void pattern_inference::candidates2multi_patterns(unsigned max_num_patterns, for (unsigned j = 0; j < m_pre_patterns.size(); j++) { pre_pattern * curr = m_pre_patterns[j]; if (curr->m_free_vars.num_elems() == m_num_bindings) { - app * new_pattern = m_manager.mk_pattern(curr->m_exprs.size(), curr->m_exprs.c_ptr()); + app * new_pattern = m.mk_pattern(curr->m_exprs.size(), curr->m_exprs.c_ptr()); result.push_back(new_pattern); if (result.size() >= max_num_patterns) return; @@ -489,7 +489,7 @@ bool pattern_inference::is_forbidden(app * n) const { // occur outside of the quantifier. That is, Z3 will never match this kind of // pattern. if (m_params.m_pi_avoid_skolems && decl->is_skolem()) { - CTRACE("pattern_inference_skolem", decl->is_skolem(), tout << "ignoring: " << mk_pp(n, m_manager) << "\n";); + CTRACE("pattern_inference_skolem", decl->is_skolem(), tout << "ignoring: " << mk_pp(n, m) << "\n";); return true; } if (is_forbidden(decl)) @@ -509,8 +509,8 @@ bool pattern_inference::has_preferred_patterns(ptr_vector & candidate_patte expr2info::obj_map_entry * e = m_candidates_info.find_core(candidate); info const & i = e->get_data().m_value; if (i.m_free_vars.num_elems() == m_num_bindings) { - TRACE("pattern_inference", tout << "found preferred pattern:\n" << mk_pp(candidate, m_manager) << "\n";); - app * p = m_manager.mk_pattern(candidate); + TRACE("pattern_inference", tout << "found preferred pattern:\n" << mk_pp(candidate, m) << "\n";); + app * p = m.mk_pattern(candidate); result.push_back(p); found = true; } @@ -531,11 +531,11 @@ void pattern_inference::mk_patterns(unsigned num_bindings, m_collect(n, num_bindings); TRACE("pattern_inference", - tout << mk_pp(n, m_manager); + tout << mk_pp(n, m); tout << "\ncandidates:\n"; unsigned num = m_candidates.size(); for (unsigned i = 0; i < num; i++) { - tout << mk_pp(m_candidates.get(i), m_manager) << "\n"; + tout << mk_pp(m_candidates.get(i), m) << "\n"; }); if (!m_candidates.empty()) { @@ -543,7 +543,7 @@ void pattern_inference::mk_patterns(unsigned num_bindings, filter_looping_patterns(m_tmp1); TRACE("pattern_inference", tout << "candidates after removing looping-patterns:\n"; - dump_app_vector(tout, m_tmp1, m_manager);); + dump_app_vector(tout, m_tmp1, m);); SASSERT(!m_tmp1.empty()); if (!has_preferred_patterns(m_tmp1, result)) { // continue if there are no preferred patterns @@ -552,7 +552,7 @@ void pattern_inference::mk_patterns(unsigned num_bindings, SASSERT(!m_tmp2.empty()); TRACE("pattern_inference", tout << "candidates after removing bigger patterns:\n"; - dump_app_vector(tout, m_tmp2, m_manager);); + dump_app_vector(tout, m_tmp2, m);); m_tmp1.reset(); candidates2unary_patterns(m_tmp2, m_tmp1, result); unsigned num_extra_multi_patterns = m_params.m_pi_max_multi_patterns; @@ -563,7 +563,7 @@ void pattern_inference::mk_patterns(unsigned num_bindings, std::stable_sort(m_tmp1.begin(), m_tmp1.end(), m_pattern_weight_lt); TRACE("pattern_inference", tout << "candidates after sorting:\n"; - dump_app_vector(tout, m_tmp1, m_manager);); + dump_app_vector(tout, m_tmp1, m);); candidates2multi_patterns(num_extra_multi_patterns, m_tmp1, result); } } @@ -577,7 +577,7 @@ void pattern_inference::mk_patterns(unsigned num_bindings, #include"database.h" // defines g_pattern_database void pattern_inference::reduce1_quantifier(quantifier * q) { - TRACE("pattern_inference", tout << "processing:\n" << mk_pp(q, m_manager) << "\n";); + TRACE("pattern_inference", tout << "processing:\n" << mk_pp(q, m) << "\n";); if (!q->is_forall()) { simplifier::reduce1_quantifier(q); return; @@ -587,27 +587,27 @@ void pattern_inference::reduce1_quantifier(quantifier * q) { if (m_params.m_pi_use_database) { m_database.initialize(g_pattern_database); - app_ref_vector new_patterns(m_manager); + app_ref_vector new_patterns(m); unsigned new_weight; if (m_database.match_quantifier(q, new_patterns, new_weight)) { #ifdef Z3DEBUG - for (unsigned i = 0; i < new_patterns.size(); i++) { SASSERT(is_well_sorted(m_manager, new_patterns.get(i))); } + for (unsigned i = 0; i < new_patterns.size(); i++) { SASSERT(is_well_sorted(m, new_patterns.get(i))); } #endif - quantifier_ref new_q(m_manager); + quantifier_ref new_q(m); if (q->get_num_patterns() > 0) { // just update the weight... - TRACE("pattern_inference", tout << "updating weight to: " << new_weight << "\n" << mk_pp(q, m_manager) << "\n";); - new_q = m_manager.update_quantifier_weight(q, new_weight); + TRACE("pattern_inference", tout << "updating weight to: " << new_weight << "\n" << mk_pp(q, m) << "\n";); + new_q = m.update_quantifier_weight(q, new_weight); } else { - quantifier_ref tmp(m_manager); - tmp = m_manager.update_quantifier(q, new_patterns.size(), (expr**) new_patterns.c_ptr(), q->get_expr()); - new_q = m_manager.update_quantifier_weight(tmp, new_weight); - TRACE("pattern_inference", tout << "found patterns in database, weight: " << new_weight << "\n" << mk_pp(new_q, m_manager) << "\n";); + quantifier_ref tmp(m); + tmp = m.update_quantifier(q, new_patterns.size(), (expr**) new_patterns.c_ptr(), q->get_expr()); + new_q = m.update_quantifier_weight(tmp, new_weight); + TRACE("pattern_inference", tout << "found patterns in database, weight: " << new_weight << "\n" << mk_pp(new_q, m) << "\n";); } proof * pr = 0; - if (m_manager.fine_grain_proofs()) - pr = m_manager.mk_rewrite(q, new_q); + if (m.fine_grain_proofs()) + pr = m.mk_rewrite(q, new_q); cache_result(q, new_q, pr); return; } @@ -635,7 +635,7 @@ void pattern_inference::reduce1_quantifier(quantifier * q) { new_no_patterns.push_back(new_pattern); } - app_ref_buffer new_patterns(m_manager); + app_ref_buffer new_patterns(m); if (m_params.m_pi_arith == AP_CONSERVATIVE) m_forbidden.push_back(m_afid); @@ -677,26 +677,26 @@ void pattern_inference::reduce1_quantifier(quantifier * q) { warning_msg("using non nested arith. pattern (quantifier id: %s), the weight was increased to %d (this value can be modified using PI_NON_NESTED_ARITH_WEIGHT=).", q->get_qid().str().c_str(), weight); } - // verbose_stream() << mk_pp(q, m_manager) << "\n"; + // verbose_stream() << mk_pp(q, m) << "\n"; } } } - quantifier_ref new_q(m_manager); - new_q = m_manager.update_quantifier(q, new_patterns.size(), (expr**) new_patterns.c_ptr(), new_body); + quantifier_ref new_q(m); + new_q = m.update_quantifier(q, new_patterns.size(), (expr**) new_patterns.c_ptr(), new_body); if (weight != q->get_weight()) - new_q = m_manager.update_quantifier_weight(new_q, weight); - proof_ref pr(m_manager); - if (m_manager.fine_grain_proofs()) { + new_q = m.update_quantifier_weight(new_q, weight); + proof_ref pr(m); + if (m.fine_grain_proofs()) { if (new_body_pr == 0) - new_body_pr = m_manager.mk_reflexivity(new_body); - pr = m_manager.mk_quant_intro(q, new_q, new_body_pr); + new_body_pr = m.mk_reflexivity(new_body); + pr = m.mk_quant_intro(q, new_q, new_body_pr); } if (new_patterns.empty() && m_params.m_pi_pull_quantifiers) { - pull_quant pull(m_manager); - expr_ref new_expr(m_manager); - proof_ref new_pr(m_manager); + pull_quant pull(m); + expr_ref new_expr(m); + proof_ref new_pr(m); pull(new_q, new_expr, new_pr); quantifier * new_new_q = to_quantifier(new_expr); if (new_new_q != new_q) { @@ -705,12 +705,12 @@ void pattern_inference::reduce1_quantifier(quantifier * q) { if (m_params.m_pi_warnings) { warning_msg("pulled nested quantifier to be able to find an useable pattern (quantifier id: %s)", q->get_qid().str().c_str()); } - new_q = m_manager.update_quantifier(new_new_q, new_patterns.size(), (expr**) new_patterns.c_ptr(), new_new_q->get_expr()); - if (m_manager.fine_grain_proofs()) { - pr = m_manager.mk_transitivity(pr, new_pr); - pr = m_manager.mk_transitivity(pr, m_manager.mk_quant_intro(new_new_q, new_q, m_manager.mk_reflexivity(new_q->get_expr()))); + new_q = m.update_quantifier(new_new_q, new_patterns.size(), (expr**) new_patterns.c_ptr(), new_new_q->get_expr()); + if (m.fine_grain_proofs()) { + pr = m.mk_transitivity(pr, new_pr); + pr = m.mk_transitivity(pr, m.mk_quant_intro(new_new_q, new_q, m.mk_reflexivity(new_q->get_expr()))); } - TRACE("pattern_inference", tout << "pulled quantifier:\n" << mk_pp(new_q, m_manager) << "\n";); + TRACE("pattern_inference", tout << "pulled quantifier:\n" << mk_pp(new_q, m) << "\n";); } } } @@ -719,7 +719,7 @@ void pattern_inference::reduce1_quantifier(quantifier * q) { if (m_params.m_pi_warnings) { warning_msg("failed to find a pattern for quantifier (quantifier id: %s)", q->get_qid().str().c_str()); } - TRACE("pi_failed", tout << mk_pp(q, m_manager) << "\n";); + TRACE("pi_failed", tout << mk_pp(q, m) << "\n";); } if (new_patterns.empty() && new_body == q->get_expr()) { diff --git a/src/ast/pattern/pattern_inference.h b/src/ast/pattern/pattern_inference.h index 97897835c..152f7f459 100644 --- a/src/ast/pattern/pattern_inference.h +++ b/src/ast/pattern/pattern_inference.h @@ -38,7 +38,7 @@ Revision History: every instance of f(g(X)) is also an instance of f(X). */ class smaller_pattern { - ast_manager & m_manager; + ast_manager & m; ptr_vector m_bindings; typedef std::pair expr_pair; @@ -54,7 +54,7 @@ class smaller_pattern { public: smaller_pattern(ast_manager & m): - m_manager(m) { + m(m) { } bool operator()(unsigned num_bindings, expr * p1, expr * p2); @@ -135,7 +135,7 @@ class pattern_inference : public simplifier { m_node(n, m), m_free_vars(vars), m_size(sz) {} }; - ast_manager & m_manager; + ast_manager & m; pattern_inference & m_owner; family_id m_afid; unsigned m_num_bindings; @@ -150,7 +150,7 @@ class pattern_inference : public simplifier { void save_candidate(expr * n, unsigned delta); void reset(); public: - collect(ast_manager & m, pattern_inference & o):m_manager(m), m_owner(o), m_afid(m.mk_family_id("arith")) {} + collect(ast_manager & m, pattern_inference & o):m(m), m_owner(o), m_afid(m.mk_family_id("arith")) {} void operator()(expr * n, unsigned num_bindings); }; diff --git a/src/ast/pb_decl_plugin.cpp b/src/ast/pb_decl_plugin.cpp new file mode 100644 index 000000000..36103c4f0 --- /dev/null +++ b/src/ast/pb_decl_plugin.cpp @@ -0,0 +1,282 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + pb_decl_plugin.cpp + +Abstract: + + Cardinality Constraints plugin + +Author: + + Nikolaj Bjorner (nbjorner) 2013-05-11 + +Revision History: + +--*/ + +#include "pb_decl_plugin.h" + +pb_decl_plugin::pb_decl_plugin(): + m_at_most_sym("at-most"), + m_at_least_sym("at-least"), + m_pble_sym("pble"), + m_pbge_sym("pbge"), + m_pbeq_sym("pbeq") +{} + +func_decl * pb_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { + SASSERT(m_manager); + ast_manager& m = *m_manager; + for (unsigned i = 0; i < arity; ++i) { + if (!m.is_bool(domain[i])) { + m.raise_exception("invalid non-Boolean sort applied to 'at-most'"); + } + } + symbol sym; + switch(k) { + case OP_AT_LEAST_K: sym = m_at_least_sym; break; + case OP_AT_MOST_K: sym = m_at_most_sym; break; + case OP_PB_LE: sym = m_pble_sym; break; + case OP_PB_GE: sym = m_pbge_sym; break; + case OP_PB_EQ: sym = m_pbeq_sym; break; + default: break; + } + switch(k) { + case OP_AT_LEAST_K: + case OP_AT_MOST_K: { + if (num_parameters != 1 || !parameters[0].is_int() || parameters[0].get_int() < 0) { + m.raise_exception("function expects one non-negative integer parameter"); + } + func_decl_info info(m_family_id, k, 1, parameters); + return m.mk_func_decl(sym, arity, domain, m.mk_bool_sort(), info); + } + case OP_PB_GE: + case OP_PB_LE: + case OP_PB_EQ: { + if (num_parameters != 1 + arity) { + m.raise_exception("function expects arity+1 rational parameters"); + } + vector params; + for (unsigned i = 0; i < num_parameters; ++i) { + parameter const& p = parameters[i]; + if (p.is_int()) { + params.push_back(p); + } + else if (p.is_rational()) { + // HACK: ast pretty printer does not work with rationals. + rational r = p.get_rational(); + if (r.is_int32()) { + params.push_back(parameter(r.get_int32())); + } + else { + params.push_back(p); + } + } + else { + m.raise_exception("functions 'pble/pbge/pbeq' expect arity+1 integer parameters"); + } + } + func_decl_info info(m_family_id, k, num_parameters, params.c_ptr()); + return m.mk_func_decl(sym, arity, domain, m.mk_bool_sort(), info); + } + default: + UNREACHABLE(); + return 0; + } +} + +void pb_decl_plugin::get_op_names(svector & op_names, symbol const & logic) { + if (logic == symbol::null) { + op_names.push_back(builtin_name(m_at_most_sym.bare_str(), OP_AT_MOST_K)); + op_names.push_back(builtin_name(m_at_least_sym.bare_str(), OP_AT_LEAST_K)); + op_names.push_back(builtin_name(m_pble_sym.bare_str(), OP_PB_LE)); + op_names.push_back(builtin_name(m_pbge_sym.bare_str(), OP_PB_GE)); + op_names.push_back(builtin_name(m_pbeq_sym.bare_str(), OP_PB_EQ)); + } +} + +app * pb_util::mk_le(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k) { + vector params; + params.push_back(parameter(k)); + for (unsigned i = 0; i < num_args; ++i) { + params.push_back(parameter(coeffs[i])); + } + return m.mk_app(m_fid, OP_PB_LE, params.size(), params.c_ptr(), num_args, args, m.mk_bool_sort()); +} + +app * pb_util::mk_ge(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k) { + vector params; + params.push_back(parameter(k)); + for (unsigned i = 0; i < num_args; ++i) { + params.push_back(parameter(coeffs[i])); + } + return m.mk_app(m_fid, OP_PB_GE, params.size(), params.c_ptr(), num_args, args, m.mk_bool_sort()); +} + +app * pb_util::mk_eq(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k) { + vector params; + params.push_back(parameter(k)); + for (unsigned i = 0; i < num_args; ++i) { + params.push_back(parameter(coeffs[i])); + } + return m.mk_app(m_fid, OP_PB_EQ, params.size(), params.c_ptr(), num_args, args, m.mk_bool_sort()); +} + +// ax + by < k +// <=> +// -ax - by >= -k + 1 +// <=> +// a(1-x) + b(1-y) >= -k + a + b + 1 +app * pb_util::mk_lt(unsigned num_args, rational const * _coeffs, expr * const * _args, rational const& _k) { + vector coeffs; + rational k(_k); + expr_ref_vector args(m); + expr* f; + rational d(denominator(k)); + for (unsigned i = 0; i < num_args; ++i) { + coeffs.push_back(_coeffs[i]); + d = lcm(d, denominator(coeffs[i])); + if (m.is_not(_args[i], f)) { + args.push_back(f); + } + else { + args.push_back(m.mk_not(_args[i])); + } + } + if (!d.is_one()) { + k *= d; + for (unsigned i = 0; i < num_args; ++i) { + coeffs[i] *= d; + } + } + k.neg(); + k += rational::one(); + for (unsigned i = 0; i < num_args; ++i) { + k += coeffs[i]; + } + return mk_ge(num_args, coeffs.c_ptr(), args.c_ptr(), k); +} + + +app * pb_util::mk_at_most_k(unsigned num_args, expr * const * args, unsigned k) { + parameter param(k); + return m.mk_app(m_fid, OP_AT_MOST_K, 1, ¶m, num_args, args, m.mk_bool_sort()); +} + +bool pb_util::is_at_most_k(func_decl *a) const { + return is_decl_of(a, m_fid, OP_AT_MOST_K); +} + +bool pb_util::is_at_most_k(expr *a, rational& k) const { + if (is_at_most_k(a)) { + k = get_k(a); + return true; + } + else { + return false; + } +} + +app * pb_util::mk_at_least_k(unsigned num_args, expr * const * args, unsigned k) { + parameter param(k); + return m.mk_app(m_fid, OP_AT_LEAST_K, 1, ¶m, num_args, args, m.mk_bool_sort()); +} + +bool pb_util::is_at_least_k(func_decl *a) const { + return is_decl_of(a, m_fid, OP_AT_LEAST_K); +} + +bool pb_util::is_at_least_k(expr *a, rational& k) const { + if (is_at_least_k(a)) { + k = get_k(a); + return true; + } + else { + return false; + } +} + +rational pb_util::get_k(func_decl *a) const { + parameter const& p = a->get_parameter(0); + if (is_at_most_k(a) || is_at_least_k(a)) { + return to_rational(p); + } + else { + SASSERT(is_le(a) || is_ge(a) || is_eq(a)); + return to_rational(p); + } +} + + +bool pb_util::is_le(func_decl *a) const { + return is_decl_of(a, m_fid, OP_PB_LE); +} + +bool pb_util::is_le(expr* a, rational& k) const { + if (is_le(a)) { + k = get_k(a); + return true; + } + else { + return false; + } +} + +bool pb_util::is_ge(func_decl *a) const { + return is_decl_of(a, m_fid, OP_PB_GE); +} + +bool pb_util::is_ge(expr* a, rational& k) const { + if (is_ge(a)) { + k = get_k(a); + return true; + } + else { + return false; + } +} + + +bool pb_util::is_eq(func_decl *a) const { + return is_decl_of(a, m_fid, OP_PB_EQ); +} + +bool pb_util::is_eq(expr* a, rational& k) const { + if (is_eq(a)) { + k = get_k(a); + return true; + } + else { + return false; + } +} + +rational pb_util::get_coeff(func_decl* a, unsigned index) const { + if (is_at_most_k(a) || is_at_least_k(a)) { + return rational::one(); + } + SASSERT(is_le(a) || is_ge(a) || is_eq(a)); + SASSERT(1 + index < a->get_num_parameters()); + return to_rational(a->get_parameter(index + 1)); +} + +rational pb_util::to_rational(parameter const& p) const { + if (p.is_int()) { + return rational(p.get_int()); + } + SASSERT(p.is_rational()); + return p.get_rational(); +} + +bool pb_util::has_unit_coefficients(func_decl* f) const { + if (is_at_most_k(f) || is_at_least_k(f)) return true; + unsigned sz = f->get_arity(); + for (unsigned i = 0; i < sz; ++i) { + if (!get_coeff(f, i).is_one()) return false; + } + return true; +} diff --git a/src/ast/pb_decl_plugin.h b/src/ast/pb_decl_plugin.h new file mode 100644 index 000000000..0bc8eab17 --- /dev/null +++ b/src/ast/pb_decl_plugin.h @@ -0,0 +1,123 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + pb_decl_plugin.h + +Abstract: + + Pseudo-Boolean and Cardinality Constraints plugin + +Author: + + Nikolaj Bjorner (nbjorner) 2013-05-11 + +Notes: + + + (at-most-k x1 .... x_n) means x1 + ... + x_n <= k + +hence: + + (not (at-most-k x1 .... x_n)) means x1 + ... + x_n >= k + 1 + + +--*/ +#ifndef _PB_DECL_PLUGIN_H_ +#define _PB_DECL_PLUGIN_H_ + +#include"ast.h" + +enum pb_op_kind { + OP_AT_MOST_K, // at most K Booleans are true. + OP_AT_LEAST_K, // at least K Booleans are true. + OP_PB_LE, // pseudo-Boolean <= (generalizes at_most_k) + OP_PB_GE, // pseudo-Boolean >= + OP_PB_EQ, // equality + LAST_PB_OP +}; + + +class pb_decl_plugin : public decl_plugin { + symbol m_at_most_sym; + symbol m_at_least_sym; + symbol m_pble_sym; + symbol m_pbge_sym; + symbol m_pbeq_sym; + func_decl * mk_at_most(unsigned arity, unsigned k); + func_decl * mk_at_least(unsigned arity, unsigned k); + func_decl * mk_le(unsigned arity, rational const* coeffs, int k); + func_decl * mk_ge(unsigned arity, rational const* coeffs, int k); + func_decl * mk_eq(unsigned arity, rational const* coeffs, int k); +public: + pb_decl_plugin(); + virtual ~pb_decl_plugin() {} + + virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) { + UNREACHABLE(); + return 0; + } + + virtual decl_plugin * mk_fresh() { + return alloc(pb_decl_plugin); + } + + // + // Contract for func_decl: + // parameters[0] - integer (at most k elements) + // all sorts are Booleans + // parameters[1] .. parameters[arity] - coefficients + virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); + virtual void get_op_names(svector & op_names, symbol const & logic); +}; + + +class pb_util { + ast_manager & m; + family_id m_fid; +public: + pb_util(ast_manager& m):m(m), m_fid(m.mk_family_id("pb")) {} + ast_manager & get_manager() const { return m; } + family_id get_family_id() const { return m_fid; } + app * mk_at_most_k(unsigned num_args, expr * const * args, unsigned k); + app * mk_at_least_k(unsigned num_args, expr * const * args, unsigned k); + app * mk_le(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k); + app * mk_ge(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k); + app * mk_eq(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k); + app * mk_lt(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k); + bool is_at_most_k(func_decl *a) const; + bool is_at_most_k(expr *a) const { return is_app(a) && is_at_most_k(to_app(a)->get_decl()); } + bool is_at_most_k(expr *a, rational& k) const; + bool is_at_least_k(func_decl *a) const; + bool is_at_least_k(expr *a) const { return is_app(a) && is_at_least_k(to_app(a)->get_decl()); } + bool is_at_least_k(expr *a, rational& k) const; + rational get_k(func_decl *a) const; + rational get_k(expr *a) const { return get_k(to_app(a)->get_decl()); } + bool is_le(func_decl *a) const; + bool is_le(expr *a) const { return is_app(a) && is_le(to_app(a)->get_decl()); } + bool is_le(expr* a, rational& k) const; + bool is_ge(func_decl* a) const; + bool is_ge(expr* a) const { return is_app(a) && is_ge(to_app(a)->get_decl()); } + bool is_ge(expr* a, rational& k) const; + rational get_coeff(expr* a, unsigned index) const { return get_coeff(to_app(a)->get_decl(), index); } + rational get_coeff(func_decl* a, unsigned index) const; + bool has_unit_coefficients(func_decl* f) const; + bool has_unit_coefficients(expr* f) const { return is_app(f) && has_unit_coefficients(to_app(f)->get_decl()); } + + + bool is_eq(func_decl* f) const; + bool is_eq(expr* e) const { return is_app(e) && is_eq(to_app(e)->get_decl()); } + bool is_eq(expr* e, rational& k) const; + + +private: + rational to_rational(parameter const& p) const; +}; + + + + +#endif /* _PB_DECL_PLUGIN_H_ */ + diff --git a/src/ast/reg_decl_plugins.cpp b/src/ast/reg_decl_plugins.cpp index ab1844e07..6a996d288 100644 --- a/src/ast/reg_decl_plugins.cpp +++ b/src/ast/reg_decl_plugins.cpp @@ -25,6 +25,7 @@ Revision History: #include"dl_decl_plugin.h" #include"seq_decl_plugin.h" #include"float_decl_plugin.h" +#include"pb_decl_plugin.h" void reg_decl_plugins(ast_manager & m) { if (!m.get_plugin(m.mk_family_id(symbol("arith")))) { @@ -48,4 +49,7 @@ void reg_decl_plugins(ast_manager & m) { if (!m.get_plugin(m.mk_family_id(symbol("float")))) { m.register_plugin(symbol("float"), alloc(float_decl_plugin)); } + if (!m.get_plugin(m.mk_family_id(symbol("pb")))) { + m.register_plugin(symbol("pb"), alloc(pb_decl_plugin)); + } } diff --git a/src/ast/rewriter/ast_counter.cpp b/src/ast/rewriter/ast_counter.cpp index 6f49a232f..f1ec03528 100644 --- a/src/ast/rewriter/ast_counter.cpp +++ b/src/ast/rewriter/ast_counter.cpp @@ -18,12 +18,9 @@ Revision History: --*/ #include "ast_counter.h" -#include "var_subst.h" void counter::update(unsigned el, int delta) { int & counter = get(el); - SASSERT(!m_stay_non_negative || counter>=0); - SASSERT(!m_stay_non_negative || static_cast(counter)>=-delta); counter += delta; } @@ -92,16 +89,14 @@ int counter::get_max_counter_value() const { void var_counter::count_vars(ast_manager & m, const app * pred, int coef) { unsigned n = pred->get_num_args(); for (unsigned i = 0; i < n; i++) { - m_sorts.reset(); - m_todo.reset(); - m_mark.reset(); - ::get_free_vars(m_mark, m_todo, pred->get_arg(i), m_sorts); - for (unsigned j = 0; j < m_sorts.size(); ++j) { - if (m_sorts[j]) { + m_fv(pred->get_arg(i)); + for (unsigned j = 0; j < m_fv.size(); ++j) { + if (m_fv[j]) { update(j, coef); } } } + m_fv.reset(); } diff --git a/src/ast/rewriter/ast_counter.h b/src/ast/rewriter/ast_counter.h index e7251079f..8b3ec3bbd 100644 --- a/src/ast/rewriter/ast_counter.h +++ b/src/ast/rewriter/ast_counter.h @@ -27,16 +27,16 @@ Revision History: #include "ast.h" #include "map.h" #include "uint_set.h" +#include "var_subst.h" class counter { protected: typedef u_map map_impl; map_impl m_data; - const bool m_stay_non_negative; public: typedef map_impl::iterator iterator; - counter(bool stay_non_negative = true) : m_stay_non_negative(stay_non_negative) {} + counter() {} void reset() { m_data.reset(); } iterator begin() const { return m_data.begin(); } @@ -69,14 +69,13 @@ public: class var_counter : public counter { protected: - ptr_vector m_sorts; expr_fast_mark1 m_visited; + expr_free_vars m_fv; ptr_vector m_todo; - ast_mark m_mark; unsigned_vector m_scopes; unsigned get_max_var(bool & has_var); public: - var_counter(bool stay_non_negative = true): counter(stay_non_negative) {} + var_counter() {} void count_vars(ast_manager & m, const app * t, int coef = 1); unsigned get_max_var(expr* e); unsigned get_next_var(expr* e); @@ -85,11 +84,10 @@ public: class ast_counter { typedef obj_map map_impl; map_impl m_data; - bool m_stay_non_negative; public: typedef map_impl::iterator iterator; - ast_counter(bool stay_non_negative = true) : m_stay_non_negative(stay_non_negative) {} + ast_counter() {} iterator begin() const { return m_data.begin(); } iterator end() const { return m_data.end(); } @@ -99,7 +97,6 @@ class ast_counter { } void update(ast * el, int delta){ get(el) += delta; - SASSERT(!m_stay_non_negative || get(el) >= 0); } void inc(ast * el) { update(el, 1); } diff --git a/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h b/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h index b579d698e..b762817e4 100644 --- a/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h +++ b/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h @@ -1038,6 +1038,11 @@ void bit_blaster_tpl::mk_ext_rotate_left_right(unsigned sz, expr * const * mk_rotate_right(sz, a_bits, static_cast(k.get_uint64()), out_bits); } else { + // + // Review: a better tuned implementation is possible by using shifts by power of two. + // e.g., looping over the bits of b_bits, then rotate by a power of two depending + // on the bit-position. This would get rid of the mk_urem. + // expr_ref_vector sz_bits(m()); expr_ref_vector masked_b_bits(m()); expr_ref_vector eqs(m()); diff --git a/src/ast/rewriter/datatype_rewriter.cpp b/src/ast/rewriter/datatype_rewriter.cpp index 8c55ba498..be198c3d9 100644 --- a/src/ast/rewriter/datatype_rewriter.cpp +++ b/src/ast/rewriter/datatype_rewriter.cpp @@ -60,6 +60,32 @@ br_status datatype_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr UNREACHABLE(); break; } + case OP_DT_UPDATE_FIELD: { + SASSERT(num_args == 2); + if (!is_app(args[0]) || !m_util.is_constructor(to_app(args[0]))) + return BR_FAILED; + app * a = to_app(args[0]); + func_decl * c_decl = a->get_decl(); + if (c_decl != m_util.get_accessor_constructor(f)) { + result = a; + return BR_DONE; + } + ptr_vector const * acc = m_util.get_constructor_accessors(c_decl); + SASSERT(acc && acc->size() == a->get_num_args()); + unsigned num = acc->size(); + ptr_buffer new_args; + for (unsigned i = 0; i < num; ++i) { + + if (f == (*acc)[i]) { + new_args.push_back(args[1]); + } + else { + new_args.push_back(a->get_arg(i)); + } + } + result = m().mk_app(c_decl, num, new_args.c_ptr()); + return BR_DONE; + } default: UNREACHABLE(); } diff --git a/src/ast/rewriter/expr_safe_replace.cpp b/src/ast/rewriter/expr_safe_replace.cpp index a4886ad1a..37fcdfe6a 100644 --- a/src/ast/rewriter/expr_safe_replace.cpp +++ b/src/ast/rewriter/expr_safe_replace.cpp @@ -29,43 +29,39 @@ void expr_safe_replace::insert(expr* src, expr* dst) { } void expr_safe_replace::operator()(expr* e, expr_ref& res) { - obj_map cache; - ptr_vector todo, args; - expr_ref_vector refs(m); - todo.push_back(e); + m_todo.push_back(e); expr* a, *b, *d; - todo.push_back(e); - while (!todo.empty()) { - a = todo.back(); - if (cache.contains(a)) { - todo.pop_back(); + while (!m_todo.empty()) { + a = m_todo.back(); + if (m_cache.contains(a)) { + m_todo.pop_back(); } else if (m_subst.find(a, b)) { - cache.insert(a, b); - todo.pop_back(); + m_cache.insert(a, b); + m_todo.pop_back(); } else if (is_var(a)) { - cache.insert(a, a); - todo.pop_back(); + m_cache.insert(a, a); + m_todo.pop_back(); } else if (is_app(a)) { app* c = to_app(a); unsigned n = c->get_num_args(); - args.reset(); + m_args.reset(); for (unsigned i = 0; i < n; ++i) { - if (cache.find(c->get_arg(i), d)) { - args.push_back(d); + if (m_cache.find(c->get_arg(i), d)) { + m_args.push_back(d); } else { - todo.push_back(c->get_arg(i)); + m_todo.push_back(c->get_arg(i)); } } - if (args.size() == n) { - b = m.mk_app(c->get_decl(), args.size(), args.c_ptr()); - refs.push_back(b); - cache.insert(a, b); - todo.pop_back(); + if (m_args.size() == n) { + b = m.mk_app(c->get_decl(), m_args.size(), m_args.c_ptr()); + m_refs.push_back(b); + m_cache.insert(a, b); + m_todo.pop_back(); } } else { @@ -93,12 +89,16 @@ void expr_safe_replace::operator()(expr* e, expr_ref& res) { } replace(q->get_expr(), new_body); b = m.update_quantifier(q, pats.size(), pats.c_ptr(), nopats.size(), nopats.c_ptr(), new_body); - refs.push_back(b); - cache.insert(a, b); - todo.pop_back(); + m_refs.push_back(b); + m_cache.insert(a, b); + m_todo.pop_back(); } } - res = cache.find(e); + res = m_cache.find(e); + m_cache.reset(); + m_todo.reset(); + m_args.reset(); + m_refs.reset(); } void expr_safe_replace::reset() { diff --git a/src/ast/rewriter/expr_safe_replace.h b/src/ast/rewriter/expr_safe_replace.h index ad626d18f..1f21d35e9 100644 --- a/src/ast/rewriter/expr_safe_replace.h +++ b/src/ast/rewriter/expr_safe_replace.h @@ -29,9 +29,12 @@ class expr_safe_replace { expr_ref_vector m_src; expr_ref_vector m_dst; obj_map m_subst; + obj_map m_cache; + ptr_vector m_todo, m_args; + expr_ref_vector m_refs; public: - expr_safe_replace(ast_manager& m): m(m), m_src(m), m_dst(m) {} + expr_safe_replace(ast_manager& m): m(m), m_src(m), m_dst(m), m_refs(m) {} void insert(expr* src, expr* dst); @@ -42,6 +45,8 @@ public: void apply_substitution(expr* s, expr* def, expr_ref& t); void reset(); + + bool empty() const { return m_subst.empty(); } }; #endif /* __EXPR_SAFE_REPLACE_H__ */ diff --git a/src/ast/rewriter/pb_rewriter.cpp b/src/ast/rewriter/pb_rewriter.cpp new file mode 100644 index 000000000..ce6e294c7 --- /dev/null +++ b/src/ast/rewriter/pb_rewriter.cpp @@ -0,0 +1,275 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + pb_rewriter.cpp + +Abstract: + + Basic rewriting rules for PB constraints. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-14-12 + +Notes: + +--*/ + +#include "pb_rewriter.h" +#include "pb_rewriter_def.h" +#include "ast_pp.h" +#include "ast_smt_pp.h" + + +class pb_ast_rewriter_util { + ast_manager& m; + expr_ref_vector m_refs; +public: + + typedef std::pair arg_t; + typedef vector args_t; + typedef rational numeral; + + pb_ast_rewriter_util(ast_manager& m): m(m), m_refs(m) {} + + expr* negate(expr* e) { + if (m.is_true(e)) { + return m.mk_false(); + } + if (m.is_false(e)) { + return m.mk_true(); + } + if (m.is_not(e, e)) { + return e; + } + m_refs.push_back(m.mk_not(e)); + return m_refs.back(); + } + + void display(std::ostream& out, expr* e) { + out << mk_pp(e, m); + } + + bool is_negated(expr* e) const { + return m.is_not(e); + } + + bool is_true(expr* e) const { + return m.is_true(e); + } + + bool is_false(expr* e) const { + return m.is_false(e); + } + + struct compare { + bool operator()(std::pair const& a, + std::pair const& b) { + return a.first->get_id() < b.first->get_id(); + } + + }; +}; + +expr_ref pb_rewriter::translate_pb2lia(obj_map& vars, expr* fml) { + pb_util util(m()); + arith_util a(m()); + expr_ref result(m()), tmp(m()); + expr_ref_vector es(m()); + expr*const* args = to_app(fml)->get_args(); + unsigned sz = to_app(fml)->get_num_args(); + for (unsigned i = 0; i < sz; ++i) { + expr* e = args[i]; + if (m().is_not(e, e)) { + es.push_back(a.mk_sub(a.mk_numeral(rational(1),true),vars.find(e))); + } + else { + es.push_back(vars.find(e)); + } + } + + if (util.is_at_most_k(fml) || util.is_at_least_k(fml)) { + if (es.empty()) { + tmp = a.mk_numeral(rational(0), true); + } + else { + tmp = a.mk_add(es.size(), es.c_ptr()); + } + if (util.is_at_most_k(fml)) { + result = a.mk_le(tmp, a.mk_numeral(util.get_k(fml), false)); + } + else { + result = a.mk_ge(tmp, a.mk_numeral(util.get_k(fml), false)); + } + } + else if (util.is_le(fml) || util.is_ge(fml) || util.is_eq(fml)) { + for (unsigned i = 0; i < sz; ++i) { + es[i] = a.mk_mul(a.mk_numeral(util.get_coeff(fml, i),false), es[i].get()); + } + if (es.empty()) { + tmp = a.mk_numeral(rational(0), true); + } + else { + tmp = a.mk_add(es.size(), es.c_ptr()); + } + if (util.is_le(fml)) { + result = a.mk_le(tmp, a.mk_numeral(util.get_k(fml), false)); + } + else if (util.is_ge(fml)) { + result = a.mk_ge(tmp, a.mk_numeral(util.get_k(fml), false)); + } + else { + result = m().mk_eq(tmp, a.mk_numeral(util.get_k(fml), false)); + } + } + else { + result = fml; + } + return result; +} + +expr_ref pb_rewriter::mk_validate_rewrite(app_ref& e1, app_ref& e2) { + ast_manager& m = e1.get_manager(); + arith_util a(m); + symbol name; + obj_map vars; + expr_ref_vector trail(m), fmls(m); + unsigned sz = to_app(e1)->get_num_args(); + expr*const*args = to_app(e1)->get_args(); + for (unsigned i = 0; i < sz; ++i) { + expr* e = args[i]; + if (m.is_true(e)) { + if (!vars.contains(e)) { + trail.push_back(a.mk_numeral(rational(1), true)); + vars.insert(e, trail.back()); + } + continue; + } + if (m.is_false(e)) { + if (!vars.contains(e)) { + trail.push_back(a.mk_numeral(rational(0), true)); + vars.insert(e, trail.back()); + } + continue; + } + + std::ostringstream strm; + strm << "x" << i; + name = symbol(strm.str().c_str()); + trail.push_back(m.mk_const(name, a.mk_int())); + expr* x = trail.back(); + m.is_not(e,e); + vars.insert(e, x); + fmls.push_back(a.mk_le(a.mk_numeral(rational(0), true), x)); + fmls.push_back(a.mk_le(x, a.mk_numeral(rational(1), true))); + } + expr_ref tmp(m); + expr_ref fml1 = translate_pb2lia(vars, e1); + expr_ref fml2 = translate_pb2lia(vars, e2); + tmp = m.mk_not(m.mk_eq(fml1, fml2)); + fmls.push_back(tmp); + tmp = m.mk_and(fmls.size(), fmls.c_ptr()); + return tmp; +} + +static unsigned s_lemma = 0; + +void pb_rewriter::validate_rewrite(func_decl* f, unsigned sz, expr*const* args, expr_ref& fml) { + ast_manager& m = fml.get_manager(); + app_ref tmp1(m), tmp2(m); + tmp1 = m.mk_app(f, sz, args); + tmp2 = to_app(fml); + expr_ref tmp = mk_validate_rewrite(tmp1, tmp2); + dump_pb_rewrite(tmp); +} + +void pb_rewriter::dump_pb_rewrite(expr* fml) { + std::ostringstream strm; + strm << "pb_rewrite_" << (s_lemma++) << ".smt2"; + std::ofstream out(strm.str().c_str()); + ast_smt_pp pp(m()); + pp.display_smt2(out, fml); + out.close(); +} + +br_status pb_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { + ast_manager& m = result.get_manager(); + rational sum(0), maxsum(0); + for (unsigned i = 0; i < num_args; ++i) { + if (m.is_true(args[i])) { + sum += m_util.get_coeff(f, i); + maxsum += m_util.get_coeff(f, i); + } + else if (!m.is_false(args[i])) { + maxsum += m_util.get_coeff(f, i); + } + } + rational k = m_util.get_k(f); + + vector > vec; + for (unsigned i = 0; i < num_args; ++i) { + vec.push_back(std::make_pair(args[i], m_util.get_coeff(f, i))); + } + + switch(f->get_decl_kind()) { + case OP_AT_MOST_K: + case OP_PB_LE: + for (unsigned i = 0; i < num_args; ++i) { + vec[i].second.neg(); + } + k.neg(); + break; + case OP_AT_LEAST_K: + case OP_PB_GE: + case OP_PB_EQ: + break; + default: + UNREACHABLE(); + return BR_FAILED; + } + + bool is_eq = f->get_decl_kind() == OP_PB_EQ; + + pb_ast_rewriter_util pbu(m); + pb_rewriter_util util(pbu); + + util.unique(vec, k, is_eq); + lbool is_sat = util.normalize(vec, k, is_eq); + util.prune(vec, k, is_eq); + switch (is_sat) { + case l_true: + result = m.mk_true(); + break; + case l_false: + result = m.mk_false(); + break; + default: + m_args.reset(); + m_coeffs.reset(); + for (unsigned i = 0; i < vec.size(); ++i) { + m_args.push_back(vec[i].first); + m_coeffs.push_back(vec[i].second); + } + if (is_eq) { + result = m_util.mk_eq(vec.size(), m_coeffs.c_ptr(), m_args.c_ptr(), k); + } + else { + result = m_util.mk_ge(vec.size(), m_coeffs.c_ptr(), m_args.c_ptr(), k); + } + break; + } + TRACE("pb", + expr_ref tmp(m); + tmp = m.mk_app(f, num_args, args); + tout << tmp << "\n"; + tout << result << "\n"; + ); + TRACE("pb_validate", + validate_rewrite(f, num_args, args, result);); + + return BR_DONE; +} + + diff --git a/src/ast/rewriter/pb_rewriter.h b/src/ast/rewriter/pb_rewriter.h new file mode 100644 index 000000000..4c9aaaaf1 --- /dev/null +++ b/src/ast/rewriter/pb_rewriter.h @@ -0,0 +1,65 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + pb_rewriter.h + +Abstract: + + Basic rewriting rules for PB constraints. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-14-12 + +Notes: + +--*/ +#ifndef _PB_REWRITER_H_ +#define _PB_REWRITER_H_ + +#include"pb_decl_plugin.h" +#include"rewriter_types.h" +#include"params.h" +#include"lbool.h" + + +template +class pb_rewriter_util { + PBU& m_util; + void display(std::ostream& out, typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq); +public: + pb_rewriter_util(PBU& u) : m_util(u) {} + void unique(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq); + lbool normalize(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq); + void prune(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq); +}; + +/** + \brief Cheap rewrite rules for PB constraints +*/ +class pb_rewriter { + pb_util m_util; + vector m_coeffs; + ptr_vector m_args; + + void validate_rewrite(func_decl* f, unsigned sz, expr*const* args, expr_ref& fml); +public: + pb_rewriter(ast_manager & m, params_ref const & p = params_ref()): + m_util(m) { + } + ast_manager & m() const { return m_util.get_manager(); } + family_id get_fid() const { return m_util.get_family_id(); } + + void updt_params(params_ref const & p) {} + static void get_param_descrs(param_descrs & r) {} + + br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); + + expr_ref translate_pb2lia(obj_map& vars, expr* fml); + expr_ref mk_validate_rewrite(app_ref& e1, app_ref& e2); + void dump_pb_rewrite(expr* fml); +}; + +#endif diff --git a/src/ast/rewriter/pb_rewriter_def.h b/src/ast/rewriter/pb_rewriter_def.h new file mode 100644 index 000000000..38efd2097 --- /dev/null +++ b/src/ast/rewriter/pb_rewriter_def.h @@ -0,0 +1,298 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + pb_rewriter_def.h + +Abstract: + + Basic rewriting rules for PB constraints. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-14-12 + +Notes: + +--*/ +#ifndef _PB_REWRITER_DEF_H_ +#define _PB_REWRITER_DEF_H_ + +#include"pb_rewriter.h" + + +template +void pb_rewriter_util::display(std::ostream& out, typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq) { + for (unsigned i = 0; i < args.size(); ++i) { + out << args[i].second << " * "; + m_util.display(out, args[i].first); + out << " "; + if (i+1 < args.size()) out << "+ "; + } + out << (is_eq?" = ":" >= ") << k << "\n"; +} + +template +void pb_rewriter_util::unique(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq) { + + TRACE("pb_verbose", display(tout << "pre-unique:", args, k, is_eq);); + for (unsigned i = 0; i < args.size(); ++i) { + if (m_util.is_negated(args[i].first)) { + args[i].first = m_util.negate(args[i].first); + k -= args[i].second; + args[i].second = -args[i].second; + } + } + // remove constants + for (unsigned i = 0; i < args.size(); ++i) { + if (m_util.is_true(args[i].first)) { + k -= args[i].second; + std::swap(args[i], args[args.size()-1]); + args.pop_back(); + --i; + } + else if (m_util.is_false(args[i].first)) { + std::swap(args[i], args[args.size()-1]); + args.pop_back(); + --i; + } + } + // sort and coalesce arguments: + typename PBU::compare cmp; + std::sort(args.begin(), args.end(), cmp); + + // coallesce + unsigned i, j; + for (i = 0, j = 1; j < args.size(); ++j) { + if (args[i].first == args[j].first) { + args[i].second += args[j].second; + } + else { + ++i; + args[i] = args[j]; + } + } + args.resize(i+1); + + // remove 0s. + for (i = 0, j = 0; j < args.size(); ++j) { + if (!args[j].second.is_zero()) { + if (i != j) { + args[i] = args[j]; + } + ++i; + } + } + args.resize(i); + TRACE("pb_verbose", display(tout << "post-unique:", args, k, is_eq);); +} + +template +lbool pb_rewriter_util::normalize(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq) { + TRACE("pb_verbose", display(tout << "pre-normalize:", args, k, is_eq);); + + DEBUG_CODE( + bool found = false; + for (unsigned i = 0; !found && i < args.size(); ++i) { + found = args[i].second.is_zero(); + } + if (found) display(verbose_stream(), args, k, is_eq); + SASSERT(!found);); + + // + // Ensure all coefficients are positive: + // c*l + y >= k + // <=> + // c*(1-~l) + y >= k + // <=> + // c - c*~l + y >= k + // <=> + // -c*~l + y >= k - c + // + typename PBU::numeral sum(0); + for (unsigned i = 0; i < args.size(); ++i) { + typename PBU::numeral c = args[i].second; + if (c.is_neg()) { + args[i].second = -c; + args[i].first = m_util.negate(args[i].first); + k -= c; + } + sum += args[i].second; + } + // detect tautologies: + if (!is_eq && k <= PBU::numeral::zero()) { + args.reset(); + k = PBU::numeral::zero(); + return l_true; + } + if (is_eq && k.is_zero() && args.empty()) { + return l_true; + } + + // detect infeasible constraints: + if (sum < k) { + args.reset(); + k = PBU::numeral::one(); + return l_false; + } + + if (is_eq && k == sum) { + for (unsigned i = 0; i < args.size(); ++i) { + args[i].second = PBU::numeral::one(); + } + typename PBU::numeral num(args.size()); + k = num; + return l_undef; + } + + bool all_int = true; + for (unsigned i = 0; all_int && i < args.size(); ++i) { + all_int = args[i].second.is_int(); + } + + if (!all_int) { + // normalize to integers. + typename PBU::numeral d(denominator(k)); + for (unsigned i = 0; i < args.size(); ++i) { + d = lcm(d, denominator(args[i].second)); + } + SASSERT(!d.is_one()); + k *= d; + for (unsigned i = 0; i < args.size(); ++i) { + args[i].second *= d; + } + } + + if (is_eq) { + TRACE("pb_verbose", display(tout << "post-normalize:", args, k, is_eq);); + return l_undef; + } + + // Ensure the largest coefficient is not larger than k: + sum = PBU::numeral::zero(); + for (unsigned i = 0; i < args.size(); ++i) { + typename PBU::numeral c = args[i].second; + if (c > k) { + args[i].second = k; + } + sum += args[i].second; + } + SASSERT(!args.empty()); + + // normalize tight inequalities to unit coefficients. + if (sum == k) { + for (unsigned i = 0; i < args.size(); ++i) { + args[i].second = PBU::numeral::one(); + } + typename PBU::numeral num(args.size()); + k = num; + } + + // apply cutting plane reduction: + typename PBU::numeral g(0); + for (unsigned i = 0; !g.is_one() && i < args.size(); ++i) { + typename PBU::numeral c = args[i].second; + if (c != k) { + if (g.is_zero()) { + g = c; + } + else { + g = gcd(g, c); + } + } + } + if (g.is_zero()) { + // all coefficients are equal to k. + for (unsigned i = 0; i < args.size(); ++i) { + SASSERT(args[i].second == k); + args[i].second = PBU::numeral::one(); + } + k = PBU::numeral::one(); + } + else if (g > PBU::numeral::one()) { + + // + // Example 5x + 5y + 2z + 2u >= 5 + // becomes 3x + 3y + z + u >= 3 + // + typename PBU::numeral k_new = div(k, g); + if (!(k % g).is_zero()) { // k_new is the ceiling of k / g. + k_new++; + } + for (unsigned i = 0; i < args.size(); ++i) { + SASSERT(args[i].second.is_pos()); + typename PBU::numeral c = args[i].second; + if (c == k) { + c = k_new; + } + else { + c = div(c, g); + } + args[i].second = c; + SASSERT(args[i].second.is_pos()); + } + k = k_new; + } + // + // normalize coefficients that fall within a range + // k/n <= ... < k/(n-1) for some n = 1,2,... + // + // e.g, k/n <= min <= max < k/(n-1) + // k/min <= n, n-1 < k/max + // . floor(k/max) = ceil(k/min) - 1 + // . floor(k/max) < k/max + // + // example: k = 5, min = 3, max = 4: 5/3 -> 2 5/4 -> 1, n = 2 + // replace all coefficients by 1, and k by 2. + // + if (!k.is_one()) { + typename PBU::numeral min = args[0].second, max = args[0].second; + for (unsigned i = 1; i < args.size(); ++i) { + if (args[i].second < min) min = args[i].second; + if (args[i].second > max) max = args[i].second; + } + SASSERT(min.is_pos()); + typename PBU::numeral n0 = k/max; + typename PBU::numeral n1 = floor(n0); + typename PBU::numeral n2 = ceil(k/min) - PBU::numeral::one(); + if (n1 == n2 && !n0.is_int()) { + IF_VERBOSE(3, display(verbose_stream() << "set cardinality\n", args, k, is_eq);); + + for (unsigned i = 0; i < args.size(); ++i) { + args[i].second = PBU::numeral::one(); + } + k = n1 + PBU::numeral::one(); + } + } + TRACE("pb_verbose", display(tout << "post-normalize:", args, k, is_eq);); + return l_undef; +} + +template +void pb_rewriter_util::prune(typename PBU::args_t& args, typename PBU::numeral& k, bool is_eq) { + if (is_eq) { + return; + } + typename PBU::numeral nlt(0); + unsigned occ = 0; + for (unsigned i = 0; nlt < k && i < args.size(); ++i) { + if (args[i].second < k) { + nlt += args[i].second; + ++occ; + } + } + if (0 < occ && nlt < k) { + for (unsigned i = 0; i < args.size(); ++i) { + if (args[i].second < k) { + args[i] = args.back(); + args.pop_back(); + --i; + } + } + unique(args, k, is_eq); + normalize(args, k, is_eq); + } +} + +#endif diff --git a/src/ast/rewriter/poly_rewriter_def.h b/src/ast/rewriter/poly_rewriter_def.h index 036221f96..12da0069d 100644 --- a/src/ast/rewriter/poly_rewriter_def.h +++ b/src/ast/rewriter/poly_rewriter_def.h @@ -34,6 +34,8 @@ void poly_rewriter::updt_params(params_ref const & _p) { m_hoist_mul = p.hoist_mul(); m_hoist_cmul = p.hoist_cmul(); m_som_blowup = p.som_blowup(); + if (!m_flat) m_som = false; + if (m_som) m_hoist_mul = false; } template diff --git a/src/ast/rewriter/th_rewriter.cpp b/src/ast/rewriter/th_rewriter.cpp index 0e2c8e781..cca2b593e 100644 --- a/src/ast/rewriter/th_rewriter.cpp +++ b/src/ast/rewriter/th_rewriter.cpp @@ -25,6 +25,7 @@ Notes: #include"array_rewriter.h" #include"float_rewriter.h" #include"dl_rewriter.h" +#include"pb_rewriter.h" #include"rewriter_def.h" #include"expr_substitution.h" #include"ast_smt2_pp.h" @@ -41,6 +42,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg { datatype_rewriter m_dt_rw; float_rewriter m_f_rw; dl_rewriter m_dl_rw; + pb_rewriter m_pb_rw; arith_util m_a_util; bv_util m_bv_util; unsigned long long m_max_memory; // in bytes @@ -196,6 +198,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg { return m_f_rw.mk_app_core(f, num, args, result); if (fid == m_dl_rw.get_fid()) return m_dl_rw.mk_app_core(f, num, args, result); + if (fid == m_pb_rw.get_fid()) + return m_pb_rw.mk_app_core(f, num, args, result); return BR_FAILED; } @@ -645,6 +649,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg { m_dt_rw(m), m_f_rw(m, p), m_dl_rw(m), + m_pb_rw(m), m_a_util(m), m_bv_util(m), m_used_dependencies(m), diff --git a/src/ast/rewriter/var_subst.cpp b/src/ast/rewriter/var_subst.cpp index 930267dad..1d01ef85c 100644 --- a/src/ast/rewriter/var_subst.cpp +++ b/src/ast/rewriter/var_subst.cpp @@ -164,7 +164,7 @@ void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref tout << "\n----->\n" << mk_ismt2_pp(result, m) << "\n";); } -static void get_free_vars_offset(ast_mark& mark, ptr_vector& todo, unsigned offset, expr* e, ptr_vector& sorts) { +static void get_free_vars_offset(expr_sparse_mark& mark, ptr_vector& todo, unsigned offset, expr* e, ptr_vector& sorts) { todo.push_back(e); while (!todo.empty()) { e = todo.back(); @@ -176,7 +176,7 @@ static void get_free_vars_offset(ast_mark& mark, ptr_vector& todo, unsigne switch(e->get_kind()) { case AST_QUANTIFIER: { quantifier* q = to_quantifier(e); - ast_mark mark1; + expr_sparse_mark mark1; ptr_vector todo1; get_free_vars_offset(mark1, todo1, offset+q->get_num_decls(), q->get_expr(), sorts); break; @@ -210,11 +210,33 @@ static void get_free_vars_offset(ast_mark& mark, ptr_vector& todo, unsigne void get_free_vars(expr* e, ptr_vector& sorts) { - ast_mark mark; + expr_sparse_mark mark; ptr_vector todo; get_free_vars_offset(mark, todo, 0, e, sorts); } -void get_free_vars(ast_mark& mark, ptr_vector& todo, expr* e, ptr_vector& sorts) { +void get_free_vars(expr_sparse_mark& mark, ptr_vector& todo, expr* e, ptr_vector& sorts) { get_free_vars_offset(mark, todo, 0, e, sorts); } + +void expr_free_vars::reset() { + m_mark.reset(); + m_sorts.reset(); + SASSERT(m_todo.empty()); +} + +void expr_free_vars::set_default_sort(sort *s) { + for (unsigned i = 0; i < m_sorts.size(); ++i) { + if (!m_sorts[i]) m_sorts[i] = s; + } +} + +void expr_free_vars::operator()(expr* e) { + reset(); + get_free_vars_offset(m_mark, m_todo, 0, e, m_sorts); +} + +void expr_free_vars::accumulate(expr* e) { + SASSERT(m_todo.empty()); + get_free_vars_offset(m_mark, m_todo, 0, e, m_sorts); +} diff --git a/src/ast/rewriter/var_subst.h b/src/ast/rewriter/var_subst.h index ffc21e691..7db756d30 100644 --- a/src/ast/rewriter/var_subst.h +++ b/src/ast/rewriter/var_subst.h @@ -81,9 +81,23 @@ void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref Return the sorts of the free variables. */ -void get_free_vars(expr* e, ptr_vector& sorts); -void get_free_vars(ast_mark& mark, ptr_vector& todo, expr* e, ptr_vector& sorts); +class expr_free_vars { + expr_sparse_mark m_mark; + ptr_vector m_sorts; + ptr_vector m_todo; +public: + void reset(); + void operator()(expr* e); + void accumulate(expr* e); + bool empty() const { return m_sorts.empty(); } + unsigned size() const { return m_sorts.size(); } + sort* operator[](unsigned idx) const { return m_sorts[idx]; } + bool contains(unsigned idx) const { return idx < m_sorts.size() && m_sorts[idx] != 0; } + void set_default_sort(sort* s); + void reverse() { m_sorts.reverse(); } + sort*const* c_ptr() const { return m_sorts.c_ptr(); } +}; #endif diff --git a/src/ast/simplifier/base_simplifier.h b/src/ast/simplifier/base_simplifier.h index 4afe5c9d7..26bb43838 100644 --- a/src/ast/simplifier/base_simplifier.h +++ b/src/ast/simplifier/base_simplifier.h @@ -20,21 +20,32 @@ Notes: #define _BASE_SIMPLIFIER_H_ #include"expr_map.h" +#include"ast_pp.h" /** \brief Implements basic functionality used by expression simplifiers. */ class base_simplifier { protected: - ast_manager & m_manager; + ast_manager & m; expr_map m_cache; ptr_vector m_todo; - void cache_result(expr * n, expr * r, proof * p) { m_cache.insert(n, r, p); } + void cache_result(expr * n, expr * r, proof * p) { + m_cache.insert(n, r, p); + CTRACE("simplifier", !is_rewrite_proof(n, r, p), + tout << mk_pp(n, m) << "\n"; + tout << mk_pp(r, m) << "\n"; + tout << mk_pp(p, m) << "\n";); + SASSERT(is_rewrite_proof(n, r, p)); + } void reset_cache() { m_cache.reset(); } void flush_cache() { m_cache.flush(); } void get_cached(expr * n, expr * & r, proof * & p) const { m_cache.get(n, r, p); } + void reinitialize() { m_cache.set_store_proofs(m.fine_grain_proofs()); } + + void visit(expr * n, bool & visited) { if (!is_cached(n)) { m_todo.push_back(n); @@ -44,11 +55,22 @@ protected: public: base_simplifier(ast_manager & m): - m_manager(m), + m(m), m_cache(m, m.fine_grain_proofs()) { } bool is_cached(expr * n) const { return m_cache.contains(n); } - ast_manager & get_manager() { return m_manager; } + ast_manager & get_manager() { return m; } + + bool is_rewrite_proof(expr* n, expr* r, proof* p) { + if (p && + !m.is_undef_proof(p) && + !(m.has_fact(p) && + (m.is_eq(m.get_fact(p)) || m.is_oeq(m.get_fact(p)) || m.is_iff(m.get_fact(p))) && + to_app(m.get_fact(p))->get_arg(0) == n && + to_app(m.get_fact(p))->get_arg(1) == r)) return false; + + return (!m.fine_grain_proofs() || p || (n == r)); + } }; #endif /* _BASE_SIMPLIFIER_H_ */ diff --git a/src/ast/simplifier/bv_elim.cpp b/src/ast/simplifier/bv_elim.cpp index 5c19a245e..fc4e7534b 100644 --- a/src/ast/simplifier/bv_elim.cpp +++ b/src/ast/simplifier/bv_elim.cpp @@ -100,11 +100,11 @@ bool bv_elim_star::visit_quantifier(quantifier* q) { } void bv_elim_star::reduce1_quantifier(quantifier* q) { - quantifier_ref r(m_manager); - proof_ref pr(m_manager); + quantifier_ref r(m); + proof_ref pr(m); m_bv_elim.elim(q, r); - if (m_manager.fine_grain_proofs()) { - pr = m_manager.mk_rewrite(q, r.get()); + if (m.fine_grain_proofs()) { + pr = m.mk_rewrite(q, r.get()); } else { pr = 0; diff --git a/src/ast/simplifier/datatype_simplifier_plugin.cpp b/src/ast/simplifier/datatype_simplifier_plugin.cpp index 129c0e34b..b434a8bd0 100644 --- a/src/ast/simplifier/datatype_simplifier_plugin.cpp +++ b/src/ast/simplifier/datatype_simplifier_plugin.cpp @@ -81,6 +81,8 @@ bool datatype_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * } UNREACHABLE(); } + case OP_DT_UPDATE_FIELD: + return false; default: UNREACHABLE(); } diff --git a/src/ast/simplifier/elim_bounds.cpp b/src/ast/simplifier/elim_bounds.cpp index ce15d9eb1..41ce18549 100644 --- a/src/ast/simplifier/elim_bounds.cpp +++ b/src/ast/simplifier/elim_bounds.cpp @@ -203,20 +203,20 @@ void elim_bounds_star::reduce1_quantifier(quantifier * q) { cache_result(q, q, 0); return; } - quantifier_ref new_q(m_manager); + quantifier_ref new_q(m); expr * new_body = 0; proof * new_pr; get_cached(q->get_expr(), new_body, new_pr); - new_q = m_manager.update_quantifier(q, new_body); - expr_ref r(m_manager); + new_q = m.update_quantifier(q, new_body); + expr_ref r(m); m_elim(new_q, r); if (q == r.get()) { cache_result(q, q, 0); return; } - proof_ref pr(m_manager); - if (m_manager.fine_grain_proofs()) - pr = m_manager.mk_rewrite(q, r); // TODO: improve justification + proof_ref pr(m); + if (m.fine_grain_proofs()) + pr = m.mk_rewrite(q, r); // TODO: improve justification cache_result(q, r, pr); } diff --git a/src/ast/simplifier/pull_ite_tree.cpp b/src/ast/simplifier/pull_ite_tree.cpp index 080dd5545..05bb3d885 100644 --- a/src/ast/simplifier/pull_ite_tree.cpp +++ b/src/ast/simplifier/pull_ite_tree.cpp @@ -187,7 +187,7 @@ pull_ite_tree_star::pull_ite_tree_star(ast_manager & m, simplifier & s): bool pull_ite_tree_star::get_subst(expr * n, expr_ref & r, proof_ref & p) { if (is_app(n) && is_target(to_app(n))) { - app_ref tmp(m_manager); + app_ref tmp(m); m_proc(to_app(n), tmp, p); r = tmp; return true; @@ -199,10 +199,10 @@ bool pull_cheap_ite_tree_star::is_target(app * n) const { bool r = n->get_num_args() == 2 && n->get_family_id() != null_family_id && - m_manager.is_bool(n) && - (m_manager.is_value(n->get_arg(0)) || m_manager.is_value(n->get_arg(1))) && - (m_manager.is_term_ite(n->get_arg(0)) || m_manager.is_term_ite(n->get_arg(1))); - TRACE("pull_ite_target", tout << mk_pp(n, m_manager) << "\nresult: " << r << "\n";); + m.is_bool(n) && + (m.is_value(n->get_arg(0)) || m.is_value(n->get_arg(1))) && + (m.is_term_ite(n->get_arg(0)) || m.is_term_ite(n->get_arg(1))); + TRACE("pull_ite_target", tout << mk_pp(n, m) << "\nresult: " << r << "\n";); return r; } diff --git a/src/ast/simplifier/push_app_ite.cpp b/src/ast/simplifier/push_app_ite.cpp index cec84d1f5..e33f0d094 100644 --- a/src/ast/simplifier/push_app_ite.cpp +++ b/src/ast/simplifier/push_app_ite.cpp @@ -34,7 +34,7 @@ push_app_ite::~push_app_ite() { int push_app_ite::has_ite_arg(unsigned num_args, expr * const * args) { for (unsigned i = 0; i < num_args; i++) - if (m_manager.is_ite(args[i])) + if (m.is_ite(args[i])) return i; return -1; } @@ -53,10 +53,10 @@ void push_app_ite::apply(func_decl * decl, unsigned num_args, expr * const * arg expr ** args_prime = const_cast(args); expr * old = args_prime[ite_arg_idx]; args_prime[ite_arg_idx] = t; - expr_ref t_new(m_manager); + expr_ref t_new(m); apply(decl, num_args, args_prime, t_new); args_prime[ite_arg_idx] = e; - expr_ref e_new(m_manager); + expr_ref e_new(m); apply(decl, num_args, args_prime, e_new); args_prime[ite_arg_idx] = old; expr * new_args[3] = { c, t_new, e_new }; @@ -67,11 +67,11 @@ void push_app_ite::apply(func_decl * decl, unsigned num_args, expr * const * arg \brief Default (conservative) implementation. Return true if there one and only one ite-term argument. */ bool push_app_ite::is_target(func_decl * decl, unsigned num_args, expr * const * args) { - if (m_manager.is_ite(decl)) + if (m.is_ite(decl)) return false; bool found_ite = false; for (unsigned i = 0; i < num_args; i++) { - if (m_manager.is_ite(args[i]) && !m_manager.is_bool(args[i])) { + if (m.is_ite(args[i]) && !m.is_bool(args[i])) { if (found_ite) { if (m_conservative) return false; @@ -83,7 +83,7 @@ bool push_app_ite::is_target(func_decl * decl, unsigned num_args, expr * const * } CTRACE("push_app_ite", found_ite, tout << "found target for push app ite:\n"; tout << decl->get_name(); - for (unsigned i = 0; i < num_args; i++) tout << " " << mk_pp(args[i], m_manager); + for (unsigned i = 0; i < num_args; i++) tout << " " << mk_pp(args[i], m); tout << "\n";); return found_ite; } @@ -94,19 +94,19 @@ void push_app_ite::operator()(expr * s, expr_ref & r, proof_ref & p) { reduce_core(s); get_cached(s, result, result_proof); r = result; - switch (m_manager.proof_mode()) { + switch (m.proof_mode()) { case PGM_DISABLED: - p = m_manager.mk_undef_proof(); + p = m.mk_undef_proof(); break; case PGM_COARSE: if (result == s) - p = m_manager.mk_reflexivity(s); + p = m.mk_reflexivity(s); else - p = m_manager.mk_rewrite_star(s, result, 0, 0); + p = m.mk_rewrite_star(s, result, 0, 0); break; case PGM_FINE: if (result == s) - p = m_manager.mk_reflexivity(s); + p = m.mk_reflexivity(s); else p = result_proof; break; @@ -171,24 +171,24 @@ void push_app_ite::reduce1_app(app * n) { m_args.reset(); func_decl * decl = n->get_decl(); - proof_ref p1(m_manager); + proof_ref p1(m); get_args(n, m_args, p1); - expr_ref r(m_manager); + expr_ref r(m); if (is_target(decl, m_args.size(), m_args.c_ptr())) apply(decl, m_args.size(), m_args.c_ptr(), r); else mk_app(decl, m_args.size(), m_args.c_ptr(), r); - if (!m_manager.fine_grain_proofs()) + if (!m.fine_grain_proofs()) cache_result(n, r, 0); else { - expr * s = m_manager.mk_app(decl, m_args.size(), m_args.c_ptr()); + expr * s = m.mk_app(decl, m_args.size(), m_args.c_ptr()); proof * p; if (n == r) p = 0; else if (r != s) - p = m_manager.mk_transitivity(p1, m_manager.mk_rewrite(s, r)); + p = m.mk_transitivity(p1, m.mk_rewrite(s, r)); else p = p1; cache_result(n, r, p); @@ -200,8 +200,8 @@ void push_app_ite::reduce1_quantifier(quantifier * q) { proof * new_body_pr; get_cached(q->get_expr(), new_body, new_body_pr); - quantifier * new_q = m_manager.update_quantifier(q, new_body); - proof * p = q == new_q ? 0 : m_manager.mk_quant_intro(q, new_q, new_body_pr); + quantifier * new_q = m.update_quantifier(q, new_body); + proof * p = q == new_q ? 0 : m.mk_quant_intro(q, new_q, new_body_pr); cache_result(q, new_q, p); } diff --git a/src/ast/simplifier/simplifier.cpp b/src/ast/simplifier/simplifier.cpp index c9f72f4d5..5358e01e4 100644 --- a/src/ast/simplifier/simplifier.cpp +++ b/src/ast/simplifier/simplifier.cpp @@ -61,16 +61,18 @@ void simplifier::enable_ac_support(bool flag) { */ void simplifier::operator()(expr * s, expr_ref & r, proof_ref & p) { m_need_reset = true; + reinitialize(); + expr * s_orig = s; expr * old_s; expr * result; proof * result_proof; - switch (m_manager.proof_mode()) { + switch (m.proof_mode()) { case PGM_DISABLED: // proof generation is disabled. reduce_core(s); // after executing reduce_core, the result of the simplification is in the cache get_cached(s, result, result_proof); r = result; - p = m_manager.mk_undef_proof(); + p = m.mk_undef_proof(); break; case PGM_COARSE: // coarse proofs... in this case, we do not produce a step by step (fine grain) proof to show the equivalence (or equisatisfiability) of s an r. m_subst_proofs.reset(); // m_subst_proofs is an auxiliary vector that is used to justify substitutions. See comment on method get_subst. @@ -78,10 +80,10 @@ void simplifier::operator()(expr * s, expr_ref & r, proof_ref & p) { get_cached(s, result, result_proof); r = result; if (result == s) - p = m_manager.mk_reflexivity(s); + p = m.mk_reflexivity(s); else { remove_duplicates(m_subst_proofs); - p = m_manager.mk_rewrite_star(s, result, m_subst_proofs.size(), m_subst_proofs.c_ptr()); + p = m.mk_rewrite_star(s, result, m_subst_proofs.size(), m_subst_proofs.c_ptr()); } break; case PGM_FINE: // fine grain proofs... in this mode, every proof step (or most of them) is described. @@ -90,17 +92,20 @@ void simplifier::operator()(expr * s, expr_ref & r, proof_ref & p) { // keep simplyfing until no further simplifications are possible. while (s != old_s) { TRACE("simplifier", tout << "simplification pass... " << s->get_id() << "\n";); - TRACE("simplifier_loop", tout << mk_ll_pp(s, m_manager) << "\n";); + TRACE("simplifier_loop", tout << mk_ll_pp(s, m) << "\n";); reduce_core(s); get_cached(s, result, result_proof); - if (result_proof != 0) + SASSERT(is_rewrite_proof(s, result, result_proof)); + if (result_proof != 0) { m_proofs.push_back(result_proof); + } old_s = s; s = result; } SASSERT(s != 0); r = s; - p = m_proofs.empty() ? m_manager.mk_reflexivity(s) : m_manager.mk_transitivity(m_proofs.size(), m_proofs.c_ptr()); + p = m_proofs.empty() ? m.mk_reflexivity(s) : m.mk_transitivity(m_proofs.size(), m_proofs.c_ptr()); + SASSERT(is_rewrite_proof(s_orig, r, p)); break; default: UNREACHABLE(); @@ -259,9 +264,9 @@ void simplifier::reduce1(expr * n) { specific simplifications via plugins. */ void simplifier::reduce1_app(app * n) { - expr_ref r(m_manager); - proof_ref p(m_manager); - TRACE("reduce", tout << "reducing...\n" << mk_pp(n, m_manager) << "\n";); + expr_ref r(m); + proof_ref p(m); + TRACE("reduce", tout << "reducing...\n" << mk_pp(n, m) << "\n";); if (get_subst(n, r, p)) { TRACE("reduce", tout << "applying substitution...\n";); cache_result(n, r, p); @@ -279,7 +284,7 @@ void simplifier::reduce1_app(app * n) { void simplifier::reduce1_app_core(app * n) { m_args.reset(); func_decl * decl = n->get_decl(); - proof_ref p1(m_manager); + proof_ref p1(m); // Stores the new arguments of n in m_args. // Let n be of the form // (decl arg_0 ... arg_{n-1}) @@ -296,23 +301,23 @@ void simplifier::reduce1_app_core(app * n) { // If none of the arguments have been simplified, and n is not a theory symbol, // Then no simplification is possible, and we can cache the result of the simplification of n as n. if (has_new_args || decl->get_family_id() != null_family_id) { - expr_ref r(m_manager); - TRACE("reduce", tout << "reduce1_app\n"; for(unsigned i = 0; i < m_args.size(); i++) tout << mk_ll_pp(m_args[i], m_manager);); + expr_ref r(m); + TRACE("reduce", tout << "reduce1_app\n"; for(unsigned i = 0; i < m_args.size(); i++) tout << mk_ll_pp(m_args[i], m);); // the method mk_app invokes get_subst and plugins to simplify // (decl arg_0' ... arg_{n-1}') mk_app(decl, m_args.size(), m_args.c_ptr(), r); - if (!m_manager.fine_grain_proofs()) { + if (!m.fine_grain_proofs()) { cache_result(n, r, 0); } else { - expr * s = m_manager.mk_app(decl, m_args.size(), m_args.c_ptr()); + expr * s = m.mk_app(decl, m_args.size(), m_args.c_ptr()); proof * p; if (n == r) p = 0; else if (r != s) // we use a "theory rewrite generic proof" to justify the step // s = (decl arg_0' ... arg_{n-1}') --> r - p = m_manager.mk_transitivity(p1, m_manager.mk_rewrite(s, r)); + p = m.mk_transitivity(p1, m.mk_rewrite(s, r)); else p = p1; cache_result(n, r, p); @@ -354,11 +359,11 @@ bool is_ac_vector(app * n) { } void simplifier::reduce1_ac_app_core(app * n) { - app_ref n_c(m_manager); - proof_ref p1(m_manager); + app_ref n_c(m); + proof_ref p1(m); mk_ac_congruent_term(n, n_c, p1); - TRACE("ac", tout << "expr:\n" << mk_pp(n, m_manager) << "\ncongruent term:\n" << mk_pp(n_c, m_manager) << "\n";); - expr_ref r(m_manager); + TRACE("ac", tout << "expr:\n" << mk_pp(n, m) << "\ncongruent term:\n" << mk_pp(n_c, m) << "\n";); + expr_ref r(m); func_decl * decl = n->get_decl(); family_id fid = decl->get_family_id(); plugin * p = get_plugin(fid); @@ -376,7 +381,7 @@ void simplifier::reduce1_ac_app_core(app * n) { // done... } else { - r = m_manager.mk_app(decl, m_args.size(), m_args.c_ptr()); + r = m.mk_app(decl, m_args.size(), m_args.c_ptr()); } } else { @@ -385,7 +390,7 @@ void simplifier::reduce1_ac_app_core(app * n) { get_ac_args(n_c, m_args, m_mults); TRACE("ac", tout << "AC args:\n"; for (unsigned i = 0; i < m_args.size(); i++) { - tout << mk_pp(m_args[i], m_manager) << " * " << m_mults[i] << "\n"; + tout << mk_pp(m_args[i], m) << " * " << m_mults[i] << "\n"; }); if (p != 0 && p->reduce(decl, m_args.size(), m_mults.c_ptr(), m_args.c_ptr(), r)) { // done... @@ -393,12 +398,12 @@ void simplifier::reduce1_ac_app_core(app * n) { else { ptr_buffer new_args; expand_args(m_args.size(), m_mults.c_ptr(), m_args.c_ptr(), new_args); - r = m_manager.mk_app(decl, new_args.size(), new_args.c_ptr()); + r = m.mk_app(decl, new_args.size(), new_args.c_ptr()); } } - TRACE("ac", tout << "AC result:\n" << mk_pp(r, m_manager) << "\n";); + TRACE("ac", tout << "AC result:\n" << mk_pp(r, m) << "\n";); - if (!m_manager.fine_grain_proofs()) { + if (!m.fine_grain_proofs()) { cache_result(n, r, 0); } else { @@ -406,7 +411,7 @@ void simplifier::reduce1_ac_app_core(app * n) { if (n == r.get()) p = 0; else if (r.get() != n_c.get()) - p = m_manager.mk_transitivity(p1, m_manager.mk_rewrite(n_c, r)); + p = m.mk_transitivity(p1, m.mk_rewrite(n_c, r)); else p = p1; cache_result(n, r, p); @@ -416,8 +421,8 @@ void simplifier::reduce1_ac_app_core(app * n) { static unsigned g_rewrite_lemma_id = 0; void simplifier::dump_rewrite_lemma(func_decl * decl, unsigned num_args, expr * const * args, expr* result) { - expr_ref arg(m_manager); - arg = m_manager.mk_app(decl, num_args, args); + expr_ref arg(m); + arg = m.mk_app(decl, num_args, args); if (arg.get() != result) { char buffer[128]; #ifdef _WINDOWS @@ -425,11 +430,11 @@ void simplifier::dump_rewrite_lemma(func_decl * decl, unsigned num_args, expr * #else sprintf(buffer, "rewrite_lemma_%d.smt", g_rewrite_lemma_id); #endif - ast_smt_pp pp(m_manager); + ast_smt_pp pp(m); pp.set_benchmark_name("rewrite_lemma"); pp.set_status("unsat"); - expr_ref n(m_manager); - n = m_manager.mk_not(m_manager.mk_eq(arg.get(), result)); + expr_ref n(m); + n = m.mk_not(m.mk_eq(arg.get(), result)); std::ofstream out(buffer); pp.display(out, n); out.close(); @@ -445,14 +450,14 @@ void simplifier::dump_rewrite_lemma(func_decl * decl, unsigned num_args, expr * */ void simplifier::mk_app(func_decl * decl, unsigned num_args, expr * const * args, expr_ref & result) { m_need_reset = true; - if (m_manager.is_eq(decl)) { - sort * s = m_manager.get_sort(args[0]); + if (m.is_eq(decl)) { + sort * s = m.get_sort(args[0]); plugin * p = get_plugin(s->get_family_id()); if (p != 0 && p->reduce_eq(args[0], args[1], result)) return; } - else if (m_manager.is_distinct(decl)) { - sort * s = m_manager.get_sort(args[0]); + else if (m.is_distinct(decl)) { + sort * s = m.get_sort(args[0]); plugin * p = get_plugin(s->get_family_id()); if (p != 0 && p->reduce_distinct(num_args, args, result)) return; @@ -464,7 +469,7 @@ void simplifier::mk_app(func_decl * decl, unsigned num_args, expr * const * args //dump_rewrite_lemma(decl, num_args, args, result.get()); return; } - result = m_manager.mk_app(decl, num_args, args); + result = m.mk_app(decl, num_args, args); } /** @@ -484,7 +489,7 @@ void simplifier::mk_congruent_term(app * n, app_ref & r, proof_ref & p) { get_cached(arg, new_arg, arg_proof); CTRACE("simplifier_bug", (arg != new_arg) != (arg_proof != 0), - tout << mk_ll_pp(arg, m_manager) << "\n---->\n" << mk_ll_pp(new_arg, m_manager) << "\n"; + tout << mk_ll_pp(arg, m) << "\n---->\n" << mk_ll_pp(new_arg, m) << "\n"; tout << "#" << arg->get_id() << " #" << new_arg->get_id() << "\n"; tout << arg << " " << new_arg << "\n";); @@ -500,11 +505,11 @@ void simplifier::mk_congruent_term(app * n, app_ref & r, proof_ref & p) { args.push_back(new_arg); } if (has_new_args) { - r = m_manager.mk_app(n->get_decl(), args.size(), args.c_ptr()); + r = m.mk_app(n->get_decl(), args.size(), args.c_ptr()); if (m_use_oeq) - p = m_manager.mk_oeq_congruence(n, r, proofs.size(), proofs.c_ptr()); + p = m.mk_oeq_congruence(n, r, proofs.size(), proofs.c_ptr()); else - p = m_manager.mk_congruence(n, r, proofs.size(), proofs.c_ptr()); + p = m.mk_congruence(n, r, proofs.size(), proofs.c_ptr()); } else { r = n; @@ -523,8 +528,8 @@ void simplifier::mk_congruent_term(app * n, app_ref & r, proof_ref & p) { bool simplifier::get_args(app * n, ptr_vector & result, proof_ref & p) { bool has_new_args = false; unsigned num = n->get_num_args(); - if (m_manager.fine_grain_proofs()) { - app_ref r(m_manager); + if (m.fine_grain_proofs()) { + app_ref r(m); mk_congruent_term(n, r, p); result.append(r->get_num_args(), r->get_args()); SASSERT(n->get_num_args() == result.size()); @@ -582,7 +587,7 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) { new_args.push_back(new_arg); if (arg != new_arg) has_new_arg = true; - if (m_manager.fine_grain_proofs()) { + if (m.fine_grain_proofs()) { proof * pr = 0; m_ac_pr_cache.find(to_app(arg), pr); if (pr != 0) @@ -601,7 +606,7 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) { new_args.push_back(new_arg); if (arg != new_arg) has_new_arg = true; - if (m_manager.fine_grain_proofs() && pr != 0) + if (m.fine_grain_proofs() && pr != 0) new_arg_prs.push_back(pr); } } @@ -610,14 +615,14 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) { todo.pop_back(); if (!has_new_arg) { m_ac_cache.insert(curr, curr); - if (m_manager.fine_grain_proofs()) + if (m.fine_grain_proofs()) m_ac_pr_cache.insert(curr, 0); } else { - app * new_curr = m_manager.mk_app(f, new_args.size(), new_args.c_ptr()); + app * new_curr = m.mk_app(f, new_args.size(), new_args.c_ptr()); m_ac_cache.insert(curr, new_curr); - if (m_manager.fine_grain_proofs()) { - proof * p = m_manager.mk_congruence(curr, new_curr, new_arg_prs.size(), new_arg_prs.c_ptr()); + if (m.fine_grain_proofs()) { + proof * p = m.mk_congruence(curr, new_curr, new_arg_prs.size(), new_arg_prs.c_ptr()); m_ac_pr_cache.insert(curr, p); } } @@ -628,7 +633,7 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) { app * new_n = 0; m_ac_cache.find(n, new_n); r = new_n; - if (m_manager.fine_grain_proofs()) { + if (m.fine_grain_proofs()) { proof * new_pr = 0; m_ac_pr_cache.find(n, new_pr); p = new_pr; @@ -719,7 +724,7 @@ void simplifier::get_ac_args(app * n, ptr_vector & args, vector SASSERT(!sorted_exprs.empty()); SASSERT(sorted_exprs[sorted_exprs.size()-1] == n); - TRACE("ac", tout << mk_ll_pp(n, m_manager, true, false) << "#" << n->get_id() << "\nsorted expressions...\n"; + TRACE("ac", tout << mk_ll_pp(n, m, true, false) << "#" << n->get_id() << "\nsorted expressions...\n"; for (unsigned i = 0; i < sorted_exprs.size(); i++) { tout << "#" << sorted_exprs[i]->get_id() << " "; } @@ -754,10 +759,10 @@ void simplifier::get_ac_args(app * n, ptr_vector & args, vector void simplifier::reduce1_quantifier(quantifier * q) { expr * new_body; proof * new_body_pr; - SASSERT(is_well_sorted(m_manager, q)); + SASSERT(is_well_sorted(m, q)); get_cached(q->get_expr(), new_body, new_body_pr); - quantifier_ref q1(m_manager); + quantifier_ref q1(m); proof * p1 = 0; if (is_quantifier(new_body) && @@ -774,7 +779,7 @@ void simplifier::reduce1_quantifier(quantifier * q) { sorts.append(nested_q->get_num_decls(), nested_q->get_decl_sorts()); names.append(nested_q->get_num_decls(), nested_q->get_decl_names()); - q1 = m_manager.mk_quantifier(q->is_forall(), + q1 = m.mk_quantifier(q->is_forall(), sorts.size(), sorts.c_ptr(), names.c_ptr(), @@ -783,13 +788,13 @@ void simplifier::reduce1_quantifier(quantifier * q) { q->get_qid(), q->get_skid(), 0, 0, 0, 0); - SASSERT(is_well_sorted(m_manager, q1)); + SASSERT(is_well_sorted(m, q1)); - if (m_manager.fine_grain_proofs()) { - quantifier * q0 = m_manager.update_quantifier(q, new_body); - proof * p0 = q == q0 ? 0 : m_manager.mk_quant_intro(q, q0, new_body_pr); - p1 = m_manager.mk_pull_quant(q0, q1); - p1 = m_manager.mk_transitivity(p0, p1); + if (m.fine_grain_proofs()) { + quantifier * q0 = m.update_quantifier(q, new_body); + proof * p0 = q == q0 ? 0 : m.mk_quant_intro(q, q0, new_body_pr); + p1 = m.mk_pull_quant(q0, q1); + p1 = m.mk_transitivity(p0, p1); } } else { @@ -802,7 +807,7 @@ void simplifier::reduce1_quantifier(quantifier * q) { unsigned num = q->get_num_patterns(); for (unsigned i = 0; i < num; i++) { get_cached(q->get_pattern(i), new_pattern, new_pattern_pr); - if (m_manager.is_pattern(new_pattern)) { + if (m.is_pattern(new_pattern)) { new_patterns.push_back(new_pattern); } } @@ -815,7 +820,7 @@ void simplifier::reduce1_quantifier(quantifier * q) { remove_duplicates(new_patterns); remove_duplicates(new_no_patterns); - q1 = m_manager.mk_quantifier(q->is_forall(), + q1 = m.mk_quantifier(q->is_forall(), q->get_num_decls(), q->get_decl_sorts(), q->get_decl_names(), @@ -827,26 +832,26 @@ void simplifier::reduce1_quantifier(quantifier * q) { new_patterns.c_ptr(), new_no_patterns.size(), new_no_patterns.c_ptr()); - SASSERT(is_well_sorted(m_manager, q1)); + SASSERT(is_well_sorted(m, q1)); - TRACE("simplifier", tout << mk_pp(q, m_manager) << "\n" << mk_pp(q1, m_manager) << "\n";); - if (m_manager.fine_grain_proofs()) { + TRACE("simplifier", tout << mk_pp(q, m) << "\n" << mk_pp(q1, m) << "\n";); + if (m.fine_grain_proofs()) { if (q != q1 && !new_body_pr) { - new_body_pr = m_manager.mk_rewrite(q->get_expr(), new_body); + new_body_pr = m.mk_rewrite(q->get_expr(), new_body); } - p1 = q == q1 ? 0 : m_manager.mk_quant_intro(q, q1, new_body_pr); + p1 = q == q1 ? 0 : m.mk_quant_intro(q, q1, new_body_pr); } } - expr_ref r(m_manager); - elim_unused_vars(m_manager, q1, r); + expr_ref r(m); + elim_unused_vars(m, q1, r); proof * pr = 0; - if (m_manager.fine_grain_proofs()) { + if (m.fine_grain_proofs()) { proof * p2 = 0; if (q1.get() != r.get()) - p2 = m_manager.mk_elim_unused_vars(q1, r); - pr = m_manager.mk_transitivity(p1, p2); + p2 = m.mk_elim_unused_vars(q1, r); + pr = m.mk_transitivity(p1, p2); } cache_result(q, r, pr); @@ -892,7 +897,7 @@ bool subst_simplifier::get_subst(expr * n, expr_ref & r, proof_ref & p) { m_subst_map->get(n, _r, _p); r = _r; p = _p; - if (m_manager.coarse_grain_proofs()) + if (m.coarse_grain_proofs()) m_subst_proofs.push_back(p); return true; } diff --git a/src/ast/simplifier/simplifier.h b/src/ast/simplifier/simplifier.h index 7c5bc3102..78e28bea9 100644 --- a/src/ast/simplifier/simplifier.h +++ b/src/ast/simplifier/simplifier.h @@ -210,7 +210,7 @@ public: plugin * get_plugin(family_id fid) const { return m_plugins.get_plugin(fid); } - ast_manager & get_manager() { return m_manager; } + ast_manager & get_manager() { return m; } void borrow_plugins(simplifier const & s); void release_plugins(); diff --git a/src/ast/substitution/substitution_tree.cpp b/src/ast/substitution/substitution_tree.cpp index 037d51e32..6aaa2da66 100644 --- a/src/ast/substitution/substitution_tree.cpp +++ b/src/ast/substitution/substitution_tree.cpp @@ -793,8 +793,10 @@ bool substitution_tree::visit(expr * e, st_visitor & st, node * r) { } else { TRACE("st_bug", tout << "found match:\n"; m_subst->display(tout); tout << "m_subst: " << m_subst << "\n";); - if (!st(n->m_expr)) + if (!st(n->m_expr)) { + clear_stack(); return false; + } if (!backtrack()) break; } @@ -806,12 +808,16 @@ bool substitution_tree::visit(expr * e, st_visitor & st, node * r) { else if (!backtrack()) break; } + clear_stack(); + return true; +} + +void substitution_tree::clear_stack() { while (!m_bstack.empty()) { m_subst->pop_scope(); m_bstack.pop_back(); } m_subst->pop_scope(); - return true; } template diff --git a/src/ast/substitution/substitution_tree.h b/src/ast/substitution/substitution_tree.h index caa3d37cb..07723a8e4 100644 --- a/src/ast/substitution/substitution_tree.h +++ b/src/ast/substitution/substitution_tree.h @@ -123,6 +123,8 @@ class substitution_tree { template void visit(expr * e, st_visitor & st, unsigned in_offset, unsigned st_offset, unsigned reg_offset); + void clear_stack(); + public: substitution_tree(ast_manager & m); ~substitution_tree(); diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 731608524..4a51da9b0 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -25,6 +25,7 @@ Notes: #include"datatype_decl_plugin.h" #include"seq_decl_plugin.h" #include"float_decl_plugin.h" +#include"pb_decl_plugin.h" #include"ast_pp.h" #include"var_subst.h" #include"pp.h" @@ -314,8 +315,9 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l): m_numeral_as_real(false), m_ignore_check(false), m_exit_on_error(false), - m_manager(m), + m_manager(m), m_own_manager(m == 0), + m_manager_initialized(false), m_pmanager(0), m_sexpr_manager(0), m_regular("stdout", std::cout), @@ -326,8 +328,6 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l): install_core_tactic_cmds(*this); install_interpolant_cmds(*this); SASSERT(m != 0 || !has_manager()); - if (m) - init_external_manager(); if (m_main_ctx) { set_verbose_stream(diagnostic_stream()); } @@ -337,10 +337,10 @@ cmd_context::~cmd_context() { if (m_main_ctx) { set_verbose_stream(std::cerr); } - reset(true); finalize_cmds(); finalize_tactic_cmds(); finalize_probes(); + reset(true); m_solver = 0; m_check_sat_result = 0; } @@ -358,6 +358,18 @@ void cmd_context::set_cancel(bool f) { m().set_cancel(f); } +opt_wrapper* cmd_context::get_opt() { + return m_opt.get(); +} + +void cmd_context::set_opt(opt_wrapper* opt) { + m_opt = opt; + for (unsigned i = 0; i < m_scopes.size(); ++i) { + m_opt->push(); + } + m_opt->set_logic(m_logic); +} + void cmd_context::global_params_updated() { m_params.updt_params(); if (m_params.m_smtlib2_compliant) @@ -471,6 +483,16 @@ void cmd_context::register_plugin(symbol const & name, decl_plugin * p, bool ins } } +void cmd_context::load_plugin(symbol const & name, bool install, svector& fids) { + family_id id = m_manager->get_family_id(name); + decl_plugin* p = m_manager->get_plugin(id); + if (install && p && fids.contains(id)) { + register_builtin_sorts(p); + register_builtin_ops(p); + } + fids.erase(id); +} + bool cmd_context::logic_has_arith_core(symbol const & s) const { return s == "QF_LRA" || @@ -551,6 +573,7 @@ bool cmd_context::logic_has_floats() const { return !has_logic() || m_logic == "QF_FPA" || m_logic == "QF_FPABV"; } + bool cmd_context::logic_has_array_core(symbol const & s) const { return s == "QF_AX" || @@ -587,17 +610,27 @@ void cmd_context::init_manager_core(bool new_manager) { register_builtin_sorts(basic); register_builtin_ops(basic); // the manager was created by the command context. - register_plugin(symbol("arith"), alloc(arith_decl_plugin), logic_has_arith()); - register_plugin(symbol("bv"), alloc(bv_decl_plugin), logic_has_bv()); - register_plugin(symbol("array"), alloc(array_decl_plugin), logic_has_array()); + register_plugin(symbol("arith"), alloc(arith_decl_plugin), logic_has_arith()); + register_plugin(symbol("bv"), alloc(bv_decl_plugin), logic_has_bv()); + register_plugin(symbol("array"), alloc(array_decl_plugin), logic_has_array()); register_plugin(symbol("datatype"), alloc(datatype_decl_plugin), logic_has_datatype()); register_plugin(symbol("seq"), alloc(seq_decl_plugin), logic_has_seq()); register_plugin(symbol("float"), alloc(float_decl_plugin), logic_has_floats()); + register_plugin(symbol("pb"), alloc(pb_decl_plugin), !has_logic()); } else { - // the manager was created by an external module, we must register all plugins available in the manager. + // the manager was created by an external module + // we register all plugins available in the manager. + // unless the logic specifies otherwise. svector fids; m_manager->get_range(fids); + load_plugin(symbol("arith"), logic_has_arith(), fids); + load_plugin(symbol("bv"), logic_has_bv(), fids); + load_plugin(symbol("array"), logic_has_array(), fids); + load_plugin(symbol("datatype"), logic_has_datatype(), fids); + load_plugin(symbol("seq"), logic_has_seq(), fids); + load_plugin(symbol("float"), logic_has_floats(), fids); + svector::iterator it = fids.begin(); svector::iterator end = fids.end(); for (; it != end; ++it) { @@ -620,12 +653,22 @@ void cmd_context::init_manager_core(bool new_manager) { } void cmd_context::init_manager() { - SASSERT(m_manager == 0); - SASSERT(m_pmanager == 0); - m_check_sat_result = 0; - m_manager = m_params.mk_ast_manager(); - m_pmanager = alloc(pdecl_manager, *m_manager); - init_manager_core(true); + if (m_manager_initialized) { + // no-op + } + else if (m_manager) { + m_manager_initialized = true; + SASSERT(!m_own_manager); + init_external_manager(); + } + else { + m_manager_initialized = true; + SASSERT(m_pmanager == 0); + m_check_sat_result = 0; + m_manager = m_params.mk_ast_manager(); + m_pmanager = alloc(pdecl_manager, *m_manager); + init_manager_core(true); + } } void cmd_context::init_external_manager() { @@ -708,7 +751,7 @@ void cmd_context::insert(symbol const & s, func_decl * f) { if (!m_global_decls) { m_func_decls_stack.push_back(sf_pair(s, f)); } - TRACE("cmd_context", tout << "new sort decl\n" << mk_pp(f, m()) << "\n";); + TRACE("cmd_context", tout << "new function decl\n" << mk_pp(f, m()) << "\n";); } void cmd_context::insert(symbol const & s, psort_decl * p) { @@ -1141,7 +1184,6 @@ void cmd_context::insert_aux_pdecl(pdecl * p) { } void cmd_context::reset(bool finalize) { - m_check_sat_result = 0; m_logic = symbol::null; m_check_sat_result = 0; m_numeral_as_real = false; @@ -1157,6 +1199,7 @@ void cmd_context::reset(bool finalize) { restore_assertions(0); if (m_solver) m_solver = 0; + m_opt = 0; m_pp_env = 0; m_dt_eh = 0; if (m_manager) { @@ -1165,12 +1208,15 @@ void cmd_context::reset(bool finalize) { if (m_own_manager) { dealloc(m_manager); m_manager = 0; + m_manager_initialized = false; } else { // doesn't own manager... so it cannot be deleted // reinit cmd_context if this is not a finalization step if (!finalize) init_external_manager(); + else + m_manager_initialized = false; } } if (m_sexpr_manager) { @@ -1211,8 +1257,7 @@ void cmd_context::assert_expr(symbol const & name, expr * t) { void cmd_context::push() { m_check_sat_result = 0; - if (!has_manager()) - init_manager(); + init_manager(); m_scopes.push_back(scope()); scope & s = m_scopes.back(); s.m_func_decls_stack_lim = m_func_decls_stack.size(); @@ -1222,6 +1267,8 @@ void cmd_context::push() { s.m_assertions_lim = m_assertions.size(); if (m_solver) m_solver->push(); + if (m_opt) + m_opt->push(); } void cmd_context::push(unsigned n) { @@ -1317,6 +1364,8 @@ void cmd_context::pop(unsigned n) { if (m_solver) { m_solver->pop(n); } + if (m_opt) + m_opt->pop(n); unsigned new_lvl = lvl - n; scope & s = m_scopes[new_lvl]; restore_func_decls(s.m_func_decls_stack_lim); @@ -1332,17 +1381,49 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions return; IF_VERBOSE(100, verbose_stream() << "(started \"check-sat\")" << std::endl;); TRACE("before_check_sat", dump_assertions(tout);); - if (!has_manager()) - init_manager(); - if (m_solver) { + init_manager(); + unsigned timeout = m_params.m_timeout; + scoped_watch sw(*this); + lbool r; + + if (m_opt && !m_opt->empty()) { + bool was_pareto = false; + m_check_sat_result = get_opt(); + cancel_eh eh(*get_opt()); + scoped_ctrl_c ctrlc(eh); + scoped_timer timer(timeout, &eh); + ptr_vector cnstr(m_assertions); + cnstr.append(num_assumptions, assumptions); + get_opt()->set_hard_constraints(cnstr); + try { + r = get_opt()->optimize(); + while (r == l_true && get_opt()->is_pareto()) { + was_pareto = true; + get_opt()->display_assignment(regular_stream()); + regular_stream() << "\n"; + r = get_opt()->optimize(); + } + } + catch (z3_error & ex) { + throw ex; + } + catch (z3_exception & ex) { + throw cmd_exception(ex.msg()); + } + if (was_pareto && r == l_false) { + r = l_true; + } + get_opt()->set_status(r); + if (r != l_false && !was_pareto) { + get_opt()->display_assignment(regular_stream()); + } + } + else if (m_solver) { m_check_sat_result = m_solver.get(); // solver itself stores the result. m_solver->set_progress_callback(this); - unsigned timeout = m_params.m_timeout; - scoped_watch sw(*this); cancel_eh eh(*m_solver); scoped_ctrl_c ctrlc(eh); scoped_timer timer(timeout, &eh); - lbool r; try { r = m_solver->check_sat(num_assumptions, assumptions); } @@ -1353,15 +1434,17 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions throw cmd_exception(ex.msg()); } m_solver->set_status(r); - display_sat_result(r); - validate_check_sat_result(r); - if (r == l_true) - validate_model(); } else { // There is no solver installed in the command context. regular_stream() << "unknown" << std::endl; + return; } + display_sat_result(r); + validate_check_sat_result(r); + if (r == l_true) + validate_model(); + } void cmd_context::display_sat_result(lbool r) { @@ -1538,6 +1621,9 @@ void cmd_context::display_statistics(bool show_total_time, double total_time) { else if (m_solver) { m_solver->collect_statistics(st); } + else if (m_opt) { + m_opt->collect_statistics(st); + } st.display_smt2(regular_stream()); } diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 8ad07e8cc..4e93992d1 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -111,6 +111,21 @@ struct builtin_decl { builtin_decl(family_id fid, decl_kind k, builtin_decl * n = 0):m_fid(fid), m_decl(k), m_next(n) {} }; +class opt_wrapper : public check_sat_result { +public: + virtual bool empty() = 0; + virtual void push() = 0; + virtual void pop(unsigned n) = 0; + virtual void set_cancel(bool f) = 0; + virtual void reset_cancel() = 0; + virtual void cancel() = 0; + virtual lbool optimize() = 0; + virtual void set_hard_constraints(ptr_vector & hard) = 0; + virtual void display_assignment(std::ostream& out) = 0; + virtual bool is_pareto() = 0; + virtual void set_logic(symbol const& s) = 0; +}; + class cmd_context : public progress_callback, public tactic_manager, public ast_printer_context { public: enum status { @@ -149,6 +164,7 @@ protected: ast_manager * m_manager; bool m_own_manager; + bool m_manager_initialized; pdecl_manager * m_pmanager; sexpr_manager * m_sexpr_manager; check_logic m_check_logic; @@ -187,8 +203,9 @@ protected: svector m_scopes; scoped_ptr m_solver_factory; scoped_ptr m_interpolating_solver_factory; - ref m_solver; + ref m_solver; ref m_check_sat_result; + ref m_opt; stopwatch m_watch; @@ -212,7 +229,7 @@ protected: void register_builtin_sorts(decl_plugin * p); void register_builtin_ops(decl_plugin * p); - void register_plugin(symbol const & name, decl_plugin * p, bool install_names); + void load_plugin(symbol const & name, bool install_names, svector& fids); void init_manager_core(bool new_manager); void init_manager(); void init_external_manager(); @@ -256,6 +273,8 @@ public: context_params & params() { return m_params; } solver_factory &get_solver_factory() { return *m_solver_factory; } solver_factory &get_interpolating_solver_factory() { return *m_interpolating_solver_factory; } + opt_wrapper* get_opt(); + void set_opt(opt_wrapper* o); void global_params_updated(); // this method should be invoked when global (and module) params are updated. bool set_logic(symbol const & s); bool has_logic() const { return m_logic != symbol::null; } @@ -293,7 +312,7 @@ public: std::string reason_unknown() const; bool has_manager() const { return m_manager != 0; } - ast_manager & m() const { if (!m_manager) const_cast(this)->init_manager(); return *m_manager; } + ast_manager & m() const { const_cast(this)->init_manager(); return *m_manager; } virtual ast_manager & get_ast_manager() { return m(); } pdecl_manager & pm() const { if (!m_pmanager) const_cast(this)->init_manager(); return *m_pmanager; } sexpr_manager & sm() const { if (!m_sexpr_manager) const_cast(this)->m_sexpr_manager = alloc(sexpr_manager); return *m_sexpr_manager; } @@ -304,7 +323,8 @@ public: check_sat_result * get_check_sat_result() const { return m_check_sat_result.get(); } check_sat_state cs_state() const; void validate_model(); - + + void register_plugin(symbol const & name, decl_plugin * p, bool install_names); bool is_func_decl(symbol const & s) const; bool is_sort_decl(symbol const& s) const { return m_psort_decls.contains(s); } void insert(cmd * c); diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index f87c8d264..f4ec140ef 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -83,13 +83,13 @@ void context_params::set(char const * param, char const * value) { set_bool(m_smtlib2_compliant, param, value); } else { - param_descrs d; - collect_param_descrs(d); - std::stringstream strm; - strm << "unknown parameter '" << p << "'\n"; - strm << "Legal parameters are:\n"; - d.display(strm, 2, false, false); - throw default_exception(strm.str()); + param_descrs d; + collect_param_descrs(d); + std::stringstream strm; + strm << "unknown parameter '" << p << "'\n"; + strm << "Legal parameters are:\n"; + d.display(strm, 2, false, false); + throw default_exception(strm.str()); } } diff --git a/src/duality/duality.h b/src/duality/duality.h old mode 100755 new mode 100644 index edd89d78f..04527450c --- a/src/duality/duality.h +++ b/src/duality/duality.h @@ -778,6 +778,10 @@ protected: struct Bad { }; + // thrown on more serious internal error + struct ReallyBad { + }; + /** Pop a scope (see Push). Note, you cannot pop axioms. */ void Pop(int num_scopes); diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp index f2824c9b0..cb71bd99c 100755 --- a/src/duality/duality_rpfp.cpp +++ b/src/duality/duality_rpfp.cpp @@ -2643,6 +2643,10 @@ namespace Duality { GetGroundLitsUnderQuants(memo,f.body(),res,1); return; } + if(f.is_var()){ + // std::cout << "foo!\n"; + return; + } if(under && f.is_ground()) res.push_back(f); } @@ -3065,10 +3069,14 @@ namespace Duality { node->Annotation.SetEmpty(); hash_set *core = new hash_set; core->insert(node->Outgoing->dual); + expr prev_annot = ctx.bool_val(false); + expr prev_impl = ctx.bool_val(false); + int repeated_case_count = 0; while(1){ by_case_counter++; is.push(); expr annot = !GetAnnotation(node); + Transformer old_annot = node->Annotation; is.add(annot); if(is.check() == unsat){ is.pop(1); @@ -3076,56 +3084,70 @@ namespace Duality { } is.pop(1); Push(); - ConstrainEdgeLocalized(node->Outgoing,is.get_implicant()); + expr the_impl = is.get_implicant(); + if(eq(the_impl,prev_impl)){ + // std::cout << "got old implicant\n"; + repeated_case_count++; + } + prev_impl = the_impl; + ConstrainEdgeLocalized(node->Outgoing,the_impl); ConstrainEdgeLocalized(node->Outgoing,!GetAnnotation(node)); //TODO: need this? - check_result foo = Check(root); - if(foo != unsat){ - slvr().print("should_be_unsat.smt2"); - throw "should be unsat"; - } - std::vector assumps, axioms_to_add; - slvr().get_proof().get_assumptions(assumps); - for(unsigned i = 0; i < assumps.size(); i++){ - (*core).insert(assumps[i]); - if(axioms_needed.find(assumps[i]) != axioms_needed.end()){ - axioms_to_add.push_back(assumps[i]); - axioms_needed.erase(assumps[i]); - } - } - // AddToProofCore(*core); - Transformer old_annot = node->Annotation; - SolveSingleNode(root,node); - - { - expr itp = GetAnnotation(node); - dualModel = is.get_model(); // TODO: what does this mean? - std::vector case_lits; - itp = StrengthenFormulaByCaseSplitting(itp, case_lits); - SetAnnotation(node,itp); - node->Annotation.Formula = node->Annotation.Formula.simplify(); - } - - for(unsigned i = 0; i < axioms_to_add.size(); i++) - is.add(axioms_to_add[i]); -#define TEST_BAD -#ifdef TEST_BAD { - static int bad_count = 0, num_bads = 1; - if(bad_count >= num_bads){ - bad_count = 0; - num_bads = num_bads * 2; + check_result foo = Check(root); + if(foo != unsat){ Pop(1); is.pop(1); delete core; timer_stop("InterpolateByCases"); - throw Bad(); + throw ReallyBad(); + // slvr().print("should_be_unsat.smt2"); + // throw "should be unsat"; } - bad_count++; - } -#endif + std::vector assumps, axioms_to_add; + slvr().get_proof().get_assumptions(assumps); + for(unsigned i = 0; i < assumps.size(); i++){ + (*core).insert(assumps[i]); + if(axioms_needed.find(assumps[i]) != axioms_needed.end()){ + axioms_to_add.push_back(assumps[i]); + axioms_needed.erase(assumps[i]); + } + } + // AddToProofCore(*core); + SolveSingleNode(root,node); - if(node->Annotation.IsEmpty()){ + { + expr itp = GetAnnotation(node); + dualModel = is.get_model(); // TODO: what does this mean? + std::vector case_lits; + itp = StrengthenFormulaByCaseSplitting(itp, case_lits); + SetAnnotation(node,itp); + node->Annotation.Formula = node->Annotation.Formula.simplify(); + } + + for(unsigned i = 0; i < axioms_to_add.size(); i++) + is.add(axioms_to_add[i]); + +#define TEST_BAD +#ifdef TEST_BAD + { + static int bad_count = 0, num_bads = 1; + if(bad_count >= num_bads){ + bad_count = 0; + num_bads = num_bads * 2; + Pop(1); + is.pop(1); + delete core; + timer_stop("InterpolateByCases"); + throw Bad(); + } + bad_count++; + } +#endif + } + + if(node->Annotation.IsEmpty() || eq(node->Annotation.Formula,prev_annot) || (repeated_case_count > 0 && !axioms_added) || (repeated_case_count >= 10)){ +// looks_bad: if(!axioms_added){ // add the axioms in the off chance they are useful const std::vector &theory = ls->get_axioms(); @@ -3134,6 +3156,7 @@ namespace Duality { axioms_added = true; } else { + //#define KILL_ON_BAD_INTERPOLANT #ifdef KILL_ON_BAD_INTERPOLANT std::cout << "bad in InterpolateByCase -- core:\n"; #if 0 @@ -3175,10 +3198,11 @@ namespace Duality { is.pop(1); delete core; timer_stop("InterpolateByCases"); - throw Bad(); + throw ReallyBad(); } } Pop(1); + prev_annot = node->Annotation.Formula; node->Annotation.UnionWith(old_annot); } if(proof_core) diff --git a/src/duality/duality_solver.cpp b/src/duality/duality_solver.cpp old mode 100755 new mode 100644 index 69759f9bb..b40ab9370 --- a/src/duality/duality_solver.cpp +++ b/src/duality/duality_solver.cpp @@ -2279,6 +2279,18 @@ namespace Duality { // bad interpolants can get us here throw DoRestart(); } + catch(const RPFP::ReallyBad &){ + // this could be caused by incompleteness + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + node->map->Annotation.SetFull(); + std::vector &chs = node->map->Outgoing->Children; + for(unsigned j = 0; j < chs.size(); j++) + chs[j]->Annotation.SetFull(); + reporter->Message("incompleteness: cleared annotation and child annotations"); + } + throw DoRestart(); + } catch(char const *msg){ // bad interpolants can get us here reporter->Message(std::string("interpolation failure:") + msg); diff --git a/src/duality/duality_wrapper.h b/src/duality/duality_wrapper.h old mode 100755 new mode 100644 index 979717580..0e367129d --- a/src/duality/duality_wrapper.h +++ b/src/duality/duality_wrapper.h @@ -1489,4 +1489,3 @@ namespace std { } #endif - diff --git a/src/interp/iz3base.h b/src/interp/iz3base.h index bca9b8518..956191290 100755 --- a/src/interp/iz3base.h +++ b/src/interp/iz3base.h @@ -161,7 +161,7 @@ class iz3base : public iz3mgr, public scopes { stl_ext::hash_map simplify_memo; stl_ext::hash_map frame_map; // map assertions to frames - int frames; // number of frames + // int frames; // number of frames protected: void add_frame_range(int frame, ast t); diff --git a/src/interp/iz3hash.h b/src/interp/iz3hash.h index cd94f0e04..5d401d49f 100644 --- a/src/interp/iz3hash.h +++ b/src/interp/iz3hash.h @@ -56,7 +56,7 @@ namespace hash_space { class hash { public: size_t operator()(const std::string &s) const { - return string_hash(s.c_str(), s.size(), 0); + return string_hash(s.c_str(), static_cast(s.size()), 0); } }; @@ -111,7 +111,7 @@ namespace hash_space { 4294967291ul }; - inline unsigned long next_prime(unsigned long n) { + inline size_t next_prime(size_t n) { const unsigned long* to = primes + (int)num_primes; for(const unsigned long* p = primes; p < to; p++) if(*p >= n) return *p; @@ -378,7 +378,7 @@ namespace hash_space { void resize(size_t new_size) { const size_t old_n = buckets.size(); if (new_size <= old_n) return; - const size_t n = next_prime(new_size); + const size_t n = next_prime(static_cast(new_size)); if (n <= old_n) return; Table tmp(n, (Entry*)(0)); for (size_t i = 0; i < old_n; ++i) { diff --git a/src/interp/iz3mgr.cpp b/src/interp/iz3mgr.cpp index a39065922..e3ac59dfd 100755 --- a/src/interp/iz3mgr.cpp +++ b/src/interp/iz3mgr.cpp @@ -778,6 +778,8 @@ int iz3mgr::occurs_in(ast var, ast e){ bool iz3mgr::solve_arith(const ast &v, const ast &x, const ast &y, ast &res){ + if(occurs_in(v,y)) + return false; if(op(x) == Plus){ int n = num_args(x); for(int i = 0; i < n; i++){ @@ -801,8 +803,8 @@ iz3mgr::ast iz3mgr::cont_eq(stl_ext::hash_set &cont_eq_memo, bool truth, as return ast(); cont_eq_memo.insert(e); if(!truth && op(e) == Equal){ - if(arg(e,0) == v) return(arg(e,1)); - if(arg(e,1) == v) return(arg(e,0)); + if(arg(e,0) == v && !occurs_in(v,arg(e,1))) return(arg(e,1)); + if(arg(e,1) == v && !occurs_in(v,arg(e,0))) return(arg(e,0)); ast res; if(solve_arith(v,arg(e,0),arg(e,1),res)) return res; if(solve_arith(v,arg(e,1),arg(e,0),res)) return res; diff --git a/src/interp/iz3mgr.h b/src/interp/iz3mgr.h index 3ec2c42d1..7f66bb2d8 100755 --- a/src/interp/iz3mgr.h +++ b/src/interp/iz3mgr.h @@ -278,7 +278,8 @@ class iz3mgr { } symb sym(ast t){ - return to_app(t.raw())->get_decl(); + raw_ast *_ast = t.raw(); + return is_app(_ast) ? to_app(_ast)->get_decl() : 0; } std::string string_of_symbol(symb s){ diff --git a/src/interp/iz3proof_itp.cpp b/src/interp/iz3proof_itp.cpp index 52ddcd64f..251a56e7a 100755 --- a/src/interp/iz3proof_itp.cpp +++ b/src/interp/iz3proof_itp.cpp @@ -1027,7 +1027,7 @@ class iz3proof_itp_impl : public iz3proof_itp { linear_comb(Aineqs,coeff,make(Leq,make_int(rational(0)),make(Sub,term2,term1))); } else { - ast pf = extract_rewrites(make(concat,mk_true(),rest),p1); + ast pf = extract_rewrites(make(concat,mk_true(),last),p1); ast new_normal = fix_normal(term1,term2,pf); normals = merge_normal_chains(normals,cons_normal(new_normal,mk_true()), Aproves, Bproves); } @@ -2747,7 +2747,8 @@ class iz3proof_itp_impl : public iz3proof_itp { ast orig_e = e; pf = make_refl(e); // proof that e = e - prover::range erng = pv->ast_scope(e); + // prover::range erng = + pv->ast_scope(e); #if 0 if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){ return e; // this term occurs in range, so it's O.K. diff --git a/src/interp/iz3translate.cpp b/src/interp/iz3translate.cpp index 26786d57a..f65ec72d4 100755 --- a/src/interp/iz3translate.cpp +++ b/src/interp/iz3translate.cpp @@ -1712,11 +1712,17 @@ public: std::cout << "foo!\n"; // no idea why this shows up - if(dk == PR_MODUS_PONENS_OEQ) + if(dk == PR_MODUS_PONENS_OEQ){ if(conc(prem(proof,0)) == con){ res = translate_main(prem(proof,0),expect_clause); return res; } + if(expect_clause && op(con) == Or){ // skolemization does this + Iproof::node clause = translate_main(prem(proof,0),true); + res = RewriteClause(clause,prem(proof,1)); + return res; + } + } #if 0 if(1 && dk == PR_TRANSITIVITY && pr(prem(proof,1)) == PR_COMMUTATIVITY){ @@ -1800,7 +1806,9 @@ public: } break; } - case PR_MONOTONICITY: { + case PR_QUANT_INTRO: + case PR_MONOTONICITY: + { std::vector eqs; eqs.resize(args.size()); for(unsigned i = 0; i < args.size(); i++) eqs[i] = conc(prem(proof,i)); diff --git a/src/math/simplex/network_flow.h b/src/math/simplex/network_flow.h new file mode 100644 index 000000000..e0b415c03 --- /dev/null +++ b/src/math/simplex/network_flow.h @@ -0,0 +1,200 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + network_flow.h + +Abstract: + + Implements Network Simplex algorithm for min cost flow problem + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-24 + +Notes: + + This will be used to solve the dual of min cost flow problem + i.e. optimization of difference constraint. + + We need a function to reduce DL constraints to min cost flow problem + and another function to convert from min cost flow solution to DL solution. + + It remains unclear how to convert DL assignment to a basic feasible solution of Network Simplex. + A naive approach is to run an algorithm on max flow in order to get a spanning tree. + +--*/ +#ifndef _NETWORK_FLOW_H_ +#define _NETWORK_FLOW_H_ + +#include"inf_rational.h" +#include"diff_logic.h" +#include"spanning_tree.h" + +namespace smt { + + enum min_flow_result { + // Min cost flow problem is infeasible. + // Diff logic optimization could be unbounded or infeasible. + INFEASIBLE, + // Min cost flow and diff logic optimization are both optimal. + OPTIMAL, + // Min cost flow problem is unbounded. + // Diff logic optimization has to be infeasible. + UNBOUNDED, + }; + + enum pivot_rule { + // First eligible edge pivot rule + // Edges are traversed in a wraparound fashion + FIRST_ELIGIBLE, + // Best eligible edge pivot rule + // The best edge is selected in every iteration + BEST_ELIGIBLE, + // Candidate list pivot rule + // Major iterations: candidate list is built from eligible edges (in a wraparound way) + // Minor iterations: the best edge is selected from the list + CANDIDATE_LIST + }; + + // Solve minimum cost flow problem using Network Simplex algorithm + template + class network_flow : private Ext { + private: + enum edge_state { + LOWER = 1, + BASIS = 0, + }; + + typedef dl_var node; + typedef dl_edge edge; + typedef dl_graph graph; + typedef typename Ext::numeral numeral; + typedef typename Ext::fin_numeral fin_numeral; + + class pivot_rule_impl { + protected: + graph & m_graph; + svector & m_states; + vector & m_potentials; + edge_id & m_enter_id; + bool edge_in_tree(edge_id id) const { return m_states[id] == BASIS; } + public: + pivot_rule_impl(graph & g, vector & potentials, + svector & states, edge_id & enter_id) + : m_graph(g), + m_potentials(potentials), + m_states(states), + m_enter_id(enter_id) { + } + virtual ~pivot_rule_impl() {} + virtual bool choose_entering_edge() = 0; + virtual pivot_rule rule() const = 0; + }; + + class first_eligible_pivot : public pivot_rule_impl { + edge_id m_next_edge; + public: + first_eligible_pivot(graph & g, vector & potentials, + svector & states, edge_id & enter_id) : + pivot_rule_impl(g, potentials, states, enter_id), + m_next_edge(0) { + } + virtual bool choose_entering_edge(); + virtual pivot_rule rule() const { return FIRST_ELIGIBLE; } + }; + + class best_eligible_pivot : public pivot_rule_impl { + public: + best_eligible_pivot(graph & g, vector & potentials, + svector & states, edge_id & enter_id) : + pivot_rule_impl(g, potentials, states, enter_id) { + } + virtual pivot_rule rule() const { return BEST_ELIGIBLE; } + virtual bool choose_entering_edge(); + }; + + class candidate_list_pivot : public pivot_rule_impl { + private: + edge_id m_next_edge; + svector m_candidates; + unsigned m_num_candidates; + unsigned m_minor_step; + unsigned m_current_length; + static const unsigned NUM_CANDIDATES = 10; + static const unsigned MINOR_STEP_LIMIT = 5; + + public: + candidate_list_pivot(graph & g, vector & potentials, + svector & states, edge_id & enter_id) : + pivot_rule_impl(g, potentials, states, enter_id), + m_next_edge(0), + m_minor_step(0), + m_current_length(0), + m_num_candidates(NUM_CANDIDATES), + m_candidates(m_num_candidates) { + } + + virtual pivot_rule rule() const { return CANDIDATE_LIST; } + + virtual bool choose_entering_edge(); + }; + + graph m_graph; + scoped_ptr m_tree; + scoped_ptr m_pivot; + vector m_balances; // nodes + 1 |-> [b -1b] Denote supply/demand b_i on node i + vector m_potentials; // nodes + 1 |-> initial: +/- 1 + // Duals of flows which are convenient to compute dual solutions + // become solutions to Dual simplex. + vector m_flows; // edges + nodes |-> assignemnt Basic feasible flows + svector m_states; + unsigned m_step; + edge_id m_enter_id; + edge_id m_leave_id; + optional m_delta; + + // Initialize the network with a feasible spanning tree + void initialize(); + + void update_potentials(); + + void update_flows(); + + bool choose_entering_edge(pivot_rule pr); + + // Send as much flow as possible around the cycle, the first basic edge with flow 0 will leave + // Return false if the problem is unbounded + bool choose_leaving_edge(); + + void update_spanning_tree(); + + numeral get_cost() const; + + bool edge_in_tree(edge_id id) const; + + bool is_infeasible(); + bool check_well_formed(); + bool check_optimal(); + + void display_primal(std::ofstream & os); + void display_dual(std::ofstream & os); + void display_spanning_tree(std::ofstream & os); + void display_system(std::ofstream & os); + + public: + + network_flow(graph & g, vector const & balances); + + // Minimize cost flows + // Return true if found an optimal solution, and return false if unbounded + min_flow_result min_cost(pivot_rule pr = FIRST_ELIGIBLE); + + // Compute the optimal solution + numeral get_optimal_solution(vector & result, bool is_dual); + + }; +} + +#endif diff --git a/src/math/simplex/network_flow_def.h b/src/math/simplex/network_flow_def.h new file mode 100644 index 000000000..93e1ded9a --- /dev/null +++ b/src/math/simplex/network_flow_def.h @@ -0,0 +1,526 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + network_flow_def.h + +Abstract: + + Implements Network Simplex algorithm for min cost flow problem + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-24 + +Notes: + +--*/ + +#ifndef _NETWORK_FLOW_DEF_H_ +#define _NETWORK_FLOW_DEF_H_ + +#include"network_flow.h" +#include"uint_set.h" +#include"spanning_tree_def.h" + +namespace smt { + + template + bool network_flow::first_eligible_pivot::choose_entering_edge() { + numeral cost = numeral::zero(); + int num_edges = m_graph.get_num_edges(); + for (int i = m_next_edge; i < m_next_edge + num_edges; ++i) { + edge_id id = i % num_edges; + if (edge_in_tree(id)) { + continue; + } + node src = m_graph.get_source(id); + node tgt = m_graph.get_target(id); + cost = m_potentials[src] - m_potentials[tgt] - m_graph.get_weight(id); + if (cost.is_pos()) { + m_next_edge = m_enter_id = id; + return true; + } + } + return false; + }; + + template + bool network_flow::best_eligible_pivot::choose_entering_edge() { + unsigned num_edges = m_graph.get_num_edges(); + numeral cost = numeral::zero(); + for (unsigned i = 0; i < num_edges; ++i) { + node src = m_graph.get_source(i); + node tgt = m_graph.get_target(i); + if (!edge_in_tree(i)) { + numeral new_cost = m_potentials[src] - m_potentials[tgt] - m_graph.get_weight(i); + if (new_cost > cost) { + cost = new_cost; + m_enter_id = i; + } + } + } + return cost.is_pos(); + }; + + template + bool network_flow::candidate_list_pivot::choose_entering_edge() { + numeral cost = numeral::zero(); + if (m_current_length == 0 || m_minor_step == MINOR_STEP_LIMIT) { + // Build the candidate list + unsigned num_edges = m_graph.get_num_edges(); + m_current_length = 0; + for (unsigned i = m_next_edge; i < m_next_edge + num_edges; ++i) { + edge_id id = (i >= num_edges) ? i - num_edges : i; + node src = m_graph.get_source(id); + node tgt = m_graph.get_target(id); + if (!edge_in_tree(id)) { + numeral new_cost = m_potentials[src] - m_potentials[tgt] - m_graph.get_weight(id); + if (new_cost.is_pos()) { + m_candidates[m_current_length] = id; + ++m_current_length; + if (new_cost > cost) { + cost = new_cost; + m_enter_id = id; + } + } + if (m_current_length >= m_num_candidates) break; + } + } + m_next_edge = m_enter_id; + m_minor_step = 1; + return cost.is_pos(); + } + + ++m_minor_step; + for (unsigned i = 0; i < m_current_length; ++i) { + edge_id id = m_candidates[i]; + node src = m_graph.get_source(id); + node tgt = m_graph.get_target(id); + if (!edge_in_tree(id)) { + numeral new_cost = m_potentials[src] - m_potentials[tgt] - m_graph.get_weight(id); + if (new_cost > cost) { + cost = new_cost; + m_enter_id = id; + } + // Remove stale candidates + if (!new_cost.is_pos()) { + --m_current_length; + m_candidates[i] = m_candidates[m_current_length]; + --i; + } + } + } + return cost.is_pos(); + }; + + template + network_flow::network_flow(graph & g, vector const & balances) : + m_balances(balances) { + // Network flow graph has the edges in the reversed order compared to constraint graph + // We only take enabled edges from the original graph + for (unsigned i = 0; i < g.get_num_nodes(); ++i) { + m_graph.init_var(i); + } + vector const & es = g.get_all_edges(); + for (unsigned i = 0; i < es.size(); ++i) { + edge const & e = es[i]; + if (e.is_enabled()) { + m_graph.add_edge(e.get_target(), e.get_source(), e.get_weight(), explanation()); + } + } + TRACE("network_flow", { + tout << "Difference logic optimization:" << std::endl; + display_dual(tout); + tout << "Minimum cost flow:" << std::endl; + display_primal(tout); + };); + + m_step = 0; + m_tree = alloc(basic_spanning_tree, m_graph); + } + + + template + void network_flow::initialize() { + TRACE("network_flow", tout << "initialize...\n";); + // Create an artificial root node to construct initial spanning tree + unsigned num_nodes = m_graph.get_num_nodes(); + unsigned num_edges = m_graph.get_num_edges(); + + node root = num_nodes; + m_graph.init_var(root); + + m_potentials.resize(num_nodes + 1); + m_potentials[root] = numeral::zero(); + + m_balances.resize(num_nodes + 1); + fin_numeral sum_supply = fin_numeral::zero(); + for (unsigned i = 0; i < num_nodes; ++i) { + sum_supply += m_balances[i]; + } + m_balances[root] = -sum_supply; + + m_flows.resize(num_nodes + num_edges); + m_flows.fill(numeral::zero()); + m_states.resize(num_nodes + num_edges); + m_states.fill(LOWER); + + // Create artificial edges from/to root node to/from other nodes and initialize the spanning tree + svector tree; + for (unsigned i = 0; i < num_nodes; ++i) { + bool is_forward = !m_balances[i].is_neg(); + m_states[num_edges + i] = BASIS; + node src = is_forward ? i : root; + node tgt = is_forward ? root : i; + m_flows[num_edges + i] = is_forward ? m_balances[i] : -m_balances[i]; + m_potentials[i] = is_forward ? numeral::one() : -numeral::one(); + tree.push_back(m_graph.add_edge(src, tgt, numeral::one(), explanation())); + } + + m_tree->initialize(tree); + + TRACE("network_flow", + tout << pp_vector("Potentials", m_potentials); + tout << pp_vector("Flows", m_flows); + tout << "Cost: " << get_cost() << "\n"; + tout << "Spanning tree:\n"; + display_spanning_tree(tout); + display_primal(tout);); + SASSERT(check_well_formed()); + } + + template + void network_flow::update_potentials() { + node src = m_graph.get_source(m_enter_id); + node tgt = m_graph.get_target(m_enter_id); + numeral cost = m_potentials[src] - m_potentials[tgt] - m_graph.get_weight(m_enter_id); + numeral change; + node start; + if (m_tree->in_subtree_t2(tgt)) { + change = cost; + start = tgt; + } + else { + change = -cost; + start = src; + } + SASSERT(m_tree->in_subtree_t2(start)); + TRACE("network_flow", tout << "update_potentials of T_" << start << " with change = " << change << "...\n";); + svector descendants; + m_tree->get_descendants(start, descendants); + SASSERT(descendants.size() >= 1); + for (unsigned i = 0; i < descendants.size(); ++i) { + node u = descendants[i]; + m_potentials[u] += change; + } + TRACE("network_flow", tout << pp_vector("Potentials", m_potentials);); + } + + template + void network_flow::update_flows() { + m_flows[m_enter_id] += *m_delta; + node src = m_graph.get_source(m_enter_id); + node tgt = m_graph.get_target(m_enter_id); + svector path; + svector against; + m_tree->get_path(src, tgt, path, against); + SASSERT(path.size() >= 1); + for (unsigned i = 0; i < path.size(); ++i) { + edge_id e_id = path[i]; + m_flows[e_id] += against[i] ? - *m_delta : *m_delta; + } + TRACE("network_flow", tout << pp_vector("Flows", m_flows);); + } + + template + bool network_flow::choose_leaving_edge() { + node src = m_graph.get_source(m_enter_id); + node tgt = m_graph.get_target(m_enter_id); + m_delta.set_invalid(); + edge_id leave_id = null_edge_id; + svector path; + svector against; + m_tree->get_path(src, tgt, path, against); + SASSERT(path.size() >= 1); + for (unsigned i = 0; i < path.size(); ++i) { + edge_id e_id = path[i]; + if (against[i] && (!m_delta || m_flows[e_id] < *m_delta)) { + m_delta = m_flows[e_id]; + leave_id = e_id; + } + } + m_leave_id = leave_id; + + return m_delta; + } + + template + void network_flow::update_spanning_tree() { + m_tree->update(m_enter_id, m_leave_id); + } + + template + bool network_flow::choose_entering_edge(pivot_rule pr) { + if (!m_pivot || pr != m_pivot->rule()) { + switch (pr) { + case FIRST_ELIGIBLE: + m_pivot = alloc(first_eligible_pivot, m_graph, m_potentials, m_states, m_enter_id); + break; + case BEST_ELIGIBLE: + m_pivot = alloc(best_eligible_pivot, m_graph, m_potentials, m_states, m_enter_id); + break; + case CANDIDATE_LIST: + m_pivot = alloc(candidate_list_pivot, m_graph, m_potentials, m_states, m_enter_id); + break; + default: + UNREACHABLE(); + } + } + return m_pivot->choose_entering_edge(); + } + + // Minimize cost flows + template + min_flow_result network_flow::min_cost(pivot_rule pr) { + initialize(); + while (choose_entering_edge(pr)) { + bool bounded = choose_leaving_edge(); + if (!bounded) return UNBOUNDED; + vectorconst& es = m_graph.get_all_edges(); + TRACE("network_flow", + { + edge const& e_in = es[m_enter_id]; + edge const& e_out = es[m_leave_id]; + node src_in = e_in.get_source(); + node tgt_in = e_in.get_target(); + node src_out = e_out.get_source(); + node tgt_out = e_out.get_target(); + numeral c1 = m_potentials[src_in] - m_potentials[tgt_in] - m_graph.get_weight(m_enter_id); + numeral c2 = m_potentials[src_out] - m_potentials[tgt_out] - m_graph.get_weight(m_leave_id); + tout << "new base: y_" << src_in << "_" << tgt_in << " cost: " << c1 << " delta: " << *m_delta << "\n"; + tout << "old base: y_" << src_out << "_" << tgt_out << " cost: " << c2 << "\n"; + } + ); + update_flows(); + if (m_enter_id != m_leave_id) { + SASSERT(edge_in_tree(m_leave_id)); + SASSERT(!edge_in_tree(m_enter_id)); + m_states[m_enter_id] = BASIS; + m_states[m_leave_id] = LOWER; + update_spanning_tree(); + update_potentials(); + TRACE("network_flow", + tout << "Spanning tree:\n"; + display_spanning_tree(tout); + tout << "Cost: " << get_cost() << "\n"; + display_primal(tout); + ); + SASSERT(check_well_formed()); + } + } + TRACE("network_flow", + tout << "Spanning tree:\n"; + display_spanning_tree(tout); + tout << "Cost: " << get_cost() << "\n"; + display_primal(tout); + ); + if (is_infeasible()) return INFEASIBLE; + TRACE("network_flow", tout << "Found optimal solution.\n";); + SASSERT(check_optimal()); + return OPTIMAL; + } + + template + bool network_flow::is_infeasible() { + // Flows of artificial arcs should be zero + unsigned num_nodes = m_graph.get_num_nodes(); + unsigned num_edges = m_graph.get_num_edges(); + SASSERT(m_flows.size() == num_edges); + for (unsigned i = 1; i < num_nodes; ++i) { + if (m_flows[num_edges - i].is_pos()) return true; + } + return false; + } + + // Get the optimal solution + template + typename network_flow::numeral network_flow::get_optimal_solution(vector & result, bool is_dual) { + numeral objective_value = get_cost(); + result.reset(); + if (is_dual) { + result.append(m_potentials); + } + else { + result.append(m_flows); + } + return objective_value; + } + + template + typename network_flow::numeral network_flow::get_cost() const { + numeral objective_value = numeral::zero(); + unsigned num_edges = m_graph.get_num_edges(); + for (unsigned i = 0; i < num_edges; ++i) { + if (edge_in_tree(i)) { + objective_value += m_flows[i].get_rational() * m_graph.get_weight(i); + } + } + return objective_value; + } + + template + bool network_flow::edge_in_tree(edge_id id) const { + return m_states[id] == BASIS; + } + + template + bool network_flow::check_well_formed() { + SASSERT(m_tree->check_well_formed()); + SASSERT(!m_delta || !(*m_delta).is_neg()); + + // m_flows are zero on non-basic edges + for (unsigned i = 0; i < m_flows.size(); ++i) { + SASSERT(!m_flows[i].is_neg()); + SASSERT(edge_in_tree(i) || m_flows[i].is_zero()); + } + + unsigned num_edges = m_graph.get_num_edges(); + for (unsigned i = 0; i < num_edges; ++i) { + if (edge_in_tree(i)) { + dl_var src = m_graph.get_source(i); + dl_var tgt = m_graph.get_target(i); + numeral weight = m_graph.get_weight(i); + SASSERT(m_potentials[src] - m_potentials[tgt] == weight); + } + } + + return true; + } + + template + bool network_flow::check_optimal() { + numeral total_cost = get_cost(); + unsigned num_edges = m_graph.get_num_edges(); + + for (unsigned i = 0; i < num_edges; ++i) { + dl_var src = m_graph.get_source(i); + dl_var tgt = m_graph.get_target(i); + numeral weight = m_graph.get_weight(i); + SASSERT(m_potentials[src] - m_potentials[tgt] <= weight); + } + + // m_flows are zero on non-basic edges + for (unsigned i = 0; i < m_flows.size(); ++i) { + SASSERT(edge_in_tree(i) || m_flows[i].is_zero()); + } + numeral total_balance = numeral::zero(); + for (unsigned i = 0; i < m_potentials.size(); ++i) { + total_balance += m_balances[i] * m_potentials[i]; + } + TRACE("network_flow", tout << "Total balance: " << total_balance << ", total cost: " << total_cost << std::endl;); + return total_cost == total_balance; + } + + // display methods + + template + void network_flow::display_primal(std::ofstream & os) { + vector const & es = m_graph.get_all_edges(); + for (unsigned i = 0; i < m_graph.get_num_edges(); ++i) { + edge const & e = es[i]; + os << "(declare-fun y_" << e.get_source() << "_" << e.get_target() << " () Real)" << std::endl; + }; + + for (unsigned i = 0; i < m_graph.get_num_edges(); ++i) { + edge const & e = es[i]; + os << "(assert (>= y_" << e.get_source() << "_" << e.get_target() << " 0))" << std::endl; + }; + + for (unsigned i = 0; i < m_graph.get_num_nodes(); ++i) { + bool initialized = false; + for (unsigned j = 0; j < m_graph.get_num_edges(); ++j) { + edge const & e = es[j]; + if (e.get_target() == i || e.get_source() == i) { + if (!initialized) { + os << "(assert (= (+"; + } + initialized = true; + if (e.get_target() == i) { + os << " y_" << e.get_source() << "_" << e.get_target(); + } + else { + os << " (- y_" << e.get_source() << "_" << e.get_target() << ")"; + } + } + } + if(initialized) { + os << " " << m_balances[i] << ") 0))" << std::endl; + } + } + + os << "(minimize (+"; + for (unsigned i = 0; i < m_graph.get_num_edges(); ++i) { + edge const & e = es[i]; + os << " (* " << e.get_weight() << " y_" << e.get_source() << "_" << e.get_target() << ")"; + }; + os << "))" << std::endl; + os << "(optimize)" << std::endl; + if (!m_flows.empty()) { + for (unsigned i = 0; i < m_graph.get_num_edges(); ++i) { + edge const & e = es[i]; + os << "; y_" << e.get_source() << "_" << e.get_target() << " = " << m_flows[i] << "\n"; + } + } + } + + + template + void network_flow::display_dual(std::ofstream & os) { + for (unsigned i = 0; i < m_graph.get_num_nodes(); ++i) { + os << "(declare-fun v" << i << " () Real)" << std::endl; + } + vector const & es = m_graph.get_all_edges(); + for (unsigned i = 0; i < m_graph.get_num_edges(); ++i) { + edge const & e = es[i]; + os << "(assert (<= (- v" << e.get_source() << " v" << e.get_target() << ") " << e.get_weight() << "))" << std::endl; + }; + os << "(assert (= v0 0))" << std::endl; + os << "(maximize (+"; + for (unsigned i = 0; i < m_balances.size(); ++i) { + os << " (* " << m_balances[i] << " v" << i << ")"; + }; + os << "))" << std::endl; + os << "(optimize)" << std::endl; + } + + template + void network_flow::display_spanning_tree(std::ofstream & os) { + ++m_step;; + std::string prefix = "T"; + prefix.append(std::to_string(m_step)); + prefix.append("_"); + unsigned root = m_graph.get_num_nodes() - 1; + for (unsigned i = 0; i < root; ++i) { + os << prefix << i << "[shape=circle,label=\"" << prefix << i << " ["; + os << m_potentials[i] << "/" << m_balances[i] << "]\"];\n"; + } + os << prefix << root << "[shape=doublecircle,label=\"" << prefix << root << " ["; + os << m_potentials[root] << "/" << m_balances[root] << "]\"];\n"; + + unsigned num_edges = m_graph.get_num_edges(); + for (unsigned i = 0; i < num_edges; ++i) { + os << prefix << m_graph.get_source(i) << " -> " << prefix << m_graph.get_target(i); + if (edge_in_tree(i)) { + os << "[color=red,penwidth=3.0,label=\"" << m_flows[i] << "/" << m_graph.get_weight(i) << "\"];\n"; + } + else { + os << "[label=\"" << m_flows[i] << "/" << m_graph.get_weight(i) << "\"];\n"; + } + } + os << std::endl; + } +} + +#endif diff --git a/src/math/simplex/simplex.cpp b/src/math/simplex/simplex.cpp new file mode 100644 index 000000000..494c0b6bb --- /dev/null +++ b/src/math/simplex/simplex.cpp @@ -0,0 +1,26 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + simplex.h + +Abstract: + + Multi-precision simplex tableau. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-01-15 + +Notes: + +--*/ + +#include"simplex.h" +#include"sparse_matrix_def.h" +#include"simplex_def.h" +namespace simplex { + template class simplex; + template class simplex; +}; diff --git a/src/math/simplex/simplex.h b/src/math/simplex/simplex.h new file mode 100644 index 000000000..9685af589 --- /dev/null +++ b/src/math/simplex/simplex.h @@ -0,0 +1,202 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + simplex.h + +Abstract: + + Multi-precision simplex tableau. + + - It uses code from theory_arith where applicable. + + - It is detached from the theory class and ASTs. + + - It uses non-shared mpz/mpq's avoiding global locks and operations on rationals. + + - It follows the same sparse tableau layout (no LU yet). + + - It does not include features for non-linear arithmetic. + + - Branch/bound/cuts is external. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-01-15 + +Notes: + +--*/ + +#ifndef _SIMPLEX_H_ +#define _SIMPLEX_H_ + +#include "sparse_matrix.h" +#include "mpq_inf.h" +#include "heap.h" +#include "lbool.h" +#include "uint_set.h" + +namespace simplex { + + template + class simplex { + + typedef unsigned var_t; + typedef typename Ext::eps_numeral eps_numeral; + typedef typename Ext::numeral numeral; + typedef typename Ext::manager manager; + typedef typename Ext::eps_manager eps_manager; + typedef typename Ext::scoped_numeral scoped_numeral; + typedef _scoped_numeral scoped_eps_numeral; + typedef _scoped_numeral_vector scoped_eps_numeral_vector; + typedef sparse_matrix matrix; + struct var_lt { + bool operator()(var_t v1, var_t v2) const { return v1 < v2; } + }; + typedef heap var_heap; + + struct stats { + unsigned m_num_pivots; + unsigned m_num_infeasible; + unsigned m_num_checks; + stats() { reset(); } + void reset() { + memset(this, 0, sizeof(*this)); + } + }; + + enum pivot_strategy_t { + S_BLAND, + S_GREATEST_ERROR, + S_LEAST_ERROR, + S_DEFAULT + }; + + struct var_info { + unsigned m_base2row:29; + unsigned m_is_base:1; + unsigned m_lower_valid:1; + unsigned m_upper_valid:1; + eps_numeral m_value; + eps_numeral m_lower; + eps_numeral m_upper; + numeral m_base_coeff; + var_info(): + m_base2row(0), + m_is_base(false), + m_lower_valid(false), + m_upper_valid(false) + {} + }; + + static const var_t null_var; + mutable manager m; + mutable eps_manager em; + mutable matrix M; + unsigned m_max_iterations; + volatile bool m_cancel; + var_heap m_to_patch; + vector m_vars; + svector m_row2base; + bool m_bland; + unsigned m_blands_rule_threshold; + random_gen m_random; + uint_set m_left_basis; + unsigned m_infeasible_var; + unsigned_vector m_base_vars; + stats m_stats; + + public: + simplex(): + M(m), + m_max_iterations(UINT_MAX), + m_cancel(false), + m_to_patch(1024), + m_bland(false), + m_blands_rule_threshold(1000) {} + + typedef typename matrix::row row; + typedef typename matrix::row_iterator row_iterator; + typedef typename matrix::col_iterator col_iterator; + + void ensure_var(var_t v); + row add_row(var_t base, unsigned num_vars, var_t const* vars, numeral const* coeffs); + row get_infeasible_row(); + var_t get_base_var(row const& r) const { return m_row2base[r.id()]; } + numeral const& get_base_coeff(row const& r) const { return m_vars[m_row2base[r.id()]].m_base_coeff; } + void del_row(var_t base_var); + void set_lower(var_t var, eps_numeral const& b); + void set_upper(var_t var, eps_numeral const& b); + void get_lower(var_t var, scoped_eps_numeral& b) const { b = m_vars[var].m_lower; } + void get_upper(var_t var, scoped_eps_numeral& b) const { b = m_vars[var].m_upper; } + bool above_lower(var_t var, eps_numeral const& b) const; + bool below_upper(var_t var, eps_numeral const& b) const; + bool below_lower(var_t v) const; + bool above_upper(var_t v) const; + bool lower_valid(var_t var) const { return m_vars[var].m_lower_valid; } + bool upper_valid(var_t var) const { return m_vars[var].m_upper_valid; } + void unset_lower(var_t var); + void unset_upper(var_t var); + void set_value(var_t var, eps_numeral const& b); + void set_cancel(bool f) { m_cancel = f; } + void set_max_iterations(unsigned m) { m_max_iterations = m; } + void reset(); + lbool make_feasible(); + lbool minimize(var_t var); + eps_numeral const& get_value(var_t v); + void display(std::ostream& out) const; + void display_row(std::ostream& out, row const& r, bool values = true); + + unsigned get_num_vars() const { return m_vars.size(); } + + row_iterator row_begin(row const& r) { return M.row_begin(r); } + row_iterator row_end(row const& r) { return M.row_end(r); } + + void collect_statistics(::statistics & st) const; + + private: + + void del_row(row const& r); + var_t select_var_to_fix(); + pivot_strategy_t pivot_strategy(); + var_t select_smallest_var() { return m_to_patch.empty()?null_var:m_to_patch.erase_min(); } + var_t select_error_var(bool least); + void check_blands_rule(var_t v, unsigned& num_repeated); + bool make_var_feasible(var_t x_i); + void update_and_pivot(var_t x_i, var_t x_j, numeral const& a_ij, eps_numeral const& new_value); + void update_value(var_t v, eps_numeral const& delta); + void update_value_core(var_t v, eps_numeral const& delta); + void pivot(var_t x_i, var_t x_j, numeral const& a_ij); + void move_to_bound(var_t x, bool to_lower); + var_t select_pivot(var_t x_i, bool is_below, scoped_numeral& out_a_ij); + var_t select_pivot_blands(var_t x_i, bool is_below, scoped_numeral& out_a_ij); + var_t select_pivot_core(var_t x_i, bool is_below, scoped_numeral& out_a_ij); + int get_num_non_free_dep_vars(var_t x_j, int best_so_far); + + var_t pick_var_to_leave(var_t x_j, bool is_pos, + scoped_eps_numeral& gain, scoped_numeral& new_a_ij, bool& inc); + + + void select_pivot_primal(var_t v, var_t& x_i, var_t& x_j, scoped_numeral& a_ij, bool& inc_x_i, bool& inc_x_j); + + + bool at_lower(var_t v) const; + bool at_upper(var_t v) const; + bool above_lower(var_t v) const; + bool below_upper(var_t v) const; + bool outside_bounds(var_t v) const { return below_lower(v) || above_upper(v); } + bool is_free(var_t v) const { return !m_vars[v].m_lower_valid && !m_vars[v].m_upper_valid; } + bool is_non_free(var_t v) const { return !is_free(v); } + bool is_base(var_t x) const { return m_vars[x].m_is_base; } + void add_patch(var_t v); + + bool well_formed() const; + bool well_formed_row(row const& r) const; + bool is_feasible() const; + }; + +}; + +#endif diff --git a/src/math/simplex/simplex_def.h b/src/math/simplex/simplex_def.h new file mode 100644 index 000000000..3c1a90a7a --- /dev/null +++ b/src/math/simplex/simplex_def.h @@ -0,0 +1,1032 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + simplex_def.h + +Abstract: + +Author: + + Nikolaj Bjorner (nbjorner) 2014-01-15 + +Notes: + + Sign of base variables can vary. + Sign could possibly be normalized to positive. + Otherwise, sign could be accounted in pivoting. + +--*/ + +#ifndef _SIMPLEX_DEF_H_ +#define _SIMPLEX_DEF_H_ + + +namespace simplex { + + template + const typename simplex::var_t simplex::null_var = UINT_MAX; + + template + typename simplex::row + simplex::add_row(var_t base_var, unsigned num_vars, var_t const* vars, numeral const* coeffs) { + m_base_vars.reset(); + row r = M.mk_row(); + for (unsigned i = 0; i < num_vars; ++i) { + if (!m.is_zero(coeffs[i])) { + var_t v = vars[i]; + if (is_base(v)) { + m_base_vars.push_back(i); + } + M.add_var(r, coeffs[i], v); + } + } + scoped_numeral mul(m), a(m), b(m), c(m); + m.set(mul, 1); + for (unsigned i = 0; i < m_base_vars.size(); ++i) { + var_t v = vars[m_base_vars[i]]; + m.mul(coeffs[m_base_vars[i]], mul, a); + m.set(b, m_vars[v].m_base_coeff); + m.lcm(a, b, c); + TRACE("simplex", + m.display(tout << " a: ", a); + m.display(tout << " b v" << v << " : ", b); + m.display(tout << " c: ", c); + tout << "\n"; + M.display_row(tout, r); + M.display_row(tout, row(m_vars[v].m_base2row)); + if (m.is_zero(b)) { + display(tout); + }); + SASSERT(is_base(v)); + m.abs(c); + m.div(c, a, b); + m.div(c, m_vars[v].m_base_coeff, a); + m.mul(mul, b, mul); + M.mul(r, b); + m.neg(a); + M.add(r, a, row(m_vars[v].m_base2row)); + TRACE("simplex", M.display_row(tout, r);); + } + + scoped_numeral base_coeff(m); + scoped_eps_numeral value(em), tmp(em); + row_iterator it = M.row_begin(r), end = M.row_end(r); + for (; it != end; ++it) { + var_t v = it->m_var; + if (v == base_var) { + m.set(base_coeff, it->m_coeff); + } + else { + SASSERT(!is_base(v)); + em.mul(m_vars[v].m_value, it->m_coeff, tmp); + em.add(value, tmp, value); + } + } + SASSERT(!m.is_zero(base_coeff)); + TRACE("simplex", + for (unsigned i = 0; i < num_vars; ++i) { + m.display(tout << "v" << vars[i] << " * ", coeffs[i]); tout << " "; + if (i + 1 < num_vars) tout << " + "; + } + tout << "\n"; + row_iterator it2 = M.row_begin(r); + bool first = true; + for (; it2 != end; ++it2) { + if (!first) tout << " + "; + tout << "v" << it2->m_var << " * "; + m.display(tout, it2->m_coeff); tout << " "; + first = false; + } + tout << "\n"; + ); + SASSERT(!is_base(base_var)); + em.neg(value); + em.div(value, base_coeff, value); + while (m_row2base.size() <= r.id()) { + m_row2base.push_back(null_var); + } + m_row2base[r.id()] = base_var; + m_vars[base_var].m_base2row = r.id(); + m_vars[base_var].m_is_base = true; + m.set(m_vars[base_var].m_base_coeff, base_coeff); + em.set(m_vars[base_var].m_value, value); + add_patch(base_var); + SASSERT(well_formed_row(r)); + SASSERT(well_formed()); + return r; + } + + template + typename simplex::row + simplex::get_infeasible_row() { + SASSERT(is_base(m_infeasible_var)); + unsigned row_id = m_vars[m_infeasible_var].m_base2row; + return row(row_id); + } + + template + void simplex::add_patch(var_t v) { + SASSERT(is_base(v)); + if (outside_bounds(v)) { + TRACE("simplex", tout << "Add patch: v" << v << "\n";); + m_to_patch.insert(v); + } + } + + template + void simplex::del_row(row const& r) { + var_t var = m_row2base[r.id()]; + m_vars[var].m_is_base = false; + m_vars[var].m_lower_valid = false; + m_vars[var].m_upper_valid = false; + m_row2base[r.id()] = null_var; + M.del(r); + SASSERT(M.col_begin(var) == M.col_end(var)); + SASSERT(well_formed()); + } + + template + void simplex::del_row(var_t var) { + TRACE("simplex", tout << var << "\n";); + row r; + if (is_base(var)) { + r = row(m_vars[var].m_base2row); + } + else { + col_iterator it = M.col_begin(var), end = M.col_end(var); + if (it == end) { + return; + } + typename matrix::row_entry const& re = it.get_row_entry(); + r = it.get_row(); + var_t old_base = m_row2base[r.id()]; + scoped_eps_numeral new_value(em); + var_info& vi = m_vars[old_base]; + if (below_lower(old_base)) { + new_value = vi.m_lower; + } + else if (above_upper(old_base)) { + new_value = vi.m_upper; + } + else { + new_value = vi.m_value; + } + // need to move var such that old_base comes in bound. + update_and_pivot(old_base, var, re.m_coeff, new_value); + SASSERT(is_base(var)); + SASSERT(m_vars[var].m_base2row == r.id()); + SASSERT(!below_lower(old_base) && !above_upper(old_base)); + } + del_row(r); + TRACE("simplex", display(tout);); + SASSERT(well_formed()); + } + + template + bool simplex::above_lower(var_t var, eps_numeral const& b) const { + var_info const& vi = m_vars[var]; + return !vi.m_lower_valid || em.gt(b, vi.m_lower); + } + + template + bool simplex::below_upper(var_t var, eps_numeral const& b) const { + var_info const& vi = m_vars[var]; + return !vi.m_upper_valid || em.lt(b, vi.m_upper); + } + + template + void simplex::set_lower(var_t var, eps_numeral const& b) { + var_info& vi = m_vars[var]; + em.set(vi.m_lower, b); + vi.m_lower_valid = true; + TRACE("simplex", em.display(tout << "v" << var << " lower: ", b); + em.display(tout << " value: ", vi.m_value);); + SASSERT(!vi.m_upper_valid || em.le(b, vi.m_upper)); + if (!vi.m_is_base && em.lt(vi.m_value, b)) { + scoped_eps_numeral delta(em); + em.sub(b, vi.m_value, delta); + update_value(var, delta); + } + else if (vi.m_is_base && em.lt(vi.m_value, b)) { + SASSERT(outside_bounds(var)); + add_patch(var); + } + SASSERT(well_formed()); + } + + template + void simplex::set_upper(var_t var, eps_numeral const& b) { + var_info& vi = m_vars[var]; + em.set(vi.m_upper, b); + vi.m_upper_valid = true; + SASSERT(!vi.m_lower_valid || em.le(vi.m_lower, b)); + if (!vi.m_is_base && em.gt(vi.m_value, b)) { + scoped_eps_numeral delta(em); + em.sub(b, vi.m_value, delta); + update_value(var, delta); + } + else if (vi.m_is_base && em.lt(b, vi.m_value)) { + SASSERT(outside_bounds(var)); + add_patch(var); + } + SASSERT(well_formed()); + } + + template + void simplex::unset_lower(var_t var) { + m_vars[var].m_lower_valid = false; + } + + template + void simplex::unset_upper(var_t var) { + m_vars[var].m_upper_valid = false; + } + + template + void simplex::set_value(var_t var, eps_numeral const& b) { + scoped_eps_numeral delta(em); + em.sub(b, m_vars[var].m_value, delta); + update_value(var, delta); + SASSERT(well_formed()); + } + + template + typename simplex::eps_numeral const& + simplex::get_value(var_t v) { + return m_vars[v].m_value; + } + + template + void simplex::display(std::ostream& out) const { + M.display(out); + for (unsigned i = 0; i < m_vars.size(); ++i) { + var_info const& vi = m_vars[i]; + out << "v" << i << " "; + out << em.to_string(vi.m_value); + out << " ["; + if (vi.m_lower_valid) out << em.to_string(vi.m_lower); else out << "-oo"; + out << ":"; + if (vi.m_upper_valid) out << em.to_string(vi.m_upper); else out << "oo"; + out << "] "; + if (vi.m_is_base) out << "b:" << vi.m_base2row << " "; + //col_iterator it = M.col_begin(i), end = M.col_end(i); + //for (; it != end; ++it) { + // out << "r" << it.get_row().id() << " "; + //} + out << "\n"; + } + } + + template + void simplex::display_row(std::ostream& out, row const& r, bool values) { + row_iterator it = M.row_begin(r), end = M.row_end(r); + for (; it != end; ++it) { + m.display(out, it->m_coeff); + out << "*v" << it->m_var << " "; + if (values) { + var_info const& vi = m_vars[it->m_var]; + out << em.to_string(vi.m_value); + out << " ["; + if (vi.m_lower_valid) out << em.to_string(vi.m_lower); else out << "-oo"; + out << ":"; + if (vi.m_upper_valid) out << em.to_string(vi.m_upper); else out << "oo"; + out << "] "; + } + } + out << "\n"; + } + + + template + void simplex::ensure_var(var_t v) { + while (v >= m_vars.size()) { + M.ensure_var(m_vars.size()); + m_vars.push_back(var_info()); + } + if (m_to_patch.get_bounds() <= v) { + m_to_patch.set_bounds(2*v+1); + } + } + + template + void simplex::reset() { + M.reset(); + m_to_patch.reset(); + m_vars.reset(); + m_row2base.reset(); + m_left_basis.reset(); + m_base_vars.reset(); + } + + template + lbool simplex::make_feasible() { + ++m_stats.m_num_checks; + m_left_basis.reset(); + m_infeasible_var = null_var; + unsigned num_iterations = 0; + unsigned num_repeated = 0; + var_t v = null_var; + m_bland = false; + SASSERT(well_formed()); + while ((v = select_var_to_fix()) != null_var) { + TRACE("simplex", display(tout << "v" << v << "\n");); + if (m_cancel || num_iterations > m_max_iterations) { + return l_undef; + } + check_blands_rule(v, num_repeated); + if (!make_var_feasible(v)) { + m_to_patch.insert(v); + m_infeasible_var = v; + ++m_stats.m_num_infeasible; + return l_false; + } + ++num_iterations; + } + SASSERT(well_formed()); + return l_true; + } + + /** + \brief Make x_j the new base variable for row of x_i. + x_i is assumed base variable of row r_i. + x_j is assumed to have coefficient a_ij in r_i. + + a_ii*x_i + a_ij*x_j + r_i = 0 + + current value of x_i is v_i + new value of x_i is new_value + a_ii*(x_i + new_value - x_i) + a_ij*((x_i - new_value)*a_ii/a_ij + x_j) + r_i = 0 + + Let r_k be a row where x_j has coefficient x_kj != 0. + r_k <- r_k * a_ij - r_i * a_kj + */ + template + void simplex::update_and_pivot(var_t x_i, var_t x_j, numeral const& a_ij, eps_numeral const& new_value) { + SASSERT(is_base(x_i)); + SASSERT(!is_base(x_j)); + var_info& x_iI = m_vars[x_i]; + scoped_eps_numeral theta(em); + theta = x_iI.m_value; + theta -= new_value; + numeral const& a_ii = x_iI.m_base_coeff; + em.mul(theta, a_ii, theta); + em.div(theta, a_ij, theta); + update_value(x_j, theta); + SASSERT(em.eq(x_iI.m_value, new_value)); + pivot(x_i, x_j, a_ij); + } + + template + void simplex::pivot(var_t x_i, var_t x_j, numeral const& a_ij) { + ++m_stats.m_num_pivots; + var_info& x_iI = m_vars[x_i]; + var_info& x_jI = m_vars[x_j]; + unsigned r_i = x_iI.m_base2row; + m_row2base[r_i] = x_j; + x_jI.m_base2row = r_i; + m.set(x_jI.m_base_coeff, a_ij); + x_jI.m_is_base = true; + x_iI.m_is_base = false; + add_patch(x_j); + SASSERT(well_formed_row(row(r_i))); + + col_iterator it = M.col_begin(x_j), end = M.col_end(x_j); + scoped_numeral a_kj(m), g(m); + for (; it != end; ++it) { + row r_k = it.get_row(); + if (r_k.id() != r_i) { + a_kj = it.get_row_entry().m_coeff; + a_kj.neg(); + M.mul(r_k, a_ij); + M.add(r_k, a_kj, row(r_i)); + var_t s = m_row2base[r_k.id()]; + numeral& coeff = m_vars[s].m_base_coeff; + m.mul(coeff, a_ij, coeff); + M.gcd_normalize(r_k, g); + if (!m.is_one(g)) { + m.div(coeff, g, coeff); + } + SASSERT(well_formed_row(row(r_k))); + } + } + SASSERT(well_formed()); + } + + template + void simplex::update_value(var_t v, eps_numeral const& delta) { + if (em.is_zero(delta)) { + return; + } + update_value_core(v, delta); + col_iterator it = M.col_begin(v), end = M.col_end(v); + + // v <- v + delta + // s*s_coeff + v*v_coeff + R = 0 + // -> + // (v + delta)*v_coeff + (s - delta*v_coeff/s_coeff)*v + R = 0 + for (; it != end; ++it) { + row r = it.get_row(); + var_t s = m_row2base[r.id()]; + var_info& si = m_vars[s]; + scoped_eps_numeral delta2(em); + numeral const& coeff = it.get_row_entry().m_coeff; + em.mul(delta, coeff, delta2); + em.div(delta2, si.m_base_coeff, delta2); + delta2.neg(); + update_value_core(s, delta2); + } + } + + template + void simplex::update_value_core(var_t v, eps_numeral const& delta) { + eps_numeral& val = m_vars[v].m_value; + em.add(val, delta, val); + if (is_base(v)) { + add_patch(v); + } + } + + template + bool simplex::below_lower(var_t v) const { + var_info const& vi = m_vars[v]; + return vi.m_lower_valid && em.lt(vi.m_value, vi.m_lower); + } + + + + template + bool simplex::above_upper(var_t v) const { + var_info const& vi = m_vars[v]; + return vi.m_upper_valid && em.gt(vi.m_value, vi.m_upper); + } + + template + bool simplex::above_lower(var_t v) const { + var_info const& vi = m_vars[v]; + return !vi.m_lower_valid || em.gt(vi.m_value, vi.m_lower); + } + + template + bool simplex::below_upper(var_t v) const { + var_info const& vi = m_vars[v]; + return !vi.m_upper_valid || em.lt(vi.m_value, vi.m_upper); + } + + template + bool simplex::at_lower(var_t v) const { + var_info const& vi = m_vars[v]; + return vi.m_lower_valid && em.eq(vi.m_value, vi.m_lower); + } + + template + bool simplex::at_upper(var_t v) const { + var_info const& vi = m_vars[v]; + return vi.m_upper_valid && em.eq(vi.m_value, vi.m_upper); + } + + template + bool simplex::make_var_feasible(var_t x_i) { + scoped_numeral a_ij(m); + scoped_eps_numeral value(em); + bool is_below; + if (below_lower(x_i)) { + SASSERT(is_base(x_i)); + is_below = m.is_pos(m_vars[x_i].m_base_coeff); + value = m_vars[x_i].m_lower; + } + else if (above_upper(x_i)) { + SASSERT(is_base(x_i)); + is_below = m.is_neg(m_vars[x_i].m_base_coeff); + value = m_vars[x_i].m_upper; + } + else { + // x_i is already feasible + return true; + } + var_t x_j = select_pivot(x_i, is_below, a_ij); + if (x_j != null_var) { + update_and_pivot(x_i, x_j, a_ij, value); + } + return x_j != null_var; + } + + /** + \brief Wrapper for select_pivot_blands and select_pivot_core + */ + template + typename simplex::var_t + simplex::select_pivot(var_t x_i, bool is_below, scoped_numeral& out_a_ij) { + if (m_bland) { + return select_pivot_blands(x_i, is_below, out_a_ij); + } + return select_pivot_core(x_i, is_below, out_a_ij); + } + + /** + \brief Select a variable x_j in the row r defining the base var x_i, + s.t. x_j can be used to patch the error in x_i. Return null_theory_var + if there is no x_j. Otherwise, return x_j and store its coefficient + in out_a_ij. + + The argument is_below is true (false) if x_i is below its lower + bound (above its upper bound). + */ + template + typename simplex::var_t + simplex::select_pivot_core(var_t x_i, bool is_below, scoped_numeral & out_a_ij) { + SASSERT(is_base(x_i)); + var_t max = get_num_vars(); + var_t result = max; + row r = row(m_vars[x_i].m_base2row); + int n; + unsigned best_col_sz = UINT_MAX; + int best_so_far = INT_MAX; + + row_iterator it = M.row_begin(r), end = M.row_end(r); + + for (; it != end; ++it) { + var_t x_j = it->m_var; + if (x_i == x_j) continue; + numeral const & a_ij = it->m_coeff; + + bool is_neg = is_below ? m.is_neg(a_ij) : m.is_pos(a_ij); + bool is_pos = !is_neg; + bool can_pivot = ((is_pos && above_lower(x_j)) || (is_neg && below_upper(x_j))); + if (can_pivot) { + int num = get_num_non_free_dep_vars(x_j, best_so_far); + unsigned col_sz = M.column_size(x_j); + if (num < best_so_far || (num == best_so_far && col_sz < best_col_sz)) { + result = x_j; + out_a_ij = a_ij; + best_so_far = num; + best_col_sz = col_sz; + n = 1; + } + else if (num == best_so_far && col_sz == best_col_sz) { + n++; + if (m_random()%n == 0) { + result = x_j; + out_a_ij = a_ij; + } + } + } + } + return result < max ? result : null_var; + } + + /** + \brief Return the number of base variables that are non free and are v dependent. + The function adds 1 to the result if v is non free. + The function returns with a partial result r if r > best_so_far. + This function is used to select the pivot variable. + */ + template + int simplex::get_num_non_free_dep_vars(var_t x_j, int best_so_far) { + int result = is_non_free(x_j); + col_iterator it = M.col_begin(x_j), end = M.col_end(x_j); + for (; it != end; ++it) { + var_t s = m_row2base[it.get_row().id()]; + result += is_non_free(s); + if (result > best_so_far) + return result; + } + return result; + } + + /** + \brief Using Bland's rule, select a variable x_j in the row r defining the base var x_i, + s.t. x_j can be used to patch the error in x_i. Return null_var + if there is no x_j. Otherwise, return x_j and store its coefficient + in out_a_ij. + */ + template + typename simplex::var_t + simplex::select_pivot_blands(var_t x_i, bool is_below, scoped_numeral & out_a_ij) { + SASSERT(is_base(x_i)); + unsigned max = get_num_vars(); + var_t result = max; + row r(m_vars[x_i].m_base2row); + row_iterator it = M.row_begin(r), end = M.row_end(r); + for (; it != end; ++it) { + var_t x_j = it->m_var; + numeral const & a_ij = it->m_coeff; + bool is_neg = is_below ? m.is_neg(a_ij) : m.is_pos(a_ij); + if (x_i != x_j && ((!is_neg && above_lower(x_j)) || (is_neg && below_upper(x_j)))) { + SASSERT(!is_base(x_j)); + if (x_j < result) { + result = x_j; + out_a_ij = a_ij; + } + } + } + return result < max ? result : null_var; + } + + template + lbool simplex::minimize(var_t v) { + + // minimize v, such that tableau is feasible. + // Assume there are no bounds on v. + // Let k*v + c*x = 0 e.g, maximize c*x over + // tableau constraints: + // + // max { c*x | A*x = 0 and l <= x <= u } + // + // start with feasible assigment + // A*x0 = 0 and l <= x0 <= u + // + // Identify pivot: i, j: such that x_i is base, + // there is a row k1*x_i + k2*x_j + R = 0 + // and a delta such that: + // + // x_i' <- x_i + delta + // x_j' <- x_j - delta*k1/k2 + // l_i <= x_i' <= u_i + // l_j <= x_j' <= u_j + // and c*x' > c*x + // e.g., c*x := c_i*x_i + c_j*x_j + ... + // and c_i*delta > c_j*delta*k1/k2 + // and x_i < u_i (if delta > 0), l_i < x_i (if delta < 0) + // and l_j < x_j (if delta > 0), x_j < u_j (if delta < 0) + // + // update all rows, including c*x, using the pivot. + // + // If there is c_i*x_i in c*x such that c_i > 0 + // and upper_i = oo and complementary lower_j = -oo + // then the objective is unbounded. + // + // There is a singularity if there is a pivot such that + // c_i*delta == c_j*delta*k1/k2, e.g., nothing is improved, + // pivot, but use bland's rule to ensure + // convergence in the limit. + // + + SASSERT(is_feasible()); + scoped_eps_numeral delta(em); + scoped_numeral a_ij(m); + var_t x_i, x_j; + bool inc_x_i, inc_x_j; + + while (true) { + if (m_cancel) { + return l_undef; + } + select_pivot_primal(v, x_i, x_j, a_ij, inc_x_i, inc_x_j); + if (x_j == null_var) { + // optimal + return l_true; + } + TRACE("simplex", tout << "x_i: v" << x_i << " x_j: v" << x_j << "\n";); + var_info& vj = m_vars[x_j]; + if (x_i == null_var) { + if (inc_x_j && vj.m_upper_valid) { + delta = vj.m_upper; + delta -= vj.m_value; + update_value(x_j, delta); + } + else if (!inc_x_j && vj.m_lower_valid) { + delta = vj.m_lower; + delta -= vj.m_value; + update_value(x_j, delta); + } + else { + // unbounded + return l_false; + } + continue; + } + + // TBD: Change the value of x_j directly without pivoting: + // + // if (!vj.is_fixed() && vj.bounded() && gain >= upper - lower) { + // + // } + // + + pivot(x_i, x_j, a_ij); + TRACE("simplex", display(tout << "after pivot\n");); + move_to_bound(x_i, !inc_x_i); + SASSERT(well_formed_row(row(m_vars[x_j].m_base2row))); + TRACE("simplex", display(tout);); + SASSERT(is_feasible()); + } + return l_true; + } + + template + void simplex::move_to_bound(var_t x, bool to_lower) { + scoped_eps_numeral delta(em), delta2(em); + var_info& vi = m_vars[x]; + if (to_lower) { + em.sub(vi.m_value, vi.m_lower, delta); + } + else { + em.sub(vi.m_upper, vi.m_value, delta); + } + TRACE("simplex", tout << "move " << (to_lower?"to_lower":"to_upper") + << " v" << x << " delta: " << em.to_string(delta) << "\n";); + col_iterator it = M.col_begin(x), end = M.col_end(x); + for (; it != end && is_pos(delta); ++it) { + // + // base_coeff*s + coeff*x + R = 0 + // + // to_lower coeff > 0 base_coeff > 0 bound(s) + // ------------------------------------------------------ + // T T T !to_lower + // T T F to_lower + // T F T to_lower + // T F F !to_lower + // + var_t s = m_row2base[it.get_row().id()]; + var_info& vs = m_vars[s]; + numeral const& coeff = it.get_row_entry().m_coeff; + numeral const& base_coeff = vs.m_base_coeff; + SASSERT(!m.is_zero(coeff)); + bool base_to_lower = (m.is_pos(coeff) != m.is_pos(base_coeff)) == to_lower; + eps_numeral const* bound = 0; + if (!base_to_lower && vs.m_upper_valid) { + bound = &vs.m_upper; + } + else if (base_to_lower && vs.m_lower_valid) { + bound = &vs.m_lower; + } + if (bound) { + // |delta2*coeff| = |(bound-value)*base_coeff| + em.sub(*bound, vs.m_value, delta2); + em.mul(delta2, base_coeff, delta2); + em.div(delta2, coeff, delta2); + em.abs(delta2); + TRACE("simplex", tout << "Delta for v" << s << " " << delta2 << "\n";); + if (delta2 < delta) { + delta = delta2; + } + } + } + if (to_lower) { + delta.neg(); + } + update_value(x, delta); + } + + /** + \brief + Arguments: + v - base variable of row(v) to optimize + x_i - base variable of row(x_i) to become non-base + x_j - variable in row(v) to make a base variable + a_ij - coefficient to x_j in row(x_i) + inc - whether to increment x_i + */ + template + void simplex::select_pivot_primal(var_t v, var_t& x_i, var_t& x_j, scoped_numeral& a_ij, + bool& inc_x_i, bool& inc_x_j) { + row r(m_vars[v].m_base2row); + row_iterator it = M.row_begin(r), end = M.row_end(r); + + scoped_eps_numeral gain(em), new_gain(em); + scoped_numeral new_a_ij(m); + x_i = null_var; + x_j = null_var; + inc_x_i = false; + bool inc_y = false; + + for (; it != end; ++it) { + var_t x = it->m_var; + if (x == v) continue; + bool inc_x = m.is_pos(it->m_coeff) == m.is_pos(m_vars[v].m_base_coeff); + if ((inc_x && at_upper(x)) || (!inc_x && at_lower(x))) { + TRACE("simplex", tout << "v" << x << " pos: " << inc_x + << " at upper: " << at_upper(x) + << " at lower: " << at_lower(x) << "\n";); + continue; // variable cannot be used for improving bounds. + // TBD check? + } + var_t y = pick_var_to_leave(x, inc_x, new_gain, new_a_ij, inc_y); + if (y == null_var) { + // unbounded. + x_i = y; + x_j = x; + inc_x_i = inc_y; + inc_x_j = inc_x; + a_ij = new_a_ij; + break; + } + bool better = + (new_gain > gain) || + ((is_zero(new_gain) && is_zero(gain) && (x_i == null_var || y < x_i))); + + if (better) { + TRACE("simplex", + em.display(tout << "gain:", gain); + em.display(tout << " new gain:", new_gain); + tout << " base x_i: " << y << ", new base x_j: " << x << ", inc x_j: " << inc_x << "\n";); + + x_i = y; + x_j = x; + inc_x_i = inc_y; + inc_x_j = inc_x; + gain = new_gain; + a_ij = new_a_ij; + } + } + } + + // + // y is a base variable. + // v is a base variable. + // v*a_v + x*a_x + E = 0 + // y*b_y + x*b_x + F = 0 + // inc(x) := sign(a_v) == sign(a_x) + // sign_eq := sign(b_y) == sign(b_x) + // sign_eq => (inc(x) != inc(y)) + // !sign_eq => (inc(x) = inc(y)) + // -> + // inc(y) := sign_eq != inc(x) + // + + template + typename simplex::var_t + simplex::pick_var_to_leave( + var_t x_j, bool inc_x_j, + scoped_eps_numeral& gain, scoped_numeral& new_a_ij, bool& inc_x_i) { + var_t x_i = null_var; + gain.reset(); + scoped_eps_numeral curr_gain(em); + col_iterator it = M.col_begin(x_j), end = M.col_end(x_j); + for (; it != end; ++it) { + row r = it.get_row(); + var_t s = m_row2base[r.id()]; + var_info& vi = m_vars[s]; + numeral const& a_ij = it.get_row_entry().m_coeff; + numeral const& a_ii = vi.m_base_coeff; + bool sign_eq = (m.is_pos(a_ii) == m.is_pos(a_ij)); + bool inc_s = sign_eq != inc_x_j; + TRACE("simplex", tout << "x_j: v" << x_j << ", base x_i: v" << s + << ", inc_x_i: " << inc_s + << ", inc_x_j: " << inc_x_j + << ", upper valid:" << vi.m_upper_valid + << ", lower valid:" << vi.m_lower_valid << "\n"; + display_row(tout, r);); + if ((inc_s && !vi.m_upper_valid) || (!inc_s && !vi.m_lower_valid)) { + continue; + } + // + // current gain: (value(x_i)-bound)*a_ii/a_ij + // + curr_gain = vi.m_value; + curr_gain -= inc_s?vi.m_upper:vi.m_lower; + em.mul(curr_gain, a_ii, curr_gain); + em.div(curr_gain, a_ij, curr_gain); + if (is_neg(curr_gain)) { + curr_gain.neg(); + } + if (x_i == null_var || (curr_gain < gain) || + (is_zero(gain) && is_zero(curr_gain) && s < x_i)) { + x_i = s; + gain = curr_gain; + new_a_ij = a_ij; + inc_x_i = inc_s; + TRACE("simplex", tout << "x_j v" << x_j << " x_i v" << x_i << " gain: "; + tout << curr_gain << "\n";); + } + } + return x_i; + } + + template + void simplex::check_blands_rule(var_t v, unsigned& num_repeated) { + if (m_bland) + return; + if (m_left_basis.contains(v)) { + num_repeated++; + if (num_repeated > m_blands_rule_threshold) { + TRACE("simplex", tout << "using blands rule, " << num_repeated << "\n";); + // std::cerr << "BLANDS RULE...\n"; + m_bland = true; + } + } + else { + m_left_basis.insert(v); + } + } + + + template + typename simplex::pivot_strategy_t + simplex::pivot_strategy() { + if (m_bland) { + return S_BLAND; + } + return S_DEFAULT; + } + + template + typename simplex::var_t + simplex::select_var_to_fix() { + switch (pivot_strategy()) { + case S_BLAND: + return select_smallest_var(); + case S_GREATEST_ERROR: + return select_error_var(false); + case S_LEAST_ERROR: + return select_error_var(true); + default: + return select_smallest_var(); + } + } + + template + typename simplex::var_t + simplex::select_error_var(bool least) { + var_t best = null_var; + scoped_eps_numeral best_error(em); + scoped_eps_numeral curr_error(em); + typename var_heap::iterator it = m_to_patch.begin(); + typename var_heap::iterator end = m_to_patch.end(); + for (; it != end; ++it) { + var_t v = *it; + var_info const& vi = m_vars[v]; + if (below_lower(v)) + em.sub(vi.m_lower, vi.m_value, curr_error); + else if (above_upper(v)) + em.sub(vi.m_value, vi.m_lower, curr_error); + else + continue; + SASSERT(is_pos(curr_error)); + if ((best == null_var) || + (!least && curr_error > best_error) || + (least && curr_error < best_error)) { + best = v; + best_error = curr_error; + } + } + if (best == null_var) + m_to_patch.clear(); // all variables are satisfied + else + m_to_patch.erase(best); + return best; + } + + template + bool simplex::well_formed() const { + SASSERT(M.well_formed()); + for (unsigned i = 0; i < m_row2base.size(); ++i) { + var_t s = m_row2base[i]; + if (s == null_var) continue; + SASSERT(i == m_vars[s].m_base2row); + VERIFY(well_formed_row(row(i))); + } + for (unsigned i = 0; i < m_vars.size(); ++i) { + if (!is_base(i)) { + SASSERT(!above_upper(i)); + SASSERT(!below_lower(i)); + } + } + return true; + } + + template + bool simplex::is_feasible() const { + for (unsigned i = 0; i < m_vars.size(); ++i) { + if (below_lower(i) || above_upper(i)) return false; + } + return true; + } + + template + bool simplex::well_formed_row(row const& r) const { + var_t s = m_row2base[r.id()]; + SASSERT(m_vars[s].m_base2row == r.id()); + SASSERT(m_vars[s].m_is_base); + // SASSERT(m.is_neg(m_vars[s].m_base_coeff)); + row_iterator it = M.row_begin(r), end = M.row_end(r); + scoped_eps_numeral sum(em), tmp(em); + for (; it != end; ++it) { + em.mul(m_vars[it->m_var].m_value, it->m_coeff, tmp); + sum += tmp; + SASSERT(s != it->m_var || m.eq(m_vars[s].m_base_coeff, it->m_coeff)); + } + if (!em.is_zero(sum)) { + IF_VERBOSE(0, M.display_row(verbose_stream(), r);); + TRACE("pb", display(tout << "non-well formed row\n"); M.display_row(tout << "row: ", r);); + throw default_exception("non-well formed row"); + } + + return true; + } + + template + void simplex::collect_statistics(::statistics & st) const { + M.collect_statistics(st); + st.update("simplex num pivots", m_stats.m_num_pivots); + st.update("simplex num infeasible", m_stats.m_num_infeasible); + st.update("simplex num checks", m_stats.m_num_checks); + } + + +}; + +#endif + diff --git a/src/math/simplex/sparse_matrix.h b/src/math/simplex/sparse_matrix.h new file mode 100644 index 000000000..80454a52c --- /dev/null +++ b/src/math/simplex/sparse_matrix.h @@ -0,0 +1,275 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sparse_matrix.h + +Abstract: + + +Author: + + Nikolaj Bjorner (nbjorner) 2014-01-15 + +Notes: + +--*/ + +#ifndef _SPARSE_MATRIX_H_ +#define _SPARSE_MATRIX_H_ + +#include "mpq_inf.h" +#include "statistics.h" + +namespace simplex { + + template + class sparse_matrix { + public: + typedef typename Ext::numeral numeral; + typedef typename Ext::scoped_numeral scoped_numeral; + typedef typename Ext::manager manager; + typedef unsigned var_t; + + struct row_entry { + numeral m_coeff; + var_t m_var; + row_entry(numeral const& c, var_t v): m_coeff(c), m_var(v) {} + }; + + private: + + struct stats { + unsigned m_add_rows; + stats() { reset(); } + void reset() { + memset(this, 0, sizeof(*this)); + } + }; + + static const int dead_id = -1; + + /** + \brief A row_entry is: m_var*m_coeff + + m_col_idx points to the place in the + column where the variable occurs. + */ + struct _row_entry : public row_entry { + union { + int m_col_idx; + int m_next_free_row_entry_idx; + }; + _row_entry(numeral const & c, var_t v): row_entry(c, v), m_col_idx(0) {} + _row_entry() : row_entry(numeral(), dead_id), m_col_idx(0) {} + bool is_dead() const { return row_entry::m_var == dead_id; } + }; + + /** + \brief A column entry points to the row and the row_entry within the row + that has a non-zero coefficient on the variable associated + with the column entry. + */ + struct col_entry { + int m_row_id; + union { + int m_row_idx; + int m_next_free_col_entry_idx; + }; + col_entry(int r, int i): m_row_id(r), m_row_idx(i) {} + col_entry(): m_row_id(0), m_row_idx(0) {} + bool is_dead() const { return m_row_id == dead_id; } + }; + + struct column; + + /** + \brief A row contains a base variable and set of + row_entries. The base variable must occur in the set of + row_entries with coefficient 1. + */ + struct _row { + vector<_row_entry> m_entries; + unsigned m_size; // the real size, m_entries contains dead row_entries. + int m_first_free_idx; // first available position. + _row(); + unsigned size() const { return m_size; } + unsigned num_entries() const { return m_entries.size(); } + void reset(manager& m); + _row_entry & add_row_entry(unsigned & pos_idx); + void del_row_entry(unsigned idx); + void compress(manager& m, vector & cols); + void compress_if_needed(manager& m, vector & cols); + void save_var_pos(svector & result_map, unsigned_vector& idxs) const; + //bool is_coeff_of(var_t v, numeral const & expected) const; + int get_idx_of(var_t v) const; + }; + + /** + \brief A column stores in which rows a variable occurs. + The column may have free/dead entries. The field m_first_free_idx + is a reference to the first free/dead entry. + */ + struct column { + svector m_entries; + unsigned m_size; + int m_first_free_idx; + mutable unsigned m_refs; + + column():m_size(0), m_first_free_idx(-1), m_refs(0) {} + unsigned size() const { return m_size; } + unsigned num_entries() const { return m_entries.size(); } + void reset(); + void compress(vector<_row> & rows); + void compress_if_needed(vector<_row> & rows); + //void compress_singleton(vector<_row> & rows, unsigned singleton_pos); + col_entry const * get_first_col_entry() const; + col_entry & add_col_entry(int & pos_idx); + void del_col_entry(unsigned idx); + }; + + manager& m; + vector<_row> m_rows; + svector m_dead_rows; // rows to recycle + vector m_columns; // per var + svector m_var_pos; // temporary map from variables to positions in row + unsigned_vector m_var_pos_idx; // indices in m_var_pos + stats m_stats; + + bool well_formed_row(unsigned row_id) const; + bool well_formed_column(unsigned column_id) const; + void del_row_entry(_row& r, unsigned pos); + + public: + + sparse_matrix(manager& m): m(m) {} + ~sparse_matrix(); + void reset(); + + class row { + unsigned m_id; + public: + explicit row(unsigned r):m_id(r) {} + row():m_id(UINT_MAX) {} + bool operator!=(row const& other) const { + return m_id != other.m_id; + } + unsigned id() const { return m_id; } + }; + + void ensure_var(var_t v); + + row mk_row(); + void add_var(row r, numeral const& n, var_t var); + void add(row r, numeral const& n, row src); + void mul(row r, numeral const& n); + void neg(row r); + void del(row r); + + void gcd_normalize(row const& r, scoped_numeral& g); + + class row_iterator { + friend class sparse_matrix; + unsigned m_curr; + _row & m_row; + void move_to_used() { + while (m_curr < m_row.num_entries() && + m_row.m_entries[m_curr].is_dead()) { + ++m_curr; + } + } + row_iterator(_row & r, bool begin): + m_curr(0), m_row(r) { + if (begin) { + move_to_used(); + } + else { + m_curr = m_row.num_entries(); + } + } + public: + row_entry & operator*() const { return m_row.m_entries[m_curr]; } + row_entry * operator->() const { return &(operator*()); } + row_iterator & operator++() { ++m_curr; move_to_used(); return *this; } + row_iterator operator++(int) { row_iterator tmp = *this; ++*this; return tmp; } + bool operator==(row_iterator const & it) const { return m_curr == it.m_curr; } + bool operator!=(row_iterator const & it) const { return m_curr != it.m_curr; } + }; + + row_iterator row_begin(row const& r) { return row_iterator(m_rows[r.id()], true); } + row_iterator row_end(row const& r) { return row_iterator(m_rows[r.id()], false); } + + unsigned column_size(var_t v) const { return m_columns[v].size(); } + + class col_iterator { + friend class sparse_matrix; + unsigned m_curr; + column const& m_col; + vector<_row> const& m_rows; + void move_to_used() { + while (m_curr < m_col.num_entries() && m_col.m_entries[m_curr].is_dead()) { + ++m_curr; + } + } + col_iterator(column const& c, vector<_row> const& r, bool begin): + m_curr(0), m_col(c), m_rows(r) { + ++m_col.m_refs; + if (begin) { + move_to_used(); + } + else { + m_curr = m_col.num_entries(); + } + } + public: + ~col_iterator() { + --m_col.m_refs; + } + + row get_row() { + return row(m_col.m_entries[m_curr].m_row_id); + } + row_entry const& get_row_entry() { + col_entry const& c = m_col.m_entries[m_curr]; + int row_id = c.m_row_id; + return m_rows[row_id].m_entries[c.m_row_idx]; + } + + col_iterator & operator++() { ++m_curr; move_to_used(); return *this; } + col_iterator operator++(int) { col_iterator tmp = *this; ++*this; return tmp; } + bool operator==(col_iterator const & it) const { return m_curr == it.m_curr; } + bool operator!=(col_iterator const & it) const { return m_curr != it.m_curr; } + }; + + col_iterator col_begin(int v) const { return col_iterator(m_columns[v], m_rows, true); } + col_iterator col_end(int v) const { return col_iterator(m_columns[v], m_rows, false); } + + void display(std::ostream& out); + void display_row(std::ostream& out, row const& r); + bool well_formed() const; + + void collect_statistics(::statistics & st) const; + + }; + + struct mpz_ext { + typedef mpz numeral; + typedef scoped_mpz scoped_numeral; + typedef unsynch_mpz_manager manager; + typedef mpq_inf eps_numeral; + typedef unsynch_mpq_inf_manager eps_manager; + }; + + struct mpq_ext { + typedef mpq numeral; + typedef scoped_mpq scoped_numeral; + typedef unsynch_mpq_manager manager; + typedef mpq_inf eps_numeral; + typedef unsynch_mpq_inf_manager eps_manager; + }; + +}; + + +#endif diff --git a/src/math/simplex/sparse_matrix_def.h b/src/math/simplex/sparse_matrix_def.h new file mode 100644 index 000000000..9fa3ceda7 --- /dev/null +++ b/src/math/simplex/sparse_matrix_def.h @@ -0,0 +1,594 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sparse_matrix_def.h + +Abstract: + + +Author: + + Nikolaj Bjorner (nbjorner) 2014-01-15 + +Notes: + + mainly hoisted from theory_arith.h and theory_arith_aux.h + +--*/ + +#ifndef _SPARSE_MATRIX_DEF_H_ +#define _SPARSE_MATRIX_DEF_H_ + +#include "sparse_matrix.h" +#include "uint_set.h" + +namespace simplex { + + // ----------------------------------- + // + // Rows + // + // ----------------------------------- + + template + sparse_matrix::_row::_row(): + m_size(0), + m_first_free_idx(-1) { + } + + template + void sparse_matrix::_row::reset(manager& m) { + for (unsigned i = 0; i < m_entries.size(); ++i) { + m.reset(m_entries[i].m_coeff); + } + m_entries.reset(); + m_size = 0; + m_first_free_idx = -1; + } + + /** + \brief Add a new row_entry. The result is a reference to the new row_entry. + The position of the new row_entry in the + row is stored in pos_idx. + */ + template + typename sparse_matrix::_row_entry & + sparse_matrix::_row::add_row_entry(unsigned & pos_idx) { + m_size++; + if (m_first_free_idx == -1) { + pos_idx = m_entries.size(); + m_entries.push_back(_row_entry()); + return m_entries.back(); + } + else { + SASSERT(m_first_free_idx >= 0); + pos_idx = static_cast(m_first_free_idx); + _row_entry & result = m_entries[pos_idx]; + SASSERT(result.is_dead()); + m_first_free_idx = result.m_next_free_row_entry_idx; + return result; + } + } + + /** + \brief Delete row_entry at position idx. + */ + template + void sparse_matrix::_row::del_row_entry(unsigned idx) { + _row_entry & t = m_entries[idx]; + SASSERT(!t.is_dead()); + t.m_next_free_row_entry_idx = m_first_free_idx; + t.m_var = dead_id; + m_size--; + m_first_free_idx = idx; + SASSERT(t.is_dead()); + } + + /** + \brief Remove holes (i.e., dead entries) from the row. + */ + template + void sparse_matrix::_row::compress(manager& m, vector & cols) { + unsigned i = 0; + unsigned j = 0; + unsigned sz = m_entries.size(); + for (; i < sz; i++) { + _row_entry & t1 = m_entries[i]; + if (!t1.is_dead()) { + if (i != j) { + _row_entry & t2 = m_entries[j]; + t2.m_coeff.swap(t1.m_coeff); + t2.m_var = t1.m_var; + t2.m_col_idx = t1.m_col_idx; + SASSERT(!t2.is_dead()); + column & col = cols[t2.m_var]; + col.m_entries[t2.m_col_idx].m_row_idx = j; + } + j++; + } + } + SASSERT(j == m_size); + // + // alternative: update the free-list to point to the + // tail and avoid shrinking. + // if m.does not allocate memory (for wrapper around + // double), also bypass this step. + // + for (unsigned i = m_size; i < m_entries.size(); ++i) { + m.reset(m_entries[i].m_coeff); + } + m_entries.shrink(m_size); + m_first_free_idx = -1; + } + + template + void sparse_matrix::_row::compress_if_needed(manager& m, vector & cols) { + if (size() *2 < num_entries()) { + compress(m, cols); + } + } + + /** + \brief Fill the map var -> pos/idx + */ + template + inline void sparse_matrix::_row::save_var_pos(svector & result_map, unsigned_vector& idxs) const { + typename vector<_row_entry>::const_iterator it = m_entries.begin(); + typename vector<_row_entry>::const_iterator end = m_entries.end(); + unsigned idx = 0; + for (; it != end; ++it, ++idx) { + if (!it->is_dead()) { + result_map[it->m_var] = idx; + idxs.push_back(it->m_var); + } + } + } + + + template + int sparse_matrix::_row::get_idx_of(var_t v) const { + typename vector<_row_entry>::const_iterator it = m_entries.begin(); + typename vector<_row_entry>::const_iterator end = m_entries.end(); + for (unsigned idx = 0; it != end; ++it, ++idx) { + if (!it->is_dead() && it->m_var == v) + return idx; + } + return -1; + } + + // ----------------------------------- + // + // Columns + // + // ----------------------------------- + + template + void sparse_matrix::column::reset() { + m_entries.reset(); + m_size = 0; + m_first_free_idx = -1; + } + + /** + \brief Remove holes (i.e., dead entries) from the column. + */ + template + void sparse_matrix::column::compress(vector<_row> & rows) { + unsigned i = 0; + unsigned j = 0; + unsigned sz = m_entries.size(); + for (; i < sz; i++) { + col_entry & e1 = m_entries[i]; + if (!e1.is_dead()) { + if (i != j) { + m_entries[j] = e1; + _row & r = rows[e1.m_row_id]; + r.m_entries[e1.m_row_idx].m_col_idx = j; + } + j++; + } + } + SASSERT(j == m_size); + m_entries.shrink(m_size); + m_first_free_idx = -1; + } + + /** + \brief Invoke compress if the column contains too many holes (i.e., dead entries). + */ + template + inline void sparse_matrix::column::compress_if_needed(vector<_row> & rows) { + if (size() * 2 < num_entries() && m_refs == 0) { + compress(rows); + } + } + +#if 0 + /** + \brief Special version of compress, that is used when the column contain + only one entry located at position singleton_pos. + */ + template + void sparse_matrix::column::compress_singleton(vector<_row> & rows, unsigned singleton_pos) { + SASSERT(m_size == 1); + if (singleton_pos != 0) { + col_entry & s = m_entries[singleton_pos]; + m_entries[0] = s; + row & r = rows[s.m_row_id]; + r[s.m_row_idx].m_col_idx = 0; + } + m_first_free_idx = -1; + m_entries.shrink(1); + } +#endif + template + const typename sparse_matrix::col_entry * + sparse_matrix::column::get_first_col_entry() const { + typename svector::const_iterator it = m_entries.begin(); + typename svector::const_iterator end = m_entries.end(); + for (; it != end; ++it) { + if (!it->is_dead()) { + return it; + } + } + return 0; + } + + template + typename sparse_matrix::col_entry & + sparse_matrix::column::add_col_entry(int & pos_idx) { + m_size++; + if (m_first_free_idx == -1) { + pos_idx = m_entries.size(); + m_entries.push_back(col_entry()); + return m_entries.back(); + } + else { + pos_idx = m_first_free_idx; + col_entry & result = m_entries[pos_idx]; + SASSERT(result.is_dead()); + m_first_free_idx = result.m_next_free_col_entry_idx; + return result; + } + } + + template + void sparse_matrix::column::del_col_entry(unsigned idx) { + col_entry & c = m_entries[idx]; + SASSERT(!c.is_dead()); + c.m_row_id = dead_id; + c.m_next_free_col_entry_idx = m_first_free_idx; + m_first_free_idx = idx; + m_size--; + } + + // ----------------------------------- + // + // Matrix + // + // ----------------------------------- + + template + sparse_matrix::~sparse_matrix() { + for (unsigned i = 0; i < m_rows.size(); ++i) { + _row& r = m_rows[i]; + for (unsigned j = 0; j < r.m_entries.size(); ++j) { + m.reset(r.m_entries[j].m_coeff); + } + } + } + + template + void sparse_matrix::reset() { + m_rows.reset(); + m_dead_rows.reset(); + m_columns.reset(); + m_var_pos.reset(); + m_var_pos_idx.reset(); + + } + + template + void sparse_matrix::ensure_var(var_t v) { + while (m_columns.size() <= v) { + m_columns.push_back(column()); + m_var_pos.push_back(-1); + } + } + + template + typename sparse_matrix::row + sparse_matrix::mk_row() { + if (m_dead_rows.empty()) { + row r(m_rows.size()); + m_rows.push_back(_row()); + return r; + } + else { + row r(m_dead_rows.back()); + m_dead_rows.pop_back(); + return r; + } + } + + template + void sparse_matrix::add_var(row dst, numeral const& n, var_t v) { + _row& r = m_rows[dst.id()]; + column& c = m_columns[v]; + unsigned r_idx; + int c_idx; + _row_entry & r_entry = r.add_row_entry(r_idx); + col_entry& c_entry = c.add_col_entry(c_idx); + r_entry.m_var = v; + m.set(r_entry.m_coeff, n); + r_entry.m_col_idx = c_idx; + c_entry.m_row_id = dst.id(); + c_entry.m_row_idx = r_idx; + } + + /** + \brief Set row1 <- row1 + row2 * n + */ + template + void sparse_matrix::add(row row1, numeral const& n, row row2) { + m_stats.m_add_rows++; + _row & r1 = m_rows[row1.id()]; + + r1.save_var_pos(m_var_pos, m_var_pos_idx); + + // + // loop over variables in row2, + // add terms in row2 to row1. + // + +#define ADD_ROW(_SET_COEFF_, _ADD_COEFF_) \ + row_iterator it = row_begin(row2); \ + row_iterator end = row_end(row2); \ + for (; it != end; ++it) { \ + var_t v = it->m_var; \ + int pos = m_var_pos[v]; \ + if (pos == -1) { \ + /* variable v is not in row1 */ \ + unsigned row_idx; \ + _row_entry & r_entry = r1.add_row_entry(row_idx); \ + r_entry.m_var = v; \ + m.set(r_entry.m_coeff, it->m_coeff); \ + _SET_COEFF_; \ + column & c = m_columns[v]; \ + int col_idx; \ + col_entry & c_entry = c.add_col_entry(col_idx); \ + r_entry.m_col_idx = col_idx; \ + c_entry.m_row_id = row1.id(); \ + c_entry.m_row_idx = row_idx; \ + } \ + else { \ + /* variable v is in row1 */ \ + _row_entry & r_entry = r1.m_entries[pos]; \ + SASSERT(r_entry.m_var == v); \ + _ADD_COEFF_; \ + if (m.is_zero(r_entry.m_coeff)) { \ + del_row_entry(r1, pos); \ + } \ + } \ + } \ + ((void) 0) + + if (m.is_one(n)) { + ADD_ROW({}, + m.add(r_entry.m_coeff, it->m_coeff, r_entry.m_coeff)); + } + else if (m.is_minus_one(n)) { + ADD_ROW(m.neg(r_entry.m_coeff), + m.sub(r_entry.m_coeff, it->m_coeff, r_entry.m_coeff)); + } + else { + scoped_numeral tmp(m); + ADD_ROW(m.mul(r_entry.m_coeff, n, r_entry.m_coeff), + m.mul(it->m_coeff, n, tmp); + m.add(r_entry.m_coeff, tmp, r_entry.m_coeff)); + } + + // reset m_var_pos: + for (unsigned i = 0; i < m_var_pos_idx.size(); ++i) { + m_var_pos[m_var_pos_idx[i]] = -1; + } + m_var_pos_idx.reset(); + r1.compress_if_needed(m, m_columns); + } + + + template + void sparse_matrix::del_row_entry(_row& r, unsigned pos) { + _row_entry & r_entry = r.m_entries[pos]; + var_t v = r_entry.m_var; + int col_idx = r_entry.m_col_idx; + r.del_row_entry(pos); + column & c = m_columns[v]; + c.del_col_entry(col_idx); + c.compress_if_needed(m_rows); + } + + /** + \brief Set row <- -row + */ + template + void sparse_matrix::neg(row r) { + row_iterator it = row_begin(r); + row_iterator end = row_end(r); + for (; it != end; ++it) { + m.neg(it->m_coeff); + } + } + + /** + \brief Set row <- n*row + */ + template + void sparse_matrix::mul(row r, numeral const& n) { + SASSERT(!m.is_zero(n)); + if (m.is_one(n)) { + // no op + } + else if (m.is_minus_one(n)) { + neg(r); + } + else { + row_iterator it = row_begin(r); + row_iterator end = row_end(r); + for (; it != end; ++it) { + m.mul(it->m_coeff, n, it->m_coeff); + } + } + } + + /** + \brief Delete row. + */ + template + void sparse_matrix::del(row r) { + _row& rw = m_rows[r.id()]; + for (unsigned i = 0; i < rw.m_entries.size(); ++i) { + _row_entry& e = rw.m_entries[i]; + if (!e.is_dead()) { + del_row_entry(rw, i); + } + } + SASSERT(rw.m_size == 0); + m_dead_rows.push_back(r.id()); + } + + /** + \brief normalize coefficients by dividing with they coefficients. + return the gcd. + */ + template + void sparse_matrix::gcd_normalize(row const& r, scoped_numeral& g) { + g.reset(); + row_iterator it = row_begin(r), end = row_end(r); + for (; it != end && !m.is_one(g); ++it) { + if (m.is_zero(g)) g = it->m_coeff; + else m.gcd(g, it->m_coeff, g); + } + if (m.is_zero(g)) { + g = numeral(1); + } + if (!m.is_one(g)) { + row_iterator it2 = row_begin(r); + for (; it2 != end; ++it2) { + m.div(it2->m_coeff, g, it2->m_coeff); + } + } + } + + /** + \brief well_formed check + */ + template + bool sparse_matrix::well_formed() const { + for (unsigned i = 0; i < m_rows.size(); ++i) { + well_formed_row(i); + } + for (unsigned i = 0; i < m_columns.size(); ++i) { + well_formed_column(i); + } + return true; + } + + /** + \brief well_formed row check + */ + template + bool sparse_matrix::well_formed_row(unsigned row_id) const { + uint_set vars, dead; + _row const& r = m_rows[row_id]; + for (unsigned i = 0; i < r.num_entries(); ++i) { + _row_entry const& e = r.m_entries[i]; + if (e.is_dead()) { + dead.insert(i); + continue; + } + SASSERT(!vars.contains(e.m_var)); + SASSERT(!m.is_zero(e.m_coeff)); + SASSERT(e.m_var != dead_id); + col_entry const& c = m_columns[e.m_var].m_entries[e.m_col_idx]; + SASSERT(c.m_row_id == row_id); + SASSERT(c.m_row_idx == i); + vars.insert(e.m_var); + } + int idx = r.m_first_free_idx; + while (idx != -1) { + SASSERT(dead.contains(idx)); + dead.remove(idx); + idx = r.m_entries[idx].m_next_free_row_entry_idx; + } + SASSERT(dead.empty()); + return true; + } + + /** + \brief well_formed column check + */ + template + bool sparse_matrix::well_formed_column(var_t v) const { + uint_set rows, dead; + column const& col = m_columns[v]; + for (unsigned i = 0; i < col.num_entries(); ++i) { + col_entry const& c = col.m_entries[i]; + if (c.is_dead()) { + dead.insert(i); + continue; + } + SASSERT(!rows.contains(c.m_row_id)); + _row const& row = m_rows[c.m_row_id]; + _row_entry const& r = row.m_entries[c.m_row_idx]; + SASSERT(r.m_var == v); + SASSERT(r.m_col_idx == i); + rows.insert(c.m_row_id); + } + int idx = col.m_first_free_idx; + while (idx != -1) { + SASSERT(dead.contains(idx)); + dead.remove(idx); + idx = col.m_entries[idx].m_next_free_col_entry_idx; + } + SASSERT(dead.empty()); + return true; + } + + /** + \brief statistics + */ + template + void sparse_matrix::collect_statistics(::statistics & st) const { + st.update("simplex add rows", m_stats.m_add_rows); + } + + + /** + \brief display method + */ + template + void sparse_matrix::display(std::ostream& out) { + for (unsigned i = 0; i < m_rows.size(); ++i) { + if (m_rows[i].size() == 0) continue; + display_row(out, row(i)); + } + } + + template + void sparse_matrix::display_row(std::ostream& out, row const& r) { + row_iterator it = row_begin(r), end = row_end(r); + for (; it != end; ++it) { + m.display(out, it->m_coeff); + out << "*v" << it->m_var << " "; + } + out << "\n"; + } + + + +}; + +#endif diff --git a/src/model/func_interp.cpp b/src/model/func_interp.cpp index ae4c657bd..406f7a89b 100644 --- a/src/model/func_interp.cpp +++ b/src/model/func_interp.cpp @@ -159,11 +159,17 @@ void func_interp::insert_entry(expr * const * args, expr * r) { void func_interp::insert_new_entry(expr * const * args, expr * r) { reset_interp_cache(); CTRACE("func_interp_bug", get_entry(args) != 0, + tout << "Old: " << mk_ismt2_pp(get_entry(args)->m_result, m_manager) << "\n"; + tout << "Args:"; + for (unsigned i = 0; i < m_arity; i++) { + tout << mk_ismt2_pp(get_entry(args)->get_arg(i), m_manager) << "\n"; + } + tout << "New: " << mk_ismt2_pp(r, m_manager) << "\n"; + tout << "Args:"; for (unsigned i = 0; i < m_arity; i++) { tout << mk_ismt2_pp(args[i], m_manager) << "\n"; } - tout << "Old: " << mk_ismt2_pp(get_entry(args)->m_result, m_manager) << "\n"; - tout << "New: " << mk_ismt2_pp(r, m_manager) << "\n";); + ); SASSERT(get_entry(args) == 0); func_entry * new_entry = func_entry::mk(m_manager, m_arity, args, r); if (!new_entry->args_are_values()) diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index 41bca940d..9bb17f730 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -23,6 +23,7 @@ Revision History: #include"bool_rewriter.h" #include"arith_rewriter.h" #include"bv_rewriter.h" +#include"pb_rewriter.h" #include"datatype_rewriter.h" #include"array_rewriter.h" #include"float_rewriter.h" @@ -36,6 +37,7 @@ struct evaluator_cfg : public default_rewriter_cfg { bv_rewriter m_bv_rw; array_rewriter m_ar_rw; datatype_rewriter m_dt_rw; + pb_rewriter m_pb_rw; float_rewriter m_f_rw; unsigned long long m_max_memory; unsigned m_max_steps; @@ -52,6 +54,7 @@ struct evaluator_cfg : public default_rewriter_cfg { // See comment above. We want to allow customers to set :sort-store m_ar_rw(m, p), m_dt_rw(m), + m_pb_rw(m), m_f_rw(m) { m_b_rw.set_flat(false); m_a_rw.set_flat(false); @@ -153,6 +156,8 @@ struct evaluator_cfg : public default_rewriter_cfg { return m_ar_rw.mk_app_core(f, num, args, result); if (fid == m_dt_rw.get_fid()) return m_dt_rw.mk_app_core(f, num, args, result); + if (fid == m_pb_rw.get_fid()) + return m_pb_rw.mk_app_core(f, num, args, result); if (fid == m_f_rw.get_fid()) return m_f_rw.mk_app_core(f, num, args, result); return BR_FAILED; diff --git a/src/model/model_implicant.cpp b/src/model/model_implicant.cpp new file mode 100644 index 000000000..44c70036c --- /dev/null +++ b/src/model/model_implicant.cpp @@ -0,0 +1,917 @@ +/*++ +Copyright (c) 2011 Microsoft Corporation + +Module Name: + + model_implicant.cpp + +Abstract: + + Facility to extract prime implicant from model. + +Author: + + Krystof Hoder (t-khoder) 2011-8-19. + +Revision History: + + +Notes: + + +--*/ + +#include +#include "array_decl_plugin.h" +#include "ast_pp.h" +#include "bool_rewriter.h" +#include "for_each_expr.h" +#include "model.h" +#include "ref_vector.h" +#include "rewriter.h" +#include "rewriter_def.h" +#include "util.h" +#include "model_implicant.h" +#include "arith_decl_plugin.h" +#include "expr_replacer.h" +#include "model_smt2_pp.h" +#include "poly_rewriter.h" +#include "poly_rewriter_def.h" +#include "arith_rewriter.h" +#include "scoped_proof.h" + + + +///////////////////////// +// model_implicant +// + + +void model_implicant::assign_value(expr* e, expr* val) { + rational r; + if (m.is_true(val)) { + set_true(e); + } + else if (m.is_false(val)) { + set_false(e); + } + else if (m_arith.is_numeral(val, r)) { + set_number(e, r); + } + else if (m.is_value(val)) { + set_value(e, val); + } + else { + IF_VERBOSE(3, verbose_stream() << "Not evaluated " << mk_pp(e, m) << " := " << mk_pp(val, m) << "\n";); + TRACE("pdr", tout << "Variable is not tracked: " << mk_pp(e, m) << " := " << mk_pp(val, m) << "\n";); + set_x(e); + } +} + +void model_implicant::setup_model(model_ref& model) { + m_numbers.reset(); + m_values.reset(); + m_model = model; + rational r; + unsigned sz = model->get_num_constants(); + for (unsigned i = 0; i < sz; i++) { + func_decl * d = model->get_constant(i); + expr* val = model->get_const_interp(d); + expr* e = m.mk_const(d); + m_refs.push_back(e); + assign_value(e, val); + } +} + +void model_implicant::reset() { + m1.reset(); + m2.reset(); + m_values.reset(); + m_visited.reset(); + m_numbers.reset(); + m_refs.reset(); + m_model = 0; +} + +expr_ref_vector model_implicant::minimize_model(ptr_vector const & formulas, model_ref& mdl) { + setup_model(mdl); + + TRACE("pdr_verbose", + tout << "formulas:\n"; + for (unsigned i = 0; i < formulas.size(); ++i) tout << mk_pp(formulas[i], m) << "\n"; + ); + + expr_ref_vector model = prune_by_cone_of_influence(formulas); + TRACE("pdr_verbose", + tout << "pruned model:\n"; + for (unsigned i = 0; i < model.size(); ++i) tout << mk_pp(model[i].get(), m) << "\n";); + + reset(); + + DEBUG_CODE( + setup_model(mdl); + VERIFY(check_model(formulas)); + reset();); + + return model; +} + +expr_ref_vector model_implicant::minimize_literals(ptr_vector const& formulas, model_ref& mdl) { + + TRACE("pdr", + tout << "formulas:\n"; + for (unsigned i = 0; i < formulas.size(); ++i) tout << mk_pp(formulas[i], m) << "\n"; + ); + + expr_ref_vector result(m); + expr_ref tmp(m); + ptr_vector tocollect; + + setup_model(mdl); + collect(formulas, tocollect); + for (unsigned i = 0; i < tocollect.size(); ++i) { + expr* e = tocollect[i]; + expr* e1, *e2; + SASSERT(m.is_bool(e)); + SASSERT(is_true(e) || is_false(e)); + if (is_true(e)) { + result.push_back(e); + } + // hack to break disequalities for arithmetic variables. + else if (m.is_eq(e, e1, e2) && m_arith.is_int_real(e1)) { + if (get_number(e1) < get_number(e2)) { + result.push_back(m_arith.mk_lt(e1,e2)); + } + else { + result.push_back(m_arith.mk_lt(e2,e1)); + } + } + else { + result.push_back(m.mk_not(e)); + } + } + reset(); + TRACE("pdr", + tout << "minimized model:\n"; + for (unsigned i = 0; i < result.size(); ++i) tout << mk_pp(result[i].get(), m) << "\n"; + ); + + return result; +} + +void model_implicant::process_formula(app* e, ptr_vector& todo, ptr_vector& tocollect) { + SASSERT(m.is_bool(e)); + SASSERT(is_true(e) || is_false(e)); + unsigned v = is_true(e); + unsigned sz = e->get_num_args(); + expr* const* args = e->get_args(); + if (e->get_family_id() == m.get_basic_family_id()) { + switch(e->get_decl_kind()) { + case OP_TRUE: + break; + case OP_FALSE: + break; + case OP_EQ: + case OP_IFF: + if (args[0] == args[1]) { + SASSERT(v); + // no-op + } + else if (m.is_bool(args[0])) { + todo.append(sz, args); + } + else { + tocollect.push_back(e); + } + break; + case OP_DISTINCT: + tocollect.push_back(e); + break; + case OP_ITE: + if (args[1] == args[2]) { + tocollect.push_back(args[1]); + } + else if (is_true(args[1]) && is_true(args[2])) { + todo.append(2, args+1); + } + else if (is_false(args[1]) && is_false(args[2])) { + todo.append(2, args+1); + } + else if (is_true(args[0])) { + todo.append(2, args); + } + else { + SASSERT(is_false(args[0])); + todo.push_back(args[0]); + todo.push_back(args[2]); + } + break; + case OP_AND: + if (v) { + todo.append(sz, args); + } + else { + unsigned i = 0; + for (; !is_false(args[i]) && i < sz; ++i); + if (i == sz) { + fatal_error(1); + } + VERIFY(i < sz); + todo.push_back(args[i]); + } + break; + case OP_OR: + if (v) { + unsigned i = 0; + for (; !is_true(args[i]) && i < sz; ++i); + if (i == sz) { + fatal_error(1); + } + VERIFY(i < sz); + todo.push_back(args[i]); + } + else { + todo.append(sz, args); + } + break; + case OP_XOR: + case OP_NOT: + todo.append(sz, args); + break; + case OP_IMPLIES: + if (v) { + if (is_true(args[1])) { + todo.push_back(args[1]); + } + else if (is_false(args[0])) { + todo.push_back(args[0]); + } + else { + IF_VERBOSE(0, verbose_stream() << "Term not handled " << mk_pp(e, m) << "\n";); + UNREACHABLE(); + } + } + else { + todo.append(sz, args); + } + break; + default: + IF_VERBOSE(0, verbose_stream() << "Term not handled " << mk_pp(e, m) << "\n";); + UNREACHABLE(); + } + } + else { + tocollect.push_back(e); + } +} + +void model_implicant::collect(ptr_vector const& formulas, ptr_vector& tocollect) { + ptr_vector todo; + todo.append(formulas); + m_visited.reset(); + + VERIFY(check_model(formulas)); + + while (!todo.empty()) { + app* e = to_app(todo.back()); + todo.pop_back(); + if (!m_visited.is_marked(e)) { + process_formula(e, todo, tocollect); + m_visited.mark(e, true); + } + } + m_visited.reset(); +} + +expr_ref_vector model_implicant::prune_by_cone_of_influence(ptr_vector const & formulas) { + ptr_vector tocollect; + collect(formulas, tocollect); + m1.reset(); + m2.reset(); + for (unsigned i = 0; i < tocollect.size(); ++i) { + TRACE("pdr_verbose", tout << "collect: " << mk_pp(tocollect[i], m) << "\n";); + for_each_expr(*this, m_visited, tocollect[i]); + } + unsigned sz = m_model->get_num_constants(); + expr_ref e(m), eq(m), val(m); + expr_ref_vector model(m); + for (unsigned i = 0; i < sz; i++) { + e = m.mk_const(m_model->get_constant(i)); + if (m_visited.is_marked(e)) { + val = eval(m_model, e); + eq = m.mk_eq(e, val); + model.push_back(eq); + } + } + m_visited.reset(); + TRACE("pdr", tout << sz << " ==> " << model.size() << "\n";); + return model; + +} + +void model_implicant::eval_arith(app* e) { + rational r, r2; + +#define ARG1 e->get_arg(0) +#define ARG2 e->get_arg(1) + + unsigned arity = e->get_num_args(); + for (unsigned i = 0; i < arity; ++i) { + expr* arg = e->get_arg(i); + if (is_x(arg)) { + set_x(e); + return; + } + SASSERT(!is_unknown(arg)); + } + switch(e->get_decl_kind()) { + case OP_NUM: + VERIFY(m_arith.is_numeral(e, r)); + set_number(e, r); + break; + case OP_IRRATIONAL_ALGEBRAIC_NUM: + set_x(e); + break; + case OP_LE: + set_bool(e, get_number(ARG1) <= get_number(ARG2)); + break; + case OP_GE: + set_bool(e, get_number(ARG1) >= get_number(ARG2)); + break; + case OP_LT: + set_bool(e, get_number(ARG1) < get_number(ARG2)); + break; + case OP_GT: + set_bool(e, get_number(ARG1) > get_number(ARG2)); + break; + case OP_ADD: + r = rational::zero(); + for (unsigned i = 0; i < arity; ++i) { + r += get_number(e->get_arg(i)); + } + set_number(e, r); + break; + case OP_SUB: + r = get_number(e->get_arg(0)); + for (unsigned i = 1; i < arity; ++i) { + r -= get_number(e->get_arg(i)); + } + set_number(e, r); + break; + case OP_UMINUS: + SASSERT(arity == 1); + set_number(e, get_number(e->get_arg(0))); + break; + case OP_MUL: + r = rational::one(); + for (unsigned i = 0; i < arity; ++i) { + r *= get_number(e->get_arg(i)); + } + set_number(e, r); + break; + case OP_DIV: + SASSERT(arity == 2); + r = get_number(ARG2); + if (r.is_zero()) { + set_x(e); + } + else { + set_number(e, get_number(ARG1) / r); + } + break; + case OP_IDIV: + SASSERT(arity == 2); + r = get_number(ARG2); + if (r.is_zero()) { + set_x(e); + } + else { + set_number(e, div(get_number(ARG1), r)); + } + break; + case OP_REM: + // rem(v1,v2) = if v2 >= 0 then mod(v1,v2) else -mod(v1,v2) + SASSERT(arity == 2); + r = get_number(ARG2); + if (r.is_zero()) { + set_x(e); + } + else { + r2 = mod(get_number(ARG1), r); + if (r.is_neg()) r2.neg(); + set_number(e, r2); + } + break; + case OP_MOD: + SASSERT(arity == 2); + r = get_number(ARG2); + if (r.is_zero()) { + set_x(e); + } + else { + set_number(e, mod(get_number(ARG1), r)); + } + break; + case OP_TO_REAL: + SASSERT(arity == 1); + set_number(e, get_number(ARG1)); + break; + case OP_TO_INT: + SASSERT(arity == 1); + set_number(e, floor(get_number(ARG1))); + break; + case OP_IS_INT: + SASSERT(arity == 1); + set_bool(e, get_number(ARG1).is_int()); + break; + case OP_POWER: + set_x(e); + break; + default: + IF_VERBOSE(0, verbose_stream() << "Term not handled " << mk_pp(e, m) << "\n";); + UNREACHABLE(); + break; + } +} + +void model_implicant::inherit_value(expr* e, expr* v) { + expr* w; + SASSERT(!is_unknown(v)); + SASSERT(m.get_sort(e) == m.get_sort(v)); + if (is_x(v)) { + set_x(e); + } + else if (m.is_bool(e)) { + SASSERT(m.is_bool(v)); + if (is_true(v)) set_true(e); + else if (is_false(v)) set_false(e); + else { + TRACE("pdr", tout << "not inherited:\n" << mk_pp(e, m) << "\n" << mk_pp(v, m) << "\n";); + set_x(e); + } + } + else if (m_arith.is_int_real(e)) { + set_number(e, get_number(v)); + } + else if (m.is_value(v)) { + set_value(e, v); + } + else if (m_values.find(v, w)) { + set_value(e, w); + } + else { + TRACE("pdr", tout << "not inherited:\n" << mk_pp(e, m) << "\n" << mk_pp(v, m) << "\n";); + set_x(e); + } +} + +void model_implicant::eval_exprs(expr_ref_vector& es) { + model_ref mr(m_model); + for (unsigned j = 0; j < es.size(); ++j) { + if (m_array.is_as_array(es[j].get())) { + es[j] = eval(mr, es[j].get()); + } + } +} + +bool model_implicant::extract_array_func_interp(expr* a, vector& stores, expr_ref& else_case) { + SASSERT(m_array.is_array(a)); + + TRACE("pdr", tout << mk_pp(a, m) << "\n";); + while (m_array.is_store(a)) { + expr_ref_vector store(m); + store.append(to_app(a)->get_num_args()-1, to_app(a)->get_args()+1); + eval_exprs(store); + stores.push_back(store); + a = to_app(a)->get_arg(0); + } + + if (m_array.is_const(a)) { + else_case = to_app(a)->get_arg(0); + return true; + } + + while (m_array.is_as_array(a)) { + func_decl* f = m_array.get_as_array_func_decl(to_app(a)); + func_interp* g = m_model->get_func_interp(f); + unsigned sz = g->num_entries(); + unsigned arity = f->get_arity(); + for (unsigned i = 0; i < sz; ++i) { + expr_ref_vector store(m); + func_entry const* fe = g->get_entry(i); + store.append(arity, fe->get_args()); + store.push_back(fe->get_result()); + for (unsigned j = 0; j < store.size(); ++j) { + if (!is_ground(store[j].get())) { + TRACE("pdr", tout << "could not extract array interpretation: " << mk_pp(a, m) << "\n" << mk_pp(store[j].get(), m) << "\n";); + return false; + } + } + eval_exprs(store); + stores.push_back(store); + } + else_case = g->get_else(); + if (!else_case) { + TRACE("pdr", tout << "no else case " << mk_pp(a, m) << "\n";); + return false; + } + if (!is_ground(else_case)) { + TRACE("pdr", tout << "non-ground else case " << mk_pp(a, m) << "\n" << mk_pp(else_case, m) << "\n";); + return false; + } + if (m_array.is_as_array(else_case)) { + model_ref mr(m_model); + else_case = eval(mr, else_case); + } + TRACE("pdr", tout << "else case: " << mk_pp(else_case, m) << "\n";); + return true; + } + TRACE("pdr", tout << "no translation: " << mk_pp(a, m) << "\n";); + + return false; +} + +/** + best effort evaluator of extensional array equality. +*/ +void model_implicant::eval_array_eq(app* e, expr* arg1, expr* arg2) { + TRACE("pdr", tout << "array equality: " << mk_pp(e, m) << "\n";); + expr_ref v1(m), v2(m); + m_model->eval(arg1, v1); + m_model->eval(arg2, v2); + if (v1 == v2) { + set_true(e); + return; + } + sort* s = m.get_sort(arg1); + sort* r = get_array_range(s); + // give up evaluating finite domain/range arrays + if (!r->is_infinite() && !r->is_very_big() && !s->is_infinite() && !s->is_very_big()) { + TRACE("pdr", tout << "equality is unknown: " << mk_pp(e, m) << "\n";); + set_x(e); + return; + } + vector store; + expr_ref else1(m), else2(m); + if (!extract_array_func_interp(v1, store, else1) || + !extract_array_func_interp(v2, store, else2)) { + TRACE("pdr", tout << "equality is unknown: " << mk_pp(e, m) << "\n";); + set_x(e); + return; + } + + if (else1 != else2) { + if (m.is_value(else1) && m.is_value(else2)) { + TRACE("pdr", tout + << "defaults are different: " << mk_pp(e, m) << " " + << mk_pp(else1, m) << " " << mk_pp(else2, m) << "\n";); + set_false(e); + } + else if (m_array.is_array(else1)) { + eval_array_eq(e, else1, else2); + } + else { + TRACE("pdr", tout << "equality is unknown: " << mk_pp(e, m) << "\n";); + set_x(e); + } + return; + } + + expr_ref s1(m), s2(m), w1(m), w2(m); + expr_ref_vector args1(m), args2(m); + args1.push_back(v1); + args2.push_back(v2); + for (unsigned i = 0; i < store.size(); ++i) { + args1.resize(1); + args2.resize(1); + args1.append(store[i].size()-1, store[i].c_ptr()); + args2.append(store[i].size()-1, store[i].c_ptr()); + s1 = m_array.mk_select(args1.size(), args1.c_ptr()); + s2 = m_array.mk_select(args2.size(), args2.c_ptr()); + m_model->eval(s1, w1); + m_model->eval(s2, w2); + if (w1 == w2) { + continue; + } + if (m.is_value(w1) && m.is_value(w2)) { + TRACE("pdr", tout << "Equality evaluation: " << mk_pp(e, m) << "\n"; + tout << mk_pp(s1, m) << " |-> " << mk_pp(w1, m) << "\n"; + tout << mk_pp(s2, m) << " |-> " << mk_pp(w2, m) << "\n";); + set_false(e); + } + else if (m_array.is_array(w1)) { + eval_array_eq(e, w1, w2); + if (is_true(e)) { + continue; + } + } + else { + TRACE("pdr", tout << "equality is unknown: " << mk_pp(e, m) << "\n";); + set_x(e); + } + return; + } + set_true(e); +} + +void model_implicant::eval_eq(app* e, expr* arg1, expr* arg2) { + if (arg1 == arg2) { + set_true(e); + } + else if (m_array.is_array(arg1)) { + eval_array_eq(e, arg1, arg2); + } + else if (is_x(arg1) || is_x(arg2)) { + expr_ref eq(m), vl(m); + eq = m.mk_eq(arg1, arg2); + m_model->eval(eq, vl); + if (m.is_true(vl)) { + set_bool(e, true); + } + else if (m.is_false(vl)) { + set_bool(e, false); + } + else { + TRACE("pdr", tout << "cannot evaluate: " << mk_pp(vl, m) << "\n";); + set_x(e); + } + } + else if (m.is_bool(arg1)) { + bool val = is_true(arg1) == is_true(arg2); + SASSERT(val == (is_false(arg1) == is_false(arg2))); + if (val) { + set_true(e); + } + else { + set_false(e); + } + } + else if (m_arith.is_int_real(arg1)) { + set_bool(e, get_number(arg1) == get_number(arg2)); + } + else { + expr* e1 = get_value(arg1); + expr* e2 = get_value(arg2); + if (m.is_value(e1) && m.is_value(e2)) { + set_bool(e, e1 == e2); + } + else if (e1 == e2) { + set_bool(e, true); + } + else { + TRACE("pdr", tout << "not value equal:\n" << mk_pp(e1, m) << "\n" << mk_pp(e2, m) << "\n";); + set_x(e); + } + } +} + +void model_implicant::eval_basic(app* e) { + expr* arg1, *arg2; + expr *argCond, *argThen, *argElse, *arg; + bool has_x = false; + unsigned arity = e->get_num_args(); + switch(e->get_decl_kind()) { + case OP_AND: + for (unsigned j = 0; j < arity; ++j) { + expr * arg = e->get_arg(j); + if (is_false(arg)) { + set_false(e); + return; + } + else if (is_x(arg)) { + has_x = true; + } + else { + SASSERT(is_true(arg)); + } + } + if (has_x) { + set_x(e); + } + else { + set_true(e); + } + break; + case OP_OR: + for (unsigned j = 0; j < arity; ++j) { + expr * arg = e->get_arg(j); + if (is_true(arg)) { + set_true(e); + return; + } + else if (is_x(arg)) { + has_x = true; + } + else { + SASSERT(is_false(arg)); + } + } + if (has_x) { + set_x(e); + } + else { + set_false(e); + } + break; + case OP_NOT: + VERIFY(m.is_not(e, arg)); + if (is_true(arg)) { + set_false(e); + } + else if (is_false(arg)) { + set_true(e); + } + else { + SASSERT(is_x(arg)); + set_x(e); + } + break; + case OP_IMPLIES: + VERIFY(m.is_implies(e, arg1, arg2)); + if (is_false(arg1) || is_true(arg2)) { + set_true(e); + } + else if (arg1 == arg2) { + set_true(e); + } + else if (is_true(arg1) && is_false(arg2)) { + set_false(e); + } + else { + SASSERT(is_x(arg1) || is_x(arg2)); + set_x(e); + } + break; + case OP_IFF: + VERIFY(m.is_iff(e, arg1, arg2)); + eval_eq(e, arg1, arg2); + break; + case OP_ITE: + VERIFY(m.is_ite(e, argCond, argThen, argElse)); + if (is_true(argCond)) { + inherit_value(e, argThen); + } + else if (is_false(argCond)) { + inherit_value(e, argElse); + } + else if (argThen == argElse) { + inherit_value(e, argThen); + } + else if (m.is_bool(e)) { + SASSERT(is_x(argCond)); + if (is_x(argThen) || is_x(argElse)) { + set_x(e); + } + else if (is_true(argThen) == is_true(argElse)) { + inherit_value(e, argThen); + } + else { + set_x(e); + } + } + else { + set_x(e); + } + break; + case OP_TRUE: + set_true(e); + break; + case OP_FALSE: + set_false(e); + break; + case OP_EQ: + VERIFY(m.is_eq(e, arg1, arg2)); + eval_eq(e, arg1, arg2); + break; + case OP_DISTINCT: { + vector values; + for (unsigned i = 0; i < arity; ++i) { + expr* arg = e->get_arg(i); + if (is_x(arg)) { + set_x(e); + return; + } + values.push_back(get_number(arg)); + } + std::sort(values.begin(), values.end()); + for (unsigned i = 0; i + 1 < values.size(); ++i) { + if (values[i] == values[i+1]) { + set_false(e); + return; + } + } + set_true(e); + break; + } + default: + IF_VERBOSE(0, verbose_stream() << "Term not handled " << mk_pp(e, m) << "\n";); + UNREACHABLE(); + } +} + +bool model_implicant::check_model(ptr_vector const& formulas) { + ptr_vector todo(formulas); + + while (!todo.empty()) { + expr * curr_e = todo.back(); + + if (!is_app(curr_e)) { + todo.pop_back(); + continue; + } + app * curr = to_app(curr_e); + + if (!is_unknown(curr)) { + todo.pop_back(); + continue; + } + unsigned arity = curr->get_num_args(); + for (unsigned i = 0; i < arity; ++i) { + if (is_unknown(curr->get_arg(i))) { + todo.push_back(curr->get_arg(i)); + } + } + if (todo.back() != curr) { + continue; + } + todo.pop_back(); + if (curr->get_family_id() == m_arith.get_family_id()) { + eval_arith(curr); + } + else if (curr->get_family_id() == m.get_basic_family_id()) { + eval_basic(curr); + } + else { + expr_ref vl(m); + m_model->eval(curr, vl); + assign_value(curr, vl); + } + + IF_VERBOSE(35,verbose_stream() << "assigned "<get_arity() == 0); + expr_ref result(m); + if (m_array.is_array(d->get_range())) { + expr_ref e(m); + e = m.mk_const(d); + result = eval(model, e); + } + else { + result = model->get_const_interp(d); + } + return result; +} + +expr_ref model_implicant::eval(model_ref& model, expr* e) { + expr_ref result(m); + m_model = model; + VERIFY(m_model->eval(e, result, true)); + if (m_array.is_array(e)) { + vector stores; + expr_ref_vector args(m); + expr_ref else_case(m); + if (extract_array_func_interp(result, stores, else_case)) { + result = m_array.mk_const_array(m.get_sort(e), else_case); + while (!stores.empty() && stores.back().back() == else_case) { + stores.pop_back(); + } + for (unsigned i = stores.size(); i > 0; ) { + --i; + args.resize(1); + args[0] = result; + args.append(stores[i]); + result = m_array.mk_store(args.size(), args.c_ptr()); + } + return result; + } + } + return result; +} + + + + diff --git a/src/model/model_implicant.h b/src/model/model_implicant.h new file mode 100644 index 000000000..21c91b3cb --- /dev/null +++ b/src/model/model_implicant.h @@ -0,0 +1,118 @@ +/*++ +Copyright (c) 2011 Microsoft Corporation + +Module Name: + + model_implicant.h + +Abstract: + + Facility to extract prime implicant from model. + +Author: + + Krystof Hoder (t-khoder) 2011-8-19. + +Revision History: + +--*/ + +#ifndef _MODEL_IMPLICANT_H_ +#define _MODEL_IMPLICANT_H_ + +#include "ast.h" +#include "ast_pp.h" +#include "obj_hashtable.h" +#include "ref_vector.h" +#include "trace.h" +#include "vector.h" +#include "arith_decl_plugin.h" +#include "array_decl_plugin.h" + +class model; +class model_core; + +class model_implicant { + ast_manager& m; + arith_util m_arith; + array_util m_array; + obj_map m_numbers; + expr_ref_vector m_refs; + obj_map m_values; + model_ref m_model; + + //00 -- non-visited + //01 -- X + //10 -- false + //11 -- true + expr_mark m1; + expr_mark m2; + expr_mark m_visited; + + + void reset(); + void setup_model(model_ref& model); + void assign_value(expr* e, expr* v); + void collect(ptr_vector const& formulas, ptr_vector& tocollect); + void process_formula(app* e, ptr_vector& todo, ptr_vector& tocollect); + expr_ref_vector prune_by_cone_of_influence(ptr_vector const & formulas); + void eval_arith(app* e); + void eval_basic(app* e); + void eval_eq(app* e, expr* arg1, expr* arg2); + void eval_array_eq(app* e, expr* arg1, expr* arg2); + void inherit_value(expr* e, expr* v); + + inline bool is_unknown(expr* x) { return !m1.is_marked(x) && !m2.is_marked(x); } + inline void set_unknown(expr* x) { m1.mark(x, false); m2.mark(x, false); } + inline bool is_x(expr* x) { return !m1.is_marked(x) && m2.is_marked(x); } + inline bool is_false(expr* x) { return m1.is_marked(x) && !m2.is_marked(x); } + inline bool is_true(expr* x) { return m1.is_marked(x) && m2.is_marked(x); } + inline void set_x(expr* x) { SASSERT(is_unknown(x)); m2.mark(x); } + inline void set_v(expr* x) { SASSERT(is_unknown(x)); m1.mark(x); } + inline void set_false(expr* x) { SASSERT(is_unknown(x)); m1.mark(x); } + inline void set_true(expr* x) { SASSERT(is_unknown(x)); m1.mark(x); m2.mark(x); } + inline void set_bool(expr* x, bool v) { if (v) { set_true(x); } else { set_false(x); } } + inline rational const& get_number(expr* x) const { return m_numbers.find(x); } + inline void set_number(expr* x, rational const& v) { + set_v(x); TRACE("pdr_verbose", tout << mk_pp(x,m) << " " << v << "\n";); m_numbers.insert(x,v); + } + inline expr* get_value(expr* x) { return m_values.find(x); } + inline void set_value(expr* x, expr* v) { set_v(x); m_refs.push_back(v); m_values.insert(x, v); } + + bool check_model(ptr_vector const & formulas); + + bool extract_array_func_interp(expr* a, vector& stores, expr_ref& else_case); + + void eval_exprs(expr_ref_vector& es); + +public: + model_implicant(ast_manager& m) : + m(m), m_arith(m), m_array(m), m_refs(m) {} + + /** + \brief extract equalities from model that suffice to satisfy formula. + + \pre model satisfies formulas + */ + + expr_ref_vector minimize_model(ptr_vector const & formulas, model_ref& mdl); + + /** + \brief extract literals from model that satisfy formulas. + + \pre model satisfies formulas + */ + expr_ref_vector minimize_literals(ptr_vector const & formulas, model_ref& mdl); + + /** + for_each_expr visitor. + */ + void operator()(expr* e) {} + + expr_ref eval(model_ref& mdl, expr* e); + + expr_ref eval(model_ref& mdl, func_decl* d); +}; + + +#endif diff --git a/src/muz/base/bind_variables.cpp b/src/muz/base/bind_variables.cpp new file mode 100644 index 000000000..0cc50625e --- /dev/null +++ b/src/muz/base/bind_variables.cpp @@ -0,0 +1,154 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + bind_variables.cpp + +Abstract: + + Utility to find constants that are declared as variables. + +Author: + + Nikolaj Bjorner (nbjorner) 9-24-2014 + +Notes: + + +--*/ + +#include "bind_variables.h" + +bind_variables::bind_variables(ast_manager & m): + m(m), + m_vars(m), + m_pinned(m) +{} + +bind_variables::~bind_variables() { +} + +expr_ref bind_variables::operator()(expr* fml, bool is_forall) { + if (m_vars.empty()) { + return expr_ref(fml, m); + } + SASSERT(m_pinned.empty()); + expr_ref result = abstract(fml, m_cache, 0); + if (!m_names.empty()) { + m_bound.reverse(); + m_names.reverse(); + result = m.mk_quantifier(is_forall, m_bound.size(), m_bound.c_ptr(), m_names.c_ptr(), result); + } + m_pinned.reset(); + m_cache.reset(); + m_names.reset(); + m_bound.reset(); + for (var2bound::iterator it = m_var2bound.begin(); it != m_var2bound.end(); ++it) { + it->m_value = 0; + } + return result; +} + + +expr_ref bind_variables::abstract(expr* term, cache_t& cache, unsigned scope) { + unsigned sz = m_todo.size(); + m_todo.push_back(term); + m_args.reset(); + expr* b, *arg; + while (m_todo.size() > sz) { + expr* e = m_todo.back(); + if (cache.contains(e)) { + m_todo.pop_back(); + continue; + } + switch(e->get_kind()) { + case AST_VAR: { + SASSERT(to_var(e)->get_idx() < scope); + // mixing bound variables and free is possible for the caller, + // but not proper use. + // So we assert here even though we don't check for it. + cache.insert(e, e); + m_todo.pop_back(); + break; + } + case AST_APP: { + app* a = to_app(e); + var2bound::obj_map_entry* w = m_var2bound.find_core(a); + if (w) { + var* v = w->get_data().m_value; + if (!v) { + // allocate a bound index. + v = m.mk_var(m_names.size(), m.get_sort(a)); + m_names.push_back(a->get_decl()->get_name()); + m_bound.push_back(m.get_sort(a)); + w->get_data().m_value = v; + m_pinned.push_back(v); + } + if (scope == 0) { + cache.insert(e, v); + } + else { + var* v1 = m.mk_var(scope + v->get_idx(), m.get_sort(v)); + m_pinned.push_back(v1); + cache.insert(e, v1); + } + m_todo.pop_back(); + break; + } + bool all_visited = true; + bool some_diff = false; + m_args.reset(); + for (unsigned i = 0; i < a->get_num_args(); ++i) { + arg = a->get_arg(i); + if (!cache.find(arg, b)) { + m_todo.push_back(arg); + all_visited = false; + } + else if (all_visited) { + m_args.push_back(b); + if (b != arg) { + some_diff = true; + } + } + } + if (all_visited) { + if (some_diff) { + b = m.mk_app(a->get_decl(), m_args.size(), m_args.c_ptr()); + m_pinned.push_back(b); + } + else { + b = a; + } + cache.insert(e, b); + m_todo.pop_back(); + } + break; + } + case AST_QUANTIFIER: { + quantifier* q = to_quantifier(e); + expr_ref_buffer patterns(m); + expr_ref result1(m); + unsigned new_scope = scope + q->get_num_decls(); + cache_t new_cache; + for (unsigned i = 0; i < q->get_num_patterns(); ++i) { + patterns.push_back(abstract(q->get_pattern(i), new_cache, new_scope)); + } + result1 = abstract(q->get_expr(), new_cache, new_scope); + b = m.update_quantifier(q, patterns.size(), patterns.c_ptr(), result1.get()); + m_pinned.push_back(b); + cache.insert(e, b); + m_todo.pop_back(); + break; + } + default: + UNREACHABLE(); + } + } + return expr_ref(cache.find(term), m); +} + +void bind_variables::add_var(app* v) { + m_vars.push_back(v); + m_var2bound.insert(v, 0); +} diff --git a/src/muz/base/bind_variables.h b/src/muz/base/bind_variables.h new file mode 100644 index 000000000..87b2f186b --- /dev/null +++ b/src/muz/base/bind_variables.h @@ -0,0 +1,51 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + bind_variables.h + +Abstract: + + Utility to find constants that are declard as varaibles. + +Author: + + Nikolaj Bjorner (nbjorner) 9-24-2014 + +Notes: + + +--*/ + +#ifndef _BIND_VARIABLES_H_ +#define _BIND_VARIABLES_H_ + +#include"ast.h" + +class bind_variables { + typedef obj_map var2bound; + typedef obj_map cache_t; + ast_manager& m; + app_ref_vector m_vars; + obj_map m_cache; + var2bound m_var2bound; + expr_ref_vector m_pinned; + ptr_vector m_bound; + svector m_names; + ptr_vector m_todo; + ptr_vector m_args; + + + + expr_ref abstract(expr* fml, cache_t& cache, unsigned scope); +public: + bind_variables(ast_manager & m); + ~bind_variables(); + + expr_ref operator()(expr* fml, bool is_forall); + + void add_var(app* v); +}; + +#endif /* _BIND_VARIABLES_H_ */ diff --git a/src/muz/base/dl_context.cpp b/src/muz/base/dl_context.cpp index 2548d1180..6aa6d5ea5 100644 --- a/src/muz/base/dl_context.cpp +++ b/src/muz/base/dl_context.cpp @@ -210,14 +210,12 @@ namespace datalog { m_rewriter(m), m_var_subst(m), m_rule_manager(*this), - m_elim_unused_vars(m), - m_abstractor(m), m_contains_p(*this), - m_check_pred(m_contains_p, m), + m_rule_properties(m, m_rule_manager, *this, m_contains_p), m_transf(*this), m_trail(*this), m_pinned(m), - m_vars(m), + m_bind_variables(m), m_rule_set(*this), m_transformed_rule_set(*this), m_rule_fmls_head(0), @@ -233,6 +231,7 @@ namespace datalog { m_engine_type(LAST_ENGINE), m_cancel(false) { re.set_context(this); + updt_params(pa); } context::~context() { @@ -272,35 +271,39 @@ namespace datalog { } - bool context::generate_proof_trace() const { return m_params->generate_proof_trace(); } - bool context::output_profile() const { return m_params->output_profile(); } - bool context::output_tuples() const { return m_params->output_tuples(); } - bool context::use_map_names() const { return m_params->use_map_names(); } - bool context::fix_unbound_vars() const { return m_params->fix_unbound_vars(); } - symbol context::default_table() const { return m_params->default_table(); } - symbol context::default_relation() const { return m_params->default_relation(); } // external_relation_plugin::get_name()); - symbol context::default_table_checker() const { return m_params->default_table_checker(); } - bool context::default_table_checked() const { return m_params->default_table_checked(); } - bool context::dbg_fpr_nonempty_relation_signature() const { return m_params->dbg_fpr_nonempty_relation_signature(); } - unsigned context::dl_profile_milliseconds_threshold() const { return m_params->profile_timeout_milliseconds(); } - bool context::all_or_nothing_deltas() const { return m_params->all_or_nothing_deltas(); } - bool context::compile_with_widening() const { return m_params->compile_with_widening(); } - bool context::unbound_compressor() const { return m_params->unbound_compressor(); } - bool context::similarity_compressor() const { return m_params->similarity_compressor(); } - unsigned context::similarity_compressor_threshold() const { return m_params->similarity_compressor_threshold(); } + bool context::generate_proof_trace() const { return m_generate_proof_trace; } + bool context::output_profile() const { return m_params->datalog_output_profile(); } + bool context::output_tuples() const { return m_params->datalog_print_tuples(); } + bool context::use_map_names() const { return m_params->datalog_use_map_names(); } + bool context::fix_unbound_vars() const { return m_params->xform_fix_unbound_vars(); } + symbol context::default_table() const { return m_params->datalog_default_table(); } + symbol context::default_relation() const { return m_default_relation; } + void context::set_default_relation(symbol const& s) { m_default_relation = s; } + symbol context::print_aig() const { return m_params->print_aig(); } + symbol context::check_relation() const { return m_params->datalog_check_relation(); } + symbol context::default_table_checker() const { return m_params->datalog_default_table_checker(); } + bool context::default_table_checked() const { return m_params->datalog_default_table_checked(); } + bool context::dbg_fpr_nonempty_relation_signature() const { return m_params->datalog_dbg_fpr_nonempty_relation_signature(); } + unsigned context::dl_profile_milliseconds_threshold() const { return m_params->datalog_profile_timeout_milliseconds(); } + bool context::all_or_nothing_deltas() const { return m_params->datalog_all_or_nothing_deltas(); } + bool context::compile_with_widening() const { return m_params->datalog_compile_with_widening(); } + bool context::unbound_compressor() const { return m_unbound_compressor; } + void context::set_unbound_compressor(bool f) { m_unbound_compressor = f; } + bool context::similarity_compressor() const { return m_params->datalog_similarity_compressor(); } + unsigned context::similarity_compressor_threshold() const { return m_params->datalog_similarity_compressor_threshold(); } unsigned context::soft_timeout() const { return m_fparams.m_soft_timeout; } - unsigned context::initial_restart_timeout() const { return m_params->initial_restart_timeout(); } - bool context::generate_explanations() const { return m_params->generate_explanations(); } - bool context::explanations_on_relation_level() const { return m_params->explanations_on_relation_level(); } - bool context::magic_sets_for_queries() const { return m_params->magic_sets_for_queries(); } - bool context::eager_emptiness_checking() const { return m_params->eager_emptiness_checking(); } - - bool context::bit_blast() const { return m_params->bit_blast(); } - bool context::karr() const { return m_params->karr(); } - bool context::scale() const { return m_params->scale(); } - bool context::magic() const { return m_params->magic(); } - bool context::quantify_arrays() const { return m_params->quantify_arrays(); } - bool context::instantiate_quantifiers() const { return m_params->instantiate_quantifiers(); } + unsigned context::initial_restart_timeout() const { return m_params->datalog_initial_restart_timeout(); } + bool context::generate_explanations() const { return m_params->datalog_generate_explanations(); } + bool context::explanations_on_relation_level() const { return m_params->datalog_explanations_on_relation_level(); } + bool context::magic_sets_for_queries() const { return m_params->datalog_magic_sets_for_queries(); } + symbol context::tab_selection() const { return m_params->tab_selection(); } + bool context::xform_slice() const { return m_params->xform_slice(); } + bool context::xform_bit_blast() const { return m_params->xform_bit_blast(); } + bool context::karr() const { return m_params->xform_karr(); } + bool context::scale() const { return m_params->xform_scale(); } + bool context::magic() const { return m_params->xform_magic(); } + bool context::quantify_arrays() const { return m_params->xform_quantify_arrays(); } + bool context::instantiate_quantifiers() const { return m_params->xform_instantiate_quantifiers(); } void context::register_finite_sort(sort * s, sort_kind k) { @@ -321,48 +324,11 @@ namespace datalog { } void context::register_variable(func_decl* var) { - m_vars.push_back(m.mk_const(var)); + m_bind_variables.add_var(m.mk_const(var)); } - expr_ref context::bind_variables(expr* fml, bool is_forall) { - expr_ref result(m); - app_ref_vector const & vars = m_vars; - rule_manager& rm = get_rule_manager(); - if (vars.empty()) { - result = fml; - } - else { - m_names.reset(); - m_abstractor(0, vars.size(), reinterpret_cast(vars.c_ptr()), fml, result); - rm.collect_vars(result); - ptr_vector& sorts = rm.get_var_sorts(); - if (sorts.empty()) { - result = fml; - } - else { - for (unsigned i = 0; i < sorts.size(); ++i) { - if (!sorts[i]) { - if (i < vars.size()) { - sorts[i] = vars[i]->get_decl()->get_range(); - } - else { - sorts[i] = m.mk_bool_sort(); - } - } - if (i < vars.size()) { - m_names.push_back(vars[i]->get_decl()->get_name()); - } - else { - m_names.push_back(symbol(i)); - } - } - quantifier_ref q(m); - sorts.reverse(); - q = m.mk_quantifier(is_forall, sorts.size(), sorts.c_ptr(), m_names.c_ptr(), result); - m_elim_unused_vars(q, result); - } - } - return result; + expr_ref context::bind_vars(expr* fml, bool is_forall) { + return m_bind_variables(fml, is_forall); } void context::register_predicate(func_decl * decl, bool named) { @@ -490,12 +456,7 @@ namespace datalog { rm.mk_rule(fml, p, m_rule_set, m_rule_names[m_rule_fmls_head]); ++m_rule_fmls_head; } - rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end(); - rule_ref r(m_rule_manager); - for (; it != end; ++it) { - r = *it; - check_rule(r); - } + check_rules(m_rule_set); } // @@ -581,147 +542,57 @@ namespace datalog { m_engine->add_cover(level, pred, property); } - void context::check_uninterpreted_free(rule_ref& r) { - func_decl* f = 0; - if (r->has_uninterpreted_non_predicates(m, f)) { - std::stringstream stm; - stm << "Uninterpreted '" - << f->get_name() - << "' in "; - r->display(*this, stm); - throw default_exception(stm.str()); - } - } - - void context::check_quantifier_free(rule_ref& r) { - if (r->has_quantifiers()) { - std::stringstream stm; - stm << "cannot process quantifiers in rule "; - r->display(*this, stm); - throw default_exception(stm.str()); - } - } - - - void context::check_existential_tail(rule_ref& r) { - unsigned ut_size = r->get_uninterpreted_tail_size(); - unsigned t_size = r->get_tail_size(); - - TRACE("dl", r->display_smt2(get_manager(), tout); tout << "\n";); - for (unsigned i = ut_size; i < t_size; ++i) { - app* t = r->get_tail(i); - TRACE("dl", tout << "checking: " << mk_ismt2_pp(t, get_manager()) << "\n";); - if (m_check_pred(t)) { - std::ostringstream out; - out << "interpreted body " << mk_ismt2_pp(t, get_manager()) << " contains recursive predicate"; - throw default_exception(out.str()); - } - } - } - - void context::check_positive_predicates(rule_ref& r) { - ast_mark visited; - ptr_vector todo, tocheck; - unsigned ut_size = r->get_uninterpreted_tail_size(); - unsigned t_size = r->get_tail_size(); - for (unsigned i = 0; i < ut_size; ++i) { - if (r->is_neg_tail(i)) { - tocheck.push_back(r->get_tail(i)); - } - } - ast_manager& m = get_manager(); - contains_pred contains_p(*this); - check_pred check_pred(contains_p, get_manager()); - - for (unsigned i = ut_size; i < t_size; ++i) { - todo.push_back(r->get_tail(i)); - } - while (!todo.empty()) { - expr* e = todo.back(), *e1, *e2; - todo.pop_back(); - if (visited.is_marked(e)) { - continue; - } - visited.mark(e, true); - if (is_predicate(e)) { - } - else if (m.is_and(e) || m.is_or(e)) { - todo.append(to_app(e)->get_num_args(), to_app(e)->get_args()); - } - else if (m.is_implies(e, e1, e2)) { - tocheck.push_back(e1); - todo.push_back(e2); - } - else if (is_quantifier(e)) { - todo.push_back(to_quantifier(e)->get_expr()); - } - else if ((m.is_eq(e, e1, e2) || m.is_iff(e, e1, e2)) && - m.is_true(e1)) { - todo.push_back(e2); - } - else if ((m.is_eq(e, e1, e2) || m.is_iff(e, e1, e2)) && - m.is_true(e2)) { - todo.push_back(e1); - } - else { - tocheck.push_back(e); - } - } - for (unsigned i = 0; i < tocheck.size(); ++i) { - expr* e = tocheck[i]; - if (check_pred(e)) { - std::ostringstream out; - out << "recursive predicate " << mk_ismt2_pp(e, get_manager()) << " occurs nested in body"; - r->display(*this, out << "\n"); - throw default_exception(out.str()); - - } - } - } - - void context::check_rule(rule_ref& r) { + void context::check_rules(rule_set& r) { + m_rule_properties.set_generate_proof(generate_proof_trace()); switch(get_engine()) { - case DATALOG_ENGINE: - check_quantifier_free(r); - check_uninterpreted_free(r); - check_existential_tail(r); + case DATALOG_ENGINE: + m_rule_properties.collect(r); + m_rule_properties.check_quantifier_free(); + m_rule_properties.check_uninterpreted_free(); + m_rule_properties.check_nested_free(); break; case PDR_ENGINE: - check_existential_tail(r); - check_positive_predicates(r); - check_uninterpreted_free(r); + m_rule_properties.collect(r); + m_rule_properties.check_existential_tail(); + m_rule_properties.check_for_negated_predicates(); + m_rule_properties.check_uninterpreted_free(); break; case QPDR_ENGINE: - check_positive_predicates(r); - check_uninterpreted_free(r); + m_rule_properties.collect(r); + m_rule_properties.check_for_negated_predicates(); + m_rule_properties.check_uninterpreted_free(); break; case BMC_ENGINE: - check_positive_predicates(r); + m_rule_properties.collect(r); + m_rule_properties.check_for_negated_predicates(); break; case QBMC_ENGINE: - check_existential_tail(r); - check_positive_predicates(r); + m_rule_properties.collect(r); + m_rule_properties.check_existential_tail(); + m_rule_properties.check_for_negated_predicates(); break; case TAB_ENGINE: - check_existential_tail(r); - check_positive_predicates(r); + m_rule_properties.collect(r); + m_rule_properties.check_existential_tail(); + m_rule_properties.check_for_negated_predicates(); break; case DUALITY_ENGINE: - check_existential_tail(r); - check_positive_predicates(r); + m_rule_properties.collect(r); + m_rule_properties.check_existential_tail(); + m_rule_properties.check_for_negated_predicates(); break; case CLP_ENGINE: - check_existential_tail(r); - check_positive_predicates(r); + m_rule_properties.collect(r); + m_rule_properties.check_existential_tail(); + m_rule_properties.check_for_negated_predicates(); + break; + case DDNF_ENGINE: break; case LAST_ENGINE: default: UNREACHABLE(); break; } - if (generate_proof_trace() && !r->get_proof()) { - m_rule_manager.mk_rule_asserted_proof(*r.get()); - } } void context::add_rule(rule_ref& r) { @@ -847,6 +718,9 @@ namespace datalog { void context::updt_params(params_ref const& p) { m_params_ref.copy(p); if (m_engine.get()) m_engine->updt_params(); + m_generate_proof_trace = m_params->generate_proof_trace(); + m_unbound_compressor = m_params->datalog_unbound_compressor(); + m_default_relation = m_params->datalog_default_relation(); } expr_ref context::get_background_assertion() { @@ -908,6 +782,9 @@ namespace datalog { }; void context::configure_engine() { + if (m_engine_type != LAST_ENGINE) { + return; + } symbol e = m_params->engine(); if (e == symbol("datalog")) { @@ -934,6 +811,9 @@ namespace datalog { else if (e == symbol("duality")) { m_engine_type = DUALITY_ENGINE; } + else if (e == symbol("ddnf")) { + m_engine_type = DDNF_ENGINE; + } if (m_engine_type == LAST_ENGINE) { expr_fast_mark1 mark; @@ -963,12 +843,7 @@ namespace datalog { // TODO: what? if(get_engine() != DUALITY_ENGINE) { new_query(); - rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end(); - rule_ref r(m_rule_manager); - for (; it != end; ++it) { - r = *it; - check_rule(r); - } + check_rules(m_rule_set); } #endif m_mc = mk_skip_model_converter(); @@ -982,6 +857,7 @@ namespace datalog { case QBMC_ENGINE: case TAB_ENGINE: case CLP_ENGINE: + case DDNF_ENGINE: flush_add_rules(); break; case DUALITY_ENGINE: @@ -1009,6 +885,7 @@ namespace datalog { void context::ensure_engine() { if (!m_engine.get()) { m_engine = m_register_engine.mk_engine(get_engine()); + m_engine->updt_params(); // break abstraction. if (get_engine() == DATALOG_ENGINE) { @@ -1109,7 +986,7 @@ namespace datalog { void context::get_raw_rule_formulas(expr_ref_vector& rules, svector& names, vector &bounds){ for (unsigned i = 0; i < m_rule_fmls.size(); ++i) { - expr_ref r = bind_variables(m_rule_fmls[i].get(), true); + expr_ref r = bind_vars(m_rule_fmls[i].get(), true); rules.push_back(r.get()); // rules.push_back(m_rule_fmls[i].get()); names.push_back(m_rule_names[i]); @@ -1117,15 +994,15 @@ namespace datalog { } } - void context::get_rules_as_formulas(expr_ref_vector& rules, svector& names) { + void context::get_rules_as_formulas(expr_ref_vector& rules, expr_ref_vector& queries, svector& names) { expr_ref fml(m); - datalog::rule_manager& rm = get_rule_manager(); + rule_manager& rm = get_rule_manager(); // ensure that rules are all using bound variables. for (unsigned i = m_rule_fmls_head; i < m_rule_fmls.size(); ++i) { ptr_vector sorts; - get_free_vars(m_rule_fmls[i].get(), sorts); - if (!sorts.empty()) { + m_free_vars(m_rule_fmls[i].get()); + if (!m_free_vars.empty()) { rm.mk_rule(m_rule_fmls[i].get(), 0, m_rule_set, m_rule_names[i]); m_rule_fmls[i] = m_rule_fmls.back(); m_rule_names[i] = m_rule_names.back(); @@ -1137,9 +1014,30 @@ namespace datalog { } rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end(); for (; it != end; ++it) { - (*it)->to_formula(fml); - rules.push_back(fml); - names.push_back((*it)->name()); + rule* r = *it; + rm.to_formula(*r, fml); + func_decl* h = r->get_decl(); + if (m_rule_set.is_output_predicate(h)) { + expr* body = fml; + expr* e2; + if (is_quantifier(body)) { + quantifier* q = to_quantifier(body); + expr* e = q->get_expr(); + VERIFY(m.is_implies(e, body, e2)); + fml = m.mk_quantifier(false, q->get_num_decls(), + q->get_decl_sorts(), q->get_decl_names(), + body); + } + else { + VERIFY(m.is_implies(body, body, e2)); + fml = body; + } + queries.push_back(fml); + } + else { + rules.push_back(fml); + names.push_back(r->name()); + } } for (unsigned i = m_rule_fmls_head; i < m_rule_fmls.size(); ++i) { rules.push_back(m_rule_fmls[i].get()); @@ -1147,10 +1045,7 @@ namespace datalog { } } - void context::display_smt2( - unsigned num_queries, - expr* const* queries, - std::ostream& out) { + void context::display_smt2(unsigned num_queries, expr* const* qs, std::ostream& out) { ast_manager& m = get_manager(); free_func_visitor visitor(m); expr_mark visited; @@ -1158,21 +1053,22 @@ namespace datalog { unsigned num_axioms = m_background.size(); expr* const* axioms = m_background.c_ptr(); expr_ref fml(m); - expr_ref_vector rules(m); + expr_ref_vector rules(m), queries(m); svector names; - bool use_fixedpoint_extensions = m_params->print_with_fixedpoint_extensions(); + bool use_fixedpoint_extensions = m_params->print_fixedpoint_extensions(); bool print_low_level = m_params->print_low_level_smt2(); bool do_declare_vars = m_params->print_with_variable_declarations(); #define PP(_e_) if (print_low_level) out << mk_smt_pp(_e_, m); else ast_smt2_pp(out, _e_, env); - get_rules_as_formulas(rules, names); + get_rules_as_formulas(rules, queries, names); + queries.append(num_queries, qs); smt2_pp_environment_dbg env(m); mk_fresh_name fresh_names; collect_free_funcs(num_axioms, axioms, visited, visitor, fresh_names); collect_free_funcs(rules.size(), rules.c_ptr(), visited, visitor, fresh_names); - collect_free_funcs(num_queries, queries, visited, visitor, fresh_names); + collect_free_funcs(queries.size(), queries.c_ptr(), visited, visitor, fresh_names); func_decl_set funcs; func_decl_set::iterator it = visitor.funcs().begin(); func_decl_set::iterator end = visitor.funcs().end(); @@ -1258,22 +1154,22 @@ namespace datalog { out << ")\n"; } if (use_fixedpoint_extensions) { - for (unsigned i = 0; i < num_queries; ++i) { + for (unsigned i = 0; i < queries.size(); ++i) { out << "(query "; - PP(queries[i]); + PP(queries[i].get()); out << ")\n"; } } else { - for (unsigned i = 0; i < num_queries; ++i) { - if (num_queries > 1) out << "(push)\n"; + for (unsigned i = 0; i < queries.size(); ++i) { + if (queries.size() > 1) out << "(push)\n"; out << "(assert "; expr_ref q(m); - q = m.mk_not(queries[i]); + q = m.mk_not(queries[i].get()); PP(q); out << ")\n"; out << "(check-sat)\n"; - if (num_queries > 1) out << "(pop)\n"; + if (queries.size() > 1) out << "(pop)\n"; } } } diff --git a/src/muz/base/dl_context.h b/src/muz/base/dl_context.h index cf2c53913..52b3cbaf2 100644 --- a/src/muz/base/dl_context.h +++ b/src/muz/base/dl_context.h @@ -39,9 +39,10 @@ Revision History: #include"model2expr.h" #include"smt_params.h" #include"dl_rule_transformer.h" -#include"expr_abstract.h" #include"expr_functors.h" #include"dl_engine_base.h" +#include"bind_variables.h" +#include"rule_properties.h" struct fixedpoint_params; @@ -142,19 +143,6 @@ namespace datalog { SK_UINT64, SK_SYMBOL }; - - private: - class sort_domain; - class symbol_sort_domain; - class uint64_sort_domain; - class restore_rules; - class contains_pred; - - typedef hashtable symbol_set; - typedef map sym2decl; - typedef obj_map > pred2syms; - typedef obj_map sort_domain_map; - class contains_pred : public i_expr_pred { context const& ctx; public: @@ -167,30 +155,43 @@ namespace datalog { }; + private: + class sort_domain; + class symbol_sort_domain; + class uint64_sort_domain; + class restore_rules; + + typedef hashtable symbol_set; + typedef map sym2decl; + typedef obj_map > pred2syms; + typedef obj_map sort_domain_map; + + ast_manager & m; register_engine_base& m_register_engine; smt_params & m_fparams; params_ref m_params_ref; fixedpoint_params* m_params; + bool m_generate_proof_trace; // cached configuration parameter + bool m_unbound_compressor; // cached configuration parameter + symbol m_default_relation; // cached configuration parameter dl_decl_util m_decl_util; th_rewriter m_rewriter; var_subst m_var_subst; rule_manager m_rule_manager; - unused_vars_eliminator m_elim_unused_vars; - expr_abstractor m_abstractor; contains_pred m_contains_p; - check_pred m_check_pred; + rule_properties m_rule_properties; rule_transformer m_transf; trail_stack m_trail; ast_ref_vector m_pinned; - app_ref_vector m_vars; - svector m_names; + bind_variables m_bind_variables; sort_domain_map m_sorts; func_decl_set m_preds; sym2decl m_preds_by_name; pred2syms m_argument_var_names; rule_set m_rule_set; rule_set m_transformed_rule_set; + expr_free_vars m_free_vars; unsigned m_rule_fmls_head; expr_ref_vector m_rule_fmls; svector m_rule_names; @@ -249,27 +250,32 @@ namespace datalog { bool fix_unbound_vars() const; symbol default_table() const; symbol default_relation() const; - symbol default_table_checker() const; + void set_default_relation(symbol const& s); + symbol default_table_checker() const; + symbol check_relation() const; bool default_table_checked() const; bool dbg_fpr_nonempty_relation_signature() const; unsigned dl_profile_milliseconds_threshold() const; bool all_or_nothing_deltas() const; bool compile_with_widening() const; bool unbound_compressor() const; + void set_unbound_compressor(bool f); bool similarity_compressor() const; + symbol print_aig() const; + symbol tab_selection() const; unsigned similarity_compressor_threshold() const; unsigned soft_timeout() const; unsigned initial_restart_timeout() const; bool generate_explanations() const; bool explanations_on_relation_level() const; bool magic_sets_for_queries() const; - bool eager_emptiness_checking() const; - bool bit_blast() const; bool karr() const; bool scale() const; bool magic() const; bool quantify_arrays() const; bool instantiate_quantifiers() const; + bool xform_bit_blast() const; + bool xform_slice() const; void register_finite_sort(sort * s, sort_kind k); @@ -286,7 +292,7 @@ namespace datalog { universal (if is_forall is true) or existential quantifier. */ - expr_ref bind_variables(expr* fml, bool is_forall); + expr_ref bind_vars(expr* fml, bool is_forall); /** Register datalog relation. @@ -366,7 +372,7 @@ namespace datalog { rule_set & get_rules() { flush_add_rules(); return m_rule_set; } - void get_rules_as_formulas(expr_ref_vector& fmls, svector& names); + void get_rules_as_formulas(expr_ref_vector& fmls, expr_ref_vector& qs, svector& names); void get_raw_rule_formulas(expr_ref_vector& fmls, svector& names, vector &bounds); void add_fact(app * head); @@ -420,7 +426,7 @@ namespace datalog { /** \brief Check if rule is well-formed according to engine. */ - void check_rule(rule_ref& r); + void check_rules(rule_set& r); /** \brief Return true if facts to \c pred can be added using the \c add_table_fact() function. @@ -467,7 +473,7 @@ namespace datalog { void display(std::ostream & out) const; - void display_smt2(unsigned num_queries, expr* const* queries, std::ostream& out); + void display_smt2(unsigned num_queries, expr* const* qs, std::ostream& out); void display_profile(std::ostream& out) const; @@ -566,11 +572,6 @@ namespace datalog { void ensure_engine(); - void check_quantifier_free(rule_ref& r); - void check_uninterpreted_free(rule_ref& r); - void check_existential_tail(rule_ref& r); - void check_positive_predicates(rule_ref& r); - // auxilary functions for SMT2 pretty-printer. void declare_vars(expr_ref_vector& rules, mk_fresh_name& mk_fresh, std::ostream& out); diff --git a/src/muz/base/dl_engine_base.h b/src/muz/base/dl_engine_base.h index eaeebe979..21a07fcb0 100644 --- a/src/muz/base/dl_engine_base.h +++ b/src/muz/base/dl_engine_base.h @@ -30,8 +30,9 @@ namespace datalog { QBMC_ENGINE, TAB_ENGINE, CLP_ENGINE, - LAST_ENGINE, - DUALITY_ENGINE + DUALITY_ENGINE, + DDNF_ENGINE, + LAST_ENGINE }; class engine_base { diff --git a/src/muz/base/dl_rule.cpp b/src/muz/base/dl_rule.cpp index 017bac724..b846bc06a 100644 --- a/src/muz/base/dl_rule.cpp +++ b/src/muz/base/dl_rule.cpp @@ -56,7 +56,8 @@ namespace datalog { m_hnf(m), m_qe(m), m_cfg(m), - m_rwr(m, false, m_cfg) {} + m_rwr(m, false, m_cfg), + m_ufproc(m) {} void rule_manager::inc_ref(rule * r) { if (r) { @@ -111,16 +112,14 @@ namespace datalog { } void rule_manager::reset_collect_vars() { - m_vars.reset(); m_var_idx.reset(); - m_todo.reset(); - m_mark.reset(); + m_free_vars.reset(); } var_idx_set& rule_manager::finalize_collect_vars() { - unsigned sz = m_vars.size(); - for (unsigned i=0; i sorts; - ::get_free_vars(fml, sorts); ); expr_ref_vector fmls(m); proof_ref_vector prs(m); m_hnf.reset(); @@ -200,8 +197,6 @@ namespace datalog { m_ctx.register_predicate(m_hnf.get_fresh_predicates()[i], false); } for (unsigned i = 0; i < fmls.size(); ++i) { - DEBUG_CODE(ptr_vector sorts; - ::get_free_vars(fmls[i].get(), sorts); ); mk_horn_rule(fmls[i].get(), prs[i].get(), rules, name); } } @@ -228,7 +223,7 @@ namespace datalog { expr_ref fml1(m); if (p) { - r->to_formula(fml1); + to_formula(*r, fml1); if (fml1 == fml) { // no-op. } @@ -246,7 +241,7 @@ namespace datalog { if (p) { expr_ref fml2(m); - r->to_formula(fml2); + to_formula(*r, fml2); if (fml1 != fml2) { p = m.mk_modus_ponens(p, m.mk_rewrite(fml1, fml2)); } @@ -257,17 +252,16 @@ namespace datalog { unsigned rule_manager::extract_horn(expr* fml, app_ref_vector& body, app_ref& head) { expr* e1, *e2; - unsigned index = m_counter.get_next_var(fml); if (::is_forall(fml)) { - index += to_quantifier(fml)->get_num_decls(); fml = to_quantifier(fml)->get_expr(); } + unsigned index = m_counter.get_next_var(fml); if (m.is_implies(fml, e1, e2)) { - expr_ref_vector es(m); + m_args.reset(); head = ensure_app(e2); - qe::flatten_and(e1, es); - for (unsigned i = 0; i < es.size(); ++i) { - body.push_back(ensure_app(es[i].get())); + qe::flatten_and(e1, m_args); + for (unsigned i = 0; i < m_args.size(); ++i) { + body.push_back(ensure_app(m_args[i].get())); } } else { @@ -299,7 +293,8 @@ namespace datalog { quantifier_hoister qh(m); qh.pull_quantifier(false, q, 0, &names); // retrieve free variables. - get_free_vars(q, vars); + m_free_vars(q); + vars.append(m_free_vars.size(), m_free_vars.c_ptr()); if (vars.contains(static_cast(0))) { var_subst sub(m, false); expr_ref_vector args(m); @@ -316,7 +311,8 @@ namespace datalog { } sub(q, args.size(), args.c_ptr(), q); vars.reset(); - get_free_vars(q, vars); + m_free_vars(q); + vars.append(m_free_vars.size(), m_free_vars.c_ptr()); } SASSERT(!vars.contains(static_cast(0)) && "Unused variables have been eliminated"); @@ -373,7 +369,7 @@ namespace datalog { } void rule_manager::bind_variables(expr* fml, bool is_forall, expr_ref& result) { - result = m_ctx.bind_variables(fml, is_forall); + result = m_ctx.bind_vars(fml, is_forall); } void rule_manager::flatten_body(app_ref_vector& body) { @@ -498,11 +494,6 @@ namespace datalog { app * * uninterp_tail = r->m_tail; //grows upwards app * * interp_tail = r->m_tail+n; //grows downwards - DEBUG_CODE(ptr_vector sorts; - ::get_free_vars(head, sorts); - for (unsigned i = 0; i < n; ++i) { - ::get_free_vars(tail[i], sorts); - }); bool has_neg = false; @@ -556,11 +547,6 @@ namespace datalog { if (normalize) { r->norm_vars(*this); } - DEBUG_CODE(ptr_vector sorts; - ::get_free_vars(head, sorts); - for (unsigned i = 0; i < n; ++i) { - ::get_free_vars(tail[i], sorts); - }); return r; } @@ -587,6 +573,55 @@ namespace datalog { return r; } + void rule_manager::to_formula(rule const& r, expr_ref& fml) { + ast_manager & m = fml.get_manager(); + expr_ref_vector body(m); + for (unsigned i = 0; i < r.get_tail_size(); i++) { + body.push_back(r.get_tail(i)); + if (r.is_neg_tail(i)) { + body[body.size()-1] = m.mk_not(body.back()); + } + } + fml = r.get_head(); + switch (body.size()) { + case 0: break; + case 1: fml = m.mk_implies(body[0].get(), fml); break; + default: fml = m.mk_implies(m.mk_and(body.size(), body.c_ptr()), fml); break; + } + + m_free_vars(fml); + if (m_free_vars.empty()) { + return; + } + svector names; + used_symbols<> us; + m_free_vars.set_default_sort(m.mk_bool_sort()); + + us(fml); + m_free_vars.reverse(); + for (unsigned j = 0, i = 0; i < m_free_vars.size(); ++j) { + for (char c = 'A'; i < m_free_vars.size() && c <= 'Z'; ++c) { + func_decl_ref f(m); + std::stringstream _name; + _name << c; + if (j > 0) _name << j; + symbol name(_name.str().c_str()); + if (!us.contains(name)) { + names.push_back(name); + ++i; + } + } + } + fml = m.mk_forall(m_free_vars.size(), m_free_vars.c_ptr(), names.c_ptr(), fml); + } + + std::ostream& rule_manager::display_smt2(rule const& r, std::ostream & out) { + expr_ref fml(m); + to_formula(r, fml); + return out << mk_ismt2_pp(fml, m); + } + + void rule_manager::reduce_unbound_vars(rule_ref& r) { unsigned ut_len = r->get_uninterpreted_tail_size(); unsigned t_len = r->get_tail_size(); @@ -647,9 +682,7 @@ namespace datalog { svector tail_neg; app_ref head(r->get_head(), m); - collect_rule_vars(r); vctr.count_vars(m, head); - ptr_vector& free_rule_vars = m_vars; for (unsigned i = 0; i < ut_len; i++) { app * t = r->get_tail(i); @@ -658,18 +691,16 @@ namespace datalog { tail_neg.push_back(r->is_neg_tail(i)); } - ptr_vector interp_vars; var_idx_set unbound_vars; expr_ref_vector tails_with_unbound(m); for (unsigned i = ut_len; i < t_len; i++) { app * t = r->get_tail(i); - interp_vars.reset(); - ::get_free_vars(t, interp_vars); + m_free_vars(t); bool has_unbound = false; - unsigned iv_size = interp_vars.size(); + unsigned iv_size = m_free_vars.size(); for (unsigned i=0; i qsorts; qsorts.resize(q_var_cnt); unsigned q_idx = 0; - for (unsigned v = 0; v <= max_var; ++v) { - sort * v_sort = free_rule_vars[v]; + for (unsigned v = 0; v < m_free_vars.size(); ++v) { + sort * v_sort = m_free_vars[v]; if (!v_sort) { //this variable index is not used continue; @@ -780,7 +810,7 @@ namespace datalog { !new_rule.get_proof() && old_rule.get_proof()) { expr_ref fml(m); - new_rule.to_formula(fml); + to_formula(new_rule, fml); scoped_proof _sc(m); proof* p = m.mk_rewrite(m.get_fact(old_rule.get_proof()), fml); new_rule.set_proof(m, m.mk_modus_ponens(old_rule.get_proof(), p)); @@ -791,7 +821,7 @@ namespace datalog { if (m_ctx.generate_proof_trace()) { scoped_proof _scp(m); expr_ref fml(m); - r.to_formula(fml); + to_formula(r, fml); r.set_proof(m, m.mk_asserted(fml)); } } @@ -881,83 +911,40 @@ namespace datalog { return false; } - struct uninterpreted_function_finder_proc { - ast_manager& m; - datatype_util m_dt; - bool m_found; - func_decl* m_func; - uninterpreted_function_finder_proc(ast_manager& m): - m(m), m_dt(m), m_found(false), m_func(0) {} - void operator()(var * n) { } - void operator()(quantifier * n) { } - void operator()(app * n) { - if (is_uninterp(n)) { - m_found = true; - m_func = n->get_decl(); - } - else if (m_dt.is_accessor(n)) { - sort* s = m.get_sort(n->get_arg(0)); - SASSERT(m_dt.is_datatype(s)); - if (m_dt.get_datatype_constructors(s)->size() > 1) { - m_found = true; - m_func = n->get_decl(); - } - } - } - - bool found(func_decl*& f) const { f = m_func; return m_found; } - }; // // non-predicates may appear only in the interpreted tail, it is therefore // sufficient only to check the tail. // - bool rule::has_uninterpreted_non_predicates(ast_manager& m, func_decl*& f) const { - unsigned sz = get_tail_size(); - uninterpreted_function_finder_proc proc(m); - expr_mark visited; - for (unsigned i = get_uninterpreted_tail_size(); i < sz && !proc.found(f); ++i) { - for_each_expr(proc, visited, get_tail(i)); + bool rule_manager::has_uninterpreted_non_predicates(rule const& r, func_decl*& f) const { + unsigned sz = r.get_tail_size(); + m_ufproc.reset(); + m_visited.reset(); + for (unsigned i = r.get_uninterpreted_tail_size(); i < sz && !m_ufproc.found(f); ++i) { + for_each_expr_core(m_ufproc, m_visited, r.get_tail(i)); } - return proc.found(f); + return m_ufproc.found(f); } - struct quantifier_finder_proc { - bool m_exist; - bool m_univ; - quantifier_finder_proc() : m_exist(false), m_univ(false) {} - void operator()(var * n) { } - void operator()(quantifier * n) { - if (n->is_forall()) { - m_univ = true; - } - else { - SASSERT(n->is_exists()); - m_exist = true; - } - } - void operator()(app * n) { } - }; - // // Quantifiers may appear only in the interpreted tail, it is therefore // sufficient only to check the interpreted tail. // - void rule::has_quantifiers(bool& existential, bool& universal) const { - unsigned sz = get_tail_size(); - quantifier_finder_proc proc; - expr_mark visited; - for (unsigned i = get_uninterpreted_tail_size(); i < sz; ++i) { - for_each_expr(proc, visited, get_tail(i)); + void rule_manager::has_quantifiers(rule const& r, bool& existential, bool& universal) const { + unsigned sz = r.get_tail_size(); + m_qproc.reset(); + m_visited.reset(); + for (unsigned i = r.get_uninterpreted_tail_size(); i < sz; ++i) { + for_each_expr_core(m_qproc, m_visited, r.get_tail(i)); } - existential = proc.m_exist; - universal = proc.m_univ; + existential = m_qproc.m_exist; + universal = m_qproc.m_univ; } - bool rule::has_quantifiers() const { + bool rule_manager::has_quantifiers(rule const& r) const { bool exist, univ; - has_quantifiers(exist, univ); + has_quantifiers(r, exist, univ); return exist || univ; } @@ -1066,57 +1053,6 @@ namespace datalog { } } - void rule::to_formula(expr_ref& fml) const { - ast_manager & m = fml.get_manager(); - expr_ref_vector body(m); - for (unsigned i = 0; i < m_tail_size; i++) { - body.push_back(get_tail(i)); - if (is_neg_tail(i)) { - body[body.size()-1] = m.mk_not(body.back()); - } - } - switch(body.size()) { - case 0: fml = m_head; break; - case 1: fml = m.mk_implies(body[0].get(), m_head); break; - default: fml = m.mk_implies(m.mk_and(body.size(), body.c_ptr()), m_head); break; - } - - ptr_vector sorts; - get_free_vars(fml, sorts); - if (sorts.empty()) { - return; - } - svector names; - used_symbols<> us; - for (unsigned i = 0; i < sorts.size(); ++i) { - if (!sorts[i]) { - sorts[i] = m.mk_bool_sort(); - } - } - - us(fml); - sorts.reverse(); - for (unsigned j = 0, i = 0; i < sorts.size(); ++j) { - for (char c = 'A'; i < sorts.size() && c <= 'Z'; ++c) { - func_decl_ref f(m); - std::stringstream _name; - _name << c; - if (j > 0) _name << j; - symbol name(_name.str().c_str()); - if (!us.contains(name)) { - names.push_back(name); - ++i; - } - } - } - fml = m.mk_forall(sorts.size(), sorts.c_ptr(), names.c_ptr(), fml); - } - - std::ostream& rule::display_smt2(ast_manager& m, std::ostream & out) const { - expr_ref fml(m); - to_formula(fml); - return out << mk_ismt2_pp(fml, m); - } bool rule_eq_proc::operator()(const rule * r1, const rule * r2) const { if (r1->get_head()!=r2->get_head()) { return false; } diff --git a/src/muz/base/dl_rule.h b/src/muz/base/dl_rule.h index 7104bae1f..50211e1d9 100644 --- a/src/muz/base/dl_rule.h +++ b/src/muz/base/dl_rule.h @@ -30,6 +30,8 @@ Revision History: #include"rewriter.h" #include"hnf.h" #include"qe_lite.h" +#include"var_subst.h" +#include"datatype_decl_plugin.h" namespace datalog { @@ -42,6 +44,57 @@ namespace datalog { typedef obj_ref rule_ref; typedef ref_vector rule_ref_vector; typedef ptr_vector rule_vector; + + + struct quantifier_finder_proc { + bool m_exist; + bool m_univ; + quantifier_finder_proc() : m_exist(false), m_univ(false) {} + void operator()(var * n) { } + void operator()(quantifier * n) { + if (n->is_forall()) { + m_univ = true; + } + else { + SASSERT(n->is_exists()); + m_exist = true; + } + } + void operator()(app * n) { } + void reset() { m_exist = m_univ = false; } + }; + + struct uninterpreted_function_finder_proc { + ast_manager& m; + datatype_util m_dt; + bool m_found; + func_decl* m_func; + uninterpreted_function_finder_proc(ast_manager& m): + m(m), m_dt(m), m_found(false), m_func(0) {} + + void reset() { m_found = false; m_func = 0; } + + void operator()(var * n) { } + void operator()(quantifier * n) { } + void operator()(app * n) { + if (is_uninterp(n)) { + m_found = true; + m_func = n->get_decl(); + } + else if (m_dt.is_accessor(n)) { + sort* s = m.get_sort(n->get_arg(0)); + SASSERT(m_dt.is_datatype(s)); + if (m_dt.get_datatype_constructors(s)->size() > 1) { + m_found = true; + m_func = n->get_decl(); + } + } + } + + bool found(func_decl*& f) const { f = m_func; return m_found; } + }; + + /** \brief Manager for the \c rule class @@ -64,10 +117,8 @@ namespace datalog { context& m_ctx; rule_counter m_counter; used_vars m_used; - ptr_vector m_vars; var_idx_set m_var_idx; - ptr_vector m_todo; - ast_mark m_mark; + expr_free_vars m_free_vars; app_ref_vector m_body; app_ref m_head; expr_ref_vector m_args; @@ -76,6 +127,9 @@ namespace datalog { qe_lite m_qe; remove_label_cfg m_cfg; rewriter_tpl m_rwr; + mutable uninterpreted_function_finder_proc m_ufproc; + mutable quantifier_finder_proc m_qproc; + mutable expr_sparse_mark m_visited; // only the context can create a rule_manager @@ -143,7 +197,7 @@ namespace datalog { void accumulate_vars(expr* pred); - ptr_vector& get_var_sorts() { return m_vars; } + // ptr_vector& get_var_sorts() { return m_vars; } var_idx_set& get_var_idx() { return m_var_idx; } @@ -213,11 +267,18 @@ namespace datalog { */ bool is_fact(app * head) const; - static bool is_forall(ast_manager& m, expr* e, quantifier*& q); rule_counter& get_counter() { return m_counter; } + void to_formula(rule const& r, expr_ref& result); + + std::ostream& display_smt2(rule const& r, std::ostream & out); + + bool has_uninterpreted_non_predicates(rule const& r, func_decl*& f) const; + void has_quantifiers(rule const& r, bool& existential, bool& universal) const; + bool has_quantifiers(rule const& r) const; + }; class rule : public accounted_object { @@ -293,9 +354,6 @@ namespace datalog { */ bool is_in_tail(const func_decl * p, bool only_positive=false) const; - bool has_uninterpreted_non_predicates(ast_manager& m, func_decl*& f) const; - void has_quantifiers(bool& existential, bool& universal) const; - bool has_quantifiers() const; bool has_negation() const; /** @@ -306,12 +364,8 @@ namespace datalog { void get_vars(ast_manager& m, ptr_vector& sorts) const; - void to_formula(expr_ref& result) const; - void display(context & ctx, std::ostream & out) const; - std::ostream& display_smt2(ast_manager& m, std::ostream & out) const; - symbol const& name() const { return m_name; } unsigned hash() const; diff --git a/src/muz/base/dl_rule_set.h b/src/muz/base/dl_rule_set.h index c1fc7ea3f..e13d92105 100644 --- a/src/muz/base/dl_rule_set.h +++ b/src/muz/base/dl_rule_set.h @@ -39,10 +39,10 @@ namespace datalog { Each master object is also present as a key of the map, even if its master set is empty. */ - deps_type m_data; - context & m_context; + deps_type m_data; + context & m_context; ptr_vector m_todo; - ast_mark m_visited; + expr_sparse_mark m_visited; //we need to take care with removing to avoid memory leaks diff --git a/src/muz/base/dl_util.cpp b/src/muz/base/dl_util.cpp index a6647a1d2..2f60ddec8 100644 --- a/src/muz/base/dl_util.cpp +++ b/src/muz/base/dl_util.cpp @@ -56,9 +56,9 @@ namespace datalog { bool contains_var(expr * trm, unsigned var_idx) { - ptr_vector vars; - ::get_free_vars(trm, vars); - return var_idx < vars.size() && vars[var_idx] != 0; + expr_free_vars fv; + fv(trm); + return fv.contains(var_idx); } unsigned count_variable_arguments(app * pred) @@ -300,14 +300,15 @@ namespace datalog { } - void resolve_rule(replace_proof_converter* pc, rule const& r1, rule const& r2, unsigned idx, + void resolve_rule(rule_manager& rm, + replace_proof_converter* pc, rule const& r1, rule const& r2, unsigned idx, expr_ref_vector const& s1, expr_ref_vector const& s2, rule const& res) { if (!pc) return; ast_manager& m = s1.get_manager(); expr_ref fml1(m), fml2(m), fml3(m); - r1.to_formula(fml1); - r2.to_formula(fml2); - res.to_formula(fml3); + rm.to_formula(r1, fml1); + rm.to_formula(r2, fml2); + rm.to_formula(res, fml3); vector substs; svector > positions; substs.push_back(s1); @@ -337,7 +338,7 @@ namespace datalog { pc->insert(pr); } - void resolve_rule(rule const& r1, rule const& r2, unsigned idx, + void resolve_rule(rule_manager& rm, rule const& r1, rule const& r2, unsigned idx, expr_ref_vector const& s1, expr_ref_vector const& s2, rule& res) { if (!r1.get_proof()) { return; @@ -345,7 +346,7 @@ namespace datalog { SASSERT(r2.get_proof()); ast_manager& m = s1.get_manager(); expr_ref fml(m); - res.to_formula(fml); + rm.to_formula(res, fml); vector substs; svector > positions; substs.push_back(s1); diff --git a/src/muz/base/dl_util.h b/src/muz/base/dl_util.h index 57f7575ca..bf5c225ef 100644 --- a/src/muz/base/dl_util.h +++ b/src/muz/base/dl_util.h @@ -41,12 +41,13 @@ namespace datalog { class pentagon_relation; class relation_fact; class relation_signature; + class rule_manager; class verbose_action { unsigned m_lvl; class stopwatch* m_sw; public: - verbose_action(char const* msg, unsigned lvl = 1); + verbose_action(char const* msg, unsigned lvl = 11); ~verbose_action(); }; @@ -345,17 +346,19 @@ namespace datalog { class rule_counter : public var_counter { public: - rule_counter(bool stay_non_negative = true): var_counter(stay_non_negative) {} + rule_counter(){} void count_rule_vars(ast_manager & m, const rule * r, int coef = 1); unsigned get_max_rule_var(const rule& r); }; void del_rule(horn_subsume_model_converter* mc, rule& r); - void resolve_rule(replace_proof_converter* pc, rule const& r1, rule const& r2, unsigned idx, + void resolve_rule(rule_manager& rm, + replace_proof_converter* pc, rule const& r1, rule const& r2, unsigned idx, expr_ref_vector const& s1, expr_ref_vector const& s2, rule const& res); - void resolve_rule(rule const& r1, rule const& r2, unsigned idx, + void resolve_rule(rule_manager& rm, + rule const& r1, rule const& r2, unsigned idx, expr_ref_vector const& s1, expr_ref_vector const& s2, rule& res); model_converter* mk_skip_model_converter(); diff --git a/src/muz/base/fixedpoint_params.pyg b/src/muz/base/fixedpoint_params.pyg index 832e3329e..87fd4e2af 100644 --- a/src/muz/base/fixedpoint_params.pyg +++ b/src/muz/base/fixedpoint_params.pyg @@ -2,83 +2,147 @@ def_module_params('fixedpoint', description='fixedpoint parameters', export=True, params=(('timeout', UINT, UINT_MAX, 'set timeout'), - ('engine', SYMBOL, 'auto-config', 'Select: auto-config, datalog, pdr, bmc'), - ('default_table', SYMBOL, 'sparse', 'default table implementation: sparse, hashtable, bitvector, interval'), - ('default_relation', SYMBOL, 'pentagon', 'default relation implementation: external_relation, pentagon'), - ('generate_explanations', BOOL, False, '(DATALOG) produce explanations for produced facts when using the datalog engine'), - ('use_map_names', BOOL, True, "(DATALOG) use names from map files when displaying tuples"), - ('bit_blast', BOOL, False, '(PDR) bit-blast bit-vectors'), - ('explanations_on_relation_level', BOOL, False, '(DATALOG) if true, explanations are generated as history of each relation, rather than per fact (generate_explanations must be set to true for this option to have any effect)'), - ('magic_sets_for_queries', BOOL, False, "(DATALOG) magic set transformation will be used for queries"), - ('magic', BOOL, False, "perform symbolic magic set transformation"), - ('scale', BOOL, False, "add scaling variable to linear real arithemtic clauses"), - ('unbound_compressor', BOOL, True, "auxiliary relations will be introduced to avoid unbound variables in rule heads"), - ('similarity_compressor', BOOL, True, "(DATALOG) rules that differ only in values of constants will be merged into a single rule"), - ('similarity_compressor_threshold', UINT, 11, "(DATALOG) if similarity_compressor is on, this value determines how many similar rules there must be in order for them to be merged"), - ('all_or_nothing_deltas', BOOL, False, "(DATALOG) compile rules so that it is enough for the delta relation in union and widening operations to determine only whether the updated relation was modified or not"), - ('compile_with_widening', BOOL, False, "(DATALOG) widening will be used to compile recursive rules"), - ('eager_emptiness_checking', BOOL, True, "(DATALOG) emptiness of affected relations will be checked after each instruction, so that we may ommit unnecessary instructions"), - ('default_table_checked', BOOL, False, "if true, the detault table will be default_table inside a wrapper that checks that its results are the same as of default_table_checker table"), - ('default_table_checker', SYMBOL, 'null', "see default_table_checked"), - - - ('initial_restart_timeout', UINT, 0, "length of saturation run before the first restart (in ms), zero means no restarts"), - ('output_profile', BOOL, False, "determines whether profile informations should be output when outputting Datalog rules or instructions"), - ('inline_linear', BOOL, True, "try linear inlining method"), - ('inline_eager', BOOL, True, "try eager inlining of rules"), - ('inline_linear_branch', BOOL, False, "try linear inlining method with potential expansion"), - ('fix_unbound_vars', BOOL, False, "fix unbound variables in tail"), - ('output_tuples', BOOL, True, "determines whether tuples for output predicates should be output"), - ('print_with_fixedpoint_extensions', BOOL, True, "use SMT-LIB2 fixedpoint extensions, instead of pure SMT2, when printing rules"), - ('print_low_level_smt2', BOOL, False, "use (faster) low-level SMT2 printer (the printer is scalable but the result may not be as readable)"), - ('print_with_variable_declarations', BOOL, True, "use variable declarations when displaying rules (instead of attempting to use original names)"), - ('bfs_model_search', BOOL, True, "PDR: use BFS strategy for expanding model search"), - ('use_farkas', BOOL, True, "PDR: use lemma generator based on Farkas (for linear real arithmetic)"), - ('generate_proof_trace', BOOL, False, "PDR: trace for 'sat' answer as proof object"), - ('flexible_trace', BOOL, False, "PDR: allow PDR generate long counter-examples " - "by extending candidate trace within search area"), - ('unfold_rules', UINT, 0, "PDR: unfold rules statically using iterative squarring"), - ('use_model_generalizer', BOOL, False, "PDR: use model for backwards propagation (instead of symbolic simulation)"), - ('validate_result', BOOL, False, "PDR validate result (by proof checking or model checking)"), - ('simplify_formulas_pre', BOOL, False, "PDR: simplify derived formulas before inductive propagation"), - ('simplify_formulas_post', BOOL, False, "PDR: simplify derived formulas after inductive propagation"), - ('slice', BOOL, True, "PDR: simplify clause set using slicing"), - ('karr', BOOL, False, "Add linear invariants to clauses using Karr's method"), - ('quantify_arrays', BOOL, False, "create quantified Horn clauses from clauses with arrays"), - ('instantiate_quantifiers', BOOL, False, "instantiate quantified Horn clauses using E-matching heuristic"), - ('coalesce_rules', BOOL, False, "BMC: coalesce rules"), - ('use_multicore_generalizer', BOOL, False, "PDR: extract multiple cores for blocking states"), - ('use_inductive_generalizer', BOOL, True, "PDR: generalize lemmas using induction strengthening"), - ('use_arith_inductive_generalizer', BOOL, False, "PDR: generalize lemmas using arithmetic heuristics for induction strengthening"), - ('use_convex_closure_generalizer', BOOL, False, "PDR: generalize using convex closures of lemmas"), - ('use_convex_interior_generalizer', BOOL, False, "PDR: generalize using convex interiors of lemmas"), - ('cache_mode', UINT, 0, "PDR: use no (0), symbolic (1) or explicit cache (2) for model search"), - ('inductive_reachability_check', BOOL, False, "PDR: assume negation of the cube on the previous level when " - "checking for reachability (not only during cube weakening)"), - ('max_num_contexts', UINT, 500, "PDR: maximal number of contexts to create"), - ('try_minimize_core', BOOL, False, "PDR: try to reduce core size (before inductive minimization)"), - ('profile_timeout_milliseconds', UINT, 0, "instructions and rules that took less than the threshold will not be printed when printed the instruction/rule list"), - ('dbg_fpr_nonempty_relation_signature', BOOL, False, - "if true, finite_product_relation will attempt to avoid creating inner relation with empty signature " - "by putting in half of the table columns, if it would have been empty otherwise"), - ('print_answer', BOOL, False, 'print answer instance(s) to query'), - ('print_certificate', BOOL, False, 'print certificate for reachability or non-reachability'), - ('print_boogie_certificate', BOOL, False, 'print certificate for reachability or non-reachability using a format understood by Boogie'), - ('print_statistics', BOOL, False, 'print statistics'), - ('use_utvpi', BOOL, True, 'PDR: Enable UTVPI strategy'), - ('tab_selection', SYMBOL, 'weight', 'selection method for tabular strategy: weight (default), first, var-use'), - ('full_expand', BOOL, False, 'DUALITY: Fully expand derivation trees'), - ('no_conj', BOOL, False, 'DUALITY: No forced covering (conjectures)'), - ('feasible_edges', BOOL, True, 'DUALITY: Don\'t expand definitley infeasible edges'), - ('use_underapprox', BOOL, False, 'DUALITY: Use underapproximations'), - ('stratified_inlining', BOOL, False, 'DUALITY: Use stratified inlining'), - ('recursion_bound', UINT, UINT_MAX, 'DUALITY: Recursion bound for stratified inlining'), - ('profile', BOOL, False, 'DUALITY: profile run time'), - ('mbqi', BOOL, True, 'DUALITY: use model-based quantifier instantion'), - ('batch_expand', BOOL, False, 'DUALITY: use batch expansion'), - ('dump_aig', SYMBOL, '', 'Dump clauses in AIG text format (AAG) to the given file name'), - ('conjecture_file', STRING, '', 'DUALITY: save conjectures to file'), - ('enable_restarts', BOOL, False, 'DUALITY: enable restarts'), + ('engine', SYMBOL, 'auto-config', + 'Select: auto-config, datalog, duality, pdr, bmc'), + ('datalog.default_table', SYMBOL, 'sparse', + 'default table implementation: sparse, hashtable, bitvector, interval'), + ('datalog.default_relation', SYMBOL, 'pentagon', + 'default relation implementation: external_relation, pentagon'), + ('datalog.generate_explanations', BOOL, False, + 'produce explanations for produced facts when using the datalog engine'), + ('datalog.use_map_names', BOOL, True, + "use names from map files when displaying tuples"), + ('datalog.magic_sets_for_queries', BOOL, False, + "magic set transformation will be used for queries"), + ('datalog.explanations_on_relation_level', BOOL, False, + 'if true, explanations are generated as history of each relation, ' + + 'rather than per fact (generate_explanations must be set to true for ' + + 'this option to have any effect)'), + ('datalog.unbound_compressor', BOOL, True, + "auxiliary relations will be introduced to avoid unbound variables " + + "in rule heads"), + ('datalog.similarity_compressor', BOOL, True, + "rules that differ only in values of constants will be merged into " + + "a single rule"), + ('datalog.similarity_compressor_threshold', UINT, 11, + "if similarity_compressor is on, this value determines how many " + + "similar rules there must be in order for them to be merged"), + ('datalog.all_or_nothing_deltas', BOOL, False, + "compile rules so that it is enough for the delta relation in " + + "union and widening operations to determine only whether the " + + "updated relation was modified or not"), + ('datalog.compile_with_widening', BOOL, False, + "widening will be used to compile recursive rules"), + ('datalog.default_table_checked', BOOL, False, "if true, the detault " + + 'table will be default_table inside a wrapper that checks that its results ' + + 'are the same as of default_table_checker table'), + ('datalog.default_table_checker', SYMBOL, 'null', "see default_table_checked"), + ('datalog.check_relation',SYMBOL,'null', "name of default relation to check. " + + "operations on the default relation will be verified using SMT solving"), + ('datalog.initial_restart_timeout', UINT, 0, + "length of saturation run before the first restart (in ms), " + + "zero means no restarts"), + ('datalog.output_profile', BOOL, False, + "determines whether profile information should be " + + "output when outputting Datalog rules or instructions"), + ('datalog.print.tuples', BOOL, True, + "determines whether tuples for output predicates should be output"), + ('datalog.profile_timeout_milliseconds', UINT, 0, + "instructions and rules that took less than the threshold " + + "will not be printed when printed the instruction/rule list"), + ('datalog.dbg_fpr_nonempty_relation_signature', BOOL, False, + "if true, finite_product_relation will attempt to avoid creating " + + "inner relation with empty signature by putting in half of the " + + "table columns, if it would have been empty otherwise"), + ('duality.full_expand', BOOL, False, 'Fully expand derivation trees'), + ('duality.no_conj', BOOL, False, 'No forced covering (conjectures)'), + ('duality.feasible_edges', BOOL, True, + 'Don\'t expand definitley infeasible edges'), + ('duality.use_underapprox', BOOL, False, 'Use underapproximations'), + ('duality.stratified_inlining', BOOL, False, 'Use stratified inlining'), + ('duality.recursion_bound', UINT, UINT_MAX, + 'Recursion bound for stratified inlining'), + ('duality.profile', BOOL, False, 'profile run time'), + ('duality.mbqi', BOOL, True, 'use model-based quantifier instantion'), + ('duality.batch_expand', BOOL, False, 'use batch expansion'), + ('duality.conjecture_file', STRING, '', 'save conjectures to file'), + ('pdr.bfs_model_search', BOOL, True, + "use BFS strategy for expanding model search"), + ('pdr.farkas', BOOL, True, + "use lemma generator based on Farkas (for linear real arithmetic)"), + ('generate_proof_trace', BOOL, False, "trace for 'sat' answer as proof object"), + ('pdr.flexible_trace', BOOL, False, + "allow PDR generate long counter-examples " + + "by extending candidate trace within search area"), + ('pdr.use_model_generalizer', BOOL, False, + "use model for backwards propagation (instead of symbolic simulation)"), + ('pdr.validate_result', BOOL, False, + "validate result (by proof checking or model checking)"), + ('pdr.simplify_formulas_pre', BOOL, False, + "simplify derived formulas before inductive propagation"), + ('pdr.simplify_formulas_post', BOOL, False, + "simplify derived formulas after inductive propagation"), + ('pdr.use_multicore_generalizer', BOOL, False, + "extract multiple cores for blocking states"), + ('pdr.use_inductive_generalizer', BOOL, True, + "generalize lemmas using induction strengthening"), + ('pdr.use_arith_inductive_generalizer', BOOL, False, + "generalize lemmas using arithmetic heuristics for induction strengthening"), + ('pdr.use_convex_closure_generalizer', BOOL, False, + "generalize using convex closures of lemmas"), + ('pdr.use_convex_interior_generalizer', BOOL, False, + "generalize using convex interiors of lemmas"), + ('pdr.cache_mode', UINT, 0, "use no (0), symbolic (1) or explicit " + + "cache (2) for model search"), + ('pdr.inductive_reachability_check', BOOL, False, + "assume negation of the cube on the previous level when " + + "checking for reachability (not only during cube weakening)"), + ('pdr.max_num_contexts', UINT, 500, "maximal number of contexts to create"), + ('pdr.try_minimize_core', BOOL, False, + "try to reduce core size (before inductive minimization)"), + ('pdr.utvpi', BOOL, True, 'Enable UTVPI strategy'), + ('print.fixedpoint_extensions', BOOL, True, + "use SMT-LIB2 fixedpoint extensions, instead of pure SMT2, " + + "when printing rules"), + ('print.low_level_smt2', BOOL, False, + "use (faster) low-level SMT2 printer (the printer is scalable " + + "but the result may not be as readable)"), + ('print.with_variable_declarations', BOOL, True, + "use variable declarations when displaying rules " + + "(instead of attempting to use original names)"), + ('print.answer', BOOL, False, 'print answer instance(s) to query'), + ('print.certificate', BOOL, False, + 'print certificate for reachability or non-reachability'), + ('print.boogie_certificate', BOOL, False, + 'print certificate for reachability or non-reachability using a ' + + 'format understood by Boogie'), + ('print.statistics', BOOL, False, 'print statistics'), + ('print.aig', SYMBOL, '', + 'Dump clauses in AIG text format (AAG) to the given file name'), + ('tab.selection', SYMBOL, 'weight', + 'selection method for tabular strategy: weight (default), first, var-use'), + ('xform.bit_blast', BOOL, False, + 'bit-blast bit-vectors'), + ('xform.magic', BOOL, False, + "perform symbolic magic set transformation"), + ('xform.scale', BOOL, False, + "add scaling variable to linear real arithemtic clauses"), + ('xform.inline_linear', BOOL, True, "try linear inlining method"), + ('xform.inline_eager', BOOL, True, "try eager inlining of rules"), + ('xform.inline_linear_branch', BOOL, False, + "try linear inlining method with potential expansion"), + ('xform.fix_unbound_vars', BOOL, False, "fix unbound variables in tail"), + ('xform.unfold_rules', UINT, 0, + "unfold rules statically using iterative squarring"), + ('xform.slice', BOOL, True, "simplify clause set using slicing"), + ('xform.karr', BOOL, False, + "Add linear invariants to clauses using Karr's method"), + ('xform.quantify_arrays', BOOL, False, + "create quantified Horn clauses from clauses with arrays"), + ('xform.instantiate_quantifiers', BOOL, False, + "instantiate quantified Horn clauses using E-matching heuristic"), + ('xform.coalesce_rules', BOOL, False, "coalesce rules"), + ('duality.enable_restarts', BOOL, False, 'DUALITY: enable restarts'), )) diff --git a/src/muz/base/hnf.cpp b/src/muz/base/hnf.cpp index 9d6f3c1ab..a0dbe9518 100644 --- a/src/muz/base/hnf.cpp +++ b/src/muz/base/hnf.cpp @@ -58,6 +58,19 @@ Notes: #include"for_each_expr.h" class hnf::imp { + + class contains_predicate_proc { + imp const& m; + public: + struct found {}; + contains_predicate_proc(imp const& m): m(m) {} + void operator()(var * n) {} + void operator()(quantifier * n) {} + void operator()(app* n) { + if (m.is_predicate(n)) throw found(); + } + }; + ast_manager& m; bool m_produce_proofs; volatile bool m_cancel; @@ -73,6 +86,9 @@ class hnf::imp { func_decl_ref_vector m_fresh_predicates; expr_ref_vector m_body; proof_ref_vector m_defs; + contains_predicate_proc m_proc; + expr_free_vars m_free_vars; + ast_fast_mark1 m_mark1; public: @@ -87,13 +103,41 @@ public: m_qh(m), m_fresh_predicates(m), m_body(m), - m_defs(m) { + m_defs(m), + m_proc(*this) { + } + + bool is_horn(expr* n) { + expr* n1, *n2; + while (is_forall(n)) n = to_quantifier(n)->get_expr(); + if (m.is_implies(n, n1, n2) && is_predicate(n2)) { + app* a1 = to_app(n1); + if (m.is_and(a1)) { + for (unsigned i = 0; i < a1->get_num_args(); ++i) { + if (!is_predicate(a1->get_arg(i)) && + contains_predicate(a1->get_arg(i))) { + return false; + } + } + } + else if (!is_predicate(a1) && contains_predicate(a1)) { + return false; + } + return true; + } + + return false; } void operator()(expr * n, proof* p, expr_ref_vector& result, proof_ref_vector& ps) { + if (is_horn(n)) { + result.push_back(n); + ps.push_back(p); + return; + } expr_ref fml(m); proof_ref pr(m); m_todo.reset(); @@ -166,24 +210,13 @@ private: return m.is_bool(f->get_range()) && f->get_family_id() == null_family_id; } - class contains_predicate_proc { - imp const& m; - public: - struct found {}; - contains_predicate_proc(imp const& m): m(m) {} - void operator()(var * n) {} - void operator()(quantifier * n) {} - void operator()(app* n) { - if (m.is_predicate(n)) throw found(); - } - }; - - bool contains_predicate(expr* fml) const { - contains_predicate_proc proc(*this); + bool contains_predicate(expr* fml) { try { - quick_for_each_expr(proc, fml); + quick_for_each_expr(m_proc, m_mark1, fml); + m_mark1.reset(); } catch (contains_predicate_proc::found) { + m_mark1.reset(); return true; } return false; @@ -348,13 +381,13 @@ private: } app_ref mk_fresh_head(expr* e) { - ptr_vector sorts0, sorts1; - get_free_vars(e, sorts0); + ptr_vector sorts1; + m_free_vars(e); expr_ref_vector args(m); - for (unsigned i = 0; i < sorts0.size(); ++i) { - if (sorts0[i]) { - args.push_back(m.mk_var(i, sorts0[i])); - sorts1.push_back(sorts0[i]); + for (unsigned i = 0; i < m_free_vars.size(); ++i) { + if (m_free_vars[i]) { + args.push_back(m.mk_var(i, m_free_vars[i])); + sorts1.push_back(m_free_vars[i]); } } func_decl_ref f(m); diff --git a/src/muz/base/hnf.h b/src/muz/base/hnf.h index 37339540b..9dc7cccd9 100644 --- a/src/muz/base/hnf.h +++ b/src/muz/base/hnf.h @@ -1,37 +1,36 @@ -/*++ -Copyright (c) 2013 Microsoft Corporation - -Module Name: - - hnf.h - -Abstract: - - Horn normal form convertion. -Author: - - -Notes: - - Very similar to NNF. +/*-- + Module Name: + + hnf.h + + Abstract: + + Horn normal form convertion. + Author: + + + Notes: + + Very similar to NNF. + --*/ - + #ifndef _HNF_H_ #define _HNF_H_ - + #include"ast.h" #include"params.h" #include"defined_names.h" #include"proof_converter.h" - + class hnf { class imp; imp * m_imp; -public: + public: hnf(ast_manager & m); ~hnf(); - + void operator()(expr * n, // [IN] expression that should be put into Horn NF proof* p, // [IN] proof of n expr_ref_vector & rs, // [OUT] resultant (conjunction) of expressions @@ -45,5 +44,5 @@ public: void reset(); func_decl_ref_vector const& get_fresh_predicates(); }; - + #endif /* _HNF_H_ */ diff --git a/src/muz/base/rule_properties.cpp b/src/muz/base/rule_properties.cpp new file mode 100644 index 000000000..f5cac29e5 --- /dev/null +++ b/src/muz/base/rule_properties.cpp @@ -0,0 +1,189 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + rule_properties.cpp + +Abstract: + + Collect properties of rules. + +Author: + + Nikolaj Bjorner (nbjorner) 9-25-2014 + +Notes: + + +--*/ + +#include"expr_functors.h" +#include"rule_properties.h" +#include"dl_rule_set.h" +#include"for_each_expr.h" +#include"dl_context.h" + +using namespace datalog; +rule_properties::rule_properties(ast_manager & m, rule_manager& rm, context& ctx, i_expr_pred& p): + m(m), rm(rm), m_ctx(ctx), m_is_predicate(p), m_dt(m), m_dl(m), m_generate_proof(false) {} + +rule_properties::~rule_properties() {} + +void rule_properties::collect(rule_set const& rules) { + reset(); + rule_set::iterator it = rules.begin(), end = rules.end(); + expr_sparse_mark visited; + for (; it != end; ++it) { + rule* r = *it; + m_rule = r; + unsigned ut_size = r->get_uninterpreted_tail_size(); + unsigned t_size = r->get_tail_size(); + if (r->has_negation()) { + m_negative_rules.push_back(r); + } + for (unsigned i = ut_size; i < t_size; ++i) { + for_each_expr_core(*this, visited, r->get_tail(i)); + } + if (m_generate_proof && !r->get_proof()) { + rm.mk_rule_asserted_proof(*r); + } + } +} + +void rule_properties::check_quantifier_free() { + if (!m_quantifiers.empty()) { + quantifier* q = m_quantifiers.begin()->m_key; + rule* r = m_quantifiers.begin()->m_value; + std::stringstream stm; + stm << "cannot process quantifier in rule "; + r->display(m_ctx, stm); + throw default_exception(stm.str()); + } +} + +void rule_properties::check_for_negated_predicates() { + if (!m_negative_rules.empty()) { + rule* r = m_negative_rules[0]; + std::stringstream stm; + stm << "Rule contains negative predicate "; + r->display(m_ctx, stm); + throw default_exception(stm.str()); + } +} + + +void rule_properties::check_uninterpreted_free() { + if (!m_uninterp_funs.empty()) { + func_decl* f = m_uninterp_funs.begin()->m_key; + rule* r = m_uninterp_funs.begin()->m_value; + std::stringstream stm; + stm << "Uninterpreted '" + << f->get_name() + << "' in "; + r->display(m_ctx, stm); + throw default_exception(stm.str()); + } +} + +void rule_properties::check_nested_free() { + if (!m_interp_pred.empty()) { + std::stringstream stm; + rule* r = m_interp_pred[0]; + stm << "Rule contains nested predicates "; + r->display(m_ctx, stm); + throw default_exception(stm.str()); + + } +} + +void rule_properties::check_existential_tail() { + ast_mark visited; + ptr_vector todo, tocheck; + for (unsigned i = 0; i < m_interp_pred.size(); ++i) { + rule& r = *m_interp_pred[i]; + unsigned ut_size = r.get_uninterpreted_tail_size(); + unsigned t_size = r.get_tail_size(); + for (unsigned i = ut_size; i < t_size; ++i) { + todo.push_back(r.get_tail(i)); + } + } + context::contains_pred contains_p(m_ctx); + check_pred check_pred(contains_p, m); + + while (!todo.empty()) { + expr* e = todo.back(), *e1, *e2; + todo.pop_back(); + if (visited.is_marked(e)) { + continue; + } + visited.mark(e, true); + if (m_is_predicate(e)) { + } + else if (m.is_and(e) || m.is_or(e)) { + todo.append(to_app(e)->get_num_args(), to_app(e)->get_args()); + } + else if (m.is_implies(e, e1, e2)) { + tocheck.push_back(e1); + todo.push_back(e2); + } + else if (is_quantifier(e)) { + todo.push_back(to_quantifier(e)->get_expr()); + } + else if ((m.is_eq(e, e1, e2) || m.is_iff(e, e1, e2)) && + m.is_true(e1)) { + todo.push_back(e2); + } + else if ((m.is_eq(e, e1, e2) || m.is_iff(e, e1, e2)) && + m.is_true(e2)) { + todo.push_back(e1); + } + else { + tocheck.push_back(e); + } + } + for (unsigned i = 0; i < tocheck.size(); ++i) { + expr* e = tocheck[i]; + if (check_pred(e)) { + std::ostringstream out; + out << "recursive predicate " << mk_ismt2_pp(e, m) << " occurs nested in the body of a rule"; + throw default_exception(out.str()); + } + } +} + + +void rule_properties::insert(ptr_vector& rules, rule* r) { + if (rules.empty() || rules.back() != r) { + rules.push_back(r); + } +} + +void rule_properties::operator()(var* n) { } + +void rule_properties::operator()(quantifier* n) { + m_quantifiers.insert(n, m_rule); +} +void rule_properties::operator()(app* n) { + if (m_is_predicate(n)) { + insert(m_interp_pred, m_rule); + } + else if (is_uninterp(n) && !m_dl.is_rule_sort(n->get_decl()->get_range())) { + m_uninterp_funs.insert(n->get_decl(), m_rule); + } + else if (m_dt.is_accessor(n)) { + sort* s = m.get_sort(n->get_arg(0)); + SASSERT(m_dt.is_datatype(s)); + if (m_dt.get_datatype_constructors(s)->size() > 1) { + m_uninterp_funs.insert(n->get_decl(), m_rule); + } + } +} + +void rule_properties::reset() { + m_quantifiers.reset(); + m_uninterp_funs.reset(); + m_interp_pred.reset(); + m_negative_rules.reset(); +} + diff --git a/src/muz/base/rule_properties.h b/src/muz/base/rule_properties.h new file mode 100644 index 000000000..a16f63507 --- /dev/null +++ b/src/muz/base/rule_properties.h @@ -0,0 +1,61 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + rule_properties.h + +Abstract: + + Collect properties of rules. + +Author: + + Nikolaj Bjorner (nbjorner) 9-25-2014 + +Notes: + + +--*/ + +#ifndef _RULE_PROPERTIES_H_ +#define _RULE_PROPERTIES_H_ + +#include"ast.h" +#include"datatype_decl_plugin.h" +#include"dl_rule.h" + +namespace datalog { + class rule_properties { + ast_manager& m; + rule_manager& rm; + context& m_ctx; + i_expr_pred& m_is_predicate; + datatype_util m_dt; + dl_decl_util m_dl; + bool m_generate_proof; + rule* m_rule; + obj_map m_quantifiers; + obj_map m_uninterp_funs; + ptr_vector m_interp_pred; + ptr_vector m_negative_rules; + + void insert(ptr_vector& rules, rule* r); + public: + rule_properties(ast_manager & m, rule_manager& rm, context& ctx, i_expr_pred& is_predicate); + ~rule_properties(); + void set_generate_proof(bool generate_proof) { m_generate_proof = generate_proof; } + void collect(rule_set const& r); + void check_quantifier_free(); + void check_uninterpreted_free(); + void check_existential_tail(); + void check_for_negated_predicates(); + void check_nested_free(); + void operator()(var* n); + void operator()(quantifier* n); + void operator()(app* n); + void reset(); + }; +} + +#endif /* _RULE_PROPERTIES_H_ */ diff --git a/src/muz/bmc/dl_bmc_engine.cpp b/src/muz/bmc/dl_bmc_engine.cpp index 51b1a5295..57e4ba8cb 100644 --- a/src/muz/bmc/dl_bmc_engine.cpp +++ b/src/muz/bmc/dl_bmc_engine.cpp @@ -32,7 +32,6 @@ Revision History: #include "dl_transforms.h" #include "dl_mk_rule_inliner.h" #include "scoped_proof.h" -#include"fixedpoint_params.hpp" namespace datalog { @@ -297,7 +296,7 @@ namespace datalog { vector substs; expr_ref fml(m), concl(m); - r->to_formula(fml); + rm.to_formula(*r, fml); r2 = r; rm.substitute(r2, sub.size(), sub.c_ptr()); proof_ref p(m); @@ -307,7 +306,7 @@ namespace datalog { expr_ref_vector sub2 = unifier.get_rule_subst(*r2.get(), false); apply_subst(sub, sub2); unifier.apply(*r0.get(), 0, *r2.get(), r1); - r1->to_formula(concl); + rm.to_formula(*r1.get(), concl); scoped_proof _sp(m); p = r->get_proof(); @@ -324,7 +323,7 @@ namespace datalog { r0 = r1; } else { - r2->to_formula(concl); + rm.to_formula(*r, concl); scoped_proof _sp(m); p = r->get_proof(); if (!p) { @@ -488,7 +487,7 @@ namespace datalog { return proof_ref(0, m); } TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";); - + rule_manager& rm = b.m_ctx.get_rule_manager(); expr_ref prop_r(m), prop_v(m), fml(m), prop_body(m), tmp(m), body(m); expr_ref_vector args(m); proof_ref_vector prs(m); @@ -508,7 +507,7 @@ namespace datalog { } } SASSERT(r); - r->to_formula(fml); + rm.to_formula(*r, fml); IF_VERBOSE(1, verbose_stream() << mk_pp(fml, m) << "\n";); prs.push_back(r->get_proof()); unsigned sz = r->get_uninterpreted_tail_size(); @@ -624,11 +623,12 @@ namespace datalog { } expr_ref bind_vars(expr* e, expr* pat) { - ptr_vector vars, sorts; + ptr_vector sorts; svector names; expr_ref_vector binding(m), patterns(m); expr_ref tmp(m), head(m); - get_free_vars(e, vars); + expr_free_vars vars; + vars(e); for (unsigned i = 0; i < vars.size(); ++i) { if (vars[i]) { binding.push_back(m.mk_var(sorts.size(), vars[i])); @@ -1028,6 +1028,7 @@ namespace datalog { proof_ref get_proof(model_ref& md, app* trace, app* path) { datatype_util dtu(m); + rule_manager& rm = b.m_ctx.get_rule_manager(); sort* trace_sort = m.get_sort(trace); func_decl* p = m_sort2pred.find(trace_sort); datalog::rule_vector const& rules = b.m_rules.get_predicate_rules(p); @@ -1046,7 +1047,7 @@ namespace datalog { var_subst vs(m, false); mk_subst(*rules[i], path, trace, sub); - rules[i]->to_formula(fml); + rm.to_formula(*rules[i], fml); prs.push_back(rules[i]->get_proof()); unsigned sz = trace->get_num_args(); if (sub.empty() && sz == 0) { @@ -1219,7 +1220,7 @@ namespace datalog { vector substs; expr_ref fml(m), concl(m); - r->to_formula(fml); + rm.to_formula(*r, fml); r2 = r; rm.substitute(r2, sub.size(), sub.c_ptr()); proof_ref p(m); @@ -1237,7 +1238,7 @@ namespace datalog { expr_ref_vector sub2 = unifier.get_rule_subst(*r2.get(), false); apply_subst(sub, sub2); unifier.apply(*r0.get(), 0, *r2.get(), r1); - r1->to_formula(concl); + rm.to_formula(*r1.get(), concl); scoped_proof _sp(m); proof* premises[2] = { pr, p }; @@ -1250,7 +1251,7 @@ namespace datalog { r0 = r1; } else { - r2->to_formula(concl); + rm.to_formula(*r2.get(), concl); scoped_proof _sp(m); if (sub.empty()) { pr = p; @@ -1442,7 +1443,7 @@ namespace datalog { expr_ref bg_assertion = m_ctx.get_background_assertion(); apply_default_transformation(m_ctx); - if (m_ctx.get_params().slice()) { + if (m_ctx.xform_slice()) { datalog::rule_transformer transformer(m_ctx); datalog::mk_slice* slice = alloc(datalog::mk_slice, m_ctx); transformer.register_plugin(slice); @@ -1498,7 +1499,7 @@ namespace datalog { if (m_rules.get_rule(i)->get_uninterpreted_tail_size() > 1) { return false; } - if (m_rules.get_rule(i)->has_quantifiers()) { + if (m_rules.get_rule_manager().has_quantifiers(*m_rules.get_rule(i))) { return false; } } diff --git a/src/muz/clp/clp_context.cpp b/src/muz/clp/clp_context.cpp index 0cd08e5b3..2c66c3cd5 100644 --- a/src/muz/clp/clp_context.cpp +++ b/src/muz/clp/clp_context.cpp @@ -123,14 +123,14 @@ namespace datalog { } void ground(expr_ref& e) { - ptr_vector sorts; - get_free_vars(e, sorts); - if (m_ground.size() < sorts.size()) { - m_ground.resize(sorts.size()); + expr_free_vars fv; + fv(e); + if (m_ground.size() < fv.size()) { + m_ground.resize(fv.size()); } - for (unsigned i = 0; i < sorts.size(); ++i) { - if (sorts[i] && !m_ground[i].get()) { - m_ground[i] = m.mk_fresh_const("c",sorts[i]); + for (unsigned i = 0; i < fv.size(); ++i) { + if (fv[i] && !m_ground[i].get()) { + m_ground[i] = m.mk_fresh_const("c", fv[i]); } } m_var_subst(e, m_ground.size(), m_ground.c_ptr(), e); diff --git a/src/muz/ddnf/ddnf.cpp b/src/muz/ddnf/ddnf.cpp new file mode 100644 index 000000000..6c4f79f7c --- /dev/null +++ b/src/muz/ddnf/ddnf.cpp @@ -0,0 +1,793 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + ddnf.cpp + +Abstract: + + DDNF based engine. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-08-21 + +Revision History: + + - inherits from Nuno Lopes Hassel utilities + and Garvit Juniwal's DDNF engine. + +--*/ + +#include "ddnf.h" +#include "dl_rule_set.h" +#include "dl_context.h" +#include "scoped_proof.h" +#include "bv_decl_plugin.h" +#include "tbv.h" + +namespace datalog { + + class ddnf_mgr; + class ddnf_node; + typedef ref_vector ddnf_node_vector; + + class ddnf_node { + public: + + struct eq { + tbv_manager& m; + eq(tbv_manager& m):m(m) {} + bool operator()(ddnf_node* n1, ddnf_node* n2) const { + return m.equals(n1->get_tbv(), n2->get_tbv()); + } + }; + + struct hash { + tbv_manager& m; + hash(tbv_manager& m):m(m) {} + unsigned operator()(ddnf_node* n) const { + return m.hash(n->get_tbv()); + } + }; + + typedef ptr_hashtable ddnf_nodes; + private: + ddnf_mgr& m; + tbv_manager& tbvm; + tbv const& m_tbv; + ddnf_node_vector m_children; + unsigned m_refs; + unsigned m_id; + ddnf_node::hash m_hash; + ddnf_node::eq m_eq; + ddnf_nodes m_descendants; + + friend class ddnf_mgr; + + public: + ddnf_node(ddnf_mgr& m, tbv_manager& tbvm, tbv const& tbv, unsigned id): + m(m), + tbvm(tbvm), + m_tbv(tbv), + m_children(m), + m_refs(0), + m_id(id), + m_hash(tbvm), + m_eq(tbvm), + m_descendants(DEFAULT_HASHTABLE_INITIAL_CAPACITY, m_hash, m_eq) { + } + + ~ddnf_node() {} + + unsigned inc_ref() { + return ++m_refs; + } + + void dec_ref() { + SASSERT(m_refs > 0); + --m_refs; + if (m_refs == 0) { + dealloc(this); + } + } + + ddnf_nodes& descendants() { return m_descendants; } + + unsigned get_id() const { return m_id; } + + unsigned num_children() const { return m_children.size(); } + + ddnf_node* operator[](unsigned index) { return m_children[index].get(); } + + tbv const& get_tbv() const { return m_tbv; } + + void add_child(ddnf_node* n); + + void remove_child(ddnf_node* n); + + bool contains_child(ddnf_node* n) const; + + void display(std::ostream& out) const { + out << "node[" << get_id() << ": "; + tbvm.display(out, m_tbv); + for (unsigned i = 0; i < m_children.size(); ++i) { + out << " " << m_children[i]->get_id(); + } + out << "]"; + } + }; + + typedef ddnf_node::ddnf_nodes ddnf_nodes; + + + class ddnf_mgr { + unsigned m_num_bits; + ddnf_node* m_root; + ddnf_node_vector m_noderefs; + bool m_internalized; + tbv_manager m_tbv; + ddnf_node::hash m_hash; + ddnf_node::eq m_eq; + ddnf_nodes m_nodes; + public: + ddnf_mgr(unsigned n): m_num_bits(n), m_noderefs(*this), m_internalized(false), m_tbv(n), + m_hash(m_tbv), m_eq(m_tbv), + m_nodes(DEFAULT_HASHTABLE_INITIAL_CAPACITY, m_hash, m_eq) { + tbv* bX = m_tbv.allocateX(); + m_root = alloc(ddnf_node, *this, m_tbv, *bX, m_nodes.size()); + m_noderefs.push_back(m_root); + m_nodes.insert(m_root); + } + + ~ddnf_mgr() { + m_noderefs.reset(); + m_tbv.reset(); + } + + void inc_ref(ddnf_node* n) { + n->inc_ref(); + } + + void dec_ref(ddnf_node* n) { + n->dec_ref(); + } + + ddnf_node* insert(tbv const& t) { + SASSERT(!m_internalized); + ptr_vector new_tbvs; + new_tbvs.push_back(&t); + for (unsigned i = 0; i < new_tbvs.size(); ++i) { + tbv const& nt = *new_tbvs[i]; + if (contains(nt)) continue; + ddnf_node* n = alloc(ddnf_node, *this, m_tbv, nt, m_noderefs.size()); + m_noderefs.push_back(n); + m_nodes.insert(n); + insert(*m_root, n, new_tbvs); + } + return find(t); + } + + tbv* allocate(uint64 v, unsigned hi, unsigned lo) { + return m_tbv.allocate(v, hi, lo); + } + + + unsigned size() const { + return m_noderefs.size(); + } + + ddnf_nodes const& lookup(tbv const& t) { + internalize(); + return find(t)->descendants(); + } + + void display(std::ostream& out) const { + for (unsigned i = 0; i < m_noderefs.size(); ++i) { + m_noderefs[i]->display(out); + out << "\n"; + } + } + + private: + + ddnf_node* find(tbv const& t) { + ddnf_node dummy(*this, m_tbv, t, 0); + return *(m_nodes.find(&dummy)); + } + + bool contains(tbv const& t) { + ddnf_node dummy(*this, m_tbv, t, 0); + return m_nodes.contains(&dummy); + } + + void insert(ddnf_node& root, ddnf_node* new_n, ptr_vector& new_intersections) { + tbv const& new_tbv = new_n->get_tbv(); + + SASSERT(m_tbv.contains(root.get_tbv(), new_tbv)); + if (&root == new_n) return; + bool inserted = false; + for (unsigned i = 0; i < root.num_children(); ++i) { + ddnf_node& child = *(root[i]); + if (m_tbv.contains(child.get_tbv(), new_tbv)) { + inserted = true; + insert(child, new_n, new_intersections); + } + } + if (inserted) { + return; + } + ddnf_node_vector subset_children(*this); + tbv* intr = m_tbv.allocate(); + for (unsigned i = 0; i < root.num_children(); ++i) { + ddnf_node& child = *(root[i]); + // cannot be superset + SASSERT(!m_tbv.contains(child.get_tbv(),new_tbv)); + // checking for subset + if (m_tbv.contains(new_tbv, child.get_tbv())) { + subset_children.push_back(&child); + } + else if (m_tbv.intersect(child.get_tbv(), new_tbv, *intr)) { + // this means there is a non-full intersection + new_intersections.push_back(intr); + intr = m_tbv.allocate(); + } + } + m_tbv.deallocate(intr); + for (unsigned i = 0; i < subset_children.size(); ++i) { + root.remove_child(subset_children[i].get()); + new_n->add_child(subset_children[i].get()); + } + root.add_child(new_n); + } + + + void internalize() { + // populate maps (should be bit-sets) of decendants. + if (m_internalized) { + return; + } + ptr_vector todo; + todo.push_back(m_root); + svector done(m_noderefs.size(), false); + while (!todo.empty()) { + ddnf_node& n = *todo.back(); + if (done[n.get_id()]) { + todo.pop_back(); + continue; + } + unsigned sz = n.num_children(); + bool all_done = true; + for (unsigned i = 0; i < sz; ++i) { + ddnf_node* child = n[i]; + if (!done[child->get_id()]) { + all_done = false; + todo.push_back(child); + } + } + if (all_done) { + n.descendants().insert(&n); + for (unsigned i = 0; i < sz; ++i) { + ddnf_node* child = n[i]; + add_table(n.descendants(), child->descendants()); + } + done[n.get_id()] = true; + todo.pop_back(); + } + } + m_internalized = true; + } + + void add_table(ddnf_nodes& dst, ddnf_nodes const& src) { + ddnf_nodes::iterator it = src.begin(), end = src.end(); + for (; it != end; ++it) { + dst.insert(*it); + } + } + + }; + + void ddnf_node::add_child(ddnf_node* n) { + //SASSERT(!m_tbv.is_subset(n->m_tbv)); + m_children.push_back(n); + } + + void ddnf_node::remove_child(ddnf_node* n) { + m_children.erase(n); + } + + bool ddnf_node::contains_child(ddnf_node* n) const { + return m_children.contains(n); + } + + + class ddnfs { + u_map m_mgrs; + public: + ddnfs() {} + + ~ddnfs() { + u_map::iterator it = m_mgrs.begin(), end = m_mgrs.end(); + for (; it != end; ++it) { + dealloc(it->m_value); + } + } + + tbv* allocate(unsigned num_bits, uint64 v, unsigned hi, unsigned lo) { + return get(num_bits).allocate(v, hi, lo); + } + void insert(unsigned num_bits, tbv const& t) { + get(num_bits).insert(t); + } + + ddnf_mgr& get(unsigned num_bits) { + return *insert(num_bits); + } + + ddnf_nodes const& lookup(unsigned n, tbv const& t) const { + return m_mgrs.find(n)->lookup(t); + } + + void display(std::ostream& out) const { + u_map::iterator it = m_mgrs.begin(), end = m_mgrs.end(); + for (; it != end; ++it) { + it->m_value->display(out); + } + } + + private: + + ddnf_mgr* insert(unsigned n) { + ddnf_mgr* m = 0; + if (!m_mgrs.find(n, m)) { + m = alloc(ddnf_mgr, n); + m_mgrs.insert(n, m); + } + return m; + } + }; + + class ddnf::imp { + struct stats { + stats() { reset(); } + void reset() { memset(this, 0, sizeof(*this)); } + }; + + context& m_ctx; + ast_manager& m; + rule_manager& rm; + bv_util bv; + volatile bool m_cancel; + ptr_vector m_todo; + ast_mark m_visited1, m_visited2; + ddnfs m_ddnfs; + stats m_stats; + obj_map m_expr2tbv; + obj_map m_cache; + expr_ref_vector m_trail; + context m_inner_ctx; + + public: + imp(context& ctx): + m_ctx(ctx), + m(ctx.get_manager()), + rm(ctx.get_rule_manager()), + bv(m), + m_cancel(false), + m_trail(m), + m_inner_ctx(m, m_ctx.get_register_engine(), m_ctx.get_fparams()) + { + params_ref params; + params.set_sym("engine", symbol("datalog")); + m_inner_ctx.updt_params(params); + } + + ~imp() {} + + lbool query(expr* query) { + m_ctx.ensure_opened(); + rule_set& old_rules = m_ctx.get_rules(); + rm.mk_query(query, old_rules); + rule_set new_rules(m_ctx); + IF_VERBOSE(10, verbose_stream() << "(ddnf.preprocess)\n";); + if (!pre_process_rules(old_rules)) { + return l_undef; + } + IF_VERBOSE(10, verbose_stream() << "(ddnf.compile)\n";); + if (!compile_rules1(old_rules, new_rules)) { + return l_undef; + } + IF_VERBOSE(15, m_ddnfs.display(verbose_stream());); + + dump_rules(new_rules); + return l_undef; + + // return execute_rules(new_rules); + } + + void cancel() { + m_cancel = true; + m_inner_ctx.cancel(); + } + + void cleanup() { + m_cancel = false; + } + + void reset_statistics() { + m_stats.reset(); + } + + void collect_statistics(statistics& st) const { + } + + void display_certificate(std::ostream& out) const { + expr_ref ans = get_answer(); + out << mk_pp(ans, m) << "\n"; + } + + expr_ref get_answer() const { + UNREACHABLE(); + return expr_ref(m.mk_true(), m); + } + + private: + + proof_ref get_proof() const { + scoped_proof sp(m); + proof_ref pr(m); + return pr; + } + + bool pre_process_rules(rule_set const& rules) { + m_visited1.reset(); + m_todo.reset(); + m_cache.reset(); + m_expr2tbv.reset(); + datalog::rule_set::iterator it = rules.begin(); + datalog::rule_set::iterator end = rules.end(); + for (; it != end; ++it) { + if (!pre_process_rule(**it)) { + return false; + } + } + return true; + } + + bool pre_process_rule(rule const& r) { + // all predicates are monadic. + unsigned utsz = r.get_uninterpreted_tail_size(); + unsigned sz = r.get_tail_size(); + for (unsigned i = utsz; i < sz; ++i) { + m_todo.push_back(r.get_tail(i)); + } + if (process_todo()) { + return true; + } + else { + r.display(m_ctx, std::cout); + return false; + } + } + + bool process_todo() { + while (!m_todo.empty()) { + expr* e = m_todo.back(); + m_todo.pop_back(); + if (m_visited1.is_marked(e)) { + continue; + } + m_visited1.mark(e, true); + if (is_var(e)) { + continue; + } + if (is_quantifier(e)) { + return false; + } + if (m.is_and(e) || + m.is_or(e) || + m.is_iff(e) || + m.is_not(e) || + m.is_implies(e)) { + m_todo.append(to_app(e)->get_num_args(), to_app(e)->get_args()); + continue; + } + if (is_ground(e)) { + continue; + } + if (process_atomic(e)) { + continue; + } + IF_VERBOSE(0, verbose_stream() << "Could not handle: " << mk_pp(e, m) << "\n";); + return false; + } + return true; + } + + bool process_atomic(expr* e) { + expr* e1, *e2, *e3; + unsigned lo, hi; + + if (m.is_eq(e, e1, e2) && bv.is_bv(e1)) { + if (is_var(e1) && is_ground(e2)) { + return process_eq(e, to_var(e1), bv.get_bv_size(e1)-1, 0, e2); + } + if (is_var(e2) && is_ground(e1)) { + return process_eq(e, to_var(e2), bv.get_bv_size(e2)-1, 0, e1); + } + if (bv.is_extract(e1, lo, hi, e3) && is_var(e3) && is_ground(e2)) { + return process_eq(e, to_var(e3), hi, lo, e2); + } + if (bv.is_extract(e2, lo, hi, e3) && is_var(e3) && is_ground(e1)) { + return process_eq(e, to_var(e3), hi, lo, e1); + } + if (is_var(e1) && is_var(e2)) { + return true; + } + } + return false; + } + + bool process_eq(expr* e, var* v, unsigned hi, unsigned lo, expr* c) { + rational val; + unsigned sz_c; + unsigned sz_v = bv.get_bv_size(v); + if (!bv.is_numeral(c, val, sz_c)) { + return false; + } + if (!val.is_uint64()) { + return false; + } + // v[hi:lo] = val + tbv* tv = m_ddnfs.allocate(sz_v, val.get_uint64(), hi, lo); + m_ddnfs.insert(sz_v, *tv); + m_expr2tbv.insert(e, tv); + // std::cout << mk_pp(v, m) << " " << lo << " " << hi << " " << v << " " << tbv << "\n"; + return true; + } + + void init_ctx(rule_set& rules) { + m_inner_ctx.reset(); + func_decl_set const& predicates = m_ctx.get_predicates(); + for (func_decl_set::iterator fit = predicates.begin(); fit != predicates.end(); ++fit) { + m_inner_ctx.register_predicate(*fit, false); + } + m_inner_ctx.ensure_opened(); + m_inner_ctx.replace_rules(rules); + m_inner_ctx.close(); + } + + void dump_rules(rule_set& rules) { + init_ctx(rules); + m_inner_ctx.display_smt2(0, 0, std::cout); + } + + lbool execute_rules(rule_set& rules) { + init_ctx(rules); + + ptr_vector heads; + rule_set::decl2rules::iterator dit = rules.begin_grouped_rules(); + rule_set::decl2rules::iterator dend = rules.end_grouped_rules(); + for (; dit != dend; ++dit) { + heads.push_back(dit->m_key); + } + return m_inner_ctx.rel_query(heads.size(), heads.c_ptr()); + } + + bool compile_rules1(rule_set const& rules, rule_set& new_rules) { + datalog::rule_set::iterator it = rules.begin(); + datalog::rule_set::iterator end = rules.end(); + unsigned idx = 0; + for (; it != end; ++idx, ++it) { + if (!compile_rule1(**it, rules, new_rules)) { + return false; + } + } + return true; + } + + bool compile_rule1(rule& r, rule_set const& old_rules, rule_set& new_rules) { + app_ref head(m), pred(m); + app_ref_vector body(m); + expr_ref tmp(m); + compile_predicate(r.get_head(), head); + unsigned utsz = r.get_uninterpreted_tail_size(); + unsigned sz = r.get_tail_size(); + for (unsigned i = 0; i < utsz; ++i) { + compile_predicate(r.get_tail(i), pred); + body.push_back(pred); + } + for (unsigned i = utsz; i < sz; ++i) { + compile_expr(r.get_tail(i), tmp); + body.push_back(to_app(tmp)); + } + rule* r_new = rm.mk(head, body.size(), body.c_ptr(), 0, r.name(), false); + new_rules.add_rule(r_new); + IF_VERBOSE(20, r_new->display(m_ctx, verbose_stream());); + if (old_rules.is_output_predicate(r.get_decl())) { + new_rules.set_output_predicate(r_new->get_decl()); + } + return true; + } + + void compile_predicate(app* p, app_ref& result) { + sort_ref_vector domain(m); + func_decl* d = p->get_decl(); + SASSERT(d->get_family_id() == null_family_id); + for (unsigned i = 0; i < p->get_num_args(); ++i) { + domain.push_back(compile_sort(m.get_sort(p->get_arg(i)))); + } + func_decl_ref fn(m); + fn = m.mk_func_decl(d->get_name(), domain.size(), domain.c_ptr(), m.mk_bool_sort()); + m_ctx.register_predicate(fn, false); + expr_ref_vector args(m); + expr_ref tmp(m); + for (unsigned i = 0; i < p->get_num_args(); ++i) { + compile_expr(p->get_arg(i), tmp); + args.push_back(tmp); + } + result = m.mk_app(fn, args.size(), args.c_ptr()); + } + + void insert_cache(expr* e, expr* r) { + m_trail.push_back(r); + m_cache.insert(e, r); + } + + void compile_var(var* v, var_ref& result) { + expr* r; + if (m_cache.find(v, r)) { + result = to_var(r); + } + else { + unsigned idx = v->get_idx(); + result = m.mk_var(idx, compile_sort(v->get_sort())); + insert_cache(v, result); + } + } + + sort* compile_sort(sort* s) { + if (m.is_bool(s)) { + return s; + } + if (bv.is_bv_sort(s)) { + unsigned sz = bv.get_bv_size(s); + ddnf_mgr const& mgr = m_ddnfs.get(sz); + unsigned num_elems = mgr.size(); + unsigned nb = 1; + while ((1UL << nb) <= num_elems) { + ++nb; + } + return bv.mk_sort(nb); + } + UNREACHABLE(); + return 0; + } + + void compile_expr(expr* e, expr_ref& result) { + expr* r = 0; + if (m_cache.find(e, r)) { + result = r; + return; + } + + if (is_ground(e)) { + result = e; + m_cache.insert(e, result); + return; + } + + if (is_var(e)) { + var_ref w(m); + compile_var(to_var(e), w); + result = w; + return; + } + + if (m.is_and(e) || + m.is_or(e) || + m.is_iff(e) || + m.is_not(e) || + m.is_implies(e)) { + app* a = to_app(e); + expr_ref tmp(m); + expr_ref_vector args(m); + for (unsigned i = 0; i < a->get_num_args(); ++i) { + compile_expr(a->get_arg(i), tmp); + args.push_back(tmp); + } + result = m.mk_app(a->get_decl(), args.size(), args.c_ptr()); + insert_cache(e, result); + return; + } + + expr* e1, *e2, *e3; + unsigned lo, hi; + if (m.is_eq(e, e1, e2) && bv.is_bv(e1)) { + if (is_var(e1) && is_ground(e2)) { + compile_eq(e, result, to_var(e1), bv.get_bv_size(e1)-1, 0, e2); + } + else if (is_var(e2) && is_ground(e1)) { + compile_eq(e, result, to_var(e2), bv.get_bv_size(e2)-1, 0, e1); + } + else if (bv.is_extract(e1, lo, hi, e3) && is_var(e3) && is_ground(e2)) { + compile_eq(e, result, to_var(e3), hi, lo, e2); + } + else if (bv.is_extract(e2, lo, hi, e3) && is_var(e3) && is_ground(e1)) { + compile_eq(e, result, to_var(e3), hi, lo, e1); + } + else if (is_var(e1) && is_var(e2)) { + var_ref v1(m), v2(m); + compile_var(to_var(e1), v1); + compile_var(to_var(e2), v2); + result = m.mk_eq(v1, v2); + } + else { + UNREACHABLE(); + } + insert_cache(e, result); + return; + } + std::cout << mk_pp(e, m) << "\n"; + UNREACHABLE(); + } + + void compile_eq(expr* e, expr_ref& result, var* v, unsigned hi, unsigned lo, expr* c) { + tbv* t; + // TBD: hi, lo are ignored. + VERIFY(m_expr2tbv.find(e, t)); + var_ref w(m); + compile_var(v, w); + unsigned num_bits = bv.get_bv_size(c); + ddnf_nodes const& ns = m_ddnfs.lookup(num_bits, *t); + ddnf_nodes::iterator it = ns.begin(), end = ns.end(); + expr_ref_vector eqs(m); + sort* s = m.get_sort(w); + for (; it != end; ++it) { + eqs.push_back(m.mk_eq(w, bv.mk_numeral(rational((*it)->get_id()), s))); + } + switch (eqs.size()) { + case 0: + UNREACHABLE(); + result = m.mk_false(); + break; + case 1: + result = eqs[0].get(); + break; + default: + result = m.mk_or(eqs.size(), eqs.c_ptr()); + break; + } + } + }; + + ddnf::ddnf(context& ctx): + datalog::engine_base(ctx.get_manager(),"tabulation"), + m_imp(alloc(imp, ctx)) { + } + ddnf::~ddnf() { + dealloc(m_imp); + } + lbool ddnf::query(expr* query) { + return m_imp->query(query); + } + void ddnf::cancel() { + m_imp->cancel(); + } + void ddnf::cleanup() { + m_imp->cleanup(); + } + void ddnf::reset_statistics() { + m_imp->reset_statistics(); + } + void ddnf::collect_statistics(statistics& st) const { + m_imp->collect_statistics(st); + } + void ddnf::display_certificate(std::ostream& out) const { + m_imp->display_certificate(out); + } + expr_ref ddnf::get_answer() { + return m_imp->get_answer(); + } +}; diff --git a/src/muz/ddnf/ddnf.h b/src/muz/ddnf/ddnf.h new file mode 100644 index 000000000..8121dc090 --- /dev/null +++ b/src/muz/ddnf/ddnf.h @@ -0,0 +1,46 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + ddnf.h + +Abstract: + + DDNF based engine. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-08-21 + +Revision History: + +--*/ +#ifndef _DDNF__H_ +#define _DDNF__H_ + +#include "ast.h" +#include "lbool.h" +#include "statistics.h" +#include "dl_engine_base.h" + +namespace datalog { + class context; + + class ddnf : public engine_base { + class imp; + imp* m_imp; + public: + ddnf(context& ctx); + ~ddnf(); + virtual lbool query(expr* query); + virtual void cancel(); + virtual void cleanup(); + virtual void reset_statistics(); + virtual void collect_statistics(statistics& st) const; + virtual void display_certificate(std::ostream& out) const; + virtual expr_ref get_answer(); + }; +}; + +#endif diff --git a/src/muz/duality/duality_dl_interface.cpp b/src/muz/duality/duality_dl_interface.cpp index 7666b39cf..8ac98317d 100755 --- a/src/muz/duality/duality_dl_interface.cpp +++ b/src/muz/duality/duality_dl_interface.cpp @@ -148,7 +148,7 @@ lbool dl_interface::query(::expr * query) { // make a new problem and solver _d = alloc(duality_data,m_ctx.get_manager()); - _d->ctx.set("mbqi",m_ctx.get_params().mbqi()); + _d->ctx.set("mbqi",m_ctx.get_params().duality_mbqi()); _d->ls = alloc(RPFP::iZ3LogicSolver,_d->ctx); _d->rpfp = alloc(RPFP,_d->ls); @@ -185,7 +185,7 @@ lbool dl_interface::query(::expr * query) { unsigned nrules = rs.get_num_rules(); for(unsigned i = 0; i < nrules; i++){ expr_ref f(m_ctx.get_manager()); - rs.get_rule(i)->to_formula(f); + rm.to_formula(*rs.get_rule(i), f); rules.push_back(f); } } @@ -283,7 +283,7 @@ lbool dl_interface::query(::expr * query) { } } } - unsigned rb = m_ctx.get_params().recursion_bound(); + unsigned rb = m_ctx.get_params().duality_recursion_bound(); std::vector std_bounds; for(unsigned i = 0; i < bounds.size(); i++){ unsigned b = bounds[i]; @@ -307,14 +307,14 @@ lbool dl_interface::query(::expr * query) { // set its options IF_VERBOSE(1, rs->SetOption("report","1");); - rs->SetOption("full_expand",m_ctx.get_params().full_expand() ? "1" : "0"); - rs->SetOption("no_conj",m_ctx.get_params().no_conj() ? "1" : "0"); - rs->SetOption("feasible_edges",m_ctx.get_params().feasible_edges() ? "1" : "0"); - rs->SetOption("use_underapprox",m_ctx.get_params().use_underapprox() ? "1" : "0"); - rs->SetOption("stratified_inlining",m_ctx.get_params().stratified_inlining() ? "1" : "0"); - rs->SetOption("batch_expand",m_ctx.get_params().batch_expand() ? "1" : "0"); - rs->SetOption("conjecture_file",m_ctx.get_params().conjecture_file()); - rs->SetOption("enable_restarts",m_ctx.get_params().enable_restarts() ? "1" : "0"); + rs->SetOption("full_expand",m_ctx.get_params().duality_full_expand() ? "1" : "0"); + rs->SetOption("no_conj",m_ctx.get_params().duality_no_conj() ? "1" : "0"); + rs->SetOption("feasible_edges",m_ctx.get_params().duality_feasible_edges() ? "1" : "0"); + rs->SetOption("use_underapprox",m_ctx.get_params().duality_use_underapprox() ? "1" : "0"); + rs->SetOption("stratified_inlining",m_ctx.get_params().duality_stratified_inlining() ? "1" : "0"); + rs->SetOption("batch_expand",m_ctx.get_params().duality_batch_expand() ? "1" : "0"); + rs->SetOption("conjecture_file",m_ctx.get_params().duality_conjecture_file()); + rs->SetOption("enable_restarts",m_ctx.get_params().duality_enable_restarts() ? "1" : "0"); #if 0 if(rb != UINT_MAX){ std::ostringstream os; os << rb; @@ -336,7 +336,7 @@ lbool dl_interface::query(::expr * query) { // profile! - if(m_ctx.get_params().profile()) + if(m_ctx.get_params().duality_profile()) print_profile(std::cout); // save the result and counterexample if there is one diff --git a/src/muz/fp/datalog_parser.cpp b/src/muz/fp/datalog_parser.cpp index 830f6d078..1567dff4f 100644 --- a/src/muz/fp/datalog_parser.cpp +++ b/src/muz/fp/datalog_parser.cpp @@ -41,15 +41,12 @@ class line_reader { static const char s_delimiter = '\n'; static const unsigned s_expansion_step = 1024; -#if 0 - std::istream & m_stm; -#else FILE * m_file; -#endif svector m_data; bool m_eof; bool m_eof_behind_buffer; unsigned m_next_index; + bool m_ok; //actually by one larger than the actual size of m_data, //to fit in the terminating delimiter @@ -88,27 +85,17 @@ class line_reader { public: -#if 0 - line_reader(std::istream & stm) - : m_stm(stm), - m_eof(false), - m_eof_behind_buffer(false), - m_next_index(0), - m_data_size(0) { - m_data.resize(2*s_expansion_step); - resize_data(0); - } -#else line_reader(const char * fname) - :m_eof(false), - m_eof_behind_buffer(false), - m_next_index(0), - m_data_size(0) { + :m_eof(false), + m_eof_behind_buffer(false), + m_next_index(0), + m_data_size(0), + m_ok(true) { m_data.resize(2*s_expansion_step); resize_data(0); #if _WINDOWS errno_t err = fopen_s(&m_file, fname, "rb"); - SASSERT(err==0); + m_ok = err == 0; #else m_file = fopen(fname, "rb"); #endif @@ -116,7 +103,8 @@ public: ~line_reader() { fclose(m_file); } -#endif + + bool operator()() { return m_ok; } /** \brief Retrieve next line from the stream. @@ -170,6 +158,38 @@ public: bool eof() const { return m_eof; } }; +class char_reader { + line_reader m_line_reader; + char const* m_line; +public: + char_reader(char const* file): + m_line_reader(file), + m_line(0) + {} + + bool operator()() { return m_line_reader(); } + + char get() { + if (!m_line) { + if (m_line_reader.eof()) { + return EOF; + } + m_line = m_line_reader.get_line(); + } + if (!(m_line[0])) { + m_line = 0; + return '\n'; + } + char result = m_line[0]; + ++m_line; + return result; + } + + bool eof() { + return m_line_reader.eof(); + } +}; + class reserved_symbols { typedef map str2token; str2token m_str2token; @@ -200,6 +220,7 @@ public: class dlexer { std::istream* m_input; + char_reader* m_reader; char m_prev_char; char m_curr_char; int m_line; @@ -219,7 +240,12 @@ public: void next() { m_prev_char = m_curr_char; - m_curr_char = m_input->get(); + if (m_reader) { + m_curr_char = m_reader->get(); + } + else { + m_curr_char = m_input->get(); + } m_pos++; } @@ -234,6 +260,7 @@ public: dlexer(): m_input(0), + m_reader(0), m_prev_char(0), m_curr_char(0), m_line(1), @@ -242,8 +269,9 @@ public: m_parsing_domains(false) { } - void set_stream(std::istream& s) { - m_input = &s; + void set_stream(std::istream* s, char_reader* r) { + m_input = s; + m_reader = r; next(); } @@ -279,7 +307,10 @@ public: m_tok_pos = m_pos; next(); while (m_curr_char != '"') { - if (m_input->eof()) { + if (m_input && m_input->eof()) { + return TK_ERROR; + } + if (m_reader && m_reader->eof()) { return TK_ERROR; } if (m_curr_char == '\n') { @@ -431,7 +462,6 @@ protected: ast_manager& m_manager; dlexer* m_lexer; - ast_ref_vector m_pinned; region m_region; dl_decl_util & m_decl_util; arith_util m_arith; @@ -450,7 +480,6 @@ public: dparser(context& ctx, ast_manager& m): m_context(ctx), m_manager(m), - m_pinned(m), m_decl_util(ctx.get_decl_util()), m_arith(m), m_num_vars(0), @@ -460,17 +489,17 @@ public: virtual bool parse_file(char const * filename) { reset(); - if (filename != 0) { + if (filename != 0) { set_path(filename); - std::ifstream stream(filename); - if (!stream) { + char_reader reader(filename); + if (!reader()) { get_err() << "ERROR: could not open file '" << filename << "'.\n"; return false; } - return parse_stream(stream); + return parse_stream(0, &reader); } else { - return parse_stream(std::cin); + return parse_stream(&std::cin, 0); } } @@ -478,7 +507,7 @@ public: reset(); std::string s(string); std::istringstream is(s); - return parse_stream(is); + return parse_stream(&is, 0); } protected: @@ -486,7 +515,6 @@ protected: void reset() { m_num_vars = 0; m_sym_idx = 0; - m_pinned.reset(); m_vars.reset(); m_region.reset(); m_path.clear(); @@ -507,13 +535,13 @@ protected: return std::cerr; } - bool parse_stream(std::istream& is) { + bool parse_stream(std::istream* is, char_reader* r) { bool result = false; try { m_error=false; dlexer lexer; m_lexer = &lexer; - m_lexer->set_stream(is); + m_lexer->set_stream(is, r); dtoken tok = m_lexer->next_token(); tok = parse_domains(tok); tok = parse_decls(tok); @@ -741,7 +769,7 @@ protected: // dtoken parse_infix(dtoken tok1, char const* td, app_ref& pred) { symbol td1(td); - expr* v1 = 0, *v2 = 0; + expr_ref v1(m_manager), v2(m_manager); sort* s = 0; dtoken tok2 = m_lexer->next_token(); if (tok2 != TK_NEQ && tok2 != TK_GT && tok2 != TK_LT && tok2 != TK_EQ) { @@ -755,12 +783,16 @@ protected: symbol td2(td); if (tok1 == TK_ID) { - m_vars.find(td1.bare_str(), v1); + expr* _v1 = 0; + m_vars.find(td1.bare_str(), _v1); + v1 = _v1; } if (tok3 == TK_ID) { - m_vars.find(td2.bare_str(), v2); + expr* _v2 = 0; + m_vars.find(td2.bare_str(), _v2); + v2 = _v2; } - if (v1 == 0 && v2 == 0) { + if (!v1 && !v2) { return unexpected(tok3, "at least one argument should be a variable"); } if (v1) { @@ -963,10 +995,11 @@ protected: } dtoken parse_include(char const* filename, bool parsing_domain) { + IF_VERBOSE(2, verbose_stream() << "include: " << filename << "\n";); std::string path(m_path); path += filename; - std::ifstream stream(path.c_str()); - if (!stream) { + char_reader stream(path.c_str()); + if (!stream()) { get_err() << "ERROR: could not open file '" << path << "'.\n"; return TK_ERROR; } @@ -974,7 +1007,7 @@ protected: dlexer lexer; { flet lexer_let(m_lexer, &lexer); - m_lexer->set_stream(stream); + m_lexer->set_stream(0, &stream); tok = m_lexer->next_token(); if(parsing_domain) { tok = parse_domains(tok); @@ -990,15 +1023,16 @@ protected: dtoken parse_mapfile(dtoken tok, sort * s, char const* filename) { std::string path(m_path); path += filename; - std::ifstream stream(path.c_str()); - if (!stream) { + line_reader reader(path.c_str()); + + if (!reader()) { get_err() << "Warning: could not open file '" << path << "'.\n"; return m_lexer->next_token(); } std::string line; - while(read_line(stream, line)) { - symbol sym=symbol(line.c_str()); + while(!reader.eof()) { + symbol sym=symbol(reader.get_line()); m_context.get_constant_number(s, sym); } return m_lexer->next_token(); @@ -1018,10 +1052,6 @@ protected: } void add_rule(app* head, unsigned sz, app* const* body, const bool * is_neg) { - m_pinned.push_back(head); - for (unsigned i = 0; i < sz; ++i) { - m_pinned.push_back(body[i]); - } rule_manager& m = m_context.get_rule_manager(); if(sz==0 && m.is_fact(head)) { @@ -1075,7 +1105,6 @@ protected: unsigned idx = m_context.get_constant_number(s, name); res = m_decl_util.mk_numeral(idx, s); } - m_pinned.push_back(res); return res; } /** @@ -1090,13 +1119,11 @@ protected: unsigned idx = m_context.get_constant_number(s, symbol(to_string(el).c_str())); res = m_decl_util.mk_numeral(idx, s); } - m_pinned.push_back(res); return res; } app* mk_const(uint64 el, sort* s) { unsigned idx = m_context.get_constant_number(s, el); app * res = m_decl_util.mk_numeral(idx, s); - m_pinned.push_back(res); return res; } @@ -1278,7 +1305,7 @@ private: dlexer lexer; m_lexer = &lexer; - m_lexer->set_stream(stm); + m_lexer->set_stream(&stm, 0); dtoken tok = m_lexer->next_token(); tok = parse_decls(tok); m_lexer = 0; diff --git a/src/muz/fp/dl_cmds.cpp b/src/muz/fp/dl_cmds.cpp index e2e3680cc..7a98fdeec 100644 --- a/src/muz/fp/dl_cmds.cpp +++ b/src/muz/fp/dl_cmds.cpp @@ -103,7 +103,7 @@ struct dl_context { void add_rule(expr * rule, symbol const& name, unsigned bound) { init(); if (m_collected_cmds) { - expr_ref rl = m_context->bind_variables(rule, true); + expr_ref rl = m_context->bind_vars(rule, true); m_collected_cmds->m_rules.push_back(rl); m_collected_cmds->m_names.push_back(name); m_trail.push(push_back_vector(m_collected_cmds->m_rules)); @@ -116,7 +116,7 @@ struct dl_context { bool collect_query(expr* q) { if (m_collected_cmds) { - expr_ref qr = m_context->bind_variables(q, false); + expr_ref qr = m_context->bind_vars(q, false); m_collected_cmds->m_queries.push_back(qr); m_trail.push(push_back_vector(m_collected_cmds->m_queries)); return true; @@ -234,6 +234,7 @@ public: bool query_exn = false; lbool status = l_undef; { + IF_VERBOSE(10, verbose_stream() << "(query)\n";); scoped_ctrl_c ctrlc(eh); scoped_timer timer(timeout, &eh); cmd_context::scoped_watch sw(ctx); diff --git a/src/muz/fp/dl_register_engine.cpp b/src/muz/fp/dl_register_engine.cpp index 57413b7cb..6e1ba40ce 100644 --- a/src/muz/fp/dl_register_engine.cpp +++ b/src/muz/fp/dl_register_engine.cpp @@ -22,6 +22,7 @@ Revision History: #include "tab_context.h" #include "rel_context.h" #include "pdr_dl_interface.h" +#include "ddnf.h" #include "duality_dl_interface.h" namespace datalog { @@ -43,6 +44,8 @@ namespace datalog { return alloc(clp, *m_ctx); case DUALITY_ENGINE: return alloc(Duality::dl_interface, *m_ctx); + case DDNF_ENGINE: + return alloc(ddnf, *m_ctx); case LAST_ENGINE: UNREACHABLE(); return 0; diff --git a/src/muz/fp/horn_tactic.cpp b/src/muz/fp/horn_tactic.cpp index 0c094c277..6032b3f02 100644 --- a/src/muz/fp/horn_tactic.cpp +++ b/src/muz/fp/horn_tactic.cpp @@ -190,7 +190,7 @@ class horn_tactic : public tactic { bool produce_proofs = g->proofs_enabled(); if (produce_proofs) { - if (!m_ctx.get_params().generate_proof_trace()) { + if (!m_ctx.generate_proof_trace()) { params_ref params = m_ctx.get_params().p; params.set_bool("generate_proof_trace", true); updt_params(params); @@ -316,7 +316,7 @@ class horn_tactic : public tactic { m_ctx.get_rules(); // flush adding rules. apply_default_transformation(m_ctx); - if (m_ctx.get_params().slice()) { + if (m_ctx.xform_slice()) { datalog::rule_transformer transformer(m_ctx); datalog::mk_slice* slice = alloc(datalog::mk_slice, m_ctx); transformer.register_plugin(slice); @@ -334,7 +334,7 @@ class horn_tactic : public tactic { datalog::rule_set::iterator it = rules.begin(), end = rules.end(); for (; it != end; ++it) { datalog::rule* r = *it; - r->to_formula(fml); + m_ctx.get_rule_manager().to_formula(*r, fml); (*rep)(fml); g->assert_expr(fml); } diff --git a/src/muz/pdr/pdr_context.cpp b/src/muz/pdr/pdr_context.cpp index a1f3af401..042806d44 100644 --- a/src/muz/pdr/pdr_context.cpp +++ b/src/muz/pdr/pdr_context.cpp @@ -47,6 +47,8 @@ Notes: #include "dl_boogie_proof.h" #include "qe_util.h" #include "scoped_proof.h" +#include "blast_term_ite_tactic.h" +#include "model_implicant.h" #include "expr_safe_replace.h" namespace pdr { @@ -78,9 +80,9 @@ namespace pdr { pred_transformer::pred_transformer(context& ctx, manager& pm, func_decl* head): pm(pm), m(pm.get_manager()), ctx(ctx), m_head(head, m), - m_sig(m), m_solver(pm, ctx.get_params(), head->get_name()), + m_sig(m), m_solver(pm, ctx.get_params().pdr_try_minimize_core(), head->get_name()), m_invariants(m), m_transition(m), m_initial_state(m), - m_reachable(pm, (datalog::PDR_CACHE_MODE)ctx.get_params().cache_mode()) {} + m_reachable(pm, (datalog::PDR_CACHE_MODE)ctx.get_params().pdr_cache_mode()) {} pred_transformer::~pred_transformer() { rule2inst::iterator it2 = m_rule2inst.begin(), end2 = m_rule2inst.end(); @@ -95,8 +97,9 @@ namespace pdr { std::ostream& pred_transformer::display(std::ostream& out) const { if (!rules().empty()) out << "rules\n"; + datalog::rule_manager& rm = ctx.get_context().get_rule_manager(); for (unsigned i = 0; i < rules().size(); ++i) { - rules()[i]->display_smt2(m, out) << "\n"; + rm.display_smt2(*rules()[i], out) << "\n"; } out << "transition\n" << mk_pp(transition(), m) << "\n"; return out; @@ -147,12 +150,13 @@ namespace pdr { } datalog::rule const& pred_transformer::find_rule(model_core const& model) const { + datalog::rule_manager& rm = ctx.get_context().get_rule_manager(); obj_map::iterator it = m_tag2rule.begin(), end = m_tag2rule.end(); TRACE("pdr_verbose", for (; it != end; ++it) { expr* pred = it->m_key; tout << mk_pp(pred, m) << ":\n"; - if (it->m_value) it->m_value->display_smt2(m, tout) << "\n"; + if (it->m_value) rm.display_smt2(*it->m_value, tout) << "\n"; } ); @@ -602,7 +606,7 @@ namespace pdr { th_rewriter rw(m); rw(fml); if (ctx.is_dl() || ctx.is_utvpi()) { - hoist_non_bool_if(fml); + blast_term_ite(fml); } TRACE("pdr", tout << mk_pp(fml, m) << "\n";); SASSERT(is_ground(fml)); @@ -637,14 +641,14 @@ namespace pdr { // create constants for free variables in tail. void pred_transformer::ground_free_vars(expr* e, app_ref_vector& vars, ptr_vector& aux_vars) { - ptr_vector sorts; - get_free_vars(e, sorts); - while (vars.size() < sorts.size()) { + expr_free_vars fv; + fv(e); + while (vars.size() < fv.size()) { vars.push_back(0); } - for (unsigned i = 0; i < sorts.size(); ++i) { - if (sorts[i] && !vars[i].get()) { - vars[i] = m.mk_fresh_const("aux", sorts[i]); + for (unsigned i = 0; i < fv.size(); ++i) { + if (fv[i] && !vars[i].get()) { + vars[i] = m.mk_fresh_const("aux", fv[i]); aux_vars.push_back(vars[i].get()); } } @@ -984,6 +988,9 @@ namespace pdr { if (n->get_model_ptr()) { models.insert(n->state(), n->get_model_ptr()); rules.insert(n->state(), n->get_rule()); + pred_transformer& pt = n->pt(); + context& ctx = pt.get_context(); + datalog::context& dctx = ctx.get_context(); } todo.pop_back(); todo.append(n->children().size(), n->children().c_ptr()); @@ -994,12 +1001,18 @@ namespace pdr { model_node* n = todo.back(); model* md = 0; ast_manager& m = n->pt().get_manager(); - if (!n->get_model_ptr() && models.find(n->state(), md)) { - TRACE("pdr", tout << mk_pp(n->state(), m) << "\n";); - model_ref mr(md); - n->set_model(mr); - datalog::rule const* rule = rules.find(n->state()); - n->set_rule(rule); + if (!n->get_model_ptr()) { + if (models.find(n->state(), md)) { + TRACE("pdr", tout << mk_pp(n->state(), m) << "\n";); + model_ref mr(md); + n->set_model(mr); + datalog::rule const* rule = rules.find(n->state()); + n->set_rule(rule); + } + else { + IF_VERBOSE(1, n->display(verbose_stream() << "no model:\n", 0); + verbose_stream() << mk_pp(n->state(), m) << "\n";); + } } todo.pop_back(); todo.append(n->children().size(), n->children().c_ptr()); @@ -1086,7 +1099,6 @@ namespace pdr { children.append(n->children()); } - expr_safe_replace repl(m); for (unsigned i = 0; i < constraints.size(); ++i) { expr* e = constraints[i].get(), *e1, *e2; @@ -1216,7 +1228,7 @@ namespace pdr { } expr_ref fml_concl(m); - reduced_rule->to_formula(fml_concl); + rm.to_formula(*reduced_rule.get(), fml_concl); p1 = m.mk_hyper_resolve(pfs.size(), pfs.c_ptr(), fml_concl, positions, substs); } @@ -1271,10 +1283,10 @@ namespace pdr { m_params(params), m(m), m_context(0), - m_pm(m_fparams, params.max_num_contexts(), m), + m_pm(m_fparams, params.pdr_max_num_contexts(), m), m_query_pred(m), m_query(0), - m_search(m_params.bfs_model_search()), + m_search(m_params.pdr_bfs_model_search()), m_last_result(l_undef), m_inductive_lvl(0), m_expanded_lvl(0), @@ -1502,93 +1514,106 @@ namespace pdr { } } }; - - void context::validate() { - if (!m_params.validate_result()) { - return; - } + + void context::validate_proof() { std::stringstream msg; - - switch(m_last_result) { - case l_true: { - proof_ref pr = get_proof(); - proof_checker checker(m); - expr_ref_vector side_conditions(m); - bool ok = checker.check(pr, side_conditions); - if (!ok) { - msg << "proof validation failed"; + proof_ref pr = get_proof(); + proof_checker checker(m); + expr_ref_vector side_conditions(m); + bool ok = checker.check(pr, side_conditions); + if (!ok) { + msg << "proof validation failed"; + IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";); + throw default_exception(msg.str()); + } + for (unsigned i = 0; i < side_conditions.size(); ++i) { + expr* cond = side_conditions[i].get(); + expr_ref tmp(m); + + tmp = m.mk_not(cond); + IF_VERBOSE(2, verbose_stream() << "checking side-condition:\n" << mk_pp(cond, m) << "\n";); + smt::kernel solver(m, get_fparams()); + solver.assert_expr(tmp); + lbool res = solver.check(); + if (res != l_false) { + msg << "rule validation failed when checking: " << mk_pp(cond, m); IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";); throw default_exception(msg.str()); - } - for (unsigned i = 0; i < side_conditions.size(); ++i) { - expr* cond = side_conditions[i].get(); - expr_ref tmp(m); - tmp = m.mk_not(cond); - IF_VERBOSE(2, verbose_stream() << "checking side-condition:\n" << mk_pp(cond, m) << "\n";); + } + } + } + + void context::validate_search() { + expr_ref tr = m_search.get_trace(*this); + // TBD: tr << "\n"; + } + + void context::validate_model() { + std::stringstream msg; + expr_ref_vector refs(m); + expr_ref tmp(m); + model_ref model; + vector rs; + model_converter_ref mc; + get_level_property(m_inductive_lvl, refs, rs); + inductive_property ex(m, mc, rs); + ex.to_model(model); + decl2rel::iterator it = m_rels.begin(), end = m_rels.end(); + var_subst vs(m, false); + expr_free_vars fv; + for (; it != end; ++it) { + ptr_vector const& rules = it->m_value->rules(); + for (unsigned i = 0; i < rules.size(); ++i) { + datalog::rule& r = *rules[i]; + model->eval(r.get_head(), tmp); + expr_ref_vector fmls(m); + fmls.push_back(m.mk_not(tmp)); + unsigned utsz = r.get_uninterpreted_tail_size(); + unsigned tsz = r.get_tail_size(); + for (unsigned j = 0; j < utsz; ++j) { + model->eval(r.get_tail(j), tmp); + fmls.push_back(tmp); + } + for (unsigned j = utsz; j < tsz; ++j) { + fmls.push_back(r.get_tail(j)); + } + tmp = m.mk_and(fmls.size(), fmls.c_ptr()); + svector names; + fv(tmp); + fv.set_default_sort(m.mk_bool_sort()); + for (unsigned i = 0; i < fv.size(); ++i) { + names.push_back(symbol(i)); + } + fv.reverse(); + if (!fv.empty()) { + tmp = m.mk_exists(fv.size(), fv.c_ptr(), names.c_ptr(), tmp); + } smt::kernel solver(m, get_fparams()); solver.assert_expr(tmp); lbool res = solver.check(); if (res != l_false) { - msg << "rule validation failed when checking: " << mk_pp(cond, m); + msg << "rule validation failed when checking: " << mk_pp(tmp, m); IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";); throw default_exception(msg.str()); - } - } - break; - } - case l_false: { - expr_ref_vector refs(m); - expr_ref tmp(m); - model_ref model; - vector rs; - model_converter_ref mc; - get_level_property(m_inductive_lvl, refs, rs); - inductive_property ex(m, mc, rs); - ex.to_model(model); - decl2rel::iterator it = m_rels.begin(), end = m_rels.end(); - var_subst vs(m, false); - for (; it != end; ++it) { - ptr_vector const& rules = it->m_value->rules(); - for (unsigned i = 0; i < rules.size(); ++i) { - datalog::rule& r = *rules[i]; - model->eval(r.get_head(), tmp); - expr_ref_vector fmls(m); - fmls.push_back(m.mk_not(tmp)); - unsigned utsz = r.get_uninterpreted_tail_size(); - unsigned tsz = r.get_tail_size(); - for (unsigned j = 0; j < utsz; ++j) { - model->eval(r.get_tail(j), tmp); - fmls.push_back(tmp); - } - for (unsigned j = utsz; j < tsz; ++j) { - fmls.push_back(r.get_tail(j)); - } - tmp = m.mk_and(fmls.size(), fmls.c_ptr()); - ptr_vector sorts; - svector names; - get_free_vars(tmp, sorts); - for (unsigned i = 0; i < sorts.size(); ++i) { - if (!sorts[i]) { - sorts[i] = m.mk_bool_sort(); - } - names.push_back(symbol(i)); - } - sorts.reverse(); - if (!sorts.empty()) { - tmp = m.mk_exists(sorts.size(), sorts.c_ptr(), names.c_ptr(), tmp); - } - smt::kernel solver(m, get_fparams()); - solver.assert_expr(tmp); - lbool res = solver.check(); - if (res != l_false) { - msg << "rule validation failed when checking: " << mk_pp(tmp, m); - IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";); - throw default_exception(msg.str()); - } } } - break; } + } + + void context::validate() { + if (!m_params.pdr_validate_result()) { + return; + } + switch(m_last_result) { + case l_true: + if (m_params.generate_proof_trace()) { + validate_proof(); + } + validate_search(); + break; + case l_false: + validate_model(); + break; default: break; } @@ -1602,7 +1627,7 @@ namespace pdr { void context::init_core_generalizers(datalog::rule_set& rules) { reset_core_generalizers(); classifier_proc classify(m, rules); - bool use_mc = m_params.use_multicore_generalizer(); + bool use_mc = m_params.pdr_use_multicore_generalizer(); if (use_mc) { m_core_generalizers.push_back(alloc(core_multi_generalizer, *this, 0)); } @@ -1612,9 +1637,9 @@ namespace pdr { m_fparams.m_arith_auto_config_simplex = true; m_fparams.m_arith_propagate_eqs = false; m_fparams.m_arith_eager_eq_axioms = false; - if (m_params.use_utvpi() && - !m_params.use_convex_closure_generalizer() && - !m_params.use_convex_interior_generalizer()) { + if (m_params.pdr_utvpi() && + !m_params.pdr_use_convex_closure_generalizer() && + !m_params.pdr_use_convex_interior_generalizer()) { if (classify.is_dl()) { m_fparams.m_arith_mode = AS_DIFF_LOGIC; m_fparams.m_arith_expand_eqs = true; @@ -1626,19 +1651,19 @@ namespace pdr { } } } - if (m_params.use_convex_closure_generalizer()) { + if (m_params.pdr_use_convex_closure_generalizer()) { m_core_generalizers.push_back(alloc(core_convex_hull_generalizer, *this, true)); } - if (m_params.use_convex_interior_generalizer()) { + if (m_params.pdr_use_convex_interior_generalizer()) { m_core_generalizers.push_back(alloc(core_convex_hull_generalizer, *this, false)); } - if (!use_mc && m_params.use_inductive_generalizer()) { + if (!use_mc && m_params.pdr_use_inductive_generalizer()) { m_core_generalizers.push_back(alloc(core_bool_inductive_generalizer, *this, 0)); } - if (m_params.inductive_reachability_check()) { + if (m_params.pdr_inductive_reachability_check()) { m_core_generalizers.push_back(alloc(core_induction_generalizer, *this)); } - if (m_params.use_arith_inductive_generalizer()) { + if (m_params.pdr_use_arith_inductive_generalizer()) { m_core_generalizers.push_back(alloc(core_arith_inductive_generalizer, *this)); } @@ -1856,7 +1881,7 @@ namespace pdr { m_expanded_lvl = n.level(); } - pred_transformer::scoped_farkas sf (n.pt(), m_params.use_farkas()); + pred_transformer::scoped_farkas sf (n.pt(), m_params.pdr_farkas()); if (n.pt().is_reachable(n.state())) { TRACE("pdr", tout << "reachable\n";); close_node(n); @@ -1897,7 +1922,7 @@ namespace pdr { n.pt().add_property(ncore, uses_level?n.level():infty_level); } CASSERT("pdr",n.level() == 0 || check_invariant(n.level()-1)); - m_search.backtrack_level(!found_invariant && m_params.flexible_trace(), n); + m_search.backtrack_level(!found_invariant && m_params.pdr_flexible_trace(), n); break; } case l_undef: { @@ -1924,7 +1949,7 @@ namespace pdr { } void context::propagate(unsigned max_prop_lvl) { - if (m_params.simplify_formulas_pre()) { + if (m_params.pdr_simplify_formulas_pre()) { simplify_formulas(); } for (unsigned lvl = m_expanded_lvl; lvl <= max_prop_lvl; lvl++) { @@ -1943,7 +1968,7 @@ namespace pdr { throw inductive_exception(); } } - if (m_params.simplify_formulas_post()) { + if (m_params.pdr_simplify_formulas_post()) { simplify_formulas(); } } @@ -1991,16 +2016,18 @@ namespace pdr { */ void context::create_children(model_node& n) { SASSERT(n.level() > 0); - bool use_model_generalizer = m_params.use_model_generalizer(); + bool use_model_generalizer = m_params.pdr_use_model_generalizer(); scoped_no_proof _sc(m); pred_transformer& pt = n.pt(); model_ref M = n.get_model_ptr(); + SASSERT(M.get()); datalog::rule const& r = pt.find_rule(*M); expr* T = pt.get_transition(r); expr* phi = n.state(); n.set_rule(&r); + TRACE("pdr", tout << "Model:\n"; @@ -2009,7 +2036,7 @@ namespace pdr { tout << "Transition:\n" << mk_pp(T, m) << "\n"; tout << "Phi:\n" << mk_pp(phi, m) << "\n";); - model_evaluator mev(m); + model_implicant mev(m); expr_ref_vector mdl(m), forms(m), Phi(m); forms.push_back(T); forms.push_back(phi); diff --git a/src/muz/pdr/pdr_context.h b/src/muz/pdr/pdr_context.h index e21f46412..44fba03d8 100644 --- a/src/muz/pdr/pdr_context.h +++ b/src/muz/pdr/pdr_context.h @@ -124,6 +124,7 @@ namespace pdr { unsigned get_num_levels() { return m_levels.size(); } expr_ref get_cover_delta(func_decl* p_orig, int level); void add_cover(unsigned level, expr* property); + context& get_context() { return ctx; } std::ostream& display(std::ostream& strm) const; @@ -249,7 +250,6 @@ namespace pdr { model_node* m_root; std::deque m_leaves; vector > m_cache; - obj_map& cache(model_node const& n); void erase_children(model_node& n, bool backtrack); void erase_leaf(model_node& n); @@ -269,7 +269,7 @@ namespace pdr { void set_root(model_node* n); model_node& get_root() const { return *m_root; } std::ostream& display(std::ostream& out) const; - expr_ref get_trace(context const& ctx); + expr_ref get_trace(context const& ctx); proof_ref get_proof_trace(context const& ctx); void backtrack_level(bool uses_level, model_node& n); }; @@ -357,6 +357,9 @@ namespace pdr { void reset_core_generalizers(); void validate(); + void validate_proof(); + void validate_search(); + void validate_model(); public: diff --git a/src/muz/pdr/pdr_dl_interface.cpp b/src/muz/pdr/pdr_dl_interface.cpp index 45872fe99..b75be70c1 100644 --- a/src/muz/pdr/pdr_dl_interface.cpp +++ b/src/muz/pdr/pdr_dl_interface.cpp @@ -105,7 +105,7 @@ lbool dl_interface::query(expr * query) { apply_default_transformation(m_ctx); - if (m_ctx.get_params().slice()) { + if (m_ctx.get_params().xform_slice()) { datalog::rule_transformer transformer(m_ctx); datalog::mk_slice* slice = alloc(datalog::mk_slice, m_ctx); transformer.register_plugin(slice); @@ -122,12 +122,12 @@ lbool dl_interface::query(expr * query) { } } - if (m_ctx.get_params().unfold_rules() > 0) { - unsigned num_unfolds = m_ctx.get_params().unfold_rules(); + if (m_ctx.get_params().xform_unfold_rules() > 0) { + unsigned num_unfolds = m_ctx.get_params().xform_unfold_rules(); datalog::rule_transformer transf1(m_ctx), transf2(m_ctx); transf1.register_plugin(alloc(datalog::mk_coalesce, m_ctx)); transf2.register_plugin(alloc(datalog::mk_unfold, m_ctx)); - if (m_ctx.get_params().coalesce_rules()) { + if (m_ctx.get_params().xform_coalesce_rules()) { m_ctx.transform_rules(transf1); } while (num_unfolds > 0) { @@ -176,7 +176,7 @@ expr_ref dl_interface::get_cover_delta(int level, func_decl* pred_orig) { } void dl_interface::add_cover(int level, func_decl* pred, expr* property) { - if (m_ctx.get_params().slice()) { + if (m_ctx.get_params().xform_slice()) { throw default_exception("Covers are incompatible with slicing. Disable slicing before using covers"); } m_context->add_cover(level, pred, property); diff --git a/src/muz/pdr/pdr_farkas_learner.cpp b/src/muz/pdr/pdr_farkas_learner.cpp index 7c38bf86f..5946ccb2a 100644 --- a/src/muz/pdr/pdr_farkas_learner.cpp +++ b/src/muz/pdr/pdr_farkas_learner.cpp @@ -34,8 +34,6 @@ Revision History: #include "proof_utils.h" #include "reg_decl_plugins.h" -#define PROOF_MODE PGM_FINE -//#define PROOF_MODE PGM_COARSE namespace pdr { @@ -374,7 +372,7 @@ namespace pdr { farkas_learner::farkas_learner(smt_params& params, ast_manager& outer_mgr) : m_proof_params(get_proof_params(params)), - m_pr(PROOF_MODE), + m_pr(PGM_FINE), m_constr(0), m_combine_farkas_coefficients(true), p2o(m_pr, outer_mgr), diff --git a/src/muz/pdr/pdr_generalizers.cpp b/src/muz/pdr/pdr_generalizers.cpp index 7c2557260..8b6f6a4c6 100644 --- a/src/muz/pdr/pdr_generalizers.cpp +++ b/src/muz/pdr/pdr_generalizers.cpp @@ -558,7 +558,6 @@ namespace pdr { { expr_ref_vector conj(m), sub(m); expr_ref result(m); - ptr_vector sorts; svector names; unsigned ut_size = rule.get_uninterpreted_tail_size(); unsigned t_size = rule.get_tail_size(); @@ -599,16 +598,15 @@ namespace pdr { expr_ref tmp = result; var_subst(m, false)(tmp, sub.size(), sub.c_ptr(), result); } - get_free_vars(result, sorts); - for (unsigned i = 0; i < sorts.size(); ++i) { - if (!sorts[i]) { - sorts[i] = m.mk_bool_sort(); - } - names.push_back(symbol(sorts.size() - i - 1)); + expr_free_vars fv; + fv(result); + fv.set_default_sort(m.mk_bool_sort()); + for (unsigned i = 0; i < fv.size(); ++i) { + names.push_back(symbol(fv.size() - i - 1)); } - if (!sorts.empty()) { - sorts.reverse(); - result = m.mk_exists(sorts.size(), sorts.c_ptr(), names.c_ptr(), result); + if (!fv.empty()) { + fv.reverse(); + result = m.mk_exists(fv.size(), fv.c_ptr(), names.c_ptr(), result); } return result; } diff --git a/src/muz/pdr/pdr_manager.cpp b/src/muz/pdr/pdr_manager.cpp index bda54dbd7..c029d1b16 100644 --- a/src/muz/pdr/pdr_manager.cpp +++ b/src/muz/pdr/pdr_manager.cpp @@ -119,7 +119,7 @@ namespace pdr { } - void inductive_property::display(ptr_vector const& rules, std::ostream& out) const { + void inductive_property::display(datalog::rule_manager& rm, ptr_vector const& rules, std::ostream& out) const { func_decl_set bound_decls, aux_decls; collect_decls_proc collect_decls(bound_decls, aux_decls); @@ -153,7 +153,7 @@ namespace pdr { for (unsigned i = 0; i < rules.size(); ++i) { out << "(push)\n"; out << "(assert (not\n"; - rules[i]->display_smt2(m, out); + rm.display_smt2(*rules[i], out); out << "))\n"; out << "(check-sat)\n"; out << "(pop)\n"; diff --git a/src/muz/pdr/pdr_manager.h b/src/muz/pdr/pdr_manager.h index 0e8e890e8..f892e4d97 100644 --- a/src/muz/pdr/pdr_manager.h +++ b/src/muz/pdr/pdr_manager.h @@ -70,8 +70,8 @@ namespace pdr { expr_ref to_expr() const; void to_model(model_ref& md) const; - - void display(ptr_vector const& rules, std::ostream& out) const; + + void display(datalog::rule_manager& rm, ptr_vector const& rules, std::ostream& out) const; }; class manager diff --git a/src/muz/pdr/pdr_prop_solver.cpp b/src/muz/pdr/pdr_prop_solver.cpp index 8fe8c0e0e..a7d0a02bf 100644 --- a/src/muz/pdr/pdr_prop_solver.cpp +++ b/src/muz/pdr/pdr_prop_solver.cpp @@ -30,7 +30,6 @@ Revision History: #include "pdr_farkas_learner.h" #include "ast_smt2_pp.h" #include "expr_replacer.h" -#include "fixedpoint_params.hpp" // // Auxiliary structure to introduce propositional names for assumptions that are not @@ -226,12 +225,12 @@ namespace pdr { }; - prop_solver::prop_solver(manager& pm, fixedpoint_params const& p, symbol const& name) : + prop_solver::prop_solver(manager& pm, bool try_minimize_core, symbol const& name) : m_fparams(pm.get_fparams()), m(pm.get_manager()), m_pm(pm), m_name(name), - m_try_minimize_core(p.try_minimize_core()), + m_try_minimize_core(try_minimize_core), m_ctx(pm.mk_fresh()), m_pos_level_atoms(m), m_neg_level_atoms(m), diff --git a/src/muz/pdr/pdr_prop_solver.h b/src/muz/pdr/pdr_prop_solver.h index a63ec2bf4..d7f13a603 100644 --- a/src/muz/pdr/pdr_prop_solver.h +++ b/src/muz/pdr/pdr_prop_solver.h @@ -31,7 +31,6 @@ Revision History: #include "pdr_manager.h" #include "pdr_smt_context_manager.h" -struct fixedpoint_params; namespace pdr { class prop_solver { @@ -75,7 +74,7 @@ namespace pdr { public: - prop_solver(pdr::manager& pm, fixedpoint_params const& p, symbol const& name); + prop_solver(pdr::manager& pm, bool try_minimize_core, symbol const& name); /** return true is s is a symbol introduced by prop_solver */ bool is_aux_symbol(func_decl * s) const { diff --git a/src/muz/pdr/pdr_smt_context_manager.h b/src/muz/pdr/pdr_smt_context_manager.h index 4775dc58f..625428042 100644 --- a/src/muz/pdr/pdr_smt_context_manager.h +++ b/src/muz/pdr/pdr_smt_context_manager.h @@ -21,7 +21,6 @@ Revision History: #define _PDR_SMT_CONTEXT_MANAGER_H_ #include "smt_kernel.h" -#include "sat_solver.h" #include "func_decl_dependencies.h" #include "dl_util.h" @@ -71,23 +70,6 @@ namespace pdr { virtual expr* get_unsat_core_expr(unsigned i) { return m_context.get_unsat_core_expr(i); } }; - // TBD: - class sat_context : public smt_context { - sat::solver m_solver; - public: - sat_context(smt::kernel & ctx, smt_context_manager& p, app* pred); - virtual ~sat_context() {} - virtual void assert_expr(expr* e); - virtual lbool check(expr_ref_vector& assumptions); - virtual void get_model(model_ref& model); - virtual proof* get_proof(); - virtual void pop() { m_solver.pop(1); } - virtual void push() { m_solver.push(); } - // TBD: add unsat core extraction with sat::solver. - virtual unsigned get_unsat_core_size(); - virtual expr* get_unsat_core_expr(unsigned i); - }; - class smt_context_manager { smt_params& m_fparams; ast_manager& m; diff --git a/src/muz/pdr/pdr_util.cpp b/src/muz/pdr/pdr_util.cpp index f122f1e2c..18e5b680d 100644 --- a/src/muz/pdr/pdr_util.cpp +++ b/src/muz/pdr/pdr_util.cpp @@ -90,879 +90,6 @@ namespace pdr { return res.str(); } - - - ///////////////////////// - // model_evaluator - // - - - void model_evaluator::assign_value(expr* e, expr* val) { - rational r; - if (m.is_true(val)) { - set_true(e); - } - else if (m.is_false(val)) { - set_false(e); - } - else if (m_arith.is_numeral(val, r)) { - set_number(e, r); - } - else if (m.is_value(val)) { - set_value(e, val); - } - else { - IF_VERBOSE(3, verbose_stream() << "Not evaluated " << mk_pp(e, m) << " := " << mk_pp(val, m) << "\n";); - TRACE("pdr", tout << "Variable is not tracked: " << mk_pp(e, m) << " := " << mk_pp(val, m) << "\n";); - set_x(e); - } - } - - void model_evaluator::setup_model(model_ref& model) { - m_numbers.reset(); - m_values.reset(); - m_model = model; - rational r; - unsigned sz = model->get_num_constants(); - for (unsigned i = 0; i < sz; i++) { - func_decl * d = model->get_constant(i); - expr* val = model->get_const_interp(d); - expr* e = m.mk_const(d); - m_refs.push_back(e); - assign_value(e, val); - } - } - - void model_evaluator::reset() { - m1.reset(); - m2.reset(); - m_values.reset(); - m_visited.reset(); - m_numbers.reset(); - m_refs.reset(); - m_model = 0; - } - - expr_ref_vector model_evaluator::minimize_model(ptr_vector const & formulas, model_ref& mdl) { - setup_model(mdl); - - TRACE("pdr_verbose", - tout << "formulas:\n"; - for (unsigned i = 0; i < formulas.size(); ++i) tout << mk_pp(formulas[i], m) << "\n"; - ); - - expr_ref_vector model = prune_by_cone_of_influence(formulas); - TRACE("pdr_verbose", - tout << "pruned model:\n"; - for (unsigned i = 0; i < model.size(); ++i) tout << mk_pp(model[i].get(), m) << "\n";); - - reset(); - - DEBUG_CODE( - setup_model(mdl); - VERIFY(check_model(formulas)); - reset();); - - return model; - } - - expr_ref_vector model_evaluator::minimize_literals(ptr_vector const& formulas, model_ref& mdl) { - - TRACE("pdr", - tout << "formulas:\n"; - for (unsigned i = 0; i < formulas.size(); ++i) tout << mk_pp(formulas[i], m) << "\n"; - ); - - expr_ref_vector result(m); - expr_ref tmp(m); - ptr_vector tocollect; - - setup_model(mdl); - collect(formulas, tocollect); - for (unsigned i = 0; i < tocollect.size(); ++i) { - expr* e = tocollect[i]; - expr* e1, *e2; - SASSERT(m.is_bool(e)); - SASSERT(is_true(e) || is_false(e)); - if (is_true(e)) { - result.push_back(e); - } - // hack to break disequalities for arithmetic variables. - else if (m.is_eq(e, e1, e2) && m_arith.is_int_real(e1)) { - if (get_number(e1) < get_number(e2)) { - result.push_back(m_arith.mk_lt(e1,e2)); - } - else { - result.push_back(m_arith.mk_lt(e2,e1)); - } - } - else { - result.push_back(m.mk_not(e)); - } - } - reset(); - TRACE("pdr", - tout << "minimized model:\n"; - for (unsigned i = 0; i < result.size(); ++i) tout << mk_pp(result[i].get(), m) << "\n"; - ); - - return result; - } - - void model_evaluator::process_formula(app* e, ptr_vector& todo, ptr_vector& tocollect) { - SASSERT(m.is_bool(e)); - SASSERT(is_true(e) || is_false(e)); - unsigned v = is_true(e); - unsigned sz = e->get_num_args(); - expr* const* args = e->get_args(); - if (e->get_family_id() == m.get_basic_family_id()) { - switch(e->get_decl_kind()) { - case OP_TRUE: - break; - case OP_FALSE: - break; - case OP_EQ: - case OP_IFF: - if (args[0] == args[1]) { - SASSERT(v); - // no-op - } - else if (m.is_bool(args[0])) { - todo.append(sz, args); - } - else { - tocollect.push_back(e); - } - break; - case OP_DISTINCT: - tocollect.push_back(e); - break; - case OP_ITE: - if (args[1] == args[2]) { - tocollect.push_back(args[1]); - } - else if (is_true(args[1]) && is_true(args[2])) { - todo.append(2, args+1); - } - else if (is_false(args[1]) && is_false(args[2])) { - todo.append(2, args+1); - } - else if (is_true(args[0])) { - todo.append(2, args); - } - else { - SASSERT(is_false(args[0])); - todo.push_back(args[0]); - todo.push_back(args[2]); - } - break; - case OP_AND: - if (v) { - todo.append(sz, args); - } - else { - unsigned i = 0; - for (; !is_false(args[i]) && i < sz; ++i); - if (i == sz) { - fatal_error(1); - } - VERIFY(i < sz); - todo.push_back(args[i]); - } - break; - case OP_OR: - if (v) { - unsigned i = 0; - for (; !is_true(args[i]) && i < sz; ++i); - if (i == sz) { - fatal_error(1); - } - VERIFY(i < sz); - todo.push_back(args[i]); - } - else { - todo.append(sz, args); - } - break; - case OP_XOR: - case OP_NOT: - todo.append(sz, args); - break; - case OP_IMPLIES: - if (v) { - if (is_true(args[1])) { - todo.push_back(args[1]); - } - else if (is_false(args[0])) { - todo.push_back(args[0]); - } - else { - IF_VERBOSE(0, verbose_stream() << "Term not handled " << mk_pp(e, m) << "\n";); - UNREACHABLE(); - } - } - else { - todo.append(sz, args); - } - break; - default: - IF_VERBOSE(0, verbose_stream() << "Term not handled " << mk_pp(e, m) << "\n";); - UNREACHABLE(); - } - } - else { - tocollect.push_back(e); - } - } - - void model_evaluator::collect(ptr_vector const& formulas, ptr_vector& tocollect) { - ptr_vector todo; - todo.append(formulas); - m_visited.reset(); - - VERIFY(check_model(formulas)); - - while (!todo.empty()) { - app* e = to_app(todo.back()); - todo.pop_back(); - if (!m_visited.is_marked(e)) { - process_formula(e, todo, tocollect); - m_visited.mark(e, true); - } - } - m_visited.reset(); - } - - expr_ref_vector model_evaluator::prune_by_cone_of_influence(ptr_vector const & formulas) { - ptr_vector tocollect; - collect(formulas, tocollect); - m1.reset(); - m2.reset(); - for (unsigned i = 0; i < tocollect.size(); ++i) { - TRACE("pdr_verbose", tout << "collect: " << mk_pp(tocollect[i], m) << "\n";); - for_each_expr(*this, m_visited, tocollect[i]); - } - unsigned sz = m_model->get_num_constants(); - expr_ref e(m), eq(m), val(m); - expr_ref_vector model(m); - for (unsigned i = 0; i < sz; i++) { - e = m.mk_const(m_model->get_constant(i)); - if (m_visited.is_marked(e)) { - val = eval(m_model, e); - eq = m.mk_eq(e, val); - model.push_back(eq); - } - } - m_visited.reset(); - TRACE("pdr", tout << sz << " ==> " << model.size() << "\n";); - return model; - - } - - void model_evaluator::eval_arith(app* e) { - rational r, r2; - -#define ARG1 e->get_arg(0) -#define ARG2 e->get_arg(1) - - unsigned arity = e->get_num_args(); - for (unsigned i = 0; i < arity; ++i) { - expr* arg = e->get_arg(i); - if (is_x(arg)) { - set_x(e); - return; - } - SASSERT(!is_unknown(arg)); - } - switch(e->get_decl_kind()) { - case OP_NUM: - VERIFY(m_arith.is_numeral(e, r)); - set_number(e, r); - break; - case OP_IRRATIONAL_ALGEBRAIC_NUM: - set_x(e); - break; - case OP_LE: - set_bool(e, get_number(ARG1) <= get_number(ARG2)); - break; - case OP_GE: - set_bool(e, get_number(ARG1) >= get_number(ARG2)); - break; - case OP_LT: - set_bool(e, get_number(ARG1) < get_number(ARG2)); - break; - case OP_GT: - set_bool(e, get_number(ARG1) > get_number(ARG2)); - break; - case OP_ADD: - r = rational::zero(); - for (unsigned i = 0; i < arity; ++i) { - r += get_number(e->get_arg(i)); - } - set_number(e, r); - break; - case OP_SUB: - r = get_number(e->get_arg(0)); - for (unsigned i = 1; i < arity; ++i) { - r -= get_number(e->get_arg(i)); - } - set_number(e, r); - break; - case OP_UMINUS: - SASSERT(arity == 1); - set_number(e, get_number(e->get_arg(0))); - break; - case OP_MUL: - r = rational::one(); - for (unsigned i = 0; i < arity; ++i) { - r *= get_number(e->get_arg(i)); - } - set_number(e, r); - break; - case OP_DIV: - SASSERT(arity == 2); - r = get_number(ARG2); - if (r.is_zero()) { - set_x(e); - } - else { - set_number(e, get_number(ARG1) / r); - } - break; - case OP_IDIV: - SASSERT(arity == 2); - r = get_number(ARG2); - if (r.is_zero()) { - set_x(e); - } - else { - set_number(e, div(get_number(ARG1), r)); - } - break; - case OP_REM: - // rem(v1,v2) = if v2 >= 0 then mod(v1,v2) else -mod(v1,v2) - SASSERT(arity == 2); - r = get_number(ARG2); - if (r.is_zero()) { - set_x(e); - } - else { - r2 = mod(get_number(ARG1), r); - if (r.is_neg()) r2.neg(); - set_number(e, r2); - } - break; - case OP_MOD: - SASSERT(arity == 2); - r = get_number(ARG2); - if (r.is_zero()) { - set_x(e); - } - else { - set_number(e, mod(get_number(ARG1), r)); - } - break; - case OP_TO_REAL: - SASSERT(arity == 1); - set_number(e, get_number(ARG1)); - break; - case OP_TO_INT: - SASSERT(arity == 1); - set_number(e, floor(get_number(ARG1))); - break; - case OP_IS_INT: - SASSERT(arity == 1); - set_bool(e, get_number(ARG1).is_int()); - break; - case OP_POWER: - set_x(e); - break; - default: - IF_VERBOSE(0, verbose_stream() << "Term not handled " << mk_pp(e, m) << "\n";); - UNREACHABLE(); - break; - } - } - - void model_evaluator::inherit_value(expr* e, expr* v) { - expr* w; - SASSERT(!is_unknown(v)); - SASSERT(m.get_sort(e) == m.get_sort(v)); - if (is_x(v)) { - set_x(e); - } - else if (m.is_bool(e)) { - SASSERT(m.is_bool(v)); - if (is_true(v)) set_true(e); - else if (is_false(v)) set_false(e); - else { - TRACE("pdr", tout << "not inherited:\n" << mk_pp(e, m) << "\n" << mk_pp(v, m) << "\n";); - set_x(e); - } - } - else if (m_arith.is_int_real(e)) { - set_number(e, get_number(v)); - } - else if (m.is_value(v)) { - set_value(e, v); - } - else if (m_values.find(v, w)) { - set_value(e, w); - } - else { - TRACE("pdr", tout << "not inherited:\n" << mk_pp(e, m) << "\n" << mk_pp(v, m) << "\n";); - set_x(e); - } - } - - void model_evaluator::eval_exprs(expr_ref_vector& es) { - model_ref mr(m_model); - for (unsigned j = 0; j < es.size(); ++j) { - if (m_array.is_as_array(es[j].get())) { - es[j] = eval(mr, es[j].get()); - } - } - } - - bool model_evaluator::extract_array_func_interp(expr* a, vector& stores, expr_ref& else_case) { - SASSERT(m_array.is_array(a)); - - TRACE("pdr", tout << mk_pp(a, m) << "\n";); - while (m_array.is_store(a)) { - expr_ref_vector store(m); - store.append(to_app(a)->get_num_args()-1, to_app(a)->get_args()+1); - eval_exprs(store); - stores.push_back(store); - a = to_app(a)->get_arg(0); - } - - if (m_array.is_const(a)) { - else_case = to_app(a)->get_arg(0); - return true; - } - - while (m_array.is_as_array(a)) { - func_decl* f = m_array.get_as_array_func_decl(to_app(a)); - func_interp* g = m_model->get_func_interp(f); - unsigned sz = g->num_entries(); - unsigned arity = f->get_arity(); - for (unsigned i = 0; i < sz; ++i) { - expr_ref_vector store(m); - func_entry const* fe = g->get_entry(i); - store.append(arity, fe->get_args()); - store.push_back(fe->get_result()); - for (unsigned j = 0; j < store.size(); ++j) { - if (!is_ground(store[j].get())) { - TRACE("pdr", tout << "could not extract array interpretation: " << mk_pp(a, m) << "\n" << mk_pp(store[j].get(), m) << "\n";); - return false; - } - } - eval_exprs(store); - stores.push_back(store); - } - else_case = g->get_else(); - if (!else_case) { - TRACE("pdr", tout << "no else case " << mk_pp(a, m) << "\n";); - return false; - } - if (!is_ground(else_case)) { - TRACE("pdr", tout << "non-ground else case " << mk_pp(a, m) << "\n" << mk_pp(else_case, m) << "\n";); - return false; - } - if (m_array.is_as_array(else_case)) { - model_ref mr(m_model); - else_case = eval(mr, else_case); - } - TRACE("pdr", tout << "else case: " << mk_pp(else_case, m) << "\n";); - return true; - } - TRACE("pdr", tout << "no translation: " << mk_pp(a, m) << "\n";); - - return false; - } - - /** - best effort evaluator of extensional array equality. - */ - void model_evaluator::eval_array_eq(app* e, expr* arg1, expr* arg2) { - TRACE("pdr", tout << "array equality: " << mk_pp(e, m) << "\n";); - expr_ref v1(m), v2(m); - m_model->eval(arg1, v1); - m_model->eval(arg2, v2); - if (v1 == v2) { - set_true(e); - return; - } - sort* s = m.get_sort(arg1); - sort* r = get_array_range(s); - // give up evaluating finite domain/range arrays - if (!r->is_infinite() && !r->is_very_big() && !s->is_infinite() && !s->is_very_big()) { - TRACE("pdr", tout << "equality is unknown: " << mk_pp(e, m) << "\n";); - set_x(e); - return; - } - vector store; - expr_ref else1(m), else2(m); - if (!extract_array_func_interp(v1, store, else1) || - !extract_array_func_interp(v2, store, else2)) { - TRACE("pdr", tout << "equality is unknown: " << mk_pp(e, m) << "\n";); - set_x(e); - return; - } - - if (else1 != else2) { - if (m.is_value(else1) && m.is_value(else2)) { - TRACE("pdr", tout - << "defaults are different: " << mk_pp(e, m) << " " - << mk_pp(else1, m) << " " << mk_pp(else2, m) << "\n";); - set_false(e); - } - else if (m_array.is_array(else1)) { - eval_array_eq(e, else1, else2); - } - else { - TRACE("pdr", tout << "equality is unknown: " << mk_pp(e, m) << "\n";); - set_x(e); - } - return; - } - - expr_ref s1(m), s2(m), w1(m), w2(m); - expr_ref_vector args1(m), args2(m); - args1.push_back(v1); - args2.push_back(v2); - for (unsigned i = 0; i < store.size(); ++i) { - args1.resize(1); - args2.resize(1); - args1.append(store[i].size()-1, store[i].c_ptr()); - args2.append(store[i].size()-1, store[i].c_ptr()); - s1 = m_array.mk_select(args1.size(), args1.c_ptr()); - s2 = m_array.mk_select(args2.size(), args2.c_ptr()); - m_model->eval(s1, w1); - m_model->eval(s2, w2); - if (w1 == w2) { - continue; - } - if (m.is_value(w1) && m.is_value(w2)) { - TRACE("pdr", tout << "Equality evaluation: " << mk_pp(e, m) << "\n"; - tout << mk_pp(s1, m) << " |-> " << mk_pp(w1, m) << "\n"; - tout << mk_pp(s2, m) << " |-> " << mk_pp(w2, m) << "\n";); - set_false(e); - } - else if (m_array.is_array(w1)) { - eval_array_eq(e, w1, w2); - if (is_true(e)) { - continue; - } - } - else { - TRACE("pdr", tout << "equality is unknown: " << mk_pp(e, m) << "\n";); - set_x(e); - } - return; - } - set_true(e); - } - - void model_evaluator::eval_eq(app* e, expr* arg1, expr* arg2) { - if (arg1 == arg2) { - set_true(e); - } - else if (m_array.is_array(arg1)) { - eval_array_eq(e, arg1, arg2); - } - else if (is_x(arg1) || is_x(arg2)) { - expr_ref eq(m), vl(m); - eq = m.mk_eq(arg1, arg2); - m_model->eval(eq, vl); - if (m.is_true(vl)) { - set_bool(e, true); - } - else if (m.is_false(vl)) { - set_bool(e, false); - } - else { - TRACE("pdr", tout << "cannot evaluate: " << mk_pp(vl, m) << "\n";); - set_x(e); - } - } - else if (m.is_bool(arg1)) { - bool val = is_true(arg1) == is_true(arg2); - SASSERT(val == (is_false(arg1) == is_false(arg2))); - if (val) { - set_true(e); - } - else { - set_false(e); - } - } - else if (m_arith.is_int_real(arg1)) { - set_bool(e, get_number(arg1) == get_number(arg2)); - } - else { - expr* e1 = get_value(arg1); - expr* e2 = get_value(arg2); - if (m.is_value(e1) && m.is_value(e2)) { - set_bool(e, e1 == e2); - } - else if (e1 == e2) { - set_bool(e, true); - } - else { - TRACE("pdr", tout << "not value equal:\n" << mk_pp(e1, m) << "\n" << mk_pp(e2, m) << "\n";); - set_x(e); - } - } - } - - void model_evaluator::eval_basic(app* e) { - expr* arg1, *arg2; - expr *argCond, *argThen, *argElse, *arg; - bool has_x = false; - unsigned arity = e->get_num_args(); - switch(e->get_decl_kind()) { - case OP_AND: - for (unsigned j = 0; j < arity; ++j) { - expr * arg = e->get_arg(j); - if (is_false(arg)) { - set_false(e); - return; - } - else if (is_x(arg)) { - has_x = true; - } - else { - SASSERT(is_true(arg)); - } - } - if (has_x) { - set_x(e); - } - else { - set_true(e); - } - break; - case OP_OR: - for (unsigned j = 0; j < arity; ++j) { - expr * arg = e->get_arg(j); - if (is_true(arg)) { - set_true(e); - return; - } - else if (is_x(arg)) { - has_x = true; - } - else { - SASSERT(is_false(arg)); - } - } - if (has_x) { - set_x(e); - } - else { - set_false(e); - } - break; - case OP_NOT: - VERIFY(m.is_not(e, arg)); - if (is_true(arg)) { - set_false(e); - } - else if (is_false(arg)) { - set_true(e); - } - else { - SASSERT(is_x(arg)); - set_x(e); - } - break; - case OP_IMPLIES: - VERIFY(m.is_implies(e, arg1, arg2)); - if (is_false(arg1) || is_true(arg2)) { - set_true(e); - } - else if (arg1 == arg2) { - set_true(e); - } - else if (is_true(arg1) && is_false(arg2)) { - set_false(e); - } - else { - SASSERT(is_x(arg1) || is_x(arg2)); - set_x(e); - } - break; - case OP_IFF: - VERIFY(m.is_iff(e, arg1, arg2)); - eval_eq(e, arg1, arg2); - break; - case OP_ITE: - VERIFY(m.is_ite(e, argCond, argThen, argElse)); - if (is_true(argCond)) { - inherit_value(e, argThen); - } - else if (is_false(argCond)) { - inherit_value(e, argElse); - } - else if (argThen == argElse) { - inherit_value(e, argThen); - } - else if (m.is_bool(e)) { - SASSERT(is_x(argCond)); - if (is_x(argThen) || is_x(argElse)) { - set_x(e); - } - else if (is_true(argThen) == is_true(argElse)) { - inherit_value(e, argThen); - } - else { - set_x(e); - } - } - else { - set_x(e); - } - break; - case OP_TRUE: - set_true(e); - break; - case OP_FALSE: - set_false(e); - break; - case OP_EQ: - VERIFY(m.is_eq(e, arg1, arg2)); - eval_eq(e, arg1, arg2); - break; - case OP_DISTINCT: { - vector values; - for (unsigned i = 0; i < arity; ++i) { - expr* arg = e->get_arg(i); - if (is_x(arg)) { - set_x(e); - return; - } - values.push_back(get_number(arg)); - } - std::sort(values.begin(), values.end()); - for (unsigned i = 0; i + 1 < values.size(); ++i) { - if (values[i] == values[i+1]) { - set_false(e); - return; - } - } - set_true(e); - break; - } - default: - IF_VERBOSE(0, verbose_stream() << "Term not handled " << mk_pp(e, m) << "\n";); - UNREACHABLE(); - } - } - - bool model_evaluator::check_model(ptr_vector const& formulas) { - ptr_vector todo(formulas); - - while (!todo.empty()) { - expr * curr_e = todo.back(); - - if (!is_app(curr_e)) { - todo.pop_back(); - continue; - } - app * curr = to_app(curr_e); - - if (!is_unknown(curr)) { - todo.pop_back(); - continue; - } - unsigned arity = curr->get_num_args(); - for (unsigned i = 0; i < arity; ++i) { - if (is_unknown(curr->get_arg(i))) { - todo.push_back(curr->get_arg(i)); - } - } - if (todo.back() != curr) { - continue; - } - todo.pop_back(); - if (curr->get_family_id() == m_arith.get_family_id()) { - eval_arith(curr); - } - else if (curr->get_family_id() == m.get_basic_family_id()) { - eval_basic(curr); - } - else { - expr_ref vl(m); - m_model->eval(curr, vl); - assign_value(curr, vl); - } - - IF_VERBOSE(35,verbose_stream() << "assigned "<get_arity() == 0); - expr_ref result(m); - if (m_array.is_array(d->get_range())) { - expr_ref e(m); - e = m.mk_const(d); - result = eval(model, e); - } - else { - result = model->get_const_interp(d); - } - return result; - } - - expr_ref model_evaluator::eval(model_ref& model, expr* e) { - expr_ref result(m); - m_model = model; - VERIFY(m_model->eval(e, result, true)); - if (m_array.is_array(e)) { - vector stores; - expr_ref_vector args(m); - expr_ref else_case(m); - if (extract_array_func_interp(result, stores, else_case)) { - result = m_array.mk_const_array(m.get_sort(e), else_case); - while (!stores.empty() && stores.back().back() == else_case) { - stores.pop_back(); - } - for (unsigned i = stores.size(); i > 0; ) { - --i; - args.resize(1); - args[0] = result; - args.append(stores[i]); - result = m_array.mk_store(args.size(), args.c_ptr()); - } - return result; - } - } - return result; - } - - void reduce_disequalities(model& model, unsigned threshold, expr_ref& fml) { ast_manager& m = fml.get_manager(); expr_ref_vector conjs(m); @@ -1030,68 +157,6 @@ namespace pdr { fml = m.mk_and(conjs.size(), conjs.c_ptr()); } - // - // (f (if c1 (if c2 e1 e2) e3) b c) -> - // (if c1 (if c2 (f e1 b c) - - class ite_hoister { - ast_manager& m; - public: - ite_hoister(ast_manager& m): m(m) {} - - br_status mk_app_core(func_decl* f, unsigned num_args, expr* const* args, expr_ref& result) { - if (m.is_ite(f)) { - return BR_FAILED; - } - for (unsigned i = 0; i < num_args; ++i) { - expr* c, *t, *e; - if (!m.is_bool(args[i]) && m.is_ite(args[i], c, t, e)) { - expr_ref e1(m), e2(m); - ptr_vector args1(num_args, args); - args1[i] = t; - e1 = m.mk_app(f, num_args, args1.c_ptr()); - if (t == e) { - result = e1; - return BR_REWRITE1; - } - args1[i] = e; - e2 = m.mk_app(f, num_args, args1.c_ptr()); - result = m.mk_app(f, num_args, args); - result = m.mk_ite(c, e1, e2); - return BR_REWRITE3; - } - } - return BR_FAILED; - } - }; - - struct ite_hoister_cfg: public default_rewriter_cfg { - ite_hoister m_r; - bool rewrite_patterns() const { return false; } - br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { - return m_r.mk_app_core(f, num, args, result); - } - ite_hoister_cfg(ast_manager & m, params_ref const & p):m_r(m) {} - }; - - class ite_hoister_star : public rewriter_tpl { - ite_hoister_cfg m_cfg; - public: - ite_hoister_star(ast_manager & m, params_ref const & p): - rewriter_tpl(m, false, m_cfg), - m_cfg(m, p) {} - }; - - void hoist_non_bool_if(expr_ref& fml) { - ast_manager& m = fml.get_manager(); - scoped_no_proof _sp(m); - params_ref p; - ite_hoister_star ite_rw(m, p); - expr_ref tmp(m); - ite_rw(fml, tmp); - fml = tmp; - } - class test_diff_logic { ast_manager& m; arith_util a; @@ -1441,7 +506,6 @@ namespace pdr { } -template class rewriter_tpl; template class rewriter_tpl; diff --git a/src/muz/pdr/pdr_util.h b/src/muz/pdr/pdr_util.h index 446bde8aa..29b640d74 100644 --- a/src/muz/pdr/pdr_util.h +++ b/src/muz/pdr/pdr_util.h @@ -54,86 +54,6 @@ namespace pdr { std::string pp_cube(unsigned sz, app * const * lits, ast_manager& manager); std::string pp_cube(unsigned sz, expr * const * lits, ast_manager& manager); - class model_evaluator { - ast_manager& m; - arith_util m_arith; - array_util m_array; - obj_map m_numbers; - expr_ref_vector m_refs; - obj_map m_values; - model_ref m_model; - - //00 -- non-visited - //01 -- X - //10 -- false - //11 -- true - expr_mark m1; - expr_mark m2; - expr_mark m_visited; - - - void reset(); - void setup_model(model_ref& model); - void assign_value(expr* e, expr* v); - void collect(ptr_vector const& formulas, ptr_vector& tocollect); - void process_formula(app* e, ptr_vector& todo, ptr_vector& tocollect); - expr_ref_vector prune_by_cone_of_influence(ptr_vector const & formulas); - void eval_arith(app* e); - void eval_basic(app* e); - void eval_eq(app* e, expr* arg1, expr* arg2); - void eval_array_eq(app* e, expr* arg1, expr* arg2); - void inherit_value(expr* e, expr* v); - - inline bool is_unknown(expr* x) { return !m1.is_marked(x) && !m2.is_marked(x); } - inline void set_unknown(expr* x) { m1.mark(x, false); m2.mark(x, false); } - inline bool is_x(expr* x) { return !m1.is_marked(x) && m2.is_marked(x); } - inline bool is_false(expr* x) { return m1.is_marked(x) && !m2.is_marked(x); } - inline bool is_true(expr* x) { return m1.is_marked(x) && m2.is_marked(x); } - inline void set_x(expr* x) { SASSERT(is_unknown(x)); m2.mark(x); } - inline void set_v(expr* x) { SASSERT(is_unknown(x)); m1.mark(x); } - inline void set_false(expr* x) { SASSERT(is_unknown(x)); m1.mark(x); } - inline void set_true(expr* x) { SASSERT(is_unknown(x)); m1.mark(x); m2.mark(x); } - inline void set_bool(expr* x, bool v) { if (v) { set_true(x); } else { set_false(x); } } - inline rational const& get_number(expr* x) const { return m_numbers.find(x); } - inline void set_number(expr* x, rational const& v) { - set_v(x); TRACE("pdr_verbose", tout << mk_pp(x,m) << " " << v << "\n";); m_numbers.insert(x,v); - } - inline expr* get_value(expr* x) { return m_values.find(x); } - inline void set_value(expr* x, expr* v) { set_v(x); m_refs.push_back(v); m_values.insert(x, v); } - - bool check_model(ptr_vector const & formulas); - - bool extract_array_func_interp(expr* a, vector& stores, expr_ref& else_case); - - void eval_exprs(expr_ref_vector& es); - - public: - model_evaluator(ast_manager& m) : m(m), m_arith(m), m_array(m), m_refs(m) {} - - /** - \brief extract equalities from model that suffice to satisfy formula. - - \pre model satisfies formulas - */ - - expr_ref_vector minimize_model(ptr_vector const & formulas, model_ref& mdl); - - /** - \brief extract literals from formulas that satisfy formulas. - - \pre model satisfies formulas - */ - expr_ref_vector minimize_literals(ptr_vector const & formulas, model_ref& mdl); - - /** - for_each_expr visitor. - */ - void operator()(expr* e) {} - - expr_ref eval(model_ref& mdl, expr* e); - - expr_ref eval(model_ref& mdl, func_decl* d); - }; /** \brief replace variables that are used in many disequalities by @@ -143,12 +63,6 @@ namespace pdr { */ void reduce_disequalities(model& model, unsigned threshold, expr_ref& fml); - /** - \brief hoist non-boolean if expressions. - */ - void hoist_non_bool_if(expr_ref& fml); - - /** \brief normalize coefficients in polynomials so that least coefficient is 1. */ diff --git a/src/muz/rel/check_relation.cpp b/src/muz/rel/check_relation.cpp new file mode 100644 index 000000000..c1b840c61 --- /dev/null +++ b/src/muz/rel/check_relation.cpp @@ -0,0 +1,785 @@ +#include "check_relation.h" +#include "dl_relation_manager.h" +#include "qe_util.h" +#include "ast_util.h" +#include "smt_kernel.h" +#include + + +namespace datalog { + + check_relation::check_relation(check_relation_plugin& p, relation_signature const& sig, relation_base* r): + relation_base(p, sig), + m(p.get_ast_manager()), + m_relation(r), + m_fml(m) { + m_relation->to_formula(m_fml); + } + check_relation::~check_relation() { + m_relation->deallocate(); + } + void check_relation::check_equiv(char const* objective, expr* f1, expr* f2) const { + get_plugin().check_equiv(objective, f1, f2); + } + void check_relation::consistent_formula() { + expr_ref fml(m); + m_relation->to_formula(fml); + if (m_fml != fml) { + IF_VERBOSE(0, display(verbose_stream() << "relation does not have a consistent formula");); + } + } + expr_ref check_relation::mk_eq(relation_fact const& f) const { + relation_signature const& sig = get_signature(); + expr_ref_vector conjs(m); + for (unsigned i = 0; i < sig.size(); ++i) { + conjs.push_back(m.mk_eq(m.mk_var(i, sig[i]), f[i])); + } + return expr_ref(mk_and(m, conjs.size(), conjs.c_ptr()), m); + } + + expr_ref check_relation::ground(expr* fml) const { + return get_plugin().ground(*this, fml); + } + + expr_ref check_relation_plugin::ground(relation_base const& dst) const { + expr_ref fml(m); + dst.to_formula(fml); + return ground(dst, fml); + } + + expr_ref check_relation_plugin::ground(relation_base const& dst, expr* fml) const { + relation_signature const& sig = dst.get_signature(); + var_subst sub(m, false); + expr_ref_vector vars(m); + for (unsigned i = 0; i < sig.size(); ++i) { + vars.push_back(m.mk_const(symbol(i), sig[i])); + } + expr_ref result(m); + sub(fml, vars.size(), vars.c_ptr(), result); + return result; + } + + void check_relation::add_fact(const relation_fact & f) { + expr_ref fml1(m); + m_relation->add_fact(f); + m_relation->to_formula(fml1); + m_fml = m.mk_or(m_fml, mk_eq(f)); + check_equiv("add_fact", ground(m_fml), ground(fml1)); + m_fml = fml1; + } + void check_relation::add_new_fact(const relation_fact & f) { + expr_ref fml1(m); + m_relation->add_new_fact(f); + m_relation->to_formula(fml1); + m_fml = m.mk_or(m_fml, mk_eq(f)); + check_equiv("add_fact", ground(m_fml), ground(fml1)); + m_fml = fml1; + } + bool check_relation::empty() const { + bool result = m_relation->empty(); + if (result && !m.is_false(m_fml)) { + check_equiv("empty", m.mk_false(), ground(m_fml)); + } + return result; + } + bool check_relation::fast_empty() const { + bool result = m_relation->fast_empty(); + if (result && !m.is_false(m_fml)) { + check_equiv("fast_empty", m.mk_false(), ground(m_fml)); + } + return result; + } + void check_relation::reset() { + m_relation->reset(); + m_fml = m.mk_false(); + } + + bool check_relation::contains_fact(const relation_fact & f) const { + bool result = m_relation->contains_fact(f); + expr_ref fml1(m), fml2(m); + fml1 = mk_eq(f); + fml2 = m.mk_and(m_fml, fml1); + if (result) { + check_equiv("contains fact", ground(fml1), ground(fml2)); + } + else if (!m.is_false(m_fml)) { + check_equiv("contains fact", ground(fml2), m.mk_false()); + } + return result; + } + check_relation * check_relation::clone() const { + check_relation* result = check_relation_plugin::get(get_plugin().mk_empty(get_signature())); + result->m_relation->deallocate(); + result->m_relation = m_relation->clone(); + result->m_relation->to_formula(result->m_fml); + if (m_fml != result->m_fml) { + check_equiv("clone", ground(m_fml), ground(result->m_fml)); + } + return result; + } + check_relation * check_relation::complement(func_decl* f) const { + check_relation* result = check_relation_plugin::get(get_plugin().mk_empty(get_signature())); + result->m_relation->deallocate(); + result->m_relation = m_relation->complement(f); + result->m_relation->to_formula(result->m_fml); + expr_ref fml(m); + fml = m.mk_not(m_fml); + check_equiv("complement", ground(fml), ground(result->m_fml)); + return result; + } + void check_relation::to_formula(expr_ref& fml) const { + fml = m_fml; + } + + check_relation_plugin& check_relation::get_plugin() const { + return static_cast(relation_base::get_plugin()); + } + + void check_relation::display(std::ostream& out) const { + m_relation->display(out); + out << m_fml << "\n"; + } + + // ------------- + + check_relation_plugin::check_relation_plugin(relation_manager& rm): + relation_plugin(check_relation_plugin::get_name(), rm), + m(rm.get_context().get_manager()), + m_base(0) { + } + check_relation_plugin::~check_relation_plugin() { + } + check_relation& check_relation_plugin::get(relation_base& r) { + return dynamic_cast(r); + } + check_relation* check_relation_plugin::get(relation_base* r) { + return r?dynamic_cast(r):0; + } + check_relation const & check_relation_plugin::get(relation_base const& r) { + return dynamic_cast(r); + } + + bool check_relation_plugin::can_handle_signature(const relation_signature & sig) { + return m_base && m_base->can_handle_signature(sig); + } + relation_base * check_relation_plugin::mk_empty(const relation_signature & sig) { + relation_base* r = m_base->mk_empty(sig); + check_relation* result = alloc(check_relation, *this, sig, r); + if (result->m_fml != m.mk_false()) { + check_equiv("mk_empty", result->ground(result->m_fml), m.mk_false()); + } + return result; + } + relation_base * check_relation_plugin::mk_full(func_decl* p, const relation_signature & s) { + relation_base* r = m_base->mk_full(p, s); + check_relation* result = alloc(check_relation, *this, s, r); + if (result->m_fml != m.mk_true()) { + check_equiv("mk_full", result->ground(result->m_fml), m.mk_true()); + } + return result; + } + + class check_relation_plugin::join_fn : public convenient_relation_join_fn { + scoped_ptr m_join; + public: + join_fn(relation_join_fn* j, + const relation_signature & o1_sig, const relation_signature & o2_sig, unsigned col_cnt, + const unsigned * cols1, const unsigned * cols2) + : convenient_join_fn(o1_sig, o2_sig, col_cnt, cols1, cols2), m_join(j) + {} + virtual ~join_fn() {} + virtual relation_base * operator()(const relation_base & r1, const relation_base & r2) { + check_relation const& t1 = get(r1); + check_relation const& t2 = get(r2); + check_relation_plugin& p = t1.get_plugin(); + relation_base* r = (*m_join)(t1.rb(), t2.rb()); + p.verify_join(r1, r2, *r, m_cols1, m_cols2); + return alloc(check_relation, p, r->get_signature(), r); + } + }; + + relation_join_fn * check_relation_plugin::mk_join_fn( + const relation_base & t1, const relation_base & t2, + unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { + relation_join_fn* j = m_base->mk_join_fn(get(t1).rb(), get(t2).rb(), col_cnt, cols1, cols2); + return j?alloc(join_fn, j, t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2):0; + } + + class check_relation_plugin::join_project_fn : public convenient_relation_join_project_fn { + scoped_ptr m_join; + public: + join_project_fn( + relation_join_fn* j, + const relation_signature & o1_sig, const relation_signature & o2_sig, unsigned col_cnt, + const unsigned * cols1, const unsigned * cols2, + unsigned removed_col_cnt, const unsigned* removed_cols) + : convenient_join_project_fn(o1_sig, o2_sig, col_cnt, cols1, cols2, + removed_col_cnt, removed_cols), m_join(j) + {} + virtual ~join_project_fn() {} + virtual relation_base * operator()(const relation_base & r1, const relation_base & r2) { + check_relation const& t1 = get(r1); + check_relation const& t2 = get(r2); + check_relation_plugin& p = t1.get_plugin(); + relation_base* r = (*m_join)(t1.rb(), t2.rb()); + p.verify_join_project(r1, r2, *r, m_cols1, m_cols2, m_removed_cols); + return alloc(check_relation, p, r->get_signature(), r); + } + }; + + relation_join_fn * check_relation_plugin::mk_join_project_fn( + const relation_base & t1, const relation_base & t2, + unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, + unsigned removed_col_cnt, const unsigned * removed_cols) { + relation_join_fn* j = m_base->mk_join_project_fn(get(t1).rb(), get(t2).rb(), col_cnt, cols1, cols2, + removed_col_cnt, removed_cols); + return j?alloc(join_project_fn, j, t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2, + removed_col_cnt, removed_cols):0; + } + + void check_relation_plugin::verify_filter_project( + relation_base const& src, relation_base const& dst, + app* cond, unsigned_vector const& removed_cols) { + expr_ref fml1(m), fml2(m); + src.to_formula(fml1); + dst.to_formula(fml2); + fml1 = m.mk_and(cond, fml1); + verify_project(src, fml1, dst, fml2, removed_cols); + } + + void check_relation_plugin::verify_project( + relation_base const& src, + relation_base const& dst, + unsigned_vector const& removed_cols) { + expr_ref fml1(m), fml2(m); + src.to_formula(fml1); + dst.to_formula(fml2); + verify_project(src, fml1, dst, fml2, removed_cols); + } + void check_relation_plugin::verify_project( + relation_base const& src, expr* f1, + relation_base const& dst, expr* f2, + unsigned_vector const& removed_cols) { + expr_ref fml1 = ground(dst, mk_project(src.get_signature(), f1, removed_cols)); + expr_ref fml2 = ground(dst, f2); + check_equiv("project", fml1, fml2); + } + expr_ref check_relation_plugin::mk_project( + relation_signature const& sig, + expr* fml, unsigned_vector const& removed_cols) { + expr_ref fml1(m); + ptr_vector bound; + svector names; + expr_ref_vector vars(m); + unsigned rm_cnt = removed_cols.size(); + for (unsigned i = 0, j = 0, k = 0; i < sig.size(); ++i) { + if (j < rm_cnt && removed_cols[j] == i) { + std::ostringstream strm; + strm << "x" << j; + bound.push_back(sig[i]); + names.push_back(symbol(strm.str().c_str())); + vars.push_back(m.mk_var(j, sig[i])); + ++j; + } + else { + vars.push_back(m.mk_var(k + rm_cnt, sig[i])); + ++k; + } + } + var_subst sub(m, false); + sub(fml, vars.size(), vars.c_ptr(), fml1); + bound.reverse(); + fml1 = m.mk_exists(bound.size(), bound.c_ptr(), names.c_ptr(), fml1); + return fml1; + } + + void check_relation_plugin::verify_join_project( + relation_base const& t1, relation_base const& t2, relation_base const& t, + unsigned_vector const& cols1, unsigned_vector const& cols2, unsigned_vector const& rm_cols) { + ast_manager& m = get_ast_manager(); + relation_signature const& sig2 = t.get_signature(); + relation_signature const& sigA = t1.get_signature(); + relation_signature const& sigB = t2.get_signature(); + relation_signature sig1; + sig1.append(sigA); + sig1.append(sigB); + + expr_ref fml1 = mk_join(t1, t2, cols1, cols2); + fml1 = mk_project(sig1, fml1, rm_cols); + fml1 = ground(t, fml1); + expr_ref fml2(m); + t.to_formula(fml2); + fml2 = ground(t, fml2); + check_equiv("join_project", fml1, fml2); + } + + expr_ref check_relation_plugin::mk_join( + relation_base const& t1, relation_base const& t2, + unsigned_vector const& cols1, unsigned_vector const& cols2) { + ast_manager& m = get_ast_manager(); + expr_ref fml1(m), fml2(m), fml3(m); + + relation_signature const& sig1 = t1.get_signature(); + relation_signature const& sig2 = t2.get_signature(); + var_ref var1(m), var2(m); + t1.to_formula(fml1); + t2.to_formula(fml2); + var_subst sub(m, false); + expr_ref_vector vars(m); + for (unsigned i = 0; i < sig2.size(); ++i) { + vars.push_back(m.mk_var(i + sig1.size(), sig2[i])); + } + sub(fml2, vars.size(), vars.c_ptr(), fml2); + fml1 = m.mk_and(fml1, fml2); + for (unsigned i = 0; i < cols1.size(); ++i) { + unsigned v1 = cols1[i]; + unsigned v2 = cols2[i]; + var1 = m.mk_var(v1, sig1[v1]); + var2 = m.mk_var(v2 + sig1.size(), sig2[v2]); + fml1 = m.mk_and(m.mk_eq(var1, var2), fml1); + } + return fml1; + } + + + void check_relation_plugin::verify_permutation( + relation_base const& src, relation_base const& dst, + unsigned_vector const& cycle) { + unsigned_vector perm; + relation_signature const& sig1 = src.get_signature(); + relation_signature const& sig2 = dst.get_signature(); + for (unsigned i = 0; i < sig1.size(); ++i) { + perm.push_back(i); + } + for (unsigned i = 0; i < cycle.size(); ++i) { + unsigned j = (i + 1)%cycle.size(); + unsigned col1 = cycle[i]; + unsigned col2 = cycle[j]; + perm[col2] = col1; + } + for (unsigned i = 0; i < perm.size(); ++i) { + SASSERT(sig2[perm[i]] == sig1[i]); + } + expr_ref_vector sub(m); + for (unsigned i = 0; i < perm.size(); ++i) { + sub.push_back(m.mk_var(perm[i], sig1[i])); + } + var_subst subst(m, false); + expr_ref fml1(m), fml2(m); + src.to_formula(fml1); + dst.to_formula(fml2); + subst(fml1, sub.size(), sub.c_ptr(), fml1); + expr_ref_vector vars(m); + for (unsigned i = 0; i < sig2.size(); ++i) { + vars.push_back(m.mk_const(symbol(i), sig2[i])); + } + + subst(fml1, vars.size(), vars.c_ptr(), fml1); + subst(fml2, vars.size(), vars.c_ptr(), fml2); + + check_equiv("permutation", fml1, fml2); + } + + void check_relation_plugin::verify_join( + relation_base const& t1, relation_base const& t2, relation_base const& t, + unsigned_vector const& cols1, unsigned_vector const& cols2) { + ast_manager& m = get_ast_manager(); + expr_ref fml1 = ground(t, mk_join(t1, t2, cols1, cols2)); + expr_ref fml2 = ground(t); + check_equiv("join", fml1, fml2); + } + + void check_relation_plugin::verify_filter(expr* fml0, relation_base const& t, expr* cond) { + expr_ref fml1(m), fml2(m); + fml1 = m.mk_and(fml0, cond); + t.to_formula(fml2); + + relation_signature const& sig = t.get_signature(); + expr_ref_vector vars(m); + var_subst sub(m, false); + for (unsigned i = 0; i < sig.size(); ++i) { + std::stringstream strm; + strm << "x" << i; + vars.push_back(m.mk_const(symbol(strm.str().c_str()), sig[i])); + } + sub(fml1, vars.size(), vars.c_ptr(), fml1); + sub(fml2, vars.size(), vars.c_ptr(), fml2); + check_equiv("filter", fml1, fml2); + } + + void check_relation_plugin::check_contains(char const* objective, expr* fml1, expr* fml2) { + expr_ref fml0(m); + fml0 = m.mk_and(fml1, fml2); + check_equiv(objective, fml0, fml2); + } + + void check_relation_plugin::check_equiv(char const* objective, expr* fml1, expr* fml2) { + TRACE("doc", tout << mk_pp(fml1, m) << "\n"; + tout << mk_pp(fml2, m) << "\n";); + smt_params fp; + smt::kernel solver(m, fp); + expr_ref tmp(m); + tmp = m.mk_not(m.mk_eq(fml1, fml2)); + solver.assert_expr(tmp); + lbool res = solver.check(); + if (res == l_false) { + IF_VERBOSE(3, verbose_stream() << objective << " verified\n";); + } + else { + IF_VERBOSE(3, verbose_stream() << "NOT verified " << res << "\n"; + verbose_stream() << mk_pp(fml1, m) << "\n"; + verbose_stream() << mk_pp(fml2, m) << "\n"; + verbose_stream().flush(); + ); + throw 0; + } + } + + void check_relation_plugin::verify_union(expr* dst0, relation_base const& src, + relation_base const& dst, + expr* delta0, relation_base const* delta) { + expr_ref fml1(m), fml2(m); + src.to_formula(fml1); + dst.to_formula(fml2); + fml1 = m.mk_or(fml1, dst0); + relation_signature const& sig = dst.get_signature(); + expr_ref_vector vars(m); + var_subst sub(m, false); + for (unsigned i = 0; i < sig.size(); ++i) { + std::stringstream strm; + strm << "x" << i; + vars.push_back(m.mk_const(symbol(strm.str().c_str()), sig[i])); + } + sub(fml1, vars.size(), vars.c_ptr(), fml1); + sub(fml2, vars.size(), vars.c_ptr(), fml2); + + check_equiv("union", fml1, fml2); + + if (delta) { + expr_ref d0(m), d(m); + delta->to_formula(d); + IF_VERBOSE(3, verbose_stream() << "verify delta " << d << "\n";); + // delta >= dst \ dst0 + // dst \ dst0 == delta & dst & \ dst0 + expr_ref fml4(m), fml5(m); + fml4 = m.mk_and(fml2, m.mk_not(dst0)); + sub(fml4, vars.size(), vars.c_ptr(), fml4); + sub(d, vars.size(), vars.c_ptr(), d); + check_contains("union_delta low", d, fml4); + // + // delta >= delta0 + // + sub(delta0, vars.size(), vars.c_ptr(), d0); + check_contains("union delta0", d, d0); + + // + // dst u delta0 = delta u dst0 + // + fml4 = m.mk_or(fml2, delta0); + fml5 = m.mk_or(d, dst0); + sub(fml4, vars.size(), vars.c_ptr(), fml4); + sub(fml5, vars.size(), vars.c_ptr(), fml5); + check_equiv("union no overflow", fml4, fml5); + } + } + + class check_relation_plugin::union_fn : public relation_union_fn { + scoped_ptr m_union; + public: + union_fn(relation_union_fn* m): m_union(m) {} + + virtual void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) { + TRACE("doc", _r.display(tout << "dst:\n"); _src.display(tout << "src:\n");); + check_relation& r = get(_r); + check_relation const& src = get(_src); + check_relation* d = get(_delta); + expr_ref fml0 = r.m_fml; + expr_ref delta0(r.m_fml.get_manager()); + if (d) d->to_formula(delta0); + (*m_union)(r.rb(), src.rb(), d?(&d->rb()):0); + r.get_plugin().verify_union(fml0, src.rb(), r.rb(), delta0, d?(&d->rb()):0); + r.rb().to_formula(r.m_fml); + if (d) d->rb().to_formula(d->m_fml); + } + }; + relation_union_fn * check_relation_plugin::mk_union_fn( + const relation_base & tgt, const relation_base & src, + const relation_base * delta) { + relation_base const* d1 = delta?(&(get(*delta).rb())):0; + relation_union_fn* u = m_base->mk_union_fn(get(tgt).rb(), get(src).rb(), d1); + return u?alloc(union_fn, u):0; + } + relation_union_fn * check_relation_plugin::mk_widen_fn( + const relation_base & tgt, const relation_base & src, + const relation_base * delta) { + relation_base const* d1 = delta?(&(get(*delta).rb())):0; + relation_union_fn* u = m_base->mk_widen_fn(get(tgt).rb(), get(src).rb(), d1); + return u?alloc(union_fn, u):0; + } + + class check_relation_plugin::filter_identical_fn : public relation_mutator_fn { + unsigned_vector m_cols; + scoped_ptr m_filter; + public: + filter_identical_fn(relation_mutator_fn* f, unsigned col_cnt, const unsigned *identical_cols) + : m_cols(col_cnt, identical_cols), + m_filter(f) { + } + + virtual ~filter_identical_fn() {} + + virtual void operator()(relation_base & _r) { + check_relation& r = get(_r); + check_relation_plugin& p = r.get_plugin(); + ast_manager& m = p.m; + expr_ref cond(m); + relation_signature const& sig = r.get_signature(); + expr_ref_vector conds(m); + unsigned c1 = m_cols[0]; + for (unsigned i = 1; i < m_cols.size(); ++i) { + unsigned c2 = m_cols[i]; + conds.push_back(m.mk_eq(m.mk_var(c1, sig[c1]), m.mk_var(c2, sig[c2]))); + } + cond = mk_and(m, conds.size(), conds.c_ptr()); + r.consistent_formula(); + (*m_filter)(r.rb()); + p.verify_filter(r.m_fml, r.rb(), cond); + r.rb().to_formula(r.m_fml); + } + }; + relation_mutator_fn * check_relation_plugin::mk_filter_identical_fn( + const relation_base & t, unsigned col_cnt, const unsigned * identical_cols) { + relation_mutator_fn* r = m_base->mk_filter_identical_fn(get(t).rb(), col_cnt, identical_cols); + return r?alloc(filter_identical_fn, r, col_cnt, identical_cols):0; + } + + class check_relation_plugin::filter_interpreted_fn : public relation_mutator_fn { + scoped_ptr m_mutator; + app_ref m_condition; + public: + filter_interpreted_fn(relation_mutator_fn* r, app_ref& condition) : + m_mutator(r), + m_condition(condition) { + } + + virtual ~filter_interpreted_fn() {} + + virtual void operator()(relation_base & tb) { + check_relation& r = get(tb); + check_relation_plugin& p = r.get_plugin(); + expr_ref fml = r.m_fml; + (*m_mutator)(r.rb()); + p.verify_filter(fml, r.rb(), m_condition); + r.rb().to_formula(r.m_fml); + } + }; + relation_mutator_fn * check_relation_plugin::mk_filter_interpreted_fn(const relation_base & t, app * condition) { + relation_mutator_fn* r = m_base->mk_filter_interpreted_fn(get(t).rb(), condition); + app_ref cond(condition, m); + return r?alloc(filter_interpreted_fn, r, cond):0; + } + + class check_relation_plugin::project_fn : public convenient_relation_project_fn { + scoped_ptr m_project; + public: + project_fn(relation_transformer_fn* p, + relation_base const & t, + unsigned removed_col_cnt, const unsigned * removed_cols) + : convenient_relation_project_fn(t.get_signature(), removed_col_cnt, removed_cols), + m_project(p) { + } + + virtual ~project_fn() {} + + virtual relation_base * operator()(const relation_base & tb) { + check_relation const& t = get(tb); + check_relation_plugin& p = t.get_plugin(); + relation_base* r = (*m_project)(t.rb()); + p.verify_project(tb, *r, m_removed_cols); + return alloc(check_relation, p, r->get_signature(), r); + } + }; + + + relation_transformer_fn * check_relation_plugin::mk_project_fn( + const relation_base & t, unsigned col_cnt, + const unsigned * removed_cols) { + relation_transformer_fn* p = m_base->mk_project_fn(get(t).rb(), col_cnt, removed_cols); + return p?alloc(project_fn, p, t, col_cnt, removed_cols):0; + } + + class check_relation_plugin::rename_fn : public convenient_relation_rename_fn { + scoped_ptr m_permute; + public: + rename_fn(relation_transformer_fn* permute, + relation_base const& t, unsigned cycle_len, const unsigned * cycle) + : convenient_relation_rename_fn(t.get_signature(), cycle_len, cycle), + m_permute(permute) { + } + + virtual ~rename_fn() {} + + virtual relation_base * operator()(const relation_base & _t) { + check_relation const& t = get(_t); + check_relation_plugin& p = t.get_plugin(); + relation_signature const& sig = get_result_signature(); + relation_base* r = (*m_permute)(t.rb()); + p.verify_permutation(t.rb(), *r, m_cycle); + return alloc(check_relation, p, sig, r); + } + }; + relation_transformer_fn * check_relation_plugin::mk_rename_fn( + const relation_base & r, + unsigned cycle_len, const unsigned * permutation_cycle) { + relation_transformer_fn* p = m_base->mk_rename_fn(get(r).rb(), cycle_len, permutation_cycle); + return p?alloc(rename_fn, p, r, cycle_len, permutation_cycle):0; + } + + class check_relation_plugin::filter_equal_fn : public relation_mutator_fn { + scoped_ptr m_filter; + relation_element m_val; + unsigned m_col; + public: + filter_equal_fn(relation_mutator_fn* filter, relation_base const& t, + const relation_element val, unsigned col): + m_filter(filter), + m_val(val), + m_col(col) + {} + virtual ~filter_equal_fn() { } + virtual void operator()(relation_base & tb) { + check_relation & t = get(tb); + check_relation_plugin& p = t.get_plugin(); + (*m_filter)(t.rb()); + expr_ref fml = t.m_fml; + t.rb().to_formula(t.m_fml); + fml = p.m.mk_and(fml, p.m.mk_eq(p.m.mk_var(m_col, t.get_signature()[m_col]), m_val)); + p.check_equiv("filter_equal", t.ground(fml), t.ground(t.m_fml)); + } + }; + relation_mutator_fn * check_relation_plugin::mk_filter_equal_fn( + const relation_base & t, const relation_element & value, unsigned col) { + relation_mutator_fn* r = m_base->mk_filter_equal_fn(get(t).rb(), value, col); + return r?alloc(filter_equal_fn, r, t, value, col):0; + } + + + + + class check_relation_plugin::negation_filter_fn : public relation_intersection_filter_fn { + scoped_ptr m_filter; + const unsigned_vector m_t_cols; + const unsigned_vector m_neg_cols; + public: + negation_filter_fn( + relation_intersection_filter_fn* filter, + unsigned joined_col_cnt, const unsigned *t_cols, const unsigned *neg_cols) + : m_filter(filter), + m_t_cols(joined_col_cnt, t_cols), m_neg_cols(joined_col_cnt, neg_cols) { + SASSERT(joined_col_cnt > 0); + } + + virtual void operator()(relation_base& tb, const relation_base& negb) { + check_relation& t = get(tb); + check_relation const& n = get(negb); + check_relation_plugin& p = t.get_plugin(); + ast_manager& m = p.get_ast_manager(); + expr_ref dst0(m); + t.to_formula(dst0); + (*m_filter)(t.rb(), n.rb()); + t.rb().to_formula(t.m_fml); + p.verify_filter_by_negation(dst0, t.rb(), n.rb(), m_t_cols, m_neg_cols); + } + }; + + relation_intersection_filter_fn * check_relation_plugin::mk_filter_by_negation_fn( + const relation_base& t, + const relation_base& neg, unsigned joined_col_cnt, const unsigned *t_cols, + const unsigned *negated_cols) { + relation_intersection_filter_fn* f = m_base->mk_filter_by_negation_fn(get(t).rb(), get(neg).rb(), joined_col_cnt, t_cols, negated_cols); + return f?alloc(negation_filter_fn, f, joined_col_cnt, t_cols, negated_cols):0; + } + + /* + The filter_by_negation postcondition: + filter_by_negation(tgt, neg, columns in tgt: c1,...,cN, + corresponding columns in neg: d1,...,dN): + tgt_1:={x: x\in tgt_0 && ! \exists y: ( y \in neg & pi_c1(x)= pi_d1(y) & ... & pi_cN(x)= pi_dN(y) ) } + */ + + void check_relation_plugin::verify_filter_by_negation( + expr* dst0, + relation_base const& dst, + relation_base const& neg, + unsigned_vector const& cols1, + unsigned_vector const& cols2) { + relation_signature const& sig1 = dst.get_signature(); + relation_signature const& sig2 = neg.get_signature(); + expr_ref dstf(m), negf(m); + std::cout << mk_pp(dst0, m) << "\n"; + expr_ref_vector eqs(m); + dst.to_formula(dstf); + std::cout << mk_pp(dstf, m) << "\n"; + neg.to_formula(negf); + std::cout << mk_pp(negf, m) << "\n"; + eqs.push_back(negf); + for (unsigned i = 0; i < cols1.size(); ++i) { + var_ref v1(m), v2(m); + unsigned c1 = cols1[i]; + unsigned c2 = cols2[i]; + SASSERT(sig1[c1] == sig2[c2]); + v1 = m.mk_var(sig2.size() + c1, sig1[c1]); + v2 = m.mk_var(c2, sig2[c2]); + eqs.push_back(m.mk_eq(v1, v2)); + } + negf = mk_and(m, eqs.size(), eqs.c_ptr()); + ptr_vector rev_sig2(sig2.size(), sig2.c_ptr()); + rev_sig2.reverse(); + svector names; + for (unsigned i = 0; i < sig2.size(); ++i) { + names.push_back(symbol(i)); + } + negf = m.mk_exists(rev_sig2.size(), rev_sig2.c_ptr(), names.c_ptr(), negf); + negf = m.mk_and(dst0, m.mk_not(negf)); + negf = ground(dst, negf); + dstf = ground(dst, dstf); + std::cout << negf << "\n"; + std::cout << dstf << "\n"; + check_equiv("filter by negation", dstf, negf); + } + + class check_relation_plugin::filter_proj_fn : public convenient_relation_project_fn { + app_ref m_cond; + scoped_ptr m_xform; + public: + filter_proj_fn(relation_transformer_fn* xform, + relation_base const& t, app_ref& cond, + unsigned col_cnt, const unsigned * removed_cols) : + convenient_relation_project_fn(t.get_signature(), col_cnt, removed_cols), + m_cond(cond), + m_xform(xform) + {} + + virtual ~filter_proj_fn() {} + + virtual relation_base* operator()(const relation_base & tb) { + check_relation const & t = get(tb); + check_relation_plugin& p = t.get_plugin(); + relation_base* r = (*m_xform)(t.rb()); + p.verify_filter_project(t.rb(), *r, m_cond, m_removed_cols); + relation_signature const& sig = get_result_signature(); + return alloc(check_relation, p, sig, r); + } + }; + relation_transformer_fn * check_relation_plugin::mk_filter_interpreted_and_project_fn( + const relation_base & t, app * condition, + unsigned removed_col_cnt, const unsigned * removed_cols) { + relation_transformer_fn* r = m_base->mk_filter_interpreted_and_project_fn(get(t).rb(), condition, removed_col_cnt, removed_cols); + app_ref cond(condition, m); + return r?alloc(filter_proj_fn, r, t, cond, removed_col_cnt, removed_cols):0; + } + + + + +} diff --git a/src/muz/rel/check_relation.h b/src/muz/rel/check_relation.h new file mode 100644 index 000000000..8000a2c72 --- /dev/null +++ b/src/muz/rel/check_relation.h @@ -0,0 +1,172 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + check_relation.h + +Abstract: + + Checked relation. + Each operation on an underlying relation is checked for correctness. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-09-23 + +Revision History: + + +--*/ + +#ifndef _CHECK_RELATION_H_ +#define _CHECK_RELATION_H_ + +#include "doc.h" +#include "dl_base.h" + +namespace datalog { + class check_relation_plugin; + class check_relation; + + class check_relation : public relation_base { + friend class check_relation_plugin; + ast_manager& m; + relation_base* m_relation; + expr_ref m_fml; + void check_equiv(char const* objective, expr* f1, expr* f2) const; + expr_ref mk_eq(relation_fact const& f) const; + public: + check_relation(check_relation_plugin& p, relation_signature const& s, relation_base* r); + virtual ~check_relation(); + virtual void reset(); + virtual void add_fact(const relation_fact & f); + virtual void add_new_fact(const relation_fact & f); + virtual bool contains_fact(const relation_fact & f) const; + virtual check_relation * clone() const; + virtual check_relation * complement(func_decl*) const; + virtual void to_formula(expr_ref& fml) const; + check_relation_plugin& get_plugin() const; + virtual bool fast_empty() const; + virtual bool empty() const; + virtual void display(std::ostream& out) const; + virtual bool is_precise() const { return m_relation->is_precise(); } + virtual unsigned get_size_estimate_rows() const { return m_relation->get_size_estimate_rows(); } + relation_base& rb() { return *m_relation; } + relation_base const& rb() const { return *m_relation; } + expr_ref ground(expr* fml) const; + void consistent_formula(); + }; + + class check_relation_plugin : public relation_plugin { + friend class check_relation; + + class join_fn; + class join_project_fn; + class project_fn; + class union_fn; + class rename_fn; + class filter_equal_fn; + class filter_identical_fn; + class filter_interpreted_fn; + class filter_by_negation_fn; + class filter_by_union_fn; + class filter_proj_fn; + class negation_filter_fn; + ast_manager& m; + relation_plugin* m_base; + static check_relation& get(relation_base& r); + static check_relation* get(relation_base* r); + static check_relation const & get(relation_base const& r); + expr_ref ground(relation_base const& rb, expr* fml) const; + expr_ref ground(relation_base const& rb) const; + + expr_ref mk_project( + relation_signature const& sig, + expr* fml, unsigned_vector const& removed_cols); + + expr_ref mk_join( + relation_base const& t1, relation_base const& t2, + unsigned_vector const& cols1, unsigned_vector const& cols2); + public: + check_relation_plugin(relation_manager& rm); + ~check_relation_plugin(); + void set_plugin(relation_plugin* p) { m_base = p; } + + virtual bool can_handle_signature(const relation_signature & s); + static symbol get_name() { return symbol("check_relation"); } + virtual relation_base * mk_empty(const relation_signature & s); + virtual relation_base * mk_full(func_decl* p, const relation_signature & s); + virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, + unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); + virtual relation_join_fn * mk_join_project_fn( + const relation_base & t1, const relation_base & t2, + unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, + unsigned removed_col_cnt, const unsigned * removed_cols); + virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, + const unsigned * removed_cols); + virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, + const unsigned * permutation_cycle); + virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, + const relation_base * delta); + virtual relation_union_fn * mk_widen_fn(const relation_base & tgt, const relation_base & src, + const relation_base * delta); + virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, + const unsigned * identical_cols); + virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, + unsigned col); + virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); + virtual relation_intersection_filter_fn * mk_filter_by_negation_fn( + const relation_base& t, + const relation_base& neg, unsigned joined_col_cnt, const unsigned *t_cols, + const unsigned *negated_cols); + virtual relation_transformer_fn * mk_filter_interpreted_and_project_fn( + const relation_base & t, app * condition, + unsigned removed_col_cnt, const unsigned * removed_cols); + + void verify_join(relation_base const& t1, relation_base const& t2, relation_base const& t, + unsigned_vector const& cols1, unsigned_vector const& cols2); + + + void verify_filter(expr* fml0, relation_base const& t, expr* cond); + + void verify_union(expr* fml0, relation_base const& src, relation_base const& dst, + expr* delta0, relation_base const* delta); + + void verify_permutation( + relation_base const& src, relation_base const& dst, + unsigned_vector const& cycle); + + void verify_project( + relation_base const& src, expr* f1, + relation_base const& dst, expr* f2, + unsigned_vector const& removed_cols); + + void verify_project( + relation_base const& src, + relation_base const& dst, + unsigned_vector const& removed_cols); + + void verify_filter_project( + relation_base const& src, relation_base const& dst, + app* cond, unsigned_vector const& removed_cols); + + void verify_join_project( + relation_base const& t1, relation_base const& t2, relation_base const& t, + unsigned_vector const& cols1, unsigned_vector const& cols2, unsigned_vector const& rm_cols); + + void check_equiv(char const* objective, expr* f1, expr* f2); + + void check_contains(char const* objective, expr* f1, expr* f2); + + void verify_filter_by_negation( + expr* dst0, + relation_base const& dst, + relation_base const& neg, + unsigned_vector const& dst_eq, + unsigned_vector const& neg_eq); + }; +}; + +#endif /* _CHECK_RELATION_H_ */ + diff --git a/src/muz/rel/dl_base.cpp b/src/muz/rel/dl_base.cpp index dc10b5f8e..7a7f9819b 100644 --- a/src/muz/rel/dl_base.cpp +++ b/src/muz/rel/dl_base.cpp @@ -89,8 +89,7 @@ namespace datalog { void relation_base::reset() { ast_manager & m = get_plugin().get_ast_manager(); app_ref bottom_ref(m.mk_false(), m); - scoped_ptr reset_fn = - get_manager().mk_filter_interpreted_fn(static_cast(*this), bottom_ref); + scoped_ptr reset_fn = get_manager().mk_filter_interpreted_fn(*this, bottom_ref); if(!reset_fn) { NOT_IMPLEMENTED_YET(); } diff --git a/src/muz/rel/dl_base.h b/src/muz/rel/dl_base.h index d03c94154..2dffa04f6 100644 --- a/src/muz/rel/dl_base.h +++ b/src/muz/rel/dl_base.h @@ -248,6 +248,7 @@ namespace datalog { class plugin_object { friend class relation_manager; friend class check_table_plugin; + friend class check_relation_plugin; family_id m_kind; symbol m_name; @@ -465,6 +466,14 @@ namespace datalog { relation_manager & get_manager() const { return get_plugin().get_manager(); } virtual bool empty() const = 0; + /** + \brief fast emptiness check. This may be partial. + The requirement is that if fast_empty returns true + then the table or relation is in fact empty. + It is allowed to return false even if the relation is non-empty. + */ + virtual bool fast_empty() const { return empty(); } + virtual void add_fact(const fact & f) = 0; /** \brief Like \c add_fact, only here the caller guarantees that the fact is not present in @@ -497,6 +506,7 @@ namespace datalog { virtual unsigned get_size_estimate_rows() const { return UINT_MAX; } virtual unsigned get_size_estimate_bytes() const { return UINT_MAX; } virtual bool knows_exact_size() const { return false; } + unsigned num_columns() const { return get_signature().size(); } virtual void display(std::ostream & out) const = 0; }; diff --git a/src/muz/rel/dl_compiler.cpp b/src/muz/rel/dl_compiler.cpp index 2a2507d7f..d73f8c4ad 100644 --- a/src/muz/rel/dl_compiler.cpp +++ b/src/muz/rel/dl_compiler.cpp @@ -184,7 +184,7 @@ namespace datalog { TRACE("dl", tout << "Adding unbound column " << mk_pp(pred, m_context.get_manager()) << "\n";); IF_VERBOSE(3, { expr_ref e(m_context.get_manager()); - compiled_rule->to_formula(e); + m_context.get_rule_manager().to_formula(*compiled_rule, e); verbose_stream() << "Compiling unsafe rule column " << col_idx << "\n" << mk_ismt2_pp(e, m_context.get_manager()) << "\n"; }); @@ -408,13 +408,14 @@ namespace datalog { void compiler::get_local_indexes_for_projection(app * t, var_counter & globals, unsigned ofs, unsigned_vector & res) { + // TODO: this can be optimized to avoid renames in some cases unsigned n = t->get_num_args(); for(unsigned i = 0; iget_arg(i); - if(!is_var(e) || globals.get(to_var(e)->get_idx())!=0) { - continue; + if (is_var(e) && globals.get(to_var(e)->get_idx()) > 0) { + globals.update(to_var(e)->get_idx(), -1); + res.push_back(i + ofs); } - res.push_back(i+ofs); } } @@ -422,11 +423,30 @@ namespace datalog { SASSERT(r->get_positive_tail_size()==2); ast_manager & m = m_context.get_manager(); rule_counter counter; - counter.count_rule_vars(m, r); + // leave one column copy per var in the head (avoids later duplication) + counter.count_vars(m, r->get_head(), -1); + + // take interp & neg preds into account (at least 1 column copy if referenced) + unsigned n = r->get_tail_size(); + if (n > 2) { + rule_counter counter_tail; + for (unsigned i = 2; i < n; ++i) { + counter_tail.count_vars(m, r->get_tail(i)); + } + + rule_counter::iterator I = counter_tail.begin(), E = counter_tail.end(); + for (; I != E; ++I) { + int& n = counter.get(I->m_key); + if (n == 0) + n = -1; + } + } + app * t1 = r->get_tail(0); app * t2 = r->get_tail(1); - counter.count_vars(m, t1, -1); - counter.count_vars(m, t2, -1); + counter.count_vars(m, t1); + counter.count_vars(m, t2); + get_local_indexes_for_projection(t1, counter, 0, res); get_local_indexes_for_projection(t2, counter, t1->get_num_args(), res); } @@ -589,7 +609,8 @@ namespace datalog { dealloc = true; } - // enforce interpreted tail predicates + + // add unbounded columns for interpreted filter unsigned ut_len = r->get_uninterpreted_tail_size(); unsigned ft_len = r->get_tail_size(); // full tail ptr_vector tail; @@ -597,17 +618,14 @@ namespace datalog { tail.push_back(r->get_tail(tail_index)); } + expr_ref_vector binding(m); if (!tail.empty()) { app_ref filter_cond(tail.size() == 1 ? to_app(tail.back()) : m.mk_and(tail.size(), tail.c_ptr()), m); - ptr_vector filter_vars; - get_free_vars(filter_cond, filter_vars); - + m_free_vars(filter_cond); // create binding - expr_ref_vector binding(m); - binding.resize(filter_vars.size()+1); - - for (unsigned v = 0; v < filter_vars.size(); ++v) { - if (!filter_vars[v]) + binding.resize(m_free_vars.size()+1); + for (unsigned v = 0; v < m_free_vars.size(); ++v) { + if (!m_free_vars[v]) continue; int2ints::entry * entry = var_indexes.find_core(v); @@ -616,7 +634,7 @@ namespace datalog { src_col = entry->get_data().m_value.back(); } else { // we have an unbound variable, so we add an unbound column for it - relation_sort unbound_sort = filter_vars[v]; + relation_sort unbound_sort = m_free_vars[v]; reg_idx new_reg; bool new_dealloc; @@ -633,19 +651,64 @@ namespace datalog { entry->get_data().m_value.push_back(src_col); } relation_sort var_sort = m_reg_signatures[filtered_res][src_col]; - binding[filter_vars.size()-v] = m.mk_var(src_col, var_sort); + binding[m_free_vars.size()-v] = m.mk_var(src_col, var_sort); } + } + + //enforce negative predicates + for (unsigned i = pt_len; iget_tail(i); + func_decl * neg_pred = neg_tail->get_decl(); + variable_intersection neg_intersection(m_context.get_manager()); + neg_intersection.populate(single_res_expr, neg_tail); + unsigned_vector t_cols(neg_intersection.size(), neg_intersection.get_cols1()); + unsigned_vector neg_cols(neg_intersection.size(), neg_intersection.get_cols2()); + + unsigned neg_len = neg_tail->get_num_args(); + for (unsigned i = 0; iget_arg(i); + if (is_var(e)) { + continue; + } + SASSERT(is_app(e)); + relation_sort arg_sort; + m_context.get_rel_context()->get_rmanager().from_predicate(neg_pred, i, arg_sort); + reg_idx new_reg; + bool new_dealloc; + make_add_constant_column(head_pred, filtered_res, arg_sort, to_app(e), new_reg, new_dealloc, acc); + + if (dealloc) + make_dealloc_non_void(filtered_res, acc); + dealloc = new_dealloc; + filtered_res = new_reg; + + t_cols.push_back(single_res_expr.size()); + neg_cols.push_back(i); + single_res_expr.push_back(e); + } + SASSERT(t_cols.size() == neg_cols.size()); + + reg_idx neg_reg = m_pred_regs.find(neg_pred); + if (!dealloc) + make_clone(filtered_res, filtered_res, acc); + acc.push_back(instruction::mk_filter_by_negation(filtered_res, neg_reg, t_cols.size(), + t_cols.c_ptr(), neg_cols.c_ptr())); + dealloc = true; + } + + // enforce interpreted tail predicates + if (!tail.empty()) { + app_ref filter_cond(tail.size() == 1 ? to_app(tail.back()) : m.mk_and(tail.size(), tail.c_ptr()), m); // check if there are any columns to remove unsigned_vector remove_columns; { unsigned_vector var_idx_to_remove; - ptr_vector vars; - get_free_vars(r->get_head(), vars); + m_free_vars(r->get_head()); for (int2ints::iterator I = var_indexes.begin(), E = var_indexes.end(); I != E; ++I) { unsigned var_idx = I->m_key; - if (!vars.get(var_idx, 0)) { + if (!m_free_vars.contains(var_idx)) { unsigned_vector & cols = I->m_value; for (unsigned i = 0; i < cols.size(); ++i) { remove_columns.push_back(cols[i]); @@ -697,47 +760,6 @@ namespace datalog { dealloc = true; } - //enforce negative predicates - for (unsigned i = pt_len; iget_tail(i); - func_decl * neg_pred = neg_tail->get_decl(); - variable_intersection neg_intersection(m_context.get_manager()); - neg_intersection.populate(single_res_expr, neg_tail); - unsigned_vector t_cols(neg_intersection.size(), neg_intersection.get_cols1()); - unsigned_vector neg_cols(neg_intersection.size(), neg_intersection.get_cols2()); - - unsigned neg_len = neg_tail->get_num_args(); - for (unsigned i = 0; iget_arg(i); - if (is_var(e)) { - continue; - } - SASSERT(is_app(e)); - relation_sort arg_sort; - m_context.get_rel_context()->get_rmanager().from_predicate(neg_pred, i, arg_sort); - reg_idx new_reg; - bool new_dealloc; - make_add_constant_column(head_pred, filtered_res, arg_sort, to_app(e), new_reg, new_dealloc, acc); - - if (dealloc) - make_dealloc_non_void(filtered_res, acc); - dealloc = new_dealloc; - filtered_res = new_reg; // here filtered_res value gets changed !! - - t_cols.push_back(single_res_expr.size()); - neg_cols.push_back(i); - single_res_expr.push_back(e); - } - SASSERT(t_cols.size() == neg_cols.size()); - - reg_idx neg_reg = m_pred_regs.find(neg_pred); - if (!dealloc) - make_clone(filtered_res, filtered_res, acc); - acc.push_back(instruction::mk_filter_by_negation(filtered_res, neg_reg, t_cols.size(), - t_cols.c_ptr(), neg_cols.c_ptr())); - dealloc = true; - } - #if 0 // this version is potentially better for non-symbolic tables, // since it constraints each unbound column at a time (reducing the @@ -745,10 +767,9 @@ namespace datalog { unsigned ft_len=r->get_tail_size(); //full tail for(unsigned tail_index=ut_len; tail_indexget_tail(tail_index); - ptr_vector t_vars; - ::get_free_vars(t, t_vars); + m_free_vars(t); - if(t_vars.empty()) { + if (m_free_vars.empty()) { expr_ref simplified(m); m_context.get_rewriter()(t, simplified); if(m.is_true(simplified)) { @@ -761,23 +782,22 @@ namespace datalog { } //determine binding size - while (!t_vars.back()) { - t_vars.pop_back(); - } - unsigned max_var = t_vars.size(); + + unsigned max_var = m_free_vars.size(); + while (max_var > 0 && !m_free_vars[max_var-1]) --max_var; //create binding expr_ref_vector binding(m); - binding.resize(max_var+1); + binding.resize(max_var); - for(unsigned v = 0; v < t_vars.size(); ++v) { - if (!t_vars[v]) { + for(unsigned v = 0; v < max_var; ++v) { + if (!m_free_vars[v]) { continue; } int2ints::entry * e = var_indexes.find_core(v); if(!e) { //we have an unbound variable, so we add an unbound column for it - relation_sort unbound_sort = t_vars[v]; + relation_sort unbound_sort = m_free_vars[v]; reg_idx new_reg; TRACE("dl", tout << mk_pp(head_pred, m_context.get_manager()) << "\n";); @@ -1338,7 +1358,7 @@ namespace datalog { acc.set_observer(0); - TRACE("dl", execution_code.display(*m_context.get_rel_context(), tout);); + TRACE("dl", execution_code.display(execution_context(m_context), tout);); } diff --git a/src/muz/rel/dl_compiler.h b/src/muz/rel/dl_compiler.h index e0f9af424..92f50eb02 100644 --- a/src/muz/rel/dl_compiler.h +++ b/src/muz/rel/dl_compiler.h @@ -111,12 +111,13 @@ namespace datalog { */ instruction_block & m_top_level_code; pred2idx m_pred_regs; - reg_idx m_new_reg; - vector m_reg_signatures; - obj_pair_map m_constant_registers; + reg_idx m_new_reg; + vector m_reg_signatures; + obj_pair_map m_constant_registers; obj_pair_map m_total_registers; - obj_map m_empty_tables_registers; - instruction_observer m_instruction_observer; + obj_map m_empty_tables_registers; + instruction_observer m_instruction_observer; + expr_free_vars m_free_vars; /** If true, the union operation on the underlying structure only provides the information diff --git a/src/muz/rel/dl_instruction.cpp b/src/muz/rel/dl_instruction.cpp index a702c27ce..7eb8d4375 100644 --- a/src/muz/rel/dl_instruction.cpp +++ b/src/muz/rel/dl_instruction.cpp @@ -37,8 +37,7 @@ namespace datalog { execution_context::execution_context(context & context) : m_context(context), m_stopwatch(0), - m_timelimit_ms(0), - m_eager_emptiness_checking(context.eager_emptiness_checking()) {} + m_timelimit_ms(0) {} execution_context::~execution_context() { reset(); @@ -63,6 +62,10 @@ namespace datalog { return dynamic_cast(*m_context.get_rel_context()); } + rel_context const& execution_context::get_rel_context() const { + return dynamic_cast(*m_context.get_rel_context()); + } + struct compare_size_proc { typedef std::pair pr; bool operator()(pr const& a, pr const& b) const { @@ -122,6 +125,22 @@ namespace datalog { m_timelimit_ms < static_cast(1000*m_stopwatch->get_current_seconds())); } + void execution_context::collect_statistics(statistics& st) const { + st.update("dl.joins", m_stats.m_join); + st.update("dl.project", m_stats.m_project); + st.update("dl.filter", m_stats.m_filter); + st.update("dl.total", m_stats.m_total); + st.update("dl.unary_singleton", m_stats.m_unary_singleton); + st.update("dl.filter_by_negation", m_stats.m_filter_by_negation); + st.update("dl.select_equal_project", m_stats.m_select_equal_project); + st.update("dl.join_project", m_stats.m_join_project); + st.update("dl.project_rename", m_stats.m_project_rename); + st.update("dl.union", m_stats.m_union); + st.update("dl.filter_interpreted_project", m_stats.m_filter_interp_project); + st.update("dl.filter_id", m_stats.m_filter_id); + st.update("dl.filter_eq", m_stats.m_filter_eq); + } + // ----------------------------------- // @@ -141,17 +160,29 @@ namespace datalog { process_costs(); } - void instruction::display_indented(rel_context_base const & _ctx, std::ostream & out, std::string indentation) const { + void instruction::collect_statistics(statistics& st) const { + costs c; + get_total_cost(c); + st.update("instruction", c.instructions); + st.update("instruction-time", c.milliseconds); + } + + + void instruction::display_indented(execution_context const & _ctx, std::ostream & out, std::string indentation) const { out << indentation; - rel_context const& ctx = dynamic_cast(_ctx); - display_head_impl(ctx, out); + rel_context const& ctx = _ctx.get_rel_context(); + display_head_impl(_ctx, out); if (ctx.output_profile()) { out << " {"; output_profile(out); out << '}'; } out << "\n"; - display_body_impl(ctx, out, indentation); + display_body_impl(_ctx, out, indentation); + } + + void instruction::log_verbose(execution_context& ctx) { + IF_VERBOSE(2, display(ctx, verbose_stream());); } class instr_io : public instruction { @@ -162,6 +193,7 @@ namespace datalog { instr_io(bool store, func_decl_ref pred, reg_idx reg) : m_store(store), m_pred(pred), m_reg(reg) {} virtual bool perform(execution_context & ctx) { + log_verbose(ctx); if (m_store) { if (ctx.reg(m_reg)) { ctx.get_rel_context().store_relation(m_pred, ctx.release_reg(m_reg)); @@ -177,7 +209,7 @@ namespace datalog { } else { relation_base& rel = ctx.get_rel_context().get_relation(m_pred); - if ((!ctx.eager_emptiness_checking() || !rel.empty())) { + if (!rel.fast_empty()) { ctx.set_reg(m_reg, rel.clone()); } else { @@ -189,7 +221,7 @@ namespace datalog { virtual void make_annotations(execution_context & ctx) { ctx.set_register_annotation(m_reg, m_pred->get_name().bare_str()); } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { const char * rel_name = m_pred->get_name().bare_str(); if (m_store) { out << "store " << m_reg << " into " << rel_name; @@ -220,7 +252,7 @@ namespace datalog { virtual void make_annotations(execution_context & ctx) { ctx.set_register_annotation(m_reg, "alloc"); } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "dealloc " << m_reg; } }; @@ -237,7 +269,7 @@ namespace datalog { instr_clone_move(bool clone, reg_idx src, reg_idx tgt) : m_clone(clone), m_src(src), m_tgt(tgt) {} virtual bool perform(execution_context & ctx) { - ctx.make_empty(m_tgt); + if (ctx.reg(m_src)) log_verbose(ctx); if (m_clone) { ctx.set_reg(m_tgt, ctx.reg(m_src) ? ctx.reg(m_src)->clone() : 0); } @@ -255,7 +287,7 @@ namespace datalog { ctx.set_register_annotation(m_src, str); } } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << (m_clone ? "clone " : "move ") << m_src << " into " << m_tgt; } }; @@ -278,7 +310,7 @@ namespace datalog { idx_vector::const_iterator end=m_controls.end(); for(; it != end; ++it) { reg_idx r = *it; - if (ctx.reg(r) && !ctx.reg(r)->empty()) { + if (ctx.reg(r) && !ctx.reg(r)->fast_empty()) { return false; } } @@ -296,6 +328,7 @@ namespace datalog { dealloc(m_body); } virtual bool perform(execution_context & ctx) { + log_verbose(ctx); TRACE("dl", tout << "loop entered\n";); unsigned count = 0; while (!control_is_empty(ctx)) { @@ -311,11 +344,11 @@ namespace datalog { virtual void make_annotations(execution_context & ctx) { m_body->make_annotations(ctx); } - virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const & ctx, std::ostream & out) const { out << "while"; print_container(m_controls, out); } - virtual void display_body_impl(rel_context_base const & ctx, std::ostream & out, std::string indentation) const { + virtual void display_body_impl(execution_context const & ctx, std::ostream & out, std::string indentation) const { m_body->display_indented(ctx, out, indentation+" "); } }; @@ -339,8 +372,10 @@ namespace datalog { : m_rel1(rel1), m_rel2(rel2), m_cols1(col_cnt, cols1), m_cols2(col_cnt, cols2), m_res(result) {} virtual bool perform(execution_context & ctx) { - ctx.make_empty(m_res); + log_verbose(ctx); + ++ctx.m_stats.m_join; if (!ctx.reg(m_rel1) || !ctx.reg(m_rel2)) { + ctx.make_empty(m_res); return true; } relation_join_fn * fn; @@ -367,7 +402,7 @@ namespace datalog { ctx.reg(m_res)->get_signature().output(ctx.get_rel_context().get_manager(), tout); tout<<":"<get_size_estimate_rows()<<"\n";); - if (ctx.eager_emptiness_checking() && ctx.reg(m_res)->empty()) { + if (ctx.reg(m_res)->fast_empty()) { ctx.make_empty(m_res); } return true; @@ -378,7 +413,7 @@ namespace datalog { ctx.get_register_annotation(m_rel1, a1); ctx.set_register_annotation(m_res, "join " + a1 + " " + a2); } - virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const & ctx, std::ostream & out) const { out << "join " << m_rel1; print_container(m_cols1, out); out << " and " << m_rel2; @@ -400,6 +435,8 @@ namespace datalog { instr_filter_equal(ast_manager & m, reg_idx reg, const relation_element & value, unsigned col) : m_reg(reg), m_value(value, m), m_col(col) {} virtual bool perform(execution_context & ctx) { + log_verbose(ctx); + ++ctx.m_stats.m_filter_eq; if (!ctx.reg(m_reg)) { return true; } @@ -417,7 +454,7 @@ namespace datalog { } (*fn)(r); - if (ctx.eager_emptiness_checking() && r.empty()) { + if (r.fast_empty()) { ctx.make_empty(m_reg); } return true; @@ -427,9 +464,9 @@ namespace datalog { a << "filter_equal " << m_col << " val: " << ctx.get_rel_context().get_rmanager().to_nice_string(m_value); ctx.set_register_annotation(m_reg, a.str()); } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "filter_equal " << m_reg << " col: " << m_col << " val: " - << ctx.get_rmanager().to_nice_string(m_value); + << ctx.get_rel_context().get_rmanager().to_nice_string(m_value); } }; @@ -447,6 +484,8 @@ namespace datalog { instr_filter_identical(reg_idx reg, unsigned col_cnt, const unsigned * identical_cols) : m_reg(reg), m_cols(col_cnt, identical_cols) {} virtual bool perform(execution_context & ctx) { + log_verbose(ctx); + ++ctx.m_stats.m_filter_id; if (!ctx.reg(m_reg)) { return true; } @@ -464,12 +503,12 @@ namespace datalog { } (*fn)(r); - if (ctx.eager_emptiness_checking() && r.empty()) { + if (r.fast_empty()) { ctx.make_empty(m_reg); } return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "filter_identical " << m_reg << " "; print_container(m_cols, out); } @@ -493,6 +532,8 @@ namespace datalog { if (!ctx.reg(m_reg)) { return true; } + log_verbose(ctx); + ++ctx.m_stats.m_filter; relation_mutator_fn * fn; relation_base & r = *ctx.reg(m_reg); @@ -508,14 +549,14 @@ namespace datalog { } (*fn)(r); - if (ctx.eager_emptiness_checking() && r.empty()) { + if (r.fast_empty()) { ctx.make_empty(m_reg); } TRACE("dl_verbose", r.display(tout <<"post-filter-interpreted:\n");); return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "filter_interpreted " << m_reg << " using " << mk_pp(m_cond, m_cond.get_manager()); } @@ -543,10 +584,12 @@ namespace datalog { m_res(result) {} virtual bool perform(execution_context & ctx) { + log_verbose(ctx); if (!ctx.reg(m_src)) { ctx.make_empty(m_res); return true; } + ++ctx.m_stats.m_filter_interp_project; relation_transformer_fn * fn; relation_base & reg = *ctx.reg(m_src); @@ -563,14 +606,14 @@ namespace datalog { ctx.set_reg(m_res, (*fn)(reg)); - if (ctx.eager_emptiness_checking() && ctx.reg(m_res)->empty()) { + if (ctx.reg(m_res)->fast_empty()) { ctx.make_empty(m_res); } TRACE("dl_verbose", reg.display(tout << "post-filter-interpreted-and-project:\n");); return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "filter_interpreted_and_project " << m_src << " into " << m_res; out << " using " << mk_pp(m_cond, m_cond.get_manager()); out << " deleting columns "; @@ -606,6 +649,8 @@ namespace datalog { if (!ctx.reg(m_src)) { return true; } + log_verbose(ctx); + ++ctx.m_stats.m_union; relation_base & r_src = *ctx.reg(m_src); if (!ctx.reg(m_tgt)) { relation_base * new_tgt = r_src.get_plugin().mk_empty(r_src); @@ -669,7 +714,7 @@ namespace datalog { r_delta->display(tout <<"delta:"); }); - if (ctx.eager_emptiness_checking() && r_delta && r_delta->empty()) { + if (r_delta && r_delta->fast_empty()) { ctx.make_empty(m_delta); } @@ -685,7 +730,7 @@ namespace datalog { } ctx.set_register_annotation(m_delta, str); } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << (m_widen ? "widen " : "union ") << m_src << " into " << m_tgt; if (m_delta!=execution_context::void_register) { out << " with delta " << m_delta; @@ -713,11 +758,13 @@ namespace datalog { reg_idx tgt) : m_projection(projection), m_src(src), m_cols(col_cnt, cols), m_tgt(tgt) {} virtual bool perform(execution_context & ctx) { - ctx.make_empty(m_tgt); if (!ctx.reg(m_src)) { + ctx.make_empty(m_tgt); return true; } + log_verbose(ctx); + ++ctx.m_stats.m_project_rename; relation_transformer_fn * fn; relation_base & r_src = *ctx.reg(m_src); if (!find_fn(r_src, fn)) { @@ -739,7 +786,7 @@ namespace datalog { return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << (m_projection ? "project " : "rename ") << m_src << " into " << m_tgt; out << (m_projection ? " deleting columns " : " with cycle "); print_container(m_cols, out); @@ -778,10 +825,12 @@ namespace datalog { m_cols2(joined_col_cnt, cols2), m_removed_cols(removed_col_cnt, removed_cols), m_res(result) { } virtual bool perform(execution_context & ctx) { - ctx.make_empty(m_res); + log_verbose(ctx); if (!ctx.reg(m_rel1) || !ctx.reg(m_rel2)) { + ctx.make_empty(m_res); return true; } + ++ctx.m_stats.m_join_project; relation_join_fn * fn; const relation_base & r1 = *ctx.reg(m_rel1); const relation_base & r2 = *ctx.reg(m_rel2); @@ -796,15 +845,25 @@ namespace datalog { TRACE("dl", tout<\n";); ctx.set_reg(m_res, (*fn)(r1, r2)); TRACE("dl", tout<get_size_estimate_rows()<<"\n";); - if (ctx.eager_emptiness_checking() && ctx.reg(m_res)->empty()) { + if (ctx.reg(m_res)->fast_empty()) { ctx.make_empty(m_res); } return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { - out << "join_project " << m_rel1; + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { + relation_base const* r1 = ctx.reg(m_rel1); + relation_base const* r2 = ctx.reg(m_rel2); + out << "join_project " << m_rel1; + if (r1) { + out << ":" << r1->num_columns(); + out << "-" << r1->get_size_estimate_rows(); + } print_container(m_cols1, out); out << " and " << m_rel2; + if (r2) { + out << ":" << r2->num_columns(); + out << "-" << r2->get_size_estimate_rows(); + } print_container(m_cols2, out); out << " into " << m_res << " removing columns "; print_container(m_removed_cols, out); @@ -843,7 +902,8 @@ namespace datalog { ctx.make_empty(m_result); return true; } - + log_verbose(ctx); + ++ctx.m_stats.m_select_equal_project; relation_transformer_fn * fn; relation_base & r = *ctx.reg(m_src); if (!find_fn(r, fn)) { @@ -857,14 +917,14 @@ namespace datalog { } ctx.set_reg(m_result, (*fn)(r)); - if (ctx.eager_emptiness_checking() && ctx.reg(m_result)->empty()) { + if (ctx.reg(m_result)->fast_empty()) { ctx.make_empty(m_result); } return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "select_equal_and_project " << m_src <<" into " << m_result << " col: " << m_col - << " val: " << ctx.get_rmanager().to_nice_string(m_value); + << " val: " << ctx.get_rel_context().get_rmanager().to_nice_string(m_value); } virtual void make_annotations(execution_context & ctx) { std::stringstream s; @@ -893,9 +953,12 @@ namespace datalog { const unsigned * cols2) : m_tgt(tgt), m_neg_rel(neg_rel), m_cols1(col_cnt, cols1), m_cols2(col_cnt, cols2) {} virtual bool perform(execution_context & ctx) { + log_verbose(ctx); if (!ctx.reg(m_tgt) || !ctx.reg(m_neg_rel)) { return true; } + ++ctx.m_stats.m_filter_by_negation; + relation_intersection_filter_fn * fn; relation_base & r1 = *ctx.reg(m_tgt); const relation_base & r2 = *ctx.reg(m_neg_rel); @@ -911,12 +974,12 @@ namespace datalog { } (*fn)(r1, r2); - if (ctx.eager_emptiness_checking() && r1.empty()) { + if (r1.fast_empty()) { ctx.make_empty(m_tgt); } return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "filter_by_negation on " << m_tgt; print_container(m_cols1, out); out << " with " << m_neg_rel; @@ -948,16 +1011,17 @@ namespace datalog { m_fact.push_back(val); } virtual bool perform(execution_context & ctx) { - ctx.make_empty(m_tgt); + log_verbose(ctx); + ++ctx.m_stats.m_unary_singleton; relation_base * rel = ctx.get_rel_context().get_rmanager().mk_empty_relation(m_sig, m_pred); rel->add_fact(m_fact); ctx.set_reg(m_tgt, rel); return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "mk_unary_singleton into " << m_tgt << " sort:" - << ctx.get_rmanager().to_nice_string(m_sig[0]) << " val:" - << ctx.get_rmanager().to_nice_string(m_sig[0], m_fact[0]); + << ctx.get_rel_context().get_rmanager().to_nice_string(m_sig[0]) << " val:" + << ctx.get_rel_context().get_rmanager().to_nice_string(m_sig[0], m_fact[0]); } virtual void make_annotations(execution_context & ctx) { std::string s; @@ -980,13 +1044,14 @@ namespace datalog { public: instr_mk_total(const relation_signature & sig, func_decl* p, reg_idx tgt) : m_sig(sig), m_pred(p), m_tgt(tgt) {} virtual bool perform(execution_context & ctx) { - ctx.make_empty(m_tgt); + log_verbose(ctx); + ++ctx.m_stats.m_total; ctx.set_reg(m_tgt, ctx.get_rel_context().get_rmanager().mk_full_relation(m_sig, m_pred)); return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "mk_total into " << m_tgt << " sort:" - << ctx.get_rmanager().to_nice_string(m_sig); + << ctx.get_rel_context().get_rmanager().to_nice_string(m_sig); } virtual void make_annotations(execution_context & ctx) { std::string s; @@ -1006,10 +1071,11 @@ namespace datalog { instr_mark_saturated(ast_manager & m, func_decl * pred) : m_pred(pred, m) {} virtual bool perform(execution_context & ctx) { + log_verbose(ctx); ctx.get_rel_context().get_rmanager().mark_saturated(m_pred); return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "mark_saturated " << m_pred->get_name().bare_str(); } virtual void make_annotations(execution_context & ctx) { @@ -1027,12 +1093,13 @@ namespace datalog { instr_assert_signature(const relation_signature & s, reg_idx tgt) : m_sig(s), m_tgt(tgt) {} virtual bool perform(execution_context & ctx) { + log_verbose(ctx); if (ctx.reg(m_tgt)) { SASSERT(ctx.reg(m_tgt)->get_signature()==m_sig); } return true; } - virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { out << "instr_assert_signature of " << m_tgt << " signature:"; print_container(m_sig, out); } @@ -1081,7 +1148,7 @@ namespace datalog { TRACE("dl", tout <<"% "; - instr->display_head_impl(ctx.get_rel_context(), tout); + instr->display_head_impl(ctx, tout); tout <<"\n";); success = !ctx.should_terminate() && instr->perform(ctx); } @@ -1096,6 +1163,15 @@ namespace datalog { } } + + void instruction_block::collect_statistics(statistics& st) const { + instr_seq_type::const_iterator it = m_data.begin(); + instr_seq_type::const_iterator end = m_data.end(); + for(; it!=end; ++it) { + (*it)->collect_statistics(st); + } + } + void instruction_block::make_annotations(execution_context & ctx) { instr_seq_type::iterator it = m_data.begin(); instr_seq_type::iterator end = m_data.end(); @@ -1104,14 +1180,14 @@ namespace datalog { } } - void instruction_block::display_indented(rel_context_base const& _ctx, std::ostream & out, std::string indentation) const { - rel_context const& ctx = dynamic_cast(_ctx); + void instruction_block::display_indented(execution_context const& _ctx, std::ostream & out, std::string indentation) const { + rel_context const& ctx = _ctx.get_rel_context(); instr_seq_type::const_iterator it = m_data.begin(); instr_seq_type::const_iterator end = m_data.end(); for(; it!=end; ++it) { instruction * i = (*it); if (i->passes_output_thresholds(ctx.get_context()) || i->being_recorded()) { - i->display_indented(ctx, out, indentation); + i->display_indented(_ctx, out, indentation); } } } diff --git a/src/muz/rel/dl_instruction.h b/src/muz/rel/dl_instruction.h index fa705a172..3910f6d0b 100644 --- a/src/muz/rel/dl_instruction.h +++ b/src/muz/rel/dl_instruction.h @@ -66,14 +66,6 @@ namespace datalog { reg_annotations m_reg_annotation; stopwatch * m_stopwatch; unsigned m_timelimit_ms; //zero means no limit - /** - \brief If true, after every operation that may result in an empty relation, a check - for emptiness will be performed, and if a relation is empty, it will be deleted - and replaced by zero. This allows us to avoid performing operations that would have - no effect due to relation emptiness, but if the check for emptiness is expensive, its - cost may overcome the gains. - */ - bool m_eager_emptiness_checking; public: execution_context(context & context); ~execution_context(); @@ -81,12 +73,32 @@ namespace datalog { void reset(); rel_context & get_rel_context(); + rel_context const & get_rel_context() const; void set_timelimit(unsigned time_in_ms); void reset_timelimit(); bool should_terminate(); - bool eager_emptiness_checking() const { return m_eager_emptiness_checking; } + struct stats { + unsigned m_join; + unsigned m_project; + unsigned m_filter; + unsigned m_total; + unsigned m_unary_singleton; + unsigned m_filter_by_negation; + unsigned m_select_equal_project; + unsigned m_join_project; + unsigned m_project_rename; + unsigned m_union; + unsigned m_filter_interp_project; + unsigned m_filter_id; + unsigned m_filter_eq; + stats() { reset(); } + void reset() { memset(this, 0, sizeof(*this)); } + }; + stats m_stats; + + void collect_statistics(statistics& st) const; /** \brief Return reference to \c i -th register that contains pointer to a relation. @@ -213,7 +225,7 @@ namespace datalog { The newline character at the end should not be printed. */ - virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const { + virtual void display_head_impl(execution_context const & ctx, std::ostream & out) const { out << ""; } /** @@ -221,7 +233,9 @@ namespace datalog { Each line must be prepended by \c indentation and ended by a newline character. */ - virtual void display_body_impl(rel_context const & ctx, std::ostream & out, std::string indentation) const {} + virtual void display_body_impl(execution_context const & ctx, std::ostream & out, std::string indentation) const {} + void log_verbose(execution_context& ctx); + public: typedef execution_context::reg_type reg_type; typedef execution_context::reg_idx reg_idx; @@ -232,10 +246,10 @@ namespace datalog { virtual void make_annotations(execution_context & ctx) = 0; - void display(rel_context_base const& ctx, std::ostream & out) const { + void display(execution_context const& ctx, std::ostream & out) const { display_indented(ctx, out, ""); } - void display_indented(rel_context_base const & ctx, std::ostream & out, std::string indentation) const; + void display_indented(execution_context const & ctx, std::ostream & out, std::string indentation) const; static instruction * mk_load(ast_manager & m, func_decl * pred, reg_idx tgt); /** @@ -288,6 +302,8 @@ namespace datalog { static instruction * mk_assert_signature(const relation_signature & s, reg_idx tgt); + void collect_statistics(statistics& st) const; + }; @@ -314,7 +330,7 @@ namespace datalog { void push_back(instruction * i) { m_data.push_back(i); - if(m_observer) { + if (m_observer) { m_observer->notify(i); } } @@ -323,6 +339,8 @@ namespace datalog { m_observer = o; } + void collect_statistics(statistics& st) const; + /** \brief Perform instructions in the block. If the run was interrupted before completion, return false; otherwise return true. @@ -336,10 +354,12 @@ namespace datalog { void make_annotations(execution_context & ctx); - void display(rel_context_base const & ctx, std::ostream & out) const { + void display(execution_context const & ctx, std::ostream & out) const { display_indented(ctx, out, ""); } - void display_indented(rel_context_base const & ctx, std::ostream & out, std::string indentation) const; + void display_indented(execution_context const & ctx, std::ostream & out, std::string indentation) const; + + unsigned num_instructions() const { return m_data.size(); } }; diff --git a/src/muz/rel/dl_interval_relation.cpp b/src/muz/rel/dl_interval_relation.cpp index c04269b02..88c262cbe 100644 --- a/src/muz/rel/dl_interval_relation.cpp +++ b/src/muz/rel/dl_interval_relation.cpp @@ -598,7 +598,7 @@ namespace datalog { // 0 <= y - x - k - 1 if (is_le(to_app(cond->get_arg(0)), x, k, y, is_int) && is_int) { k.neg(); - k -= rational::one(); + k -= rational::one(); std::swap(x, y); return true; } diff --git a/src/muz/rel/dl_mk_explanations.cpp b/src/muz/rel/dl_mk_explanations.cpp index 60a10190a..55c87f66e 100644 --- a/src/muz/rel/dl_mk_explanations.cpp +++ b/src/muz/rel/dl_mk_explanations.cpp @@ -854,7 +854,10 @@ namespace datalog { scoped_ptr product_fun = rmgr.mk_join_fn(orig_rel, *m_e_fact_relation, 0, 0, 0); SASSERT(product_fun); scoped_rel aux_extended_rel = (*product_fun)(orig_rel, *m_e_fact_relation); + TRACE("dl", tout << aux_extended_rel << " " << aux_extended_rel->get_plugin().get_name() << "\n"; + tout << e_rel.get_plugin().get_name() << "\n";); scoped_ptr union_fun = rmgr.mk_union_fn(e_rel, *aux_extended_rel); + TRACE("dl", tout << union_fun << "\n";); SASSERT(union_fun); (*union_fun)(e_rel, *aux_extended_rel); } diff --git a/src/muz/rel/dl_mk_simple_joins.cpp b/src/muz/rel/dl_mk_simple_joins.cpp index c2214dad9..e33de8c6d 100644 --- a/src/muz/rel/dl_mk_simple_joins.cpp +++ b/src/muz/rel/dl_mk_simple_joins.cpp @@ -326,7 +326,7 @@ namespace datalog { for(unsigned i=0; iget_tail(i)); } - for(unsigned i=0; iget_tail(i); var_idx_set t1_vars = rm.collect_vars(t1); counter.count_vars(m, t1, -1); //temporarily remove t1 variables from counter diff --git a/src/muz/rel/dl_product_relation.cpp b/src/muz/rel/dl_product_relation.cpp index 48cd666e6..b66e4d47d 100644 --- a/src/muz/rel/dl_product_relation.cpp +++ b/src/muz/rel/dl_product_relation.cpp @@ -184,8 +184,10 @@ namespace datalog { } relation_base * product_relation_plugin::mk_full(func_decl* p, const relation_signature & s, family_id kind) { - if (kind == null_family_id) { - return alloc(product_relation, *this, s); + if (kind == null_family_id || !m_spec_store.contains_signature(s)) { + product_relation* result = alloc(product_relation, *this, s); + result->m_default_empty = false; + return result; } rel_spec spec; m_spec_store.get_relation_spec(s, kind, spec); diff --git a/src/muz/rel/dl_relation_manager.cpp b/src/muz/rel/dl_relation_manager.cpp index 9421b26df..a2b16bcf9 100644 --- a/src/muz/rel/dl_relation_manager.cpp +++ b/src/muz/rel/dl_relation_manager.cpp @@ -122,7 +122,7 @@ namespace datalog { relation_map::iterator it = m_relations.begin(); relation_map::iterator end = m_relations.end(); for(; it!=end; ++it) { - if(!it->m_value->empty()) { + if(!it->m_value->fast_empty()) { res.insert(it->m_key); } } @@ -206,6 +206,7 @@ namespace datalog { } void relation_manager::register_relation_plugin_impl(relation_plugin * plugin) { + TRACE("dl", tout << "register: " << plugin->get_name() << "\n";); m_relation_plugins.push_back(plugin); plugin->initialize(get_next_relation_fid(*plugin)); if (plugin->get_name() == get_context().default_relation()) { @@ -537,7 +538,7 @@ namespace datalog { for(; it!=end; ++it) { func_decl * pred = *it; relation_base * rel = try_get_relation(pred); - if(!rel) { + if (!rel) { out << "Tuples in " << pred->get_name() << ": \n"; continue; } @@ -668,6 +669,27 @@ namespace datalog { return res; } + class relation_manager::default_relation_apply_sequential_fn : public relation_mutator_fn { + ptr_vector m_mutators; + public: + default_relation_apply_sequential_fn(unsigned n, relation_mutator_fn ** mutators): + m_mutators(n, mutators) { + } + virtual ~default_relation_apply_sequential_fn() { + std::for_each(m_mutators.begin(), m_mutators.end(), delete_proc()); + } + + virtual void operator()(relation_base& t) { + for (unsigned i = 0; i < m_mutators.size(); ++i) { + if (t.empty()) return; + (*(m_mutators[i]))(t); + } + } + }; + + relation_mutator_fn * relation_manager::mk_apply_sequential_fn(unsigned n, relation_mutator_fn ** mutators) { + return alloc(default_relation_apply_sequential_fn, n, mutators); + } class relation_manager::default_relation_join_project_fn : public relation_join_fn { scoped_ptr m_join; @@ -1384,7 +1406,7 @@ namespace datalog { dl_decl_util & m_decl_util; th_rewriter & m_simp; app_ref m_condition; - ptr_vector m_var_sorts; + expr_free_vars m_free_vars; expr_ref_vector m_args; public: default_table_filter_interpreted_fn(context & ctx, unsigned col_cnt, app* condition) @@ -1394,8 +1416,7 @@ namespace datalog { m_simp(ctx.get_rewriter()), m_condition(condition, ctx.get_manager()), m_args(ctx.get_manager()) { - m_var_sorts.resize(col_cnt); - get_free_vars(m_condition, m_var_sorts); + m_free_vars(m_condition); } virtual bool should_remove(const table_fact & f) const { @@ -1405,14 +1426,13 @@ namespace datalog { //arguments need to be in reverse order for the substitution unsigned col_cnt = f.size(); for(int i=col_cnt-1;i>=0;i--) { - sort * var_sort = m_var_sorts[i]; - if(!var_sort) { + if(!m_free_vars.contains(i)) { args.push_back(0); continue; //this variable does not occur in the condition; } table_element el = f[i]; - args.push_back(m_decl_util.mk_numeral(el, var_sort)); + args.push_back(m_decl_util.mk_numeral(el, m_free_vars[i])); } expr_ref ground(m_ast_manager); diff --git a/src/muz/rel/dl_relation_manager.h b/src/muz/rel/dl_relation_manager.h index 2c148c5e6..530538df5 100644 --- a/src/muz/rel/dl_relation_manager.h +++ b/src/muz/rel/dl_relation_manager.h @@ -43,6 +43,7 @@ namespace datalog { class default_relation_select_equal_and_project_fn; class default_relation_intersection_filter_fn; class default_relation_filter_interpreted_and_project_fn; + class default_relation_apply_sequential_fn; class auxiliary_table_transformer_fn; class auxiliary_table_filter_fn; @@ -175,6 +176,7 @@ namespace datalog { table_plugin * get_table_plugin(symbol const& s); relation_plugin * get_relation_plugin(symbol const& s); relation_plugin & get_relation_plugin(family_id kind); + void set_favourite_plugin(relation_plugin* p) { m_favourite_relation_plugin = p; } table_relation_plugin & get_table_relation_plugin(table_plugin & tp); bool try_get_finite_product_relation_plugin(const relation_plugin & inner, finite_product_relation_plugin * & res); @@ -352,9 +354,13 @@ namespace datalog { relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); + relation_transformer_fn * mk_filter_interpreted_and_project_fn(const relation_base & t, app * condition, unsigned removed_col_cnt, const unsigned * removed_cols); + relation_mutator_fn * mk_apply_sequential_fn(unsigned n, relation_mutator_fn* * mutators); + + /** \brief Operations that returns all rows of \c t for which is column \c col equal to \c value with the column \c col removed. diff --git a/src/muz/rel/dl_sparse_table.cpp b/src/muz/rel/dl_sparse_table.cpp index 3b2dc333a..2c806971f 100644 --- a/src/muz/rel/dl_sparse_table.cpp +++ b/src/muz/rel/dl_sparse_table.cpp @@ -509,7 +509,7 @@ namespace datalog { } bool sparse_table::add_fact(const char * data) { - verbose_action _va("add_fact", 3); + verbose_action _va("add_fact", 10); m_data.write_into_reserve(data); return add_reserve_content(); } @@ -829,7 +829,6 @@ namespace datalog { virtual table_base * operator()(const table_base & tb1, const table_base & tb2) { - verbose_action _va("join_project"); const sparse_table & t1 = get(tb1); const sparse_table & t2 = get(tb2); diff --git a/src/muz/rel/dl_vector_relation.h b/src/muz/rel/dl_vector_relation.h index 4d0917359..c349c6e19 100644 --- a/src/muz/rel/dl_vector_relation.h +++ b/src/muz/rel/dl_vector_relation.h @@ -42,8 +42,6 @@ namespace datalog { union_find_default_ctx m_ctx; union_find<>* m_eqs; - friend class vector_relation_plugin; - public: vector_relation(relation_plugin& p, relation_signature const& s, bool is_empty, T const& t = T()): relation_base(p, s), @@ -105,9 +103,10 @@ namespace datalog { display_index(i, (*m_elems)[i], out); } else { - out << i << " = " << find(i) << "\n"; + out << i << " = " << find(i) << " "; } } + out << "\n"; } diff --git a/src/muz/rel/doc.cpp b/src/muz/rel/doc.cpp new file mode 100644 index 000000000..67e2f1e2b --- /dev/null +++ b/src/muz/rel/doc.cpp @@ -0,0 +1,732 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + doc.cpp + +Abstract: + + difference of cubes. + +Author: + + Nuno Lopes (a-nlopes) 2013-03-01 + Nikolaj Bjorner (nbjorner) 2014-09-15 + +Revision History: + + Based on ternary_diff_bitvector by Nuno Lopes. + +--*/ + +#include "doc.h" +#include "smt_kernel.h" +#include "expr_safe_replace.h" +#include "smt_params.h" +#include "ast_util.h" +#include "ast_pp.h" + +doc_manager::doc_manager(unsigned n): m(n), m_alloc("doc") { + m_full = m.allocateX(); +} + +doc_manager::~doc_manager() { + m.deallocate(m_full); +} + +doc* doc_manager::allocate() { + return allocate(m.allocate()); +} +doc* doc_manager::allocate1() { + return allocate(m.allocate1()); +} +doc* doc_manager::allocate0() { + return allocate(m.allocate0()); +} +doc* doc_manager::allocateX() { + return allocate(m.allocateX()); +} +doc* doc_manager::allocate(doc const& src) { + doc* r = allocate(m.allocate(src.pos())); + for (unsigned i = 0; i < src.neg().size(); ++i) { + r->neg().push_back(m.allocate(src.neg()[i])); + } + return r; +} +doc* doc_manager::allocate(tbv* t) { + SASSERT(t); + void* mm = m_alloc.allocate(sizeof(doc)); + return new (mm) doc(t); +} +doc* doc_manager::allocate(tbv const& src) { + return allocate(m.allocate(src)); +} +doc* doc_manager::allocate(uint64 n) { + return allocate(m.allocate(n)); +} +doc* doc_manager::allocate(rational const& r) { + return allocate(m.allocate(r)); +} +doc* doc_manager::allocate(uint64 n, unsigned hi, unsigned lo) { + return allocate(m.allocate(n, hi, lo)); +} +doc* doc_manager::allocate(doc const& src, unsigned const* permutation) { + doc* r = allocate(m.allocate(src.pos(), permutation)); + for (unsigned i = 0; i < src.neg().size(); ++i) { + r->neg().push_back(m.allocate(src.neg()[i], permutation)); + } + return r; +} +void doc_manager::deallocate(doc* src) { + if (!src) return; + m.deallocate(&src->pos()); + src->neg().reset(m); + src->~doc(); + m_alloc.deallocate(sizeof(doc), src); +} +void doc_manager::copy(doc& dst, doc const& src) { + m.copy(dst.pos(), src.pos()); + dst.neg().reset(m); + for (unsigned i = 0; i < src.neg().size(); ++i) { + dst.neg().push_back(m.allocate(src.neg()[i])); + } +} +doc& doc_manager::fill0(doc& src) { + src.neg().reset(m); + m.fill0(src.pos()); + return src; +} +doc& doc_manager::fill1(doc& src) { + src.neg().reset(m); + m.fill1(src.pos()); + return src; +} +doc& doc_manager::fillX(doc& src) { + src.neg().reset(m); + m.fillX(src.pos()); + return src; +} +bool doc_manager::set_and(doc& dst, doc const& src) { + // (A \ B) & (C \ D) = (A & C) \ (B u D) + if (!m.set_and(dst.pos(), src.pos())) return false; + dst.neg().intersect(m, dst.pos()); + tbv_ref t(m); + for (unsigned i = 0; i < src.neg().size(); ++i) { + t = m.allocate(src.neg()[i]); + if (m.set_and(*t, dst.pos())) { + dst.neg().insert(m, t.detach()); + } + } + return fold_neg(dst); +} +bool doc_manager::set_and(doc& dst, tbv const& src) { + // (A \ B) & C = (A & C) \ (B & C) + if (!m.set_and(dst.pos(), src)) return false; + dst.neg().intersect(m, src); + return fold_neg(dst); +} + +bool doc_manager::well_formed(doc const& d) const { + if (!m.is_well_formed(d.pos())) return false; + for (unsigned i = 0; i < d.neg().size(); ++i) { + if (!m.is_well_formed(d.neg()[i])) return false; + if (!m.contains(d.pos(), d.neg()[i])) return false; + } + return true; +} + +bool doc_manager::fold_neg(doc& dst) { + start_over: + for (unsigned i = 0; i < dst.neg().size(); ++i) { + if (m.contains(dst.neg()[i], dst.pos())) + return false; + + unsigned index; + unsigned count = diff_by_012(dst.pos(), dst.neg()[i], index); + if (count != 2) { + if (count == 0) { + return false; + } + else if (count == 3) { + dst.neg().erase(tbvm(), i); + --i; + } + else { // count == 1: + m.set(dst.pos(), index, neg(dst.neg()[i][index])); + dst.neg().intersect(tbvm(), dst.pos()); + goto start_over; + } + } + } + SASSERT(well_formed(dst)); + return true; +} + +unsigned doc_manager::diff_by_012(tbv const& pos, tbv const& neg, unsigned& index) { + unsigned n = num_tbits(); + unsigned count = 0; + for (unsigned i = 0; i < n; ++i) { + tbit b1 = pos[i]; + tbit b2 = neg[i]; + SASSERT(b1 != BIT_z && b2 != BIT_z); + if (b1 != b2) { + if (count == 1) return 2; + if (b1 == BIT_x) { + index = i; + count = 1; + } + else if (b2 != BIT_x) { + return 3; + } + } + } + return count; +} + +void doc_manager::set(doc& d, unsigned idx, tbit value) { + m.set(d.pos(), idx, value); + for (unsigned i = 0; i < d.neg().size(); ++i) { + tbit b = d.neg()[i][idx]; + if (b != BIT_x && value != BIT_x && value != b) { + d.neg().erase(tbvm(), i); + --i; + } + else { + m.set(d.neg()[i], idx, value); + } + } +} + +// +// merge range from [lo:lo+length-1] with each index in equivalence class. +// under assumption of equalities and columns that are discarded. +// +bool doc_manager::merge( + doc& d, unsigned lo, unsigned length, + subset_ints const& equalities, bit_vector const& discard_cols) { + for (unsigned i = 0; i < length; ++i) { + unsigned idx = lo + i; + if (!merge(d, lo + i, equalities, discard_cols)) return false; + } + return true; +} +bool doc_manager::merge(doc& d, unsigned idx, subset_ints const& equalities, + bit_vector const& discard_cols) { + unsigned root = equalities.find(idx); + idx = root; + unsigned num_x = 0; + unsigned root1 = root; + tbit value = BIT_x; + do { + switch (d[idx]) { + case BIT_0: + if (value == BIT_1) return false; + value = BIT_0; + break; + case BIT_1: + if (value == BIT_0) return false; + value = BIT_1; + break; + case BIT_x: + ++num_x; + if (!discard_cols.get(idx)) { + root1 = idx; + } + break; + default: + UNREACHABLE(); + break; + } + idx = equalities.next(idx); + } + while (idx != root); + + TRACE("doc", tout << "num_x: " << num_x << " value: " << value << "\n";); + if (num_x == 0) { + // nothing to do. + } + else if (value != BIT_x) { + do { + if (d[idx] == BIT_x) { + set(d, idx, value); + } + idx = equalities.next(idx); + } + while (idx != root); + } + else { + bool all_x = true; + if (!d.neg().is_empty()) { + idx = root; + do { + for (unsigned i = 0; all_x && i < d.neg().size(); ++i) { + all_x = (BIT_x == d.neg()[i][idx]); + } + idx = equalities.next(idx); + } + while (idx != root && all_x); + } + idx = root; + do { + if ((!discard_cols.get(idx) || !all_x) && idx != root1) { + tbv* t = m.allocate(d.pos()); + m.set(*t, idx, BIT_0); + m.set(*t, root1, BIT_1); + d.neg().insert(tbvm(), t); + t = m.allocate(d.pos()); + m.set(*t, idx, BIT_1); + m.set(*t, root1, BIT_0); + d.neg().insert(tbvm(), t); + } + idx = equalities.next(idx); + } + while (idx != root); + } + return true; +} + +bool doc_manager::intersect(doc const& A, doc const& B, doc& result) { + copy(result, A); + return set_and(result, B); +} + +// +// 1. If n = 0,1: can project directly. +// 2. If tbv_i uses X in all positions with vars or constant where tbv is constant: can project directly. +// 3. Perform resolution on remaining tbv_i +// +// tbv & ~tbv1 & ~tbv2 & .. & ~tbv_n +// Semantics of ~tbv1 is that it is a clause of literals. +// indices where BIT_1 is set are negative. +// indices where BIT_0 is set are positive. +// + +doc* doc_manager::project(doc_manager& dstm, bit_vector const& to_delete, doc const& src) { + tbv_manager& dstt = dstm.m; + tbv_ref t(dstt); + t = dstt.project(to_delete, src.pos()); + doc* r = dstm.allocate(t.detach()); + SASSERT(r); + + if (src.neg().is_empty()) { + return r; + } + + // + // A negation can be projected directly if it does not constrain + // deleted variables. + // + tbv_vector todo, new_todo; + for (unsigned i = 0; i < src.neg().size(); ++i) { + todo.push_back(tbvm().allocate(src.neg()[i])); + } + unsigned idx; + bool done = false; + while (!todo.empty() && !done) { + switch(pick_resolvent(src.pos(), todo, to_delete, idx)) { + case project_is_empty: + t = dstt.allocate(r->pos()); + r->neg().push_back(t.detach()); + done = true; + break; + case project_monolithic: + done = true; + break; + case project_neg: + case project_pos: + for (unsigned i = 0; i < todo.size(); ++i) { + tbv& tx = *todo[i]; + if (tx[idx] == BIT_x) { + new_todo.push_back(&tx); + } + else { + m.deallocate(&tx); + } + } + std::swap(new_todo, todo); + new_todo.reset(); + break; + case project_resolve: { + utbv pos, neg; + for (unsigned i = 0; i < todo.size(); ++i) { + tbv& tx = *todo[i]; + switch(tx[idx]) { + case BIT_x: new_todo.push_back(&tx); break; + case BIT_0: neg.push_back(&tx); break; + case BIT_1: pos.push_back(&tx); break; + default: UNREACHABLE(); break; + } + } + TRACE("doc", + tout << "pos: "; + for (unsigned i = 0; i < pos.size(); ++i) { + tbvm().display(tout, pos[i]) << " "; + } + tout << "\nneg: "; + for (unsigned i = 0; i < neg.size(); ++i) { + tbvm().display(tout, neg[i]) << " "; + } + tout << "\n"; + ); + SASSERT(pos.size() > 0 && neg.size() > 0); + tbv_ref t1(m); + for (unsigned j = 0; j < pos.size(); ++j) { + for (unsigned k = 0; k < neg.size(); ++k) { + t1 = m.allocate(pos[j]); + m.set(*t1, idx, BIT_x); + if (tbvm().set_and(*t1, neg[k])) { + m.set(*t1, idx, BIT_x); + new_todo.push_back(t1.detach()); + } + } + } + pos.reset(m); + neg.reset(m); + std::swap(todo, new_todo); + new_todo.reset(); + break; + } + case project_done: { + for (unsigned i = 0; i < todo.size(); ++i) { + t = dstt.project(to_delete, *todo[i]); + if (dstt.equals(r->pos(), *t)) { + r->neg().reset(dstt); + r->neg().push_back(t.detach()); + break; + } + if (r->neg().size() > 0 && dstt.equals(r->neg()[0], *t)) { + continue; + } + r->neg().push_back(t.detach()); + } + done = true; + break; + } + } + } + for (unsigned i = 0; i < todo.size(); ++i) { + m.deallocate(todo[i]); + } + return r; +} + +doc* doc_manager::join(const doc& d1, const doc& d2, doc_manager& dm1, + const unsigned_vector& cols1, + const unsigned_vector& cols2) { + doc_ref d(*this, allocateX()); + tbv_ref t(m); + tbv& pos = d->pos(); + utbv& neg = d->neg(); + unsigned mid = dm1.num_tbits(); + unsigned hi = num_tbits(); + m.set(pos, d1.pos(), mid - 1, 0); + m.set(pos, d2.pos(), hi - 1, mid); + SASSERT(well_formed(*d)); + + // first fix bits + for (unsigned i = 0; i < cols1.size(); ++i) { + unsigned idx1 = cols1[i]; + unsigned idx2 = mid + cols2[i]; + tbit v1 = pos[idx1]; + tbit v2 = pos[idx2]; + + if (v1 == BIT_x) { + if (v2 != BIT_x) + m.set(pos, idx1, v2); + } + else if (v2 == BIT_x) { + m.set(pos, idx2, v1); + } + else if (v1 != v2) { + // columns don't match + return 0; + } + SASSERT(well_formed(*d)); + } + + // fix equality of don't care columns + for (unsigned i = 0; i < cols1.size(); ++i) { + unsigned idx1 = cols1[i]; + unsigned idx2 = mid + cols2[i]; + unsigned v1 = pos[idx1]; + unsigned v2 = pos[idx2]; + + if (v1 == BIT_x && v2 == BIT_x) { + // add to subtracted TBVs: 1xx0 and 0xx1 + t = m.allocate(pos); + m.set(*t, idx1, BIT_0); + m.set(*t, idx2, BIT_1); + neg.push_back(t.detach()); + t = m.allocate(pos); + m.set(*t, idx1, BIT_1); + m.set(*t, idx2, BIT_0); + neg.push_back(t.detach()); + } + SASSERT(well_formed(*d)); + } + + // handle subtracted TBVs: 1010 -> 1010xxx + for (unsigned i = 0; i < d1.neg().size(); ++i) { + t = m.allocateX(); + m.set(*t, d1.neg()[i], mid - 1, 0); + if (m.set_and(*t, pos)) + neg.push_back(t.detach()); + SASSERT(well_formed(*d)); + } + for (unsigned i = 0; i < d2.neg().size(); ++i) { + t = m.allocateX(); + m.set(*t, d2.neg()[i], hi - 1, mid); + if (m.set_and(*t, pos)) + neg.push_back(t.detach()); + SASSERT(well_formed(*d)); + } + SASSERT(well_formed(*d)); + + return d.detach(); +} + +doc_manager::project_action_t +doc_manager::pick_resolvent( + tbv const& pos, tbv_vector const& neg, bit_vector const& to_delete, unsigned& idx) { + if (neg.empty()) return project_done; + for (unsigned j = 0; j < neg.size(); ++j) { + if (m.equals(pos, *neg[j])) return project_is_empty; + } + + unsigned best_pos = UINT_MAX; + unsigned best_neg = UINT_MAX; + unsigned best_idx = UINT_MAX; + for (unsigned i = 0; i < num_tbits(); ++i) { + if (!to_delete.get(i)) continue; + if (pos[i] != BIT_x) continue; + unsigned num_pos = 0, num_neg = 0; + tbit b1 = (*neg[0])[i]; + if (b1 == BIT_0) num_neg++; + if (b1 == BIT_1) num_pos++; + bool monolithic = true; + for (unsigned j = 1; j < neg.size(); ++j) { + tbit b2 = (*neg[j])[i]; + if (b1 != b2) { + monolithic = false; + } + if (b2 == BIT_0) num_neg++; + if (b2 == BIT_1) num_pos++; + } + if (monolithic && b1 != BIT_x) { + idx = i; + return project_monolithic; + } + if (monolithic && b1 == BIT_x) { + continue; + } + SASSERT(!monolithic); + if (num_pos == 0) { + SASSERT(num_neg > 0); + idx = i; + return project_neg; + } + if (num_neg == 0) { + SASSERT(num_pos > 0); + idx = i; + return project_pos; + } + if ((best_pos >= num_pos && best_neg >= num_neg) || + num_neg == 1 || num_pos == 1) { + best_pos = num_pos; + best_neg = num_neg; + best_idx = i; + } + } + if (best_idx != UINT_MAX) { + idx = best_idx; + return project_resolve; + } + else { + return project_done; + } +} + + + +void doc_manager::complement(doc const& src, doc_vector& result) { + result.reset(); + if (is_full(src)) { + return; + } + doc* r = allocateX(); + r->neg().push_back(m.allocate(src.pos())); + result.push_back(r); + for (unsigned i = 0; i < src.neg().size(); ++i) { + result.push_back(allocate(src.neg()[i])); + } +} +// (A \ {A1}) \ (B \ {B1}) +// (A & !A1 & & !B) | (A & B1 & !A1) +// A \ {A1 u B} u (A & B1) \ {A1} +void doc_manager::subtract(doc const& A, doc const& B, doc_vector& result) { + doc_ref r(*this); + tbv_ref t(m); + r = allocate(A); + t = m.allocate(B.pos()); + if (m.set_and(*t, A.pos())) { + r->neg().insert(m, t.detach()); + } + if (fold_neg(*r)) + result.push_back(r.detach()); + + for (unsigned i = 0; i < B.neg().size(); ++i) { + r = allocate(A); + if (set_and(*r, B.neg()[i])) { + result.push_back(r.detach()); + } + } +} +bool doc_manager::equals(doc const& a, doc const& b) const { + if (!m.equals(a.pos(), b.pos())) return false; + if (a.neg().size() != b.neg().size()) return false; + for (unsigned i = 0; i < a.neg().size(); ++i) { + if (!m.equals(a.neg()[i], b.neg()[i])) return false; + } + return true; +} +bool doc_manager::is_full(doc const& src) const { + return src.neg().is_empty() && m.equals(src.pos(), *m_full); +} +bool doc_manager::is_empty_complete(ast_manager& m, doc const& src) { + if (src.neg().size() == 0) return false; + + smt_params fp; + smt::kernel s(m, fp); + expr_ref fml = to_formula(m, src); + s.assert_expr(fml); + lbool res = s.check(); + if (res == l_true) { + return false; + } + SASSERT(res == l_false); + return true; +} + +unsigned doc_manager::hash(doc const& src) const { + unsigned r = 0; + for (unsigned i = 0; i < src.neg().size(); ++i) { + r = 2*r + m.hash(src.neg()[i]); + } + return r + m.hash(src.pos()); +} +// approximation +// A \ (A1 u A2) contains B \ (B1 u B2) +// if +// A contains B +// B1 contains A1 or B2 contains A1 +// B1 contains A2 or B2 contains A2 +bool doc_manager::contains(doc const& a, doc const& b) const { + if (!m.contains(a.pos(), b.pos())) return false; + for (unsigned i = 0; i < a.neg().size(); ++i) { + bool found = false; + for (unsigned j = 0; !found && j < b.neg().size(); ++j) { + found = m.contains(b.neg()[j],a.neg()[i]); + } + if (!found) return false; + } + return true; +} + +bool doc_manager::contains(doc const& a, unsigned_vector const& colsa, + doc const& b, unsigned_vector const& colsb) const { + if (!m.contains(a.pos(), colsa, b.pos(), colsb)) + return false; + + for (unsigned i = 0; i < a.neg().size(); ++i) { + bool found = false; + for (unsigned j = 0; !found && j < b.neg().size(); ++j) { + found = m.contains(b.neg()[j], colsb, a.neg()[i], colsa); + } + if (!found) return false; + } + return true; +} + +std::ostream& doc_manager::display(std::ostream& out, doc const& b) const { + if (num_tbits() == 0) return out << "[]"; + return display(out, b, num_tbits()-1, 0); +} + +std::ostream& doc_manager::display(std::ostream& out, doc const& b, unsigned hi, unsigned lo) const { + m.display(out, b.pos(), hi, lo); + if (b.neg().is_empty()) return out; + out << " \\ "; + b.neg().display(m, out, hi, lo); + return out; +} + + +void doc_manager::verify_project(ast_manager& m, doc_manager& dstm, bit_vector const& to_delete, doc const& src, doc const& dst) { + expr_ref fml1 = to_formula(m, src); + expr_ref fml2 = dstm.to_formula(m, dst); + project_rename(fml2, to_delete); + project_expand(fml1, to_delete); + check_equiv(m, fml1, fml2); +} + +void doc_manager::check_equiv(ast_manager& m, expr* fml1, expr* fml2) { + smt_params fp; + smt::kernel solver(m, fp); + expr_ref fml(m); + fml = m.mk_not(m.mk_eq(fml1, fml2)); + solver.assert_expr(fml); + lbool res = solver.check(); + if (res != l_false) { + TRACE("doc", + tout << mk_pp(fml1, m) << "\n"; + tout << mk_pp(fml2, m) << "\n"; + ); + UNREACHABLE(); + throw 0; + } + SASSERT(res == l_false); +} + +expr_ref doc_manager::to_formula(ast_manager& m, doc const& src) { + expr_ref result(m); + expr_ref_vector conj(m); + conj.push_back(tbvm().to_formula(m, src.pos())); + for (unsigned i = 0; i < src.neg().size(); ++i) { + conj.push_back(m.mk_not(tbvm().to_formula(m, src.neg()[i]))); + } + result = mk_and(m, conj.size(), conj.c_ptr()); + return result; +} + +void doc_manager::project_expand(expr_ref& fml, bit_vector const& to_delete) { + ast_manager& m = fml.get_manager(); + expr_ref tmp1(m), tmp2(m); + for (unsigned i = 0; i < num_tbits(); ++i) { + if (to_delete.get(i)) { + expr_safe_replace rep1(m), rep2(m); + rep1.insert(tbvm().mk_var(m, i), m.mk_true()); + rep1(fml, tmp1); + rep2.insert(tbvm().mk_var(m, i), m.mk_false()); + rep2(fml, tmp2); + if (tmp1 == tmp2) { + fml = tmp1; + } + else { + fml = m.mk_or(tmp1, tmp2); + } + } + } +} + +void doc_manager::project_rename(expr_ref& fml, bit_vector const& to_delete) { + ast_manager& m = fml.get_manager(); + expr_safe_replace rep(m); + for (unsigned i = 0, j = 0; i < num_tbits(); ++i) { + if (!to_delete.get(i)) { + rep.insert(tbvm().mk_var(m, j), tbvm().mk_var(m, i)); + ++j; + } + } + rep(fml); +} diff --git a/src/muz/rel/doc.h b/src/muz/rel/doc.h new file mode 100644 index 000000000..fcb134d9e --- /dev/null +++ b/src/muz/rel/doc.h @@ -0,0 +1,386 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + doc.h + +Abstract: + + difference of cubes. + +Author: + + Nuno Lopes (a-nlopes) 2013-03-01 + Nikolaj Bjorner (nbjorner) 2014-09-15 + +Revision History: + + Based on ternary_diff_bitvector by Nuno Lopes. + +--*/ + +#ifndef _DOC_H_ +#define _DOC_H_ + +#include "tbv.h" +#include "union_find.h" +#include "buffer.h" + + +class doc; +template class union_bvec; +typedef union_find<> subset_ints; +typedef union_bvec utbv; +typedef buffer tbv_vector; +typedef buffer doc_vector; + +class doc_manager { + tbv_manager m; + tbv* m_full; + small_object_allocator m_alloc; + enum project_action_t { + project_is_empty, + project_done, + project_monolithic, + project_neg, + project_pos, + project_resolve + }; + project_action_t pick_resolvent( + tbv const& pos, tbv_vector const& neg, bit_vector const& to_delete, unsigned& idx); +public: + doc_manager(unsigned num_bits); + ~doc_manager(); + tbv_manager& tbvm() { return m; } + tbv_manager const& tbvm() const { return m; } + doc* allocate(); + doc* allocate1(); + doc* allocate0(); + doc* allocateX(); + doc* allocate(doc const& src); + doc* allocate(tbv const& src); + doc* allocate(tbv * src); + doc* allocate(uint64 n); + doc* allocate(rational const& r); + doc* allocate(uint64 n, unsigned hi, unsigned lo); + doc* allocate(doc const& src, unsigned const* permutation); + void deallocate(doc* src); + void copy(doc& dst, doc const& src); + doc& reset(doc& src) { return fill0(src); } + doc& fill0(doc& src); + doc& fill1(doc& src); + doc& fillX(doc& src); + bool is_full(doc const& src) const; + bool is_empty_complete(ast_manager& m, doc const& src); + bool set_and(doc& dst, doc const& src); + bool set_and(doc& dst, tbv const& src); + bool fold_neg(doc& dst); + bool intersect(doc const& A, doc const& B, doc& result); + void complement(doc const& src, doc_vector& result); + void subtract(doc const& A, doc const& B, doc_vector& result); + bool equals(doc const& a, doc const& b) const; + unsigned hash(doc const& src) const; + bool contains(doc const& a, doc const& b) const; + bool contains(doc const& a, unsigned_vector const& colsa, + doc const& b, unsigned_vector const& colsb) const; + std::ostream& display(std::ostream& out, doc const& b) const; + std::ostream& display(std::ostream& out, doc const& b, unsigned hi, unsigned lo) const; + unsigned num_tbits() const { return m.num_tbits(); } + doc* project(doc_manager& dstm, bit_vector const& to_delete, doc const& src); + bool well_formed(doc const& d) const; + bool merge(doc& d, unsigned lo, unsigned length, subset_ints const& equalities, bit_vector const& discard_cols); + void set(doc& d, unsigned idx, tbit value); + doc* join(const doc& a, const doc& b, doc_manager& dm1, + const unsigned_vector& cols1, const unsigned_vector& cols2); + + void verify_project(ast_manager& m, doc_manager& dstm, bit_vector const& to_delete, doc const& src, doc const& dst); +private: + unsigned diff_by_012(tbv const& pos, tbv const& neg, unsigned& index); + bool merge(doc& d, unsigned idx, subset_ints const& equalities, bit_vector const& discard_cols); + void project_rename(expr_ref& fml, bit_vector const& to_delete); + void project_expand(expr_ref& fml, bit_vector const& to_delete); + expr_ref to_formula(ast_manager& m, doc const& src); + void check_equiv(ast_manager& m, expr* fml1, expr* fml2); +}; + + +// union of tbv*, union of doc* +template +class union_bvec { + buffer m_elems; // TBD: reuse allocator of M + + enum fix_bit_result_t { + e_row_removed, // = 1 + e_duplicate_row, // = 2 + e_fixed + }; + + +public: + unsigned size() const { return m_elems.size(); } + T& operator[](unsigned idx) const { return *m_elems[idx]; } + bool is_empty() const { return m_elems.empty(); } + bool is_empty_complete(ast_manager& m, doc_manager& dm) const { + for (unsigned i = 0; i < size(); ++i) { + if (!dm.is_empty_complete(m, *m_elems[i])) + return false; + } + return true; + } + bool is_full(M& m) const { return size() == 1 && m.is_full(*m_elems[0]); } + bool contains(M& m, T& t) const { + for (unsigned i = 0; i < size(); ++i) { + if (m.contains(*m_elems[i], t)) return true; + } + return false; + } + std::ostream& display(M const& m, std::ostream& out) const { + if (m.num_tbits() == 0) return out << "[]"; + return display(m, out, m.num_tbits()-1, 0); + } + std::ostream& display(M const& m, std::ostream& out, unsigned hi, unsigned lo) const { + out << "{"; + if (size() + m.num_tbits() > 10) out << "\n "; + for (unsigned i = 0; i < size(); ++i) { + m.display(out, *m_elems[i], hi, lo); + if (i + 1 < size()) out << ", "; + if (i + 1 < size() && m.num_tbits() > 10) out << "\n "; + } + return out << "}"; + } + + void push_back(T* t) { + SASSERT(t); + m_elems.push_back(t); + } + void erase(M& m, unsigned idx) { + m.deallocate(m_elems[idx]); + unsigned sz = m_elems.size(); + for (unsigned i = idx+1; i < sz; ++i) { + m_elems[i-1] = m_elems[i]; + } + m_elems.resize(sz-1); + } + void reset(M& m) { + for (unsigned i = 0; i < m_elems.size(); ++i) { + m.deallocate(m_elems[i]); + } + m_elems.reset(); + } + bool insert(M& m, T* t) { + SASSERT(t); + unsigned sz = size(), j = 0; + bool found = false; + unsigned i = 0; + for ( ; i < sz; ++i, ++j) { + if (m.contains(*m_elems[i], *t)) { + found = true; + } + else if (m.contains(*t, *m_elems[i])) { + m.deallocate(m_elems[i]); + --j; + continue; + } + if (i != j) { + m_elems[j] = m_elems[i]; + } + } + if (j != sz) m_elems.resize(j); + if (found) { + m.deallocate(t); + } + else { + m_elems.push_back(t); + } + return !found; + } + void intersect(M& m, T const& t) { + unsigned sz = size(); + unsigned j = 0; + for (unsigned i = 0; i < sz; ++i, ++j) { + if (!m.set_and(*m_elems[i], t)) { + m.deallocate(m_elems[i]); + --j; + } + else if (i != j) { + m_elems[j] = m_elems[i]; + } + } + if (j != sz) m_elems.resize(j); + } + void insert(M& m, union_bvec const& other) { + for (unsigned i = 0; i < other.size(); ++i) { + insert(m, &other[i]); + } + } + void intersect(M& m, union_bvec const& other) { + unsigned sz = other.size(); + union_bvec tmp, result; + for (unsigned i = 0; i < sz; ++i) { + tmp.copy(m, *this); + tmp.intersect(m, other[i]); + for (unsigned j = 0; j < tmp.size(); ++j) { + result.push_back(tmp.m_elems[j]); + } + tmp.m_elems.reset(); + } + std::swap(*this, result); + result.reset(m); + } + void subtract(M& m, union_bvec const& other) { + unsigned sz = other.size(); + for (unsigned i = 0; !is_empty() && i < sz; ++i) { + subtract(m, other[i]); + } + // TBD compress? + } + void subtract(M& m, T& t) { + unsigned sz = size(); + bool found = false; + union_bvec result; + for (unsigned i = 0; i < sz; ++i) { + m.subtract(*m_elems[i], t, result.m_elems); + } + std::swap(m_elems, result.m_elems); + result.reset(m); + } + void complement(M& m, union_bvec& result) const { + union_bvec negated; + result.reset(m); + result.push_back(m.allocateX()); + unsigned sz = size(); + for (unsigned i = 0; !is_empty() && i < sz; ++i) { + m.complement(*m_elems[i], negated.m_elems); + result.intersect(m, negated); + negated.reset(m); + } + } + void copy(M& m, union_bvec const& other) { + reset(m); + for (unsigned i = 0; i < other.size(); ++i) { + push_back(m.allocate(other[i])); + } + } + void simplify(M& m) { + union_bvec result; + for (unsigned i = 0; i < size(); ++i) { + if (m.fold_neg(*m_elems[i])) { + result.insert(m, m_elems[i]); + } + else { + m.deallocate(m_elems[i]); + } + } + std::swap(*this, result); + } + + bool well_formed(M& m) const { + for (unsigned i = 0; i < size(); ++i) { + if (!m.well_formed(*m_elems[i])) return false; + } + return true; + } + + void merge(M& m, unsigned lo, unsigned length, subset_ints const& equalities, bit_vector const& discard_cols) { + unsigned j = 0; + unsigned sz = size(); + for (unsigned i = 0; i < sz; ++i, ++j) { + if (!m.merge(*m_elems[i], lo, length, equalities, discard_cols)) { + --j; + m.deallocate(m_elems[i]); + } + else if (i != j) { + m_elems[j] = m_elems[i]; + } + } + if (j != sz) m_elems.resize(j); + } + + void merge(M& m, unsigned lo1, unsigned lo2, unsigned length, bit_vector const& discard_cols) { + union_find_default_ctx union_ctx; + subset_ints equalities(union_ctx); + for (unsigned i = 0; i < discard_cols.size(); ++i) { + equalities.mk_var(); + } + for (unsigned j = 0; j < length; ++j) { + equalities.merge(lo1 + j, lo2 + j); + } + merge(m, lo1, length, equalities, discard_cols); + } + + void merge(M& m, unsigned_vector const& roots, subset_ints const& equalities, + bit_vector const& discard_cols) { + for (unsigned i = 0; i < roots.size(); ++i) { + merge(m, roots[i], 1, equalities, discard_cols); + } + } + + void join(const union_bvec& d1, const union_bvec& d2, M& dm, M& dm1, + const unsigned_vector& cols1, const unsigned_vector& cols2) { + for (unsigned i = 0; i < d1.size(); ++i) { + for (unsigned j = 0; j < d2.size(); ++j) { + if (T *d = dm.join(d1[i], d2[j], dm1, cols1, cols2)) + insert(dm, d); + } + } + } + +}; + + +class doc { + // pos \ (neg_0 \/ ... \/ neg_n) + friend class doc_manager; + tbv* m_pos; + utbv m_neg; +public: + + struct eq { + doc_manager& m; + eq(doc_manager& m):m(m) {} + bool operator()(doc const& d1, doc const& d2) const { + return m.equals(d1, d2); + } + }; + + struct hash { + doc_manager& m; + hash(doc_manager& m):m(m) {} + unsigned operator()(doc const& d) const { + return m.hash(d); + } + }; + + doc(tbv* t): m_pos(t) {} + tbv& pos() { return *m_pos; } + utbv& neg() { return m_neg; } + tbv const& pos() const { return *m_pos; } + utbv const& neg() const { return m_neg; } + tbit operator[](unsigned idx) const { return pos()[idx]; } +}; + +typedef union_bvec udoc; + +class doc_ref { + doc_manager& dm; + doc* d; +public: + doc_ref(doc_manager& dm):dm(dm),d(0) {} + doc_ref(doc_manager& dm, doc* d):dm(dm),d(d) {} + ~doc_ref() { + if (d) dm.deallocate(d); + } + doc_ref& operator=(doc* d2) { + if (d) dm.deallocate(d); + d = d2; + return *this; + } + doc& operator*() { return *d; } + doc* operator->() { return d; } + doc* detach() { doc* r = d; d = 0; return r; } + operator bool() const { return d != 0; } +}; + +#endif /* _DOC_H_ */ + diff --git a/src/muz/rel/karr_relation.h b/src/muz/rel/karr_relation.h index 00a92748a..72448f026 100644 --- a/src/muz/rel/karr_relation.h +++ b/src/muz/rel/karr_relation.h @@ -45,7 +45,7 @@ namespace datalog { {} virtual bool can_handle_signature(const relation_signature & sig) { - return true; + return get_manager().get_context().karr(); } static symbol get_name() { return symbol("karr_relation"); } diff --git a/src/muz/rel/product_set.cpp b/src/muz/rel/product_set.cpp new file mode 100644 index 000000000..9c26ed189 --- /dev/null +++ b/src/muz/rel/product_set.cpp @@ -0,0 +1,788 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + product_set.cpp + +Abstract: + + Product set. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-08-23 + +Revision History: + +--*/ + +#include "product_set.h" +#include "bv_decl_plugin.h" +#include "dl_relation_manager.h" +#include "bool_rewriter.h" + +namespace datalog { + + static unsigned s_ps_num_bits = 0; + static unsigned s_num_ps = 0; + + product_set::product_set( + product_set_plugin& p, relation_signature const& s, + initial_t init, T const& t): + vector_relation(p, s, false, t), m_refs(0) { + unsigned delta = 0; + for (unsigned i = 0; i < s.size(); ++i) { + unsigned sz = p.set_size(s[i]); + (*this)[i].resize(sz); + if (init == FULL_t) { + (*this)[i].neg(); + } + delta += sz; + } + s_ps_num_bits += delta; + s_num_ps ++; + if ((s_num_ps % 1000) == 0) { + std::cout << s_num_ps << " " << s_ps_num_bits << " " << delta << "\n"; + } + } + + product_set::~product_set() { + relation_signature const& s = get_signature(); + product_set_plugin& p = dynamic_cast(get_plugin()); + for (unsigned i = 0; i < s.size(); ++i) { + unsigned sz = p.set_size(s[i]); + s_ps_num_bits -= sz; + } + --s_num_ps; + } + + unsigned product_set::get_hash() const { + unsigned hash = 0; + for (unsigned i = 0; i < get_signature().size(); ++i) { + hash ^= (*this)[i].get_hash(); + } + return hash; + } + + bool product_set::operator==(product_set const& p) const { + for (unsigned i = 0; i < get_signature().size(); ++i) { + if ((*this)[i] != p[i]) return false; + } + return true; + } + bool product_set::contains(product_set const& p) const { + for (unsigned i = 0; i < get_signature().size(); ++i) { + if ((*this)[i].contains(p[i])) return false; + } + return true; + } + void product_set::reset() { + for (unsigned i = 0; i < get_signature().size(); ++i) { + (*this)[i].fill0(); + } + } + void product_set::add_fact(const relation_fact & f) { + UNREACHABLE(); + } + bool product_set::contains_fact(const relation_fact & f) const { + UNREACHABLE(); + return false; + } + relation_base * product_set::clone() const { + product_set* result = alloc(product_set, dynamic_cast(get_plugin()), get_signature(), EMPTY_t); + result->copy(*this); + return result; + } + relation_base * product_set::complement(func_decl*) const { + product_set* result = alloc(product_set, dynamic_cast(get_plugin()), get_signature(), EMPTY_t); + result->copy(*this); + result->complement(); + return result; + } + + void product_set::complement() { + for (unsigned i = 0; i < get_signature().size(); ++i) { + (*this)[i].neg(); + } + } + void product_set::to_formula(expr_ref& fml) const { + ast_manager& m = fml.get_manager(); + bv_util bv(m); + expr_ref_vector conjs(m), disjs(m); + relation_signature const& sig = get_signature(); + if (m_empty) { + fml = m.mk_false(); + return; + } + for (unsigned i = 0; i < sig.size(); ++i) { + sort* ty = sig[i]; + expr_ref var(m.mk_var(i, ty), m); + unsigned j = find(i); + if (i != j) { + conjs.push_back(m.mk_eq(var, m.mk_var(j, sig[j]))); + continue; + } + T const& t = (*this)[i]; + disjs.reset(); + for (j = 0; j < t.size(); ++j) { + if (t.get(j)) { + disjs.push_back(m.mk_eq(var, bv.mk_numeral(rational(j), ty))); + } + } + if (disjs.empty()) { + UNREACHABLE(); + fml = m.mk_false(); + return; + } + if (disjs.size() == 1) { + conjs.push_back(disjs[0].get()); + } + else { + conjs.push_back(m.mk_or(disjs.size(), disjs.c_ptr())); + } + } + bool_rewriter br(m); + br.mk_and(conjs.size(), conjs.c_ptr(), fml); + } + void product_set::display_index(unsigned i, const T& t, std::ostream& out) const { + out << i << ":"; + t.display(out); + } + bool product_set::mk_intersect(unsigned idx, T const& t) { + if (!m_empty) { + (*this)[idx] &= t; + m_empty = is_empty(idx, (*this)[idx]); + } + return !m_empty; + } + + // product_set_relation + + + product_set_relation::product_set_relation(product_set_plugin& p, relation_signature const& s): + relation_base(p, s) { + } + + product_set_relation::~product_set_relation() { + reset(); + } + + class product_set_plugin::filter_interpreted_fn : public relation_mutator_fn { + app_ref m_condition; + public: + filter_interpreted_fn(ast_manager& m, app* condition): m_condition(condition, m) { + + }; + virtual ~filter_interpreted_fn() {} + + virtual void operator()(relation_base & _r) { + ast_manager& m = m_condition.get_manager(); + if (m.is_false(m_condition)) { + product_set_relation & r = get(_r); + r.reset(); + return; + } + if (m.is_true(m_condition)) { + return; + } + product_set_relation & r = get(_r); + product_set_plugin & p = r.get_plugin(); + NOT_IMPLEMENTED_YET(); + } + }; + + void product_set_relation::add_fact(const relation_fact & f) { + ast_manager& m = get_plugin().get_ast_manager(); + bv_util bv(m); + product_set* s = alloc(product_set, get_plugin(), get_signature(), product_set::EMPTY_t); + rational v; + unsigned bv_size; + // the bit-vector sets are empty at this point so they need to be primed. + for (unsigned i = 0; i < f.size(); ++i) { + VERIFY(bv.is_numeral(f[i], v, bv_size)); + SASSERT(v.is_unsigned()); + (*s)[i].set(v.get_unsigned(), true); + } + // s->display(std::cout << "fact"); + if (m_elems.contains(s)) { + dealloc(s); + } + else { + s->inc_ref(); + m_elems.insert(s); + } + + } + bool product_set_relation::contains_fact(const relation_fact & f) const { + std::cout << "contains fact\n"; + NOT_IMPLEMENTED_YET(); + return false; + } + product_set_relation * product_set_relation::clone() const { + product_set_relation* r = alloc(product_set_relation, get_plugin(), get_signature()); + product_sets::iterator it = m_elems.begin(), end = m_elems.end(); + for (; it != end; ++it) { + product_set* ps = dynamic_cast((*it)->clone()); + ps->inc_ref(); + r->m_elems.insert(ps); + } + return r; + } + void product_set_relation::reset() { + product_sets::iterator it = m_elems.begin(), end = m_elems.end(); + for (; it != end; ++it) { + (*it)->dec_ref(); + } + m_elems.reset(); + } + product_set_relation * product_set_relation::complement(func_decl*) const { + std::cout << "complement\n"; + NOT_IMPLEMENTED_YET(); + return 0; + } + void product_set_relation::to_formula(expr_ref& fml) const { + product_sets::iterator it = m_elems.begin(), end = m_elems.end(); + ast_manager& m = get_plugin().get_manager().get_context().get_manager(); + expr_ref_vector disjs(m); + for (; it != end; ++it) { + (*it)->to_formula(fml); + disjs.push_back(fml); + } + fml = m.mk_or(disjs.size(), disjs.c_ptr()); + } + product_set_plugin& product_set_relation::get_plugin() const { + return static_cast(relation_base::get_plugin()); + } + + void product_set_relation::display(std::ostream& out) const { + product_sets::iterator it = m_elems.begin(), end = m_elems.end(); + for (; it != end; ++it) { + (*it)->display(out); + } + } + + // product_set_plugin + + product_set_plugin::product_set_plugin(relation_manager& rm): + relation_plugin(product_set_plugin::get_name(), rm), + m(rm.get_context().get_manager()), + bv(m) { + } + + bool product_set_plugin::can_handle_signature(const relation_signature & sig) { + bv_util bv(get_manager().get_context().get_manager()); + for (unsigned i = 0; i < sig.size(); ++i) { + if (!bv.is_bv_sort(sig[i])) return false; + } + return true; + } + + product_set_relation& product_set_plugin::get(relation_base& r) { + return dynamic_cast(r); + } + product_set_relation* product_set_plugin::get(relation_base* r) { + return r?dynamic_cast(r):0; + } + product_set_relation const & product_set_plugin::get(relation_base const& r) { + return dynamic_cast(r); + } + relation_base * product_set_plugin::mk_empty(const relation_signature & s) { + return alloc(product_set_relation, *this, s); + } + relation_base * product_set_plugin::mk_full(func_decl* p, const relation_signature & sig) { + product_set_relation* result = alloc(product_set_relation, *this, sig); + product_set* s = alloc(product_set, *this, sig, product_set::FULL_t); + s->inc_ref(); + result->m_elems.insert(s); + return result; + } + product_set* product_set_plugin::insert(product_set* s, product_set_relation* r) { + if (s->empty()) { + s->reset(); + s->complement(); + } + else if (r->m_elems.contains(s)) { + s->reset(); + s->complement(); + } + else { + s->inc_ref(); + r->m_elems.insert(s); + s = alloc(product_set, *this, r->get_signature(), product_set::FULL_t); + } + return s; + } + + unsigned product_set_plugin::set_size(sort* ty) { + bv_util bv(get_ast_manager()); + unsigned bv_size = bv.get_bv_size(ty); + SASSERT(bv_size <= 16); + if (bv_size > 16) { + throw default_exception("bit-vector based sets are not suitable for this domain size"); + } + return 1 << bv_size; + } + + class product_set_plugin::join_fn : public convenient_relation_join_fn { + public: + join_fn(const relation_signature & o1_sig, const relation_signature & o2_sig, unsigned col_cnt, + const unsigned * cols1, const unsigned * cols2) + : convenient_relation_join_fn(o1_sig, o2_sig, col_cnt, cols1, cols2){ + } + + virtual relation_base * operator()(const relation_base & _r1, const relation_base & _r2) { + product_set_relation const& r1 = get(_r1); + product_set_relation const& r2 = get(_r2); + product_set_plugin& p = r1.get_plugin(); + relation_signature const& sig = get_result_signature(); + product_set_relation * result = alloc(product_set_relation, p, sig); + product_set* s = alloc(product_set, p, sig, product_set::FULL_t); + product_sets::iterator it1 = r1.m_elems.begin(), end1 = r1.m_elems.end(); + for (; it1 != end1; ++it1) { + product_sets::iterator it2 = r2.m_elems.begin(), end2 = r2.m_elems.end(); + for (; it2 != end2; ++it2) { + s->mk_join(*(*it1), *(*it2), m_cols1.size(), m_cols1.c_ptr(), m_cols2.c_ptr()); + s = p.insert(s, result); + } + } + dealloc(s); + std::cout << "join " << result->m_elems.size() << "\n"; + return result; + } + }; + relation_join_fn * product_set_plugin::mk_join_fn( + const relation_base & r1, const relation_base & r2, + unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { + if (!check_kind(r1) || !check_kind(r2)) { + return 0; + } + return alloc(join_fn, r1.get_signature(), r2.get_signature(), col_cnt, cols1, cols2); + } + + class product_set_plugin::project_fn : public convenient_relation_project_fn { + public: + project_fn(const relation_signature & orig_sig, unsigned removed_col_cnt, + const unsigned * removed_cols) + : convenient_relation_project_fn(orig_sig, removed_col_cnt, removed_cols) { + } + + virtual relation_base * operator()(const relation_base & _r) { + product_set_relation const& r = get(_r); + product_set_plugin& p = r.get_plugin(); + relation_signature const& sig = get_result_signature(); + product_set_relation* result = alloc(product_set_relation, p, sig); + product_set* s = alloc(product_set, p, sig, product_set::FULL_t); + product_sets::iterator it = r.m_elems.begin(), end = r.m_elems.end(); + for (; it != end; ++it) { + s->mk_project(*(*it), m_removed_cols.size(), m_removed_cols.c_ptr()); + s = p.insert(s, result); + } + dealloc(s); + return result; + } + }; + relation_transformer_fn * product_set_plugin::mk_project_fn( + const relation_base & r, unsigned col_cnt, + const unsigned * removed_cols) { + if (check_kind(r)) { + return alloc(project_fn, r.get_signature(), col_cnt, removed_cols); + } + else { + return 0; + } + } + class product_set_plugin::rename_fn : public convenient_relation_rename_fn { + public: + rename_fn(const relation_signature & orig_sig, unsigned cycle_len, const unsigned * cycle) + : convenient_relation_rename_fn(orig_sig, cycle_len, cycle) { + } + + virtual relation_base * operator()(const relation_base & _r) { + product_set_relation const& r = get(_r); + product_set_plugin& p = r.get_plugin(); + relation_signature const& sig = get_result_signature(); + product_set_relation* result = alloc(product_set_relation, p, sig); + product_set* s = alloc(product_set, p, sig, product_set::FULL_t); + product_sets::iterator it = r.m_elems.begin(), end = r.m_elems.end(); + for (; it != end; ++it) { + s->mk_rename(*(*it), m_cycle.size(), m_cycle.c_ptr()); + s = p.insert(s, result); + } + dealloc(s); + return result; + } + }; + + relation_transformer_fn * product_set_plugin::mk_rename_fn(const relation_base & r, + unsigned cycle_len, const unsigned * permutation_cycle) { + if (check_kind(r)) { + return alloc(rename_fn, r.get_signature(), cycle_len, permutation_cycle); + } + else { + return 0; + } + } + + class product_set_plugin::union_fn : public relation_union_fn { + public: + union_fn() {} + + virtual void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) { + + TRACE("dl", _r.display(tout << "dst:\n"); _src.display(tout << "src:\n");); + + product_set_relation& r = get(_r); + product_set_relation const& src = get(_src); + product_set_relation* d = get(_delta); + r.get_plugin().mk_union(r, src, d); + std::cout << "union: " << r.m_elems.size() << "\n"; + } + }; + void product_set_plugin::mk_union( + product_set_relation& dst, product_set_relation const& src, product_set_relation* delta) { + product_sets::iterator it = src.m_elems.begin(), end = src.m_elems.end(); + for (; it != end; ++it) { + product_set* ps = *it; + if (!dst.m_elems.contains(ps)) { + ps->inc_ref(); + dst.m_elems.insert(ps); + if (delta) { + ps->inc_ref(); + delta->m_elems.insert(ps); + } + } + } + } + relation_union_fn * product_set_plugin::mk_union_fn( + const relation_base & tgt, const relation_base & src, + const relation_base * delta) { + if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) { + return 0; + } + return alloc(union_fn); + } + relation_union_fn * product_set_plugin::mk_widen_fn( + const relation_base & tgt, const relation_base & src, + const relation_base * delta) { + return mk_union_fn(tgt, src, delta); + } + + + class product_set_plugin::filter_identical_fn : public relation_mutator_fn { + unsigned_vector m_identical_cols; + public: + filter_identical_fn(unsigned col_cnt, const unsigned * identical_cols) + : m_identical_cols(col_cnt, identical_cols) {} + + virtual void operator()(relation_base & _r) { + product_set_relation & r = get(_r); + product_set_plugin& p = r.get_plugin(); + ptr_vector elems; + product_sets::iterator it = r.m_elems.begin(), end = r.m_elems.end(); + for (; it != end; ++it) { + elems.push_back(*it); + } + r.m_elems.reset(); + for (unsigned i = 0; i < elems.size(); ++i) { + product_set* s = elems[i]; + if (equate(*s)) { + r.m_elems.insert(s); + } + else { + s->dec_ref(); + } + } + } + private: + bool equate(product_set& dst) { + for (unsigned i = 1; !dst.empty() && i < m_identical_cols.size(); ++i) { + unsigned c1 = m_identical_cols[0]; + unsigned c2 = m_identical_cols[i]; + dst.equate(c1, c2); + } + return !dst.empty(); + } + }; + relation_mutator_fn * product_set_plugin::mk_filter_identical_fn( + const relation_base & t, unsigned col_cnt, const unsigned * identical_cols) { + return check_kind(t)?alloc(filter_identical_fn, col_cnt, identical_cols):0; + } + + + class product_set_plugin::filter_mask_fn : public relation_mutator_fn { + unsigned m_col; + bit_vector m_mask; + public: + filter_mask_fn(product_set_plugin& p, bit_vector const& mask, unsigned col) + : m_col(col), m_mask(mask) { + } + + virtual void operator()(relation_base & _r) { + product_set_relation & r = get(_r); + product_set_plugin & p = r.get_plugin(); + + ptr_vector elems; + product_sets::iterator it = r.m_elems.begin(), end = r.m_elems.end(); + for (; it != end; ++it) { + elems.push_back(*it); + } + r.m_elems.reset(); + for (unsigned i = 0; i < elems.size(); ++i) { + product_set* s = elems[i]; + + if (s->mk_intersect(m_col, m_mask)) { + r.m_elems.insert(s); + } + else { + s->dec_ref(); + } + } + } + }; + + relation_mutator_fn * product_set_plugin::mk_filter_equal_fn(const relation_base & r, + const relation_element & value, unsigned col) { + bit_vector mask; + expr* v = value; + extract_mask(1, &v, mask); + return check_kind(r)?alloc(filter_mask_fn, *this, mask, col):0; + } + + class product_set_plugin::filter_by_union_fn : public relation_mutator_fn { + ptr_vector m_mutators; + public: + filter_by_union_fn(unsigned n, relation_mutator_fn ** mutators): + m_mutators(n, mutators) { + } + virtual ~filter_by_union_fn() { + std::for_each(m_mutators.begin(), m_mutators.end(), delete_proc()); + } + + virtual void operator()(relation_base& _r) { + product_set_relation & r = get(_r); + product_set_plugin & p = r.get_plugin(); + + SASSERT(!m_mutators.empty()); + if (m_mutators.size() == 1) { + (*(m_mutators[0]))(r); + return; + } + product_set_relation src(p, r.get_signature()); + for (unsigned i = 1; i < m_mutators.size(); ++i) { + product_set_relation* r1 = r.clone(); + (*(m_mutators[i]))(*r1); + p.mk_union(src, *r1, 0); + r1->deallocate(); + } + (*(m_mutators[0]))(r); + p.mk_union(r, src, 0); + } + }; + + product_set_plugin::decomp_t product_set_plugin::decompose(expr* condition, expr_ref_vector& args, unsigned& col) { + args.reset(); + expr* e1, *e2; + app* value; + if (m.is_not(condition, e1) && m.is_not(e1, e2)) { + return decompose(e2, args, col); + } + if (m.is_not(condition, e1) && m.is_and(e1)) { + expr_ref tmp(m); + app* a = to_app(e1); + unsigned sz = a->get_num_args(); + for (unsigned i = 0; i < sz; ++i) { + args.push_back(mk_not(a->get_arg(i))); + } + tmp = m.mk_or(args.size(), args.c_ptr()); + return decompose(tmp, args, col); + } + if (m.is_not(condition, e1) && m.is_or(e1)) { + expr_ref tmp(m); + app* a = to_app(e1); + unsigned sz = a->get_num_args(); + for (unsigned i = 0; i < sz; ++i) { + args.push_back(mk_not(a->get_arg(i))); + } + tmp = m.mk_and(args.size(), args.c_ptr()); + return decompose(tmp, args, col); + } + if (m.is_and(condition)) { + app* a = to_app(condition); + unsigned sz = a->get_num_args(); + args.append(sz, a->get_args()); + return AND_d; + } + if (is_setof(condition, args, col)) { + SASSERT(!args.empty()); + return SET_d; + } + if (m.is_or(condition)) { + app* a = to_app(condition); + unsigned sz = a->get_num_args(); + args.append(sz, a->get_args()); + return OR_d; + } + if (is_value_ne(condition, value, col)) { + args.push_back(value); + return NE_d; + } + if (is_value_eq(condition, value, col)) { + args.push_back(value); + return EQ_d; + } + if (m.is_not(condition, e1) && m.is_true(e1)) { + return F_d; + } + if (m.is_false(condition)) { + return F_d; + } + if (m.is_not(condition, e1) && m.is_false(e1)) { + return T_d; + } + if (m.is_true(condition)) { + return T_d; + } + return UNHANDLED_d; + } + + bool product_set_plugin::mk_filter_interpreted( + const relation_base & t, expr_ref_vector const& args, + ptr_vector& mutators) { + unsigned sz = args.size(); + + for (unsigned i = 0; i < sz; ++i) { + expr* arg = args[i]; + if (!is_app(arg)) { + break; + } + relation_mutator_fn* mut = mk_filter_interpreted_fn(t, to_app(arg)); + if (!mut) { + break; + } + mutators.push_back(mut); + } + if (mutators.size() < sz) { + std::for_each(mutators.begin(), mutators.end(), delete_proc()); + return false; + } + else { + return true; + } + } + relation_mutator_fn * product_set_plugin::mk_filter_interpreted_fn( + const relation_base & t, app * condition) { + if (!check_kind(t)) return 0; + unsigned col; + ptr_vector mutators; + expr_ref_vector args(m); + bit_vector mask; + switch (decompose(condition, args, col)) { + case NE_d: + SASSERT(args.size() == 1); + extract_mask(1, args.c_ptr(), mask); + mask.neg(); + return alloc(filter_mask_fn, *this, mask, col); + case EQ_d: + SASSERT(args.size() == 1); + extract_mask(1, args.c_ptr(), mask); + return alloc(filter_mask_fn, *this, mask, col); + case AND_d: + if (!mk_filter_interpreted(t, args, mutators)) { + return 0; + } + return get_manager().mk_apply_sequential_fn(mutators.size(), mutators.c_ptr()); + case OR_d: + if (!mk_filter_interpreted(t, args, mutators)) { + return 0; + } + return alloc(filter_by_union_fn, mutators.size(), mutators.c_ptr()); + case F_d: + return alloc(filter_interpreted_fn, m, m.mk_false()); + case T_d: + return alloc(filter_interpreted_fn, m, m.mk_true()); + case SET_d: + extract_mask(args.size(), args.c_ptr(), mask); + return alloc(filter_mask_fn, *this, mask, col); + case UNHANDLED_d: + std::cout << "filter interpreted unhandled '" << mk_pp(condition, m) << "'\n"; + NOT_IMPLEMENTED_YET(); + return 0; + default: + UNREACHABLE(); + } + return 0; + } + + void product_set_plugin::extract_mask(unsigned n, expr* const* values, bit_vector& mask) { + SASSERT(n > 0); + unsigned sz = set_size(m.get_sort(values[0])); + mask.resize(sz, false); + rational v; + unsigned bv_size; + for (unsigned i = 0; i < n; ++i) { + expr* value = values[i]; + VERIFY(bv.is_numeral(value, v, bv_size)); + SASSERT(v.is_unsigned()); + unsigned w = v.get_unsigned(); + SASSERT(w < sz); + mask.set(w, true); + } + } + + bool product_set_plugin::is_setof(expr* condition, expr_ref_vector& values, unsigned & col) { + if (!m.is_or(condition)) return false; + unsigned sz = to_app(condition)->get_num_args(); + col = UINT_MAX; + unsigned col1; + if (sz == 0) return false; + values.reset(); + app* value; + for (unsigned i = 0; i < sz; ++i) { + expr* arg = to_app(condition)->get_arg(i); + if (is_value_eq(arg, value, col1)) { + if (col == UINT_MAX) { + col = col1; + values.push_back(value); + } + else if (col != col1) { + return false; + } + else { + values.push_back(value); + } + } + else { + return false; + } + } + return true; + } + + bool product_set_plugin::is_value_eq(expr* e, app*& value, unsigned& col) { + expr* e1, *e2; + rational val; + unsigned bv_size; + if (!m.is_eq(e, e1, e2)) return false; + if (!is_var(e1)) std::swap(e1, e2); + if (!is_var(e1)) return false; + if (!bv.is_numeral(e2, val, bv_size)) return false; + if (!val.is_unsigned()) return false; + value = to_app(e2); + col = to_var(e1)->get_idx(); + return true; + } + + bool product_set_plugin::is_value_ne(expr* condition, relation_element& value, unsigned& col) { + expr* e; + if (m.is_not(condition, e)) { + return is_value_eq(e, value, col); + } + else { + return false; + } + } + + +}; + diff --git a/src/muz/rel/product_set.h b/src/muz/rel/product_set.h new file mode 100644 index 000000000..238a33d8a --- /dev/null +++ b/src/muz/rel/product_set.h @@ -0,0 +1,284 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + product_set.h + +Abstract: + + Product set relation. + A product set is a tuple of sets. + The meaning of a product set is the set of + elements in the cross-product. + A product set relation is a set of product sets, + and the meaning of this relation is the union of + all elements from the products. + It is to be used when computing over product sets is + (much) cheaper than over the space of tuples. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-08-23 + +Revision History: + +--*/ +#ifndef _DL_PRODUCT_SET__H_ +#define _DL_PRODUCT_SET__H_ + +#include "util.h" +#include "bit_vector.h" +#include "dl_base.h" +#include "dl_vector_relation.h" + +namespace datalog { + + class product_set_plugin; + + class product_set : public vector_relation { + typedef bit_vector T; + unsigned m_refs; + public: + enum initial_t { + EMPTY_t, + FULL_t + }; + product_set(product_set_plugin& p, relation_signature const& s, initial_t init, T const& t = T()); + + virtual ~product_set(); + unsigned get_hash() const; + bool operator==(product_set const& p) const; + bool contains(product_set const& p) const; + + void inc_ref() { ++m_refs; } + void dec_ref() { --m_refs; if (0 == m_refs) dealloc(this); } + unsigned ref_count() const { return m_refs; } + + struct eq { + bool operator()(product_set const* s1, product_set const* s2) const { + return *s1 == *s2; + } + }; + + struct hash { + unsigned operator()(product_set const* s) const { + return s->get_hash(); + } + }; + + virtual void add_fact(const relation_fact & f); + virtual bool contains_fact(const relation_fact & f) const; + virtual relation_base * clone() const; + virtual relation_base * complement(func_decl*) const; + virtual void reset(); + virtual void to_formula(expr_ref& fml) const; + + bool mk_intersect(unsigned idx, T const& t); + void complement(); + + private: + virtual void display_index(unsigned i, const T&, std::ostream& out) const; + virtual T mk_intersect(T const& t1, T const& t2, bool& _is_empty) const { + T result(t1); + result &= t2; + _is_empty = is_empty(0, result); + return result; + } + + virtual T mk_widen(T const& t1, T const& t2) const { + UNREACHABLE(); + return t1; + } + + virtual T mk_unite(T const& t1, T const& t2) const { + UNREACHABLE(); + return t1; + } + + virtual bool is_subset_of(T const& t1, T const& t2) const { + return t2.contains(t1); + } + + virtual bool is_full(T const& t) const { + for (unsigned j = 0; j < t.size(); ++j) { + if (!t.get(j)) return false; + } + return true; + } + + virtual bool is_empty(unsigned i, T const& t) const { + for (unsigned j = 0; j < t.size(); ++j) { + if (t.get(j)) return false; + } + return true; + } + + virtual void mk_rename_elem(T& t, unsigned col_cnt, unsigned const* cycle) { + // no-op. + } + + virtual T mk_eq(union_find<> const& old_eqs, union_find<> const& neq_eqs, T const& t) const { + UNREACHABLE(); + return t; + } + }; + + + typedef ptr_hashtable product_sets; + + class product_set_relation : public relation_base { + friend class product_set_plugin; + product_sets m_elems; + public: + product_set_relation(product_set_plugin& p, relation_signature const& s); + virtual ~product_set_relation(); + virtual void reset(); + virtual void add_fact(const relation_fact & f); + virtual bool contains_fact(const relation_fact & f) const; + virtual product_set_relation * clone() const; + virtual product_set_relation * complement(func_decl*) const; + virtual void to_formula(expr_ref& fml) const; + product_set_plugin& get_plugin() const; + virtual bool empty() const { return m_elems.empty(); } + virtual void display(std::ostream& out) const; + + virtual bool is_precise() const { return true; } + }; + + class product_set_plugin : public relation_plugin { + friend class product_set_relation; + class join_fn; + class project_fn; + class union_fn; + class rename_fn; + class filter_mask_fn; + class filter_identical_fn; + class filter_interpreted_fn; + class filter_by_negation_fn; + class filter_by_union_fn; + ast_manager& m; + bv_util bv; + + public: + product_set_plugin(relation_manager& rm); + virtual bool can_handle_signature(const relation_signature & s); + static symbol get_name() { return symbol("product_set"); } + virtual relation_base * mk_empty(const relation_signature & s); + virtual relation_base * mk_full(func_decl* p, const relation_signature & s); + virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, + unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); + virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, + const unsigned * removed_cols); + virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, + const unsigned * permutation_cycle); + virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, + const relation_base * delta); + virtual relation_union_fn * mk_widen_fn(const relation_base & tgt, const relation_base & src, + const relation_base * delta); + virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, + const unsigned * identical_cols); + virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, + unsigned col); + virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); + + unsigned set_size(sort* ty); + + private: + static product_set_relation& get(relation_base& r); + static product_set_relation* get(relation_base* r); + static product_set_relation const & get(relation_base const& r); + product_set* insert(product_set* s, product_set_relation* r); + + enum decomp_t { + AND_d, // conjunction + OR_d, // disjunction + EQ_d, // value = col + NE_d, // value != col + F_d, // false + T_d, // true + SET_d, // disjunction value_i = col + UNHANDLED_d + }; + + decomp_t decompose(expr* condition, expr_ref_vector& args, unsigned& col); + + bool is_value_ne(expr* condition, relation_element& value, unsigned& col); + bool is_value_eq(expr* condition, relation_element& value, unsigned& col); + bool is_setof(expr* condition, expr_ref_vector& values, unsigned& col); + expr* mk_not(expr* e) { return m.is_not(e,e)?e:m.mk_not(e); } + void mk_union(product_set_relation& dst, product_set_relation const& src, product_set_relation* delta); + void extract_mask(unsigned sz, expr* const* values, bit_vector& mask); + bool mk_filter_interpreted( + const relation_base & t, expr_ref_vector const& args, + ptr_vector& mutators); + }; + + class product_set_factory; + + + class product_set2 { + friend class product_set_factory; + unsigned char m_data[0]; + public: + enum initial_t { + EMPTY_t, + FULL_t + }; + product_set2(product_set_factory& fac, initial_t init); + ~product_set2(); + unsigned get_hash(product_set_factory& fac) const; + bool equals(product_set_factory& fac, product_set2 const& other) const; + void add_fact(product_set_factory& fac, const relation_fact & f); + bool contains_fact(product_set_factory& fac, const relation_fact & f) const; + relation_base * clone(product_set_factory& fac) const; + void reset(product_set_factory& fac); + void mk_join(product_set_factory& fac, product_set2 const& r1, product_set2 const& r2, + unsigned num_cols, unsigned const* cols1, unsigned const* cols2); + void mk_project(product_set_factory& fac, + product_set2 const& r, unsigned col_cnt, unsigned const* removed_cols); + void mk_rename(product_set_factory& fac, + product_set2 const& r, unsigned col_cnt, unsigned const* cycle); + void mk_union(product_set_factory& fac, + product_set2 const& src, product_set2* delta, bool is_widen); + unsigned find(product_set_factory& fac, unsigned i); + void merge(product_set_factory& fac, unsigned i, unsigned j); + void display(product_set_factory& fac, std::ostream& out) const; + }; + + + class product_set_factory { + unsigned char m_data[0]; + public: + enum initial_t { + EMPTY_t, + FULL_t + }; + product_set_factory(product_set_plugin& p, relation_signature const& sig); + ~product_set_factory(); + product_set2* create(); + void retire(product_set2*); + + unsigned get_hash(product_set2& ps) const; + bool equals(product_set2 const& p1, product_set2 const& p2); + void add_fact(product_set2& p, const relation_fact & f); + bool contains_fact(product_set2& p, const relation_fact & f) const; + relation_base * clone(product_set2& p) const; + void reset(product_set2& p); + void mk_join(product_set2& p, product_set2 const& r1, product_set2 const& r2, + unsigned num_cols, unsigned const* cols1, unsigned const* cols2); + void mk_project(product_set2& p, + product_set2 const& r, unsigned col_cnt, unsigned const* removed_cols); + void mk_rename(product_set2& p, + product_set2 const& r, unsigned col_cnt, unsigned const* cycle); + void mk_union(product_set2& p, + product_set2 const& src, product_set2* delta, bool is_widen); + unsigned find(product_set2& p, unsigned i); + void merge(product_set2& p, unsigned i, unsigned j); + void display(product_set2& p, std::ostream& out) const; + }; + + +}; + +#endif diff --git a/src/muz/rel/rel_context.cpp b/src/muz/rel/rel_context.cpp index 02b00be39..4fd9a8fe9 100644 --- a/src/muz/rel/rel_context.cpp +++ b/src/muz/rel/rel_context.cpp @@ -21,6 +21,7 @@ Revision History: #include"rel_context.h" +#include"stopwatch.h" #include"dl_context.h" #include"dl_compiler.h" #include"dl_instruction.h" @@ -31,6 +32,9 @@ Revision History: #include"dl_interval_relation.h" #include"karr_relation.h" #include"dl_finite_product_relation.h" +#include"product_set.h" +#include"udoc_relation.h" +#include"check_relation.h" #include"dl_lazy_table.h" #include"dl_sparse_table.h" #include"dl_table.h" @@ -47,7 +51,7 @@ Revision History: #include"dl_mk_interp_tail_simplifier.h" #include"dl_mk_bit_blast.h" #include"dl_mk_separate_negated_tails.h" -#include"fixedpoint_params.hpp" +#include"ast_util.h" namespace datalog { @@ -95,7 +99,8 @@ namespace datalog { m_rmanager(ctx), m_answer(m), m_last_result_relation(0), - m_ectx(ctx) { + m_ectx(ctx), + m_sw(0) { // register plugins for builtin tables @@ -111,7 +116,10 @@ namespace datalog { rm.register_plugin(alloc(bound_relation_plugin, rm)); rm.register_plugin(alloc(interval_relation_plugin, rm)); - rm.register_plugin(alloc(karr_relation_plugin, rm)); + if (m_context.karr()) rm.register_plugin(alloc(karr_relation_plugin, rm)); + rm.register_plugin(alloc(product_set_plugin, rm)); + rm.register_plugin(alloc(udoc_plugin, rm)); + rm.register_plugin(alloc(check_relation_plugin, rm)); } rel_context::~rel_context() { @@ -149,18 +157,22 @@ namespace datalog { break; } TRACE("dl", m_context.display(tout);); + //IF_VERBOSE(3, m_context.display_smt2(0,0,verbose_stream());); - if (m_context.get_params().dump_aig().size()) { - const char *filename = static_cast(m_context.get_params().dump_aig().c_ptr()); + if (m_context.print_aig().size()) { + const char *filename = static_cast(m_context.print_aig().c_ptr()); aig_exporter aig(m_context.get_rules(), get_context(), &m_table_facts); std::ofstream strm(filename, std::ios_base::binary); aig(strm); exit(0); } + ::stopwatch sw; + sw.start(); + compiler::compile(m_context, m_context.get_rules(), m_code, termination_code); - TRACE("dl", m_code.display(*this, tout); ); + TRACE("dl", m_code.display(m_ectx, tout); ); bool timeout_after_this_round = time_limit && (restart_time==0 || remaining_time_limit<=restart_time); @@ -176,6 +188,9 @@ namespace datalog { VERIFY( termination_code.perform(m_ectx) || m_context.canceled()); m_code.process_all_costs(); + sw.stop(); + m_sw += sw.get_seconds(); + IF_VERBOSE(10, m_ectx.report_big_relations(1000, verbose_stream());); @@ -218,6 +233,7 @@ namespace datalog { } lbool rel_context::query(unsigned num_rels, func_decl * const* rels) { + setup_default_relation(); get_rmanager().reset_saturated_marks(); scoped_query _scoped_query(m_context); for (unsigned i = 0; i < num_rels; ++i) { @@ -243,11 +259,21 @@ namespace datalog { is_approx = true; } rel.to_formula(e); +#if 0 + // Alternative format: + // List the signature of the relation as + // part of the answer. + expr_ref_vector args(m); + for (unsigned j = 0; j < q->get_arity(); ++j) { + args.push_back(m.mk_var(j, q->get_domain(j))); + } + e = m.mk_implies(m.mk_app(q, args.size(), args.c_ptr()), e); +#endif ans.push_back(e); } SASSERT(!m_last_result_relation); if (some_non_empty) { - m_answer = m.mk_and(ans.size(), ans.c_ptr()); + m_answer = mk_and(m, ans.size(), ans.c_ptr()); if (is_approx) { res = l_undef; m_context.set_status(APPROX); @@ -284,7 +310,7 @@ namespace datalog { transf.register_plugin(alloc(mk_interp_tail_simplifier, m_context)); transf.register_plugin(alloc(mk_separate_negated_tails, m_context)); - if (m_context.get_params().bit_blast()) { + if (m_context.xform_bit_blast()) { transf.register_plugin(alloc(mk_bit_blast, m_context, 22000)); transf.register_plugin(alloc(mk_interp_tail_simplifier, m_context, 21000)); } @@ -303,6 +329,7 @@ namespace datalog { } lbool rel_context::query(expr* query) { + setup_default_relation(); get_rmanager().reset_saturated_marks(); scoped_query _scoped_query(m_context); rule_manager& rm = m_context.get_rule_manager(); @@ -359,7 +386,7 @@ namespace datalog { for (; it != end; ++it) { func_decl* pred = *it; relation_base & rel = get_relation(pred); - if (!rel.empty()) { + if (!rel.fast_empty()) { non_empty = true; break; } @@ -433,7 +460,7 @@ namespace datalog { bool rel_context::is_empty_relation(func_decl* pred) const { relation_base* rb = try_get_relation(pred); - return !rb || rb->empty(); + return !rb || rb->fast_empty(); } relation_manager & rel_context::get_rmanager() { return m_rmanager; } @@ -491,6 +518,12 @@ namespace datalog { get_rmanager().set_cancel(f); } + void rel_context::setup_default_relation() { + if (m_context.default_relation() == symbol("doc")) { + m_context.set_unbound_compressor(false); + } + } + relation_plugin & rel_context::get_ordinary_relation_plugin(symbol relation_name) { relation_plugin * plugin = get_rmanager().get_relation_plugin(relation_name); if (!plugin) { @@ -514,27 +547,13 @@ namespace datalog { SASSERT(m_last_result_relation); return m_last_result_relation->contains_fact(f); } - - void rel_context::reset_tables() { - get_rmanager().reset_saturated_marks(); - rule_set::decl2rules::iterator it = m_context.get_rules().begin_grouped_rules(); - rule_set::decl2rules::iterator end = m_context.get_rules().end_grouped_rules(); - for (; it != end; ++it) { - func_decl* p = it->m_key; - relation_base & rel = get_relation(p); - rel.reset(); - } - for (unsigned i = 0; i < m_table_facts.size(); ++i) { - func_decl* pred = m_table_facts[i].first; - relation_fact const& fact = m_table_facts[i].second; - get_relation(pred).add_fact(fact); - } - } void rel_context::add_fact(func_decl* pred, relation_fact const& fact) { get_rmanager().reset_saturated_marks(); get_relation(pred).add_fact(fact); - m_table_facts.push_back(std::make_pair(pred, fact)); + if (m_context.print_aig().size()) { + m_table_facts.push_back(std::make_pair(pred, fact)); + } } void rel_context::add_fact(func_decl* pred, table_fact const& fact) { @@ -563,6 +582,31 @@ namespace datalog { get_rmanager().store_relation(pred, rel); } + void rel_context::collect_statistics(statistics& st) const { + st.update("saturation time", m_sw); + m_code.collect_statistics(st); + m_ectx.collect_statistics(st); + } + + void rel_context::updt_params() { + if (m_context.check_relation() != symbol::null && + m_context.check_relation() != symbol("null")) { + symbol cr("check_relation"); + m_context.set_default_relation(cr); + relation_plugin* p = get_rmanager().get_relation_plugin(cr); + SASSERT(p); + check_relation_plugin* p1 = dynamic_cast(p); + relation_plugin* p2 = get_rmanager().get_relation_plugin(m_context.check_relation()); + SASSERT(p2); + SASSERT(p1 != p2); + p1->set_plugin(p2); + get_rmanager().set_favourite_plugin(p1); + if (m_context.check_relation() == symbol("doc")) { + m_context.set_unbound_compressor(false); + } + } + } + void rel_context::inherit_predicate_kind(func_decl* new_pred, func_decl* orig_pred) { if (orig_pred) { family_id target_kind = get_rmanager().get_requested_predicate_kind(orig_pred); @@ -586,7 +630,7 @@ namespace datalog { out << "\n--------------\n"; out << "Instructions\n"; - m_code.display(*this, out); + m_code.display(m_ectx, out); out << "\n--------------\n"; out << "Big relations\n"; diff --git a/src/muz/rel/rel_context.h b/src/muz/rel/rel_context.h index 68a6fbd90..e445c926f 100644 --- a/src/muz/rel/rel_context.h +++ b/src/muz/rel/rel_context.h @@ -41,6 +41,7 @@ namespace datalog { fact_vector m_table_facts; execution_context m_ectx; instruction_block m_code; + double m_sw; class scoped_query; @@ -48,12 +49,12 @@ namespace datalog { relation_plugin & get_ordinary_relation_plugin(symbol relation_name); - void reset_tables(); - lbool saturate(scoped_query& sq); void set_cancel(bool f); + void setup_default_relation(); + public: rel_context(context& ctx); @@ -79,9 +80,11 @@ namespace datalog { virtual void inherit_predicate_kind(func_decl* new_pred, func_decl* orig_pred); + virtual void collect_statistics(statistics& st) const; virtual void cancel() { set_cancel(true); } virtual void cleanup() { set_cancel(false);} + virtual void updt_params(); /** \brief Restrict the set of used predicates to \c res. diff --git a/src/muz/rel/tbv.cpp b/src/muz/rel/tbv.cpp new file mode 100644 index 000000000..fc3c32390 --- /dev/null +++ b/src/muz/rel/tbv.cpp @@ -0,0 +1,313 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + tbv.cpp + +Abstract: + + ternary bit-vector utilities. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-09-15 + +Revision History: + + +--*/ + +#include "tbv.h" +#include "hashtable.h" +#include "ast_util.h" + + +static bool s_debug_alloc = false; + +void tbv_manager::debug_alloc() { + s_debug_alloc = true; +} + +tbv_manager::~tbv_manager() { + DEBUG_CODE( + ptr_vector::iterator it = allocated_tbvs.begin(); + ptr_vector::iterator end = allocated_tbvs.end(); + for (; it != end; ++it) { + std::cout << "dangling: " << (*it) << "\n"; + TRACE("doc", tout << "dangling: " << (*it) << "\n";); + }); +} + +void tbv_manager::reset() { + m.reset(); +} +tbv* tbv_manager::allocate() { + tbv* r = reinterpret_cast(m.allocate()); + DEBUG_CODE( + if (s_debug_alloc) { + TRACE("doc", tout << allocated_tbvs.size() << " " << r << "\n";); + } + allocated_tbvs.insert(r); + ); + return r; +} +tbv* tbv_manager::allocate1() { + tbv* v = allocate(); + fill1(*v); + return v; +} +tbv* tbv_manager::allocate0() { + tbv* v = allocate(); + fill0(*v); + return v; +} +tbv* tbv_manager::allocateX() { + tbv* v = allocate(); + fillX(*v); + return v; +} +tbv* tbv_manager::allocate(tbv const& bv) { + tbv* r = allocate(); + copy(*r, bv); + return r; +} +tbv* tbv_manager::allocate(uint64 val) { + tbv* v = allocate0(); + for (unsigned bit = num_tbits(); bit > 0;) { + --bit; + if (val & (1ULL << bit)) { + set(*v, bit, BIT_1); + } else { + set(*v, bit, BIT_0); + } + } + return v; +} + +tbv* tbv_manager::allocate(uint64 val, unsigned hi, unsigned lo) { + tbv* v = allocateX(); + SASSERT(64 >= num_tbits() && num_tbits() > hi && hi >= lo); + set(*v, val, hi, lo); + return v; +} +tbv* tbv_manager::allocate(tbv const& bv, unsigned const* permutation) { + tbv* r = allocate(); + unsigned sz = num_tbits(); + for (unsigned i = 0; i < sz; ++i) { + set(*r, permutation[i], bv[i]); + } + return r; +} +tbv* tbv_manager::project(bit_vector const& to_delete, tbv const& src) { + tbv* r = allocate(); + unsigned i, j; + unsigned n = to_delete.size(); + for (i = 0, j = 0; i < n; ++i) { + if (!to_delete.get(i)) { + set(*r, j, src[i]); + ++j; + } + } + SASSERT(num_tbits() == j); + return r; +} + +void tbv_manager::set(tbv& dst, unsigned index, tbit value) { + SASSERT(index < num_tbits()); + m.set(dst, 2*index, (value & 2) != 0); + m.set(dst, 2*index+1, (value & 1) != 0); +} + + +void tbv_manager::set(tbv& dst, uint64 val, unsigned hi, unsigned lo) { + SASSERT(lo <= hi && hi < num_tbits()); + for (unsigned i = 0; i < hi - lo + 1; ++i) { + set(dst, lo + i, (val & (1ULL << i))?BIT_1:BIT_0); + } +} +void tbv_manager::set(tbv& dst, rational const& r, unsigned hi, unsigned lo) { + SASSERT(lo <= hi && hi < num_tbits()); + if (r.is_uint64()) { + set(dst, r.get_uint64(), hi, lo); + return; + } + for (unsigned i = 0; i < hi - lo + 1; ++i) { + if (bitwise_and(r, rational::power_of_two(i)).is_zero()) + set(dst, lo + i, BIT_0); + else + set(dst, lo + i, BIT_1); + } +} + +void tbv_manager::set(tbv& dst, tbv const& other, unsigned hi, unsigned lo) { + dst.set(other, 2*hi+1, 2*lo); +} + + +tbv* tbv_manager::allocate(rational const& r) { + if (r.is_uint64()) { + return allocate(r.get_uint64()); + } + tbv* v = allocate0(); + for (unsigned bit = num_tbits(); bit > 0; ) { + --bit; + if (bitwise_and(r, rational::power_of_two(bit)).is_zero()) { + set(*v, bit, BIT_0); + } else { + set(*v, bit, BIT_1); + } + } + return v; +} +void tbv_manager::deallocate(tbv* bv) { + DEBUG_CODE( + if (!allocated_tbvs.contains(bv)) { + std::cout << "double deallocate: " << bv << "\n"; + UNREACHABLE(); + } + if (s_debug_alloc) { + TRACE("doc", tout << "deallocate: " << bv << "\n";); + } + allocated_tbvs.erase(bv);); + m.deallocate(bv); +} +void tbv_manager::copy(tbv& dst, tbv const& src) const { + m.copy(dst, src); +} +tbv& tbv_manager::fill0(tbv& bv) const { + // 10101010 = 2 + 8 + 32 + 128 + memset(bv.m_data, 2 + 8 + 32 + 128, m.num_bytes()); + return bv; +} +tbv& tbv_manager::fill1(tbv& bv) const { + // 01010101 = 1 + 4 + 16 + 64 + memset(bv.m_data, 1 + 4 + 16 + 64, m.num_bytes()); + return bv; +} +tbv& tbv_manager::fillX(tbv& bv) const { + m.fill1(bv); + return bv; +} + +tbv& tbv_manager::set_or(tbv& dst, tbv const& src) const { + m.set_or(dst, src); + return dst; +} +bool tbv_manager::set_and(tbv& dst, tbv const& src) const { + m.set_and(dst, src); + return is_well_formed(dst); +} + +bool tbv_manager::is_well_formed(tbv const& dst) const { + unsigned nw = m.num_words(); + unsigned w; + for (unsigned i = 0; i + 1 < nw; ++i) { + w = dst.get_word(i); + w = w | (w << 1) | 0x55555555; + if (w != 0xFFFFFFFF) return false; + } + if (nw > 0) { + w = m.last_word(dst); + w = w | (w << 1) | 0x55555555 | ~m.get_mask(); + if (w != 0xFFFFFFFF) return false; + } + return true; +} + +void tbv_manager::complement(tbv const& src, ptr_vector& result) { + tbv* r; + unsigned n = num_tbits(); + for (unsigned i = 0; i < n; ++i) { + switch (src.get(i)) { + case BIT_0: + r = allocate(src); + set(*r, i, BIT_1); + result.push_back(r); + break; + case BIT_1: + r = allocate(src); + set(*r, i, BIT_0); + result.push_back(r); + break; + default: + break; + } + } +} + +bool tbv_manager::equals(tbv const& a, tbv const& b) const { + return m.equals(a, b); +} +unsigned tbv_manager::hash(tbv const& src) const { + return m.hash(src); +} +bool tbv_manager::contains(tbv const& a, tbv const& b) const { + return m.contains(a, b); +} + +bool tbv_manager::contains(tbv const& a, unsigned_vector const& colsa, + tbv const& b, unsigned_vector const& colsb) const { + for (unsigned i = 0; i < colsa.size(); ++i) { + tbit bit_a = a[colsa[i]]; + if (bit_a == BIT_x) continue; + if (bit_a != b[colsb[i]]) return false; + } + return true; +} + +bool tbv_manager::intersect(tbv const& a, tbv const& b, tbv& result) { + copy(result, a); + return set_and(result, b); +} + +std::ostream& tbv_manager::display(std::ostream& out, tbv const& b, unsigned hi, unsigned lo) const { + SASSERT(lo <= hi && hi < num_tbits()); + for (unsigned i = hi+1; i-- > lo; ) { + switch (b.get(i)) { + case BIT_0: + out << '0'; + break; + case BIT_1: + out << '1'; + break; + case BIT_x: + out << 'x'; + break; + case BIT_z: + out << 'z'; + break; + default: + UNREACHABLE(); + } + } + return out; +} + +std::ostream& tbv_manager::display(std::ostream& out, tbv const& b) const { + if (num_tbits() == 0) return out << "[]"; + return display(out, b, num_tbits()-1, 0); +} + +expr_ref tbv_manager::to_formula(ast_manager& m, tbv const& src) { + expr_ref result(m); + expr_ref_vector conj(m); + for (unsigned i = 0; i < num_tbits(); ++i) { + switch (src[i]) { + case BIT_0: + conj.push_back(m.mk_not(m.mk_const(symbol(i), m.mk_bool_sort()))); + break; + case BIT_1: + conj.push_back(m.mk_const(symbol(i), m.mk_bool_sort())); + break; + default: + break; + } + } + result = mk_and(m, conj.size(), conj.c_ptr()); + return result; +} + +expr_ref tbv_manager::mk_var(ast_manager& m, unsigned i) { + return expr_ref(m.mk_const(symbol(i), m.mk_bool_sort()), m); +} diff --git a/src/muz/rel/tbv.h b/src/muz/rel/tbv.h new file mode 100644 index 000000000..d667ccaa2 --- /dev/null +++ b/src/muz/rel/tbv.h @@ -0,0 +1,147 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + tbv.h + +Abstract: + + ternary bit-vector utilities. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-09-15 + +Revision History: + + +--*/ + +#ifndef _TBV_H_ +#define _TBV_H_ + +#include "fixed_bit_vector.h" +#include "rational.h" +#include "ast.h" + +class tbv; + +enum tbit { + BIT_z = 0x0, + BIT_0 = 0x1, + BIT_1 = 0x2, + BIT_x = 0x3 +}; + +inline tbit neg(tbit t) { + return (tbit)(t ^ 0x3); +} + +class tbv_manager { + friend class tbv; + fixed_bit_vector_manager m; + ptr_vector allocated_tbvs; +public: + tbv_manager(unsigned n): m(2*n) {} + ~tbv_manager(); + void reset(); + tbv* allocate(); + tbv* allocate1(); + tbv* allocate0(); + tbv* allocateX(); + tbv* allocate(tbv const& bv); + tbv* allocate(uint64 n); + tbv* allocate(rational const& r); + tbv* allocate(uint64 n, unsigned hi, unsigned lo); + tbv* allocate(tbv const& bv, unsigned const* permutation); + + void deallocate(tbv* bv); + + void copy(tbv& dst, tbv const& src) const; + unsigned num_tbits() const { return m.num_bits()/2; } + tbv& reset(tbv& bv) const { return fill0(bv); } + tbv& fill0(tbv& bv) const; + tbv& fill1(tbv& bv) const; + tbv& fillX(tbv& bv) const; + bool set_and(tbv& dst, tbv const& src) const; + tbv& set_or(tbv& dst, tbv const& src) const; + void complement(tbv const& src, ptr_vector& result); + bool equals(tbv const& a, tbv const& b) const; + unsigned hash(tbv const& src) const; + bool contains(tbv const& a, tbv const& b) const; + bool contains(tbv const& a, unsigned_vector const& colsa, + tbv const& b, unsigned_vector const& colsb) const; + bool intersect(tbv const& a, tbv const& b, tbv& result); + std::ostream& display(std::ostream& out, tbv const& b) const; + std::ostream& display(std::ostream& out, tbv const& b, unsigned hi, unsigned lo) const; + tbv* project(bit_vector const& to_delete, tbv const& src); + bool is_well_formed(tbv const& b) const; // - does not contain BIT_z; + void set(tbv& dst, uint64 n, unsigned hi, unsigned lo); + void set(tbv& dst, rational const& r, unsigned hi, unsigned lo); + void set(tbv& dst, tbv const& other, unsigned hi, unsigned lo); + void set(tbv& dst, unsigned index, tbit value); + + + static void debug_alloc(); + expr_ref to_formula(ast_manager& m, tbv const& src); + expr_ref mk_var(ast_manager& m, unsigned i); +}; + +class tbv: private fixed_bit_vector { + friend class fixed_bit_vector_manager; + friend class tbv_manager; + +public: + + struct eq { + tbv_manager& m; + eq(tbv_manager& m):m(m) {} + bool operator()(tbv const& d1, tbv const& d2) const { + return m.equals(d1, d2); + } + }; + + struct hash { + tbv_manager& m; + hash(tbv_manager& m):m(m) {} + unsigned operator()(tbv const& d) const { + return m.hash(d); + } + }; + + + tbit operator[](unsigned idx) const { return (tbit)get(idx); } + + +private: + + + unsigned get(unsigned index) const { + index *= 2; + return (fixed_bit_vector::get(index) << 1) | (unsigned)fixed_bit_vector::get(index+1); + } +}; + +class tbv_ref { + tbv_manager& mgr; + tbv* d; +public: + tbv_ref(tbv_manager& mgr):mgr(mgr),d(0) {} + tbv_ref(tbv_manager& mgr, tbv* d):mgr(mgr),d(d) {} + ~tbv_ref() { + if (d) mgr.deallocate(d); + } + tbv_ref& operator=(tbv* d2) { + if (d) mgr.deallocate(d); + d = d2; + return *this; + } + tbv& operator*() { return *d; } + tbv* operator->() { return d; } + tbv* get() { return d; } + tbv* detach() { tbv* result = d; d = 0; return result; } +}; + + +#endif /* _TBV_H_ */ diff --git a/src/muz/rel/udoc_relation.cpp b/src/muz/rel/udoc_relation.cpp new file mode 100644 index 000000000..90c3ec7c0 --- /dev/null +++ b/src/muz/rel/udoc_relation.cpp @@ -0,0 +1,1254 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + udoc_relation.cpp + +Abstract: + + Relation based on union of DOCs. + +Author: + + Nuno Lopes (a-nlopes) 2013-03-01 + Nikolaj Bjorner (nbjorner) 2014-09-15 + +Revision History: + + Revised version of dl_hassel_diff facilities. + +Notes: + +--*/ +#include "udoc_relation.h" +#include "dl_relation_manager.h" +#include "qe_util.h" +#include "ast_util.h" +#include "smt_kernel.h" + + +namespace datalog { + + udoc_relation::udoc_relation(udoc_plugin& p, relation_signature const& sig): + relation_base(p, sig), + dm(p.dm(p.num_signature_bits(sig))) { + unsigned column = 0; + for (unsigned i = 0; i < sig.size(); ++i) { + m_column_info.push_back(column); + column += p.num_sort_bits(sig[i]); + } + m_column_info.push_back(column); + } + udoc_relation::~udoc_relation() { + reset(); + } + void udoc_relation::reset() { + m_elems.reset(dm); + } + void udoc_relation::expand_column_vector(unsigned_vector& v, const udoc_relation* other) const { + unsigned_vector orig; + orig.swap(v); + for (unsigned i = 0; i < orig.size(); ++i) { + unsigned col, limit; + if (orig[i] < get_num_cols()) { + col = column_idx(orig[i]); + limit = col + column_num_bits(orig[i]); + } else { + unsigned idx = orig[i] - get_num_cols(); + col = get_num_bits() + other->column_idx(idx); + limit = col + other->column_num_bits(idx); + } + for (; col < limit; ++col) { + v.push_back(col); + } + } + } + + doc* udoc_relation::fact2doc(const relation_fact & f) const { + doc* d = dm.allocate0(); + for (unsigned i = 0; i < f.size(); ++i) { + unsigned bv_size; + rational val; + VERIFY(get_plugin().is_numeral(f[i], val, bv_size)); + SASSERT(bv_size == column_num_bits(i)); + unsigned lo = column_idx(i); + unsigned hi = column_idx(i + 1); + dm.tbvm().set(d->pos(),val, hi-1, lo); + } + return d; + } + void udoc_relation::add_fact(const relation_fact & f) { + doc* d = fact2doc(f); + m_elems.insert(dm, d); + } + void udoc_relation::add_new_fact(const relation_fact & f) { + m_elems.push_back(fact2doc(f)); + } + bool udoc_relation::empty() const { + return m_elems.is_empty_complete(get_plugin().m, dm); + } + bool udoc_relation::contains_fact(const relation_fact & f) const { + doc_ref d(dm, fact2doc(f)); + return m_elems.contains(dm, *d); + } + udoc_relation * udoc_relation::clone() const { + udoc_relation* result = udoc_plugin::get(get_plugin().mk_empty(get_signature())); + for (unsigned i = 0; i < m_elems.size(); ++i) { + result->m_elems.push_back(dm.allocate(m_elems[i])); + } + return result; + } + udoc_relation * udoc_relation::complement(func_decl* f) const { + udoc_relation* result = udoc_plugin::get(get_plugin().mk_empty(get_signature())); + m_elems.complement(dm, result->m_elems); + return result; + } + void udoc_relation::to_formula(expr_ref& fml) const { + ast_manager& m = fml.get_manager(); + expr_ref_vector disj(m); + for (unsigned i = 0; i < m_elems.size(); ++i) { + disj.push_back(to_formula(m_elems[i])); + } + fml = mk_or(m, disj.size(), disj.c_ptr()); + } + expr_ref udoc_relation::to_formula(doc const& d) const { + ast_manager& m = get_plugin().get_ast_manager(); + expr_ref result(m); + expr_ref_vector conjs(m); + conjs.push_back(to_formula(d.pos())); + for (unsigned i = 0; i < d.neg().size(); ++i) { + conjs.push_back(m.mk_not(to_formula(d.neg()[i]))); + } + result = mk_and(m, conjs.size(), conjs.c_ptr()); + return result; + } + expr_ref udoc_relation::to_formula(tbv const& t) const { + udoc_plugin& p = get_plugin(); + ast_manager& m = p.get_ast_manager(); + expr_ref result(m); + expr_ref_vector conjs(m); + for (unsigned i = 0; i < get_num_cols(); ++i) { + var_ref v(m); + v = m.mk_var(i, get_signature()[i]); + unsigned lo = column_idx(i); + unsigned hi = column_idx(i+1); + rational r(0); + unsigned lo1 = lo; + bool is_x = true; + for (unsigned j = lo; j < hi; ++j) { + switch(t[j]) { + case BIT_0: + if (is_x) is_x = false, lo1 = j, r.reset(); + break; + case BIT_1: + if (is_x) is_x = false, lo1 = j, r.reset(); + r += rational::power_of_two(j - lo1); + break; + case BIT_x: + if (!is_x) { + SASSERT(p.bv.is_bv_sort(get_signature()[i])); + conjs.push_back(m.mk_eq(p.bv.mk_extract(j-1-lo,lo1-lo,v), + p.bv.mk_numeral(r,j-lo1))); + } + is_x = true; + break; + default: + UNREACHABLE(); + } + } + if (!is_x) { + expr_ref num(m); + if (lo1 == lo) { + num = p.mk_numeral(r, get_signature()[i]); + conjs.push_back(m.mk_eq(v, num)); + } + else { + num = p.bv.mk_numeral(r, hi-lo1); + conjs.push_back(m.mk_eq(p.bv.mk_extract(hi-1-lo,lo1-lo,v), num)); + } + } + } + result = mk_and(m, conjs.size(), conjs.c_ptr()); + return result; + } + + udoc_plugin& udoc_relation::get_plugin() const { + return static_cast(relation_base::get_plugin()); + } + + void udoc_relation::display(std::ostream& out) const { + m_elems.display(dm, out); out << "\n"; + } + + // ------------- + + udoc_plugin::udoc_plugin(relation_manager& rm): + relation_plugin(udoc_plugin::get_name(), rm), + m(rm.get_context().get_manager()), + bv(m), + dl(m), + m_disable_fast_pass(false) { + } + udoc_plugin::~udoc_plugin() { + u_map::iterator it = m_dms.begin(), end = m_dms.end(); + for (; it != end; ++it) { + dealloc(it->m_value); + } + } + udoc_relation& udoc_plugin::get(relation_base& r) { + return dynamic_cast(r); + } + udoc_relation* udoc_plugin::get(relation_base* r) { + return r?dynamic_cast(r):0; + } + udoc_relation const & udoc_plugin::get(relation_base const& r) { + return dynamic_cast(r); + } + + doc_manager& udoc_plugin::dm(relation_signature const& sig) { + return dm(num_signature_bits(sig)); + } + + doc_manager& udoc_plugin::dm(unsigned n) { + doc_manager* r; + if (!m_dms.find(n, r)) { + r = alloc(doc_manager, n); + m_dms.insert(n, r); + } + return *r; + } + bool udoc_relation::is_var_range(expr* e, unsigned& hi, unsigned& lo, unsigned& v) const { + udoc_plugin& p = get_plugin(); + if (is_var(e)) { + v = to_var(e)->get_idx(); + hi = p.num_sort_bits(e)-1; + lo = 0; + return true; + } + expr* e2; + if (p.bv.is_extract(e, lo, hi, e2) && is_var(e2)) { + v = to_var(e2)->get_idx(); + SASSERT(lo <= hi); + return true; + } + return false; + } + + expr* udoc_plugin::mk_numeral(rational const& r, sort* s) { + if (bv.is_bv_sort(s)) { + return bv.mk_numeral(r, s); + } + if (m.is_bool(s)) { + if (r.is_zero()) return m.mk_false(); + return m.mk_true(); + } + SASSERT(dl.is_finite_sort(s)); + return dl.mk_numeral(r.get_uint64(), s); + } + bool udoc_plugin::is_numeral(expr* e, rational& r, unsigned& num_bits) { + if (bv.is_numeral(e, r, num_bits)) return true; + if (m.is_true(e)) { + r = rational(1); + num_bits = 1; + return true; + } + if (m.is_false(e)) { + r = rational(0); + num_bits = 1; + return true; + } + uint64 n, sz; + ast_manager& m = get_ast_manager(); + if (dl.is_numeral(e, n) && dl.try_get_size(m.get_sort(e), sz)) { + num_bits = 0; + while (sz > 0) ++num_bits, sz = sz/2; + r = rational(n, rational::ui64()); + return true; + } + return false; + } + unsigned udoc_plugin::num_sort_bits(sort* s) const { + unsigned num_bits = 0; + if (bv.is_bv_sort(s)) + return bv.get_bv_size(s); + if (m.is_bool(s)) + return 1; + uint64 sz; + if (dl.try_get_size(s, sz)) { + while (sz > 0) ++num_bits, sz /= 2; + return num_bits; + } + UNREACHABLE(); + return 0; + } + unsigned udoc_plugin::num_signature_bits(relation_signature const& sig) { + unsigned result = 0; + for (unsigned i = 0; i < sig.size(); ++i) { + result += num_sort_bits(sig[i]); + } + return result; + } + + bool udoc_plugin::is_finite_sort(sort* s) const { + return bv.is_bv_sort(s) || dl.is_finite_sort(s); + } + + + bool udoc_plugin::can_handle_signature(const relation_signature & sig) { + for (unsigned i = 0; i < sig.size(); ++i) { + if (!is_finite_sort(sig[i])) + return false; + } + return true; + } + relation_base * udoc_plugin::mk_empty(const relation_signature & sig) { + return alloc(udoc_relation, *this, sig); + } + relation_base * udoc_plugin::mk_full(func_decl* p, const relation_signature & s) { + udoc_relation* r = get(mk_empty(s)); + r->get_udoc().push_back(dm(s).allocateX()); + return r; + } + class udoc_plugin::join_fn : public convenient_relation_join_fn { + doc_manager& dm; + doc_manager& dm1; + doc_manager& dm2; + public: + join_fn(udoc_plugin& p, udoc_relation const& t1, udoc_relation const& t2, unsigned col_cnt, + const unsigned * cols1, const unsigned * cols2) + : convenient_relation_join_fn(t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2), + dm(p.dm(get_result_signature())), + dm1(t1.get_dm()), + dm2(t2.get_dm()) { + t1.expand_column_vector(m_cols1); + t2.expand_column_vector(m_cols2); + } + + virtual relation_base * operator()(const relation_base & _r1, const relation_base & _r2) { + udoc_relation const& r1 = get(_r1); + udoc_relation const& r2 = get(_r2); + TRACE("doc", r1.display(tout << "r1:\n"); r2.display(tout << "r2:\n");); + udoc_plugin& p = r1.get_plugin(); + relation_signature const& sig = get_result_signature(); + udoc_relation * result = alloc(udoc_relation, p, sig); + udoc const& d1 = r1.get_udoc(); + udoc const& d2 = r2.get_udoc(); + udoc& r = result->get_udoc(); + r.join(d1, d2, dm, dm1, m_cols1, m_cols2); + TRACE("doc", result->display(tout << "result:\n");); + IF_VERBOSE(3, result->display(verbose_stream() << "join result:\n");); + SASSERT(r.well_formed(result->get_dm())); + return result; + } + }; + + + relation_join_fn * udoc_plugin::mk_join_fn( + const relation_base & t1, const relation_base & t2, + unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { + if (!check_kind(t1) || !check_kind(t2)) { + return 0; + } + return alloc(join_fn, *this, get(t1), get(t2), col_cnt, cols1, cols2); + } + + class udoc_plugin::project_fn : public convenient_relation_project_fn { + bit_vector m_to_delete; + public: + project_fn(udoc_relation const & t, unsigned removed_col_cnt, const unsigned * removed_cols) + : convenient_relation_project_fn(t.get_signature(), removed_col_cnt, removed_cols) { + t.expand_column_vector(m_removed_cols); + unsigned n = t.get_dm().num_tbits(); + m_to_delete.resize(n, false); + for (unsigned i = 0; i < m_removed_cols.size(); ++i) { + m_to_delete.set(m_removed_cols[i], true); + } + } + + virtual relation_base * operator()(const relation_base & tb) { + TRACE("doc", tb.display(tout << "src:\n");); + udoc_relation const& t = get(tb); + udoc_plugin& p = t.get_plugin(); + udoc_relation* r = udoc_plugin::get(p.mk_empty(get_result_signature())); + doc_manager& dm1 = t.get_dm(); + doc_manager& dm2 = r->get_dm(); + doc_ref d2(dm2); + udoc const& ud1 = t.get_udoc(); + udoc& ud2 = r->get_udoc(); + for (unsigned i = 0; i < ud1.size(); ++i) { + d2 = dm1.project(dm2, m_to_delete, ud1[i]); + ud2.push_back(d2.detach()); + } + TRACE("doc", tout << "final size: " << r->get_size_estimate_rows() << '\n';); + SASSERT(ud2.well_formed(dm2)); + return r; + } + }; + + + relation_transformer_fn * udoc_plugin::mk_project_fn( + const relation_base & t, unsigned col_cnt, + const unsigned * removed_cols) { + if (!check_kind(t)) + return 0; + return alloc(project_fn, get(t), col_cnt, removed_cols); + } + + class udoc_plugin::rename_fn : public convenient_relation_rename_fn { + unsigned_vector m_permutation; + public: + rename_fn(udoc_relation const& t, unsigned cycle_len, const unsigned * cycle) + : convenient_relation_rename_fn(t.get_signature(), cycle_len, cycle) { + udoc_plugin& p = t.get_plugin(); + ast_manager& m = p.get_ast_manager(); + relation_signature const& sig1 = t.get_signature(); + relation_signature const& sig2 = get_result_signature(); + unsigned_vector permutation0, column_info; + for (unsigned i = 0; i < t.get_num_bits(); ++i) { + m_permutation.push_back(i); + } + for (unsigned i = 0; i < sig1.size(); ++i) { + permutation0.push_back(i); + } + for (unsigned i = 0; i < cycle_len; ++i) { + unsigned j = (i + 1)%cycle_len; + unsigned col1 = cycle[i]; + unsigned col2 = cycle[j]; + permutation0[col2] = col1; + } + unsigned column = 0; + for (unsigned i = 0; i < sig2.size(); ++i) { + column_info.push_back(column); + column += p.num_sort_bits(sig2[i]); + } + column_info.push_back(column); + SASSERT(column == t.get_num_bits()); + + TRACE("doc", + sig1.output(m, tout << "sig1: "); tout << "\n"; + sig2.output(m, tout << "sig2: "); tout << "\n"; + tout << "permute: "; + for (unsigned i = 0; i < permutation0.size(); ++i) { + tout << permutation0[i] << " "; + } + tout << "\n"; + tout << "cycle: "; + for (unsigned i = 0; i < cycle_len; ++i) { + tout << cycle[i] << " "; + } + tout << "\n"; + ); + + + // 0 -> 2 + // [3:2:1] -> [1:2:3] + // [3,4,5,1,2,0] + + for (unsigned i = 0; i < sig1.size(); ++i) { + unsigned len = t.column_num_bits(i); + unsigned lo1 = t.column_idx(i); + unsigned col2 = permutation0[i]; + unsigned lo2 = column_info[col2]; + SASSERT(lo2 + len <= t.get_num_bits()); + SASSERT(lo1 + len <= t.get_num_bits()); + for (unsigned k = 0; k < len; ++k) { + m_permutation[k + lo1] = k + lo2; + } + } + } + + virtual relation_base * operator()(const relation_base & _r) { + udoc_relation const& r = get(_r); + TRACE("doc", r.display(tout << "r:\n");); + udoc_plugin& p = r.get_plugin(); + relation_signature const& sig = get_result_signature(); + udoc_relation* result = alloc(udoc_relation, p, sig); + udoc const& src = r.get_udoc(); + udoc& dst = result->get_udoc(); + doc_manager& dm = r.get_dm(); + SASSERT(&result->get_dm() == &dm); + for (unsigned i = 0; i < src.size(); ++i) { + dst.push_back(dm.allocate(src[i], m_permutation.c_ptr())); + } + TRACE("doc", result->display(tout << "result:\n");); + SASSERT(dst.well_formed(dm)); + return result; + } + }; + relation_transformer_fn * udoc_plugin::mk_rename_fn( + const relation_base & r, + unsigned cycle_len, const unsigned * permutation_cycle) { + if (check_kind(r)) { + return alloc(rename_fn, get(r), cycle_len, permutation_cycle); + } + else { + return 0; + } + } + class udoc_plugin::union_fn : public relation_union_fn { + public: + union_fn() {} + + virtual void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) { + TRACE("doc", _r.display(tout << "dst:\n"); _src.display(tout << "src:\n");); + udoc_relation& r = get(_r); + udoc_relation const& src = get(_src); + udoc_relation* d = get(_delta); + doc_manager& dm = r.get_dm(); + ast_manager& m = r.get_plugin().get_ast_manager(); + udoc* d1 = 0; + if (d) d1 = &d->get_udoc(); + IF_VERBOSE(3, r.display(verbose_stream() << "orig: ");); + r.get_plugin().mk_union(dm, r.get_udoc(), src.get_udoc(), d1); + SASSERT(r.get_udoc().well_formed(dm)); + SASSERT(!d1 || d1->well_formed(dm)); + TRACE("doc", _r.display(tout << "dst':\n"); ); + IF_VERBOSE(3, r.display(verbose_stream() << "union: ");); + IF_VERBOSE(3, if (d) d->display(verbose_stream() << "delta: ");); + } + }; + void udoc_plugin::mk_union(doc_manager& dm, udoc& dst, udoc const& src, udoc* delta) { + for (unsigned i = 0; i < src.size(); ++i) { + doc* d = dm.allocate(src[i]); + if (dst.insert(dm, d)) { + if (delta) { + delta->insert(dm, dm.allocate(src[i])); + } + } + } + } + relation_union_fn * udoc_plugin::mk_union_fn( + const relation_base & tgt, const relation_base & src, + const relation_base * delta) { + if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) { + return 0; + } + return alloc(union_fn); + } + relation_union_fn * udoc_plugin::mk_widen_fn( + const relation_base & tgt, const relation_base & src, + const relation_base * delta) { + return mk_union_fn(tgt, src, delta); + } + + class udoc_plugin::filter_identical_fn : public relation_mutator_fn { + unsigned_vector m_cols; + unsigned m_size; + bit_vector m_empty_bv; + union_find_default_ctx union_ctx; + union_find<> m_equalities; + public: + filter_identical_fn(const relation_base & _r, unsigned col_cnt, const unsigned *identical_cols) + : m_cols(col_cnt), m_equalities(union_ctx) { + udoc_relation const& r = get(_r); + doc_manager& dm = r.get_dm(); + unsigned num_bits = dm.num_tbits(); + m_size = r.column_num_bits(identical_cols[0]); + m_empty_bv.resize(r.get_num_bits(), false); + for (unsigned i = 0; i < col_cnt; ++i) { + m_cols[i] = r.column_idx(identical_cols[i]); + } + for (unsigned i = 0, e = m_empty_bv.size(); i < e; ++i) { + m_equalities.mk_var(); + } + for (unsigned i = 1; i < col_cnt; ++i) { + for (unsigned j = 0; j < m_size; ++j) { + m_equalities.merge(m_cols[0]+j ,m_cols[i]+j); + } + } + } + + virtual void operator()(relation_base & _r) { + udoc_relation& r = get(_r); + udoc& d = r.get_udoc(); + doc_manager& dm = r.get_dm(); + d.merge(dm, m_cols[0], m_size, m_equalities, m_empty_bv); + SASSERT(d.well_formed(dm)); + TRACE("doc", tout << "final size: " << r.get_size_estimate_rows() << '\n';); + } + }; + relation_mutator_fn * udoc_plugin::mk_filter_identical_fn( + const relation_base & t, unsigned col_cnt, const unsigned * identical_cols) { + return check_kind(t)?alloc(filter_identical_fn, t, col_cnt, identical_cols):0; + } + class udoc_plugin::filter_equal_fn : public relation_mutator_fn { + doc_manager& dm; + doc* m_filter; + public: + filter_equal_fn(udoc_plugin& p, const udoc_relation & t, const relation_element val, unsigned col): + dm(p.dm(t.get_signature())) { + rational r; + unsigned num_bits; + VERIFY(p.is_numeral(val, r, num_bits)); + m_filter = dm.allocateX(); + unsigned lo = t.column_idx(col); + unsigned hi = t.column_idx(col+1); + SASSERT(num_bits == hi - lo); + dm.tbvm().set(m_filter->pos(), r, hi-1, lo); + } + virtual ~filter_equal_fn() { + dm.deallocate(m_filter); + } + virtual void operator()(relation_base & tb) { + udoc_relation & t = get(tb); + t.get_udoc().intersect(dm, *m_filter); + SASSERT(t.get_udoc().well_formed(t.get_dm())); + } + }; + relation_mutator_fn * udoc_plugin::mk_filter_equal_fn( + const relation_base & t, const relation_element & value, unsigned col) { + if (!check_kind(t)) + return 0; + return alloc(filter_equal_fn, *this, get(t), value, col); + } + + bool udoc_relation::is_guard(unsigned n, expr* const* gs) const { + for (unsigned i = 0; i < n; ++i) { + if (!is_guard(gs[i])) return false; + } + return true; + } + bool udoc_relation::is_guard(expr* g) const { + udoc_plugin& p = get_plugin(); + ast_manager& m = p.get_ast_manager(); + bv_util& bv = p.bv; + expr* e1, *e2; + unsigned hi, lo, v; + if (m.is_and(g) || m.is_or(g) || m.is_not(g) || m.is_true(g) || m.is_false(g)) { + return is_guard(to_app(g)->get_num_args(), to_app(g)->get_args()); + } + if (m.is_eq(g, e1, e2) && bv.is_bv(e1)) { + if (is_var_range(e1, hi, lo, v) && is_ground(e2)) return true; + if (is_var_range(e2, hi, lo, v) && is_ground(e1)) return true; + } + if (is_var(g)) { + return true; + } + return false; + } + + void udoc_relation::extract_guard(expr* cond, expr_ref& guard, expr_ref& rest) const { + rest.reset(); + ast_manager& m = get_plugin().get_ast_manager(); + expr_ref_vector conds(m), guards(m), rests(m); + conds.push_back(cond); + qe::flatten_and(conds); + for (unsigned i = 0; i < conds.size(); ++i) { + expr* g = conds[i].get(); + if (is_guard(g)) { + guards.push_back(g); + } + else { + rests.push_back(g); + } + } + guard = mk_and(m, guards.size(), guards.c_ptr()); + rest = mk_and(m, rests.size(), rests.c_ptr()); + } + void udoc_relation::extract_equalities(expr* g, expr_ref& rest, subset_ints& equalities, + unsigned_vector& roots) const { + rest.reset(); + ast_manager& m = get_plugin().get_ast_manager(); + expr_ref_vector conds(m); + conds.push_back(g); + qe::flatten_and(conds); + expr* e1, *e2; + for (unsigned i = 0; i < conds.size(); ++i) { + expr* g = conds[i].get(); + if (m.is_eq(g, e1, e2)) { + extract_equalities(e1, e2, conds, equalities, roots); + conds[i] = conds.back(); + conds.pop_back(); + } + } + rest = mk_and(m, conds.size(), conds.c_ptr()); + } + + void udoc_relation::extract_equalities( + expr* e1, expr* e2, expr_ref_vector& conds, + subset_ints& equalities, unsigned_vector& roots) const { + udoc_plugin& p = get_plugin(); + ast_manager& m = p.get_ast_manager(); + bv_util& bv = p.bv; + th_rewriter rw(m); + unsigned hi, lo1, lo2, hi1, hi2, v1, v2; + if (bv.is_concat(e2)) { + std::swap(e1, e2); + } + if (bv.is_concat(e1)) { + expr_ref e3(m); + app* a1 = to_app(e1); + hi = p.num_sort_bits(e1)-1; + unsigned n = a1->get_num_args(); + for (unsigned i = 0; i < n; ++i) { + expr* e = a1->get_arg(i); + unsigned sz = p.num_sort_bits(e); + e3 = bv.mk_extract(hi, hi-sz+1, e2); + rw(e3); + extract_equalities(e, e3, conds, equalities, roots); + hi -= sz; + } + return; + } + if (is_var_range(e1, hi1, lo1, v1) && + is_var_range(e2, hi2, lo2, v2)) { + unsigned col1 = column_idx(v1); + lo1 += col1; + hi1 += col1; + unsigned col2 = column_idx(v2); + lo2 += col2; + hi2 += col2; + for (unsigned j = 0; j <= hi1-lo1; ++j) { + roots.push_back(lo1 + j); + equalities.merge(lo1 + j, lo2 + j); + } + return; + } + conds.push_back(m.mk_eq(e1, e2)); + } + + void udoc_relation::compile_guard(expr* g, udoc& d, bit_vector const& discard_cols) const { + d.reset(dm); + d.push_back(dm.allocateX()); + apply_guard(g, d, discard_cols); + } + void udoc_relation::apply_guard(expr* g, udoc& result, bit_vector const& discard_cols) const { + // datastructure to store equalities with columns that will be projected out + union_find_default_ctx union_ctx; + subset_ints equalities(union_ctx); + for (unsigned i = 0, e = discard_cols.size(); i < e; ++i) { + equalities.mk_var(); + } + apply_guard(g, result, equalities, discard_cols); + } + bool udoc_relation::apply_ground_eq(doc_ref& d, unsigned v, unsigned hi, unsigned lo, expr* c) const { + udoc_plugin& p = get_plugin(); + unsigned num_bits; + rational r; + unsigned col = column_idx(v); + lo += col; + hi += col; + if (p.is_numeral(c, r, num_bits)) { + d = dm.allocateX(); + dm.tbvm().set(d->pos(), r, hi, lo); + return true; + } + // other cases? + return false; + } + + + + + bool udoc_relation::apply_bv_eq( + expr* e1, expr* e2, bit_vector const& discard_cols, udoc& result) const { + udoc_plugin& p = get_plugin(); + ast_manager& m = p.get_ast_manager(); + bv_util& bv = p.bv; + th_rewriter rw(m); + doc_ref d(get_dm()); + unsigned hi, lo, lo1, lo2, hi1, hi2, v, v1, v2; + if (bv.is_concat(e2)) { + std::swap(e1, e2); + } + if (bv.is_concat(e1)) { + expr_ref e3(m); + app* a1 = to_app(e1); + hi = p.num_sort_bits(e1)-1; + unsigned n = a1->get_num_args(); + for (unsigned i = 0; i < n; ++i) { + expr* e = a1->get_arg(i); + unsigned sz = p.num_sort_bits(e); + e3 = bv.mk_extract(hi, hi-sz+1, e2); + rw(e3); + if (!apply_bv_eq(e, e3, discard_cols, result)) return false; + hi -= sz; + } + return true; + } + if (is_ground(e1)) { + std::swap(e1, e2); + } + if (is_var_range(e1, hi, lo, v) && is_ground(e2) && + apply_ground_eq(d, v, hi, lo, e2)) { + result.intersect(dm, *d); + return true; + } + if (is_var_range(e1, hi1, lo1, v1) && + is_var_range(e2, hi2, lo2, v2)) { + unsigned idx1 = lo1 + column_idx(v1); + unsigned idx2 = lo2 + column_idx(v2); + unsigned length = hi1-lo1+1; + result.merge(dm, idx1, idx2, length, discard_cols); + return true; + } + + return false; + } + + void udoc_relation::apply_guard( + expr* g, udoc& result, subset_ints const& equalities, bit_vector const& discard_cols) const { + ast_manager& m = get_plugin().get_ast_manager(); + bv_util& bv = get_plugin().bv; + expr *e0, *e1, *e2; + unsigned hi, lo, v; + doc_ref d(get_dm()); + if (result.is_empty()) { + } + else if (m.is_true(g)) { + } + else if (m.is_false(g)) { + result.reset(dm); + } + else if (m.is_and(g)) { + for (unsigned i = 0; !result.is_empty() && i < to_app(g)->get_num_args(); ++i) { + apply_guard(to_app(g)->get_arg(i), result, equalities, discard_cols); + } + } + else if (m.is_not(g, e0) && + m.is_eq(e0, e1, e2) && bv.is_bv(e1) && + is_var_range(e1, hi, lo, v) && is_ground(e2) && + apply_ground_eq(d, v, hi, lo, e2)) { + result.subtract(dm, *d); + } + else if (m.is_not(g, e0) && + m.is_eq(e0, e2, e1) && bv.is_bv(e1) && + is_var_range(e1, hi, lo, v) && is_ground(e2) && + apply_ground_eq(d, v, hi, lo, e2)) { + result.subtract(dm, *d); + } + else if (m.is_not(g, e1)) { + udoc sub; + sub.push_back(dm.allocateX()); + // TODO: right now we state that no columns are discarded to avoid + // silent column merging. This can be optimized if the set of merged + // columns is returned so that here we remove different columns. + bit_vector empty; + empty.resize(discard_cols.size(), false); + apply_guard(e1, sub, equalities, empty); + result.subtract(dm, sub); + result.simplify(dm); + TRACE("doc", + result.display(dm, tout << "result0:") << "\n"; + sub.display(dm, tout << "sub:") << "\n";); + sub.reset(dm); + TRACE("doc", result.display(dm, tout << "result:") << "\n";); + } + else if (m.is_or(g)) { + udoc sub; + sub.push_back(dm.allocateX()); + for (unsigned i = 0; !sub.is_empty() && i < to_app(g)->get_num_args(); ++i) { + expr_ref arg(m); + arg = mk_not(m, to_app(g)->get_arg(i)); + apply_guard(arg, sub, equalities, discard_cols); + } + TRACE("doc", result.display(dm, tout << "result0:") << "\n";); + result.subtract(dm, sub); + TRACE("doc", + sub.display(dm, tout << "sub:") << "\n"; + result.display(dm, tout << "result:") << "\n";); + sub.reset(dm); + } + else if (is_var(g)) { + SASSERT(m.is_bool(g)); + unsigned v = to_var(g)->get_idx(); + unsigned idx = column_idx(v); + doc_ref d(dm); + d = dm.allocateX(); + dm.set(*d, idx, BIT_1); + result.intersect(dm, *d); + } + else if ((m.is_eq(g, e1, e2) || m.is_iff(g, e1, e2)) && m.is_bool(e1)) { + udoc diff1, diff2; + diff1.push_back(dm.allocateX()); + diff2.push_back(dm.allocateX()); + expr_ref f1(m), f2(m); + f1 = mk_not(m, e1); + f2 = mk_not(m, e2); + apply_guard(e1, diff1, equalities, discard_cols); + apply_guard(f2, diff1, equalities, discard_cols); + result.subtract(dm, diff1); + diff1.reset(dm); + apply_guard(f1, diff2, equalities, discard_cols); + apply_guard(e2, diff2, equalities, discard_cols); + result.subtract(dm, diff2); + diff2.reset(dm); + } + else if (m.is_eq(g, e1, e2) && bv.is_bv(e1)) { + if (apply_bv_eq(e1, e2, discard_cols, result)) { + // done + } + else { + goto failure_case; + } + } + else { + failure_case: + std::ostringstream strm; + strm << "Guard expression is not handled" << mk_pp(g, m); + throw default_exception(strm.str()); + } + } + + class udoc_plugin::filter_interpreted_fn : public relation_mutator_fn { + union_find_default_ctx union_ctx; + doc_manager& dm; + expr_ref m_original_condition; + expr_ref m_reduced_condition; + udoc m_udoc; + bit_vector m_empty_bv; + subset_ints m_equalities; + + public: + filter_interpreted_fn(const udoc_relation & t, ast_manager& m, app *condition) : + dm(t.get_dm()), + m_original_condition(condition, m), + m_reduced_condition(m), + m_equalities(union_ctx) { + unsigned num_bits = t.get_num_bits(); + m_empty_bv.resize(num_bits, false); + expr_ref guard(m); + for (unsigned i = 0; i < num_bits; ++i) { + m_equalities.mk_var(); + } + t.extract_guard(condition, guard, m_reduced_condition); + t.compile_guard(guard, m_udoc, m_empty_bv); + + TRACE("doc", + tout << "original condition: " << mk_pp(condition, m) << "\n"; + tout << "remaining condition: " << m_reduced_condition << "\n"; + m_udoc.display(dm, tout) << "\n";); + } + + virtual ~filter_interpreted_fn() { + m_udoc.reset(dm); + } + + virtual void operator()(relation_base & tb) { + udoc_relation & t = get(tb); + udoc& u = t.get_udoc(); + ast_manager& m = m_reduced_condition.get_manager(); + SASSERT(u.well_formed(dm)); + u.intersect(dm, m_udoc); + SASSERT(u.well_formed(dm)); + t.apply_guard(m_reduced_condition, u, m_equalities, m_empty_bv); + SASSERT(u.well_formed(dm)); + u.simplify(dm); + SASSERT(u.well_formed(dm)); + TRACE("doc", tout << "final size: " << t.get_size_estimate_rows() << '\n';); + IF_VERBOSE(3, t.display(verbose_stream());); + } + }; + relation_mutator_fn * udoc_plugin::mk_filter_interpreted_fn(const relation_base & t, app * condition) { + return check_kind(t)?alloc(filter_interpreted_fn, get(t), get_ast_manager(), condition):0; + } + + class udoc_plugin::join_project_fn : public convenient_relation_join_project_fn { +#if 0 + udoc_plugin::join_fn m_joiner; +#endif + bit_vector m_to_delete; + + public: + join_project_fn( + udoc_relation const& t1, udoc_relation const& t2, unsigned col_cnt, + const unsigned * cols1, const unsigned * cols2, + unsigned removed_col_cnt, unsigned const* rm_cols) + : convenient_relation_join_project_fn( + t1.get_signature(), t2.get_signature(), + col_cnt, cols1, cols2, + removed_col_cnt, rm_cols) +#if 0 + , m_joiner(t1.get_plugin(), t1, t2, col_cnt, cols1, cols2) +#endif + { + udoc_plugin& p = t1.get_plugin(); + unsigned num_bits1 = t1.get_num_bits(); + unsigned num_bits = num_bits1 + t2.get_num_bits(); + unsigned_vector removed_cols(removed_col_cnt, rm_cols); + t1.expand_column_vector(removed_cols, &t2); + t1.expand_column_vector(m_cols1); + t2.expand_column_vector(m_cols2); + m_to_delete.resize(num_bits, false); + for (unsigned i = 0; i < removed_cols.size(); ++i) { + m_to_delete.set(removed_cols[i], true); + } + } + + + // TBD: replace this by "join" given below. + virtual relation_base* operator()(relation_base const& t1, relation_base const& t2) { +#if 1 + return join(get(t1), get(t2)); +#else + udoc_relation *joined = get(m_joiner(t1, t2)); + relation_base* result = 0; + if (joined->fast_empty()) { + result = t1.get_plugin().mk_empty(get_result_signature()); + } + else { + project_fn projector(*joined, m_removed_cols.size(), m_removed_cols.c_ptr()); + result = projector(*joined); + } + joined->deallocate(); + return result; +#endif + } + private: + + udoc_relation* join(udoc_relation const& t1, udoc_relation const& t2) { + relation_signature prod_signature; + prod_signature.append(t1.get_signature()); + prod_signature.append(t2.get_signature()); + udoc const& d1 = t1.get_udoc(); + udoc const& d2 = t2.get_udoc(); + doc_manager& dm1 = t1.get_dm(); + doc_manager& dm2 = t2.get_dm(); + udoc_plugin& p = t1.get_plugin(); + doc_manager& dm_prod = p.dm(prod_signature); + udoc_relation* result = get(p.mk_empty(get_result_signature())); + udoc& res = result->get_udoc(); + doc_manager& dm_res = result->get_dm(); + + for (unsigned i = 0; i < d1.size(); ++i) { + for (unsigned j = 0; j < d2.size(); ++j) { + doc_ref d(dm_prod, dm_prod.join(d1[i], d2[j], dm1, m_cols1, m_cols2)); + if (d) { + res.insert(dm_res, dm_prod.project(dm_res, m_to_delete, *d)); + IF_VERBOSE(2, + if (res.size() > 0 && 0 == res.size() % 10000) { + verbose_stream() << "result size: " << res.size() + << " i:" << i << " j:" << j << " " + << 100*i/d1.size() << "% complete\n"; + }); + } + } + } + TRACE("doc", result->display(tout);); + return result; + } + }; + + + class udoc_plugin::join_project_and_fn : public relation_join_fn { + public: + join_project_and_fn() {} + + virtual relation_base* operator()(relation_base const& t1, relation_base const& t2) { + udoc_relation *result = get(t1.clone()); + result->get_udoc().intersect(result->get_dm(), get(t2).get_udoc()); + return result; + } + }; + + relation_join_fn * udoc_plugin::mk_join_project_fn( + relation_base const& t1, relation_base const& t2, + unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, + unsigned removed_col_cnt, const unsigned * removed_cols) { + if (!check_kind(t1) || !check_kind(t2)) + return 0; + // special case where we have h(X) :- f(X), g(X). + if (joined_col_cnt == removed_col_cnt && + t1.get_signature().size() == joined_col_cnt && + t2.get_signature().size() == joined_col_cnt) { + for (unsigned i = 0; i < removed_col_cnt; ++i) { + if (removed_cols[i] != i) + goto general_fn; + } + return alloc(join_project_and_fn); + } + + general_fn: + return alloc(join_project_fn, get(t1), get(t2), + joined_col_cnt, cols1, cols2, + removed_col_cnt, removed_cols); + } + + + // + // Notes: + // 1. this code could use some cleanup and simplification. + // 2. It is also not very efficient in the copy routines. + // They fall back to copying each bit instead of a chunk. + // 3. Argument about correctness is needed as comments. + // 4. Unit/stress test cases are needed. + // + class udoc_plugin::negation_filter_fn : public relation_intersection_filter_fn { + struct mk_remove_cols { + mk_remove_cols(relation_base const& t1, relation_base const& t2, unsigned_vector& remove_cols) { + unsigned sz1 = t1.get_signature().size(); + unsigned sz2 = t2.get_signature().size(); + for (unsigned i = 0; i < sz2; ++i) { + remove_cols.push_back(sz1 + i); + } + } + }; + unsigned_vector m_t_cols; + unsigned_vector m_neg_cols; + unsigned_vector m_remove_cols; + mk_remove_cols m_mk_remove_cols; + join_project_fn m_join_project; + bool m_is_subtract; + //bool m_is_aliased; + public: + negation_filter_fn(const udoc_relation & t, const udoc_relation & neg, unsigned joined_col_cnt, + const unsigned *t_cols, const unsigned *neg_cols) + : m_t_cols(joined_col_cnt, t_cols), + m_neg_cols(joined_col_cnt, neg_cols), + m_mk_remove_cols(t, neg, m_remove_cols), + m_join_project(t, neg, joined_col_cnt, t_cols, neg_cols, + m_remove_cols.size(), m_remove_cols.c_ptr()), + m_is_subtract(false)//, + /*m_is_aliased(true) */{ + SASSERT(joined_col_cnt > 0 || neg.get_signature().size() == 0); + m_is_subtract = (joined_col_cnt == t.get_signature().size()); + m_is_subtract &= (joined_col_cnt == neg.get_signature().size()); + svector found(joined_col_cnt, false); + for (unsigned i = 0; m_is_subtract && i < joined_col_cnt; ++i) { + m_is_subtract = !found[t_cols[i]] && (t_cols[i] == neg_cols[i]); + found[t_cols[i]] = true; + } + t.expand_column_vector(m_t_cols); + neg.expand_column_vector(m_neg_cols); + } + + virtual void operator()(relation_base& tb, const relation_base& negb) { + udoc_relation& t = get(tb); + udoc_relation const& n = get(negb); + udoc_plugin& p = t.get_plugin(); + IF_VERBOSE(3, t.display(verbose_stream() << "dst:");); + IF_VERBOSE(3, n.display(verbose_stream() << "neg:");); + if (t.fast_empty() || n.fast_empty()) + return; + + /* TODO: double check + if (!m_is_aliased && !p.m_disable_fast_pass) { + // fast_pass(t, n); + } + */ + if (n.get_signature().empty()) + t.get_udoc().reset(t.get_dm()); + else if (m_is_subtract) + t.get_udoc().subtract(t.get_dm(), n.get_udoc()); + else + slow_pass(t, n); + } + + private: + /* + void fast_pass(udoc_relation& t, const udoc_relation& n) { + SASSERT(!m_is_aliased); + udoc & dst = t.get_udoc(); + udoc const & neg = n.get_udoc(); + doc_manager& dmt = t.get_dm(); + doc_manager& dmn = n.get_dm(); + udoc result; + for (unsigned i = 0; i < dst.size(); ++i) { + bool subsumed = false; + for (unsigned j = 0; j < neg.size(); ++j) { + if (dmn.contains(neg[j], m_neg_cols, dst[i], m_t_cols)) { + dmt.deallocate(&dst[i]); + subsumed = true; + break; + } + } + if (!subsumed) + result.push_back(&dst[i]); + } + std::swap(dst, result); + } + */ + + void slow_pass(udoc_relation& t, udoc_relation const& n) { + doc_manager& dmt = t.get_dm(); + udoc_relation* jp = get(m_join_project(t, n)); + if (!jp->fast_empty()) { + t.get_udoc().subtract(dmt, jp->get_udoc()); + } + TRACE("doc", t.display(tout); tout << "\n"; jp->display(tout); tout << "\n";); + jp->deallocate(); + } + }; + + relation_intersection_filter_fn * udoc_plugin::mk_filter_by_negation_fn( + const relation_base& t, + const relation_base& neg, unsigned joined_col_cnt, const unsigned *t_cols, + const unsigned *negated_cols) { + if (!check_kind(t) || !check_kind(neg)) + return 0; + return alloc(negation_filter_fn, get(t), get(neg), joined_col_cnt, t_cols, negated_cols); + } + + + + class udoc_plugin::filter_proj_fn : public convenient_relation_project_fn { + union_find_default_ctx union_ctx; + doc_manager& dm; + expr_ref m_original_condition; + expr_ref m_reduced_condition; + udoc m_udoc; + udoc m_udoc2; + bit_vector m_to_delete; // map: col idx -> bool (whether the column is to be removed) + subset_ints m_equalities; + unsigned_vector m_roots; + + public: + filter_proj_fn(const udoc_relation & t, ast_manager& m, app *condition, + unsigned col_cnt, const unsigned * removed_cols) : + convenient_relation_project_fn(t.get_signature(), col_cnt, removed_cols), + dm(t.get_dm()), + m_original_condition(condition, m), + m_reduced_condition(m), + m_equalities(union_ctx) { + unsigned num_bits = t.get_num_bits(); + t.expand_column_vector(m_removed_cols); + m_to_delete.resize(num_bits, false); + for (unsigned i = 0; i < num_bits; ++i) { + m_equalities.mk_var(); + } + for (unsigned i = 0; i < m_removed_cols.size(); ++i) { + m_to_delete.set(m_removed_cols[i], true); + } + expr_ref guard(m), non_eq_cond(condition, m); + t.extract_equalities(condition, non_eq_cond, m_equalities, m_roots); + t.extract_guard(non_eq_cond, guard, m_reduced_condition); + t.compile_guard(guard, m_udoc, m_to_delete); + } + + virtual ~filter_proj_fn() { + m_udoc.reset(dm); + } + virtual relation_base* operator()(const relation_base & tb) { + udoc_relation const & t = get(tb); + udoc const& u1 = t.get_udoc(); + doc_manager& dm = t.get_dm(); + ast_manager& m = m_reduced_condition.get_manager(); + m_udoc2.copy(dm, u1); + m_udoc2.intersect(dm, m_udoc); + t.apply_guard(m_reduced_condition, m_udoc2, m_equalities, m_to_delete); + m_udoc2.merge(dm, m_roots, m_equalities, m_to_delete); + SASSERT(m_udoc2.well_formed(dm)); + udoc_relation* r = get(t.get_plugin().mk_empty(get_result_signature())); + doc_manager& dm2 = r->get_dm(); + for (unsigned i = 0; i < m_udoc2.size(); ++i) { + doc* d = dm.project(dm2, m_to_delete, m_udoc2[i]); + r->get_udoc().insert(dm2, d); + SASSERT(r->get_udoc().well_formed(dm2)); + } + m_udoc2.reset(dm); + IF_VERBOSE(3, r->display(verbose_stream() << "filter project result:\n");); + return r; + } + }; + relation_transformer_fn * udoc_plugin::mk_filter_interpreted_and_project_fn( + const relation_base & t, app * condition, + unsigned removed_col_cnt, const unsigned * removed_cols) { + return check_kind(t)?alloc(filter_proj_fn, get(t), get_ast_manager(), condition, removed_col_cnt, removed_cols):0; + } + + + + + +} diff --git a/src/muz/rel/udoc_relation.h b/src/muz/rel/udoc_relation.h new file mode 100644 index 000000000..a9d31e7d3 --- /dev/null +++ b/src/muz/rel/udoc_relation.h @@ -0,0 +1,153 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + udoc_relation.h + +Abstract: + + Relation based on union of DOCs. + +Author: + + Nuno Lopes (a-nlopes) 2013-03-01 + Nikolaj Bjorner (nbjorner) 2014-09-15 + +Revision History: + + +--*/ + +#ifndef _UDOC_RELATION_H_ +#define _UDOC_RELATION_H_ + +#include "doc.h" +#include "dl_base.h" + +namespace datalog { + class udoc_plugin; + class udoc_relation; + + class udoc_relation : public relation_base { + friend class udoc_plugin; + doc_manager& dm; + mutable udoc m_elems; + unsigned_vector m_column_info; + doc* fact2doc(relation_fact const& f) const; + expr_ref to_formula(tbv const& t) const; + expr_ref to_formula(doc const& d) const; + public: + udoc_relation(udoc_plugin& p, relation_signature const& s); + virtual ~udoc_relation(); + virtual void reset(); + virtual void add_fact(const relation_fact & f); + virtual void add_new_fact(const relation_fact & f); + virtual bool contains_fact(const relation_fact & f) const; + virtual udoc_relation * clone() const; + virtual udoc_relation * complement(func_decl*) const; + virtual void to_formula(expr_ref& fml) const; + udoc_plugin& get_plugin() const; + virtual bool fast_empty() const { return m_elems.is_empty(); } + virtual bool empty() const; + virtual void display(std::ostream& out) const; + virtual bool is_precise() const { return true; } + virtual unsigned get_size_estimate_rows() const { return m_elems.size(); } + + doc_manager& get_dm() const { return dm; } + udoc const& get_udoc() const { return m_elems; } + udoc& get_udoc() { return m_elems; } + unsigned get_num_records() const { return m_elems.size(); } + unsigned get_num_bits() const { return m_column_info.back(); } + unsigned get_num_cols() const { return m_column_info.size()-1; } + unsigned column_idx(unsigned col) const { return m_column_info[col]; } + unsigned column_num_bits(unsigned col) const { return m_column_info[col+1] - m_column_info[col]; } + void expand_column_vector(unsigned_vector& v, const udoc_relation* other = 0) const; + void extract_guard(expr* condition, expr_ref& guard, expr_ref& rest) const; + bool is_guard(expr* g) const; + bool is_guard(unsigned n, expr* const *g) const; + void compile_guard(expr* g, udoc& result, bit_vector const& discard_cols) const; + void extract_equalities(expr* g, expr_ref& rest, subset_ints& equalities, unsigned_vector& roots) const; + void extract_equalities( + expr* e1, expr* e2, expr_ref_vector& conds, + subset_ints& equalities, unsigned_vector& roots) const; + void apply_guard(expr* g, udoc& result, bit_vector const& discard_cols) const; + void apply_guard(expr* g, udoc& result, subset_ints const& equalities, bit_vector const& discard_cols) const; + bool apply_ground_eq(doc_ref& d, unsigned v, unsigned hi, unsigned lo, expr* c) const; + bool apply_bv_eq(expr* e1, expr* e2, bit_vector const& discard_cols, udoc& result) const; + bool is_var_range(expr* e, unsigned& hi, unsigned& lo, unsigned& v) const; + }; + + class udoc_plugin : public relation_plugin { + friend class udoc_relation; + class join_fn; + class join_project_fn; + class join_project_and_fn; + class project_fn; + class union_fn; + class rename_fn; + class filter_equal_fn; + class filter_identical_fn; + class filter_interpreted_fn; + class filter_by_negation_fn; + class filter_by_union_fn; + class filter_proj_fn; + class negation_filter_fn; + ast_manager& m; + bv_util bv; + dl_decl_util dl; + u_map m_dms; + bool m_disable_fast_pass; + + doc_manager& dm(unsigned sz); + doc_manager& dm(relation_signature const& sig); + static udoc_relation& get(relation_base& r); + static udoc_relation* get(relation_base* r); + static udoc_relation const & get(relation_base const& r); + void mk_union(doc_manager& dm, udoc& dst, udoc const& src, udoc* delta); + bool is_numeral(expr* e, rational& r, unsigned& num_bits); + unsigned num_sort_bits(expr* e) const { return num_sort_bits(get_ast_manager().get_sort(e)); } + unsigned num_sort_bits(sort* s) const; + bool is_finite_sort(sort* s) const; + unsigned num_signature_bits(relation_signature const& sig); + expr* mk_numeral(rational const& r, sort* s); + public: + udoc_plugin(relation_manager& rm); + ~udoc_plugin(); + virtual bool can_handle_signature(const relation_signature & s); + static symbol get_name() { return symbol("doc"); } + virtual relation_base * mk_empty(const relation_signature & s); + virtual relation_base * mk_full(func_decl* p, const relation_signature & s); + virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, + unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); + virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, + const unsigned * removed_cols); + virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, + const unsigned * permutation_cycle); + virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, + const relation_base * delta); + virtual relation_union_fn * mk_widen_fn(const relation_base & tgt, const relation_base & src, + const relation_base * delta); + virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, + const unsigned * identical_cols); + virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, + unsigned col); + virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); + virtual relation_intersection_filter_fn * mk_filter_by_negation_fn( + const relation_base& t, + const relation_base& neg, unsigned joined_col_cnt, const unsigned *t_cols, + const unsigned *negated_cols); + virtual relation_transformer_fn * mk_filter_interpreted_and_project_fn( + const relation_base & t, app * condition, + unsigned removed_col_cnt, const unsigned * removed_cols); + virtual relation_join_fn * mk_join_project_fn( + relation_base const& t1, relation_base const& t2, + unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, + unsigned removed_col_cnt, const unsigned * removed_cols); + + void disable_fast_pass() { m_disable_fast_pass = true; } + }; +}; + +#endif /* _UDOC_RELATION_H_ */ + diff --git a/src/muz/tab/tab_context.cpp b/src/muz/tab/tab_context.cpp index 83842a68b..3175d1622 100644 --- a/src/muz/tab/tab_context.cpp +++ b/src/muz/tab/tab_context.cpp @@ -216,11 +216,13 @@ namespace tb { } void get_free_vars(ptr_vector& vars) const { - ::get_free_vars(m_head, vars); + expr_free_vars fv; + fv(m_head); for (unsigned i = 0; i < m_predicates.size(); ++i) { - ::get_free_vars(m_predicates[i], vars); + fv.accumulate(m_predicates[i]); } - ::get_free_vars(m_constraint, vars); + fv.accumulate(m_constraint); + vars.append(fv.size(), fv.c_ptr()); } expr_ref to_formula() const { @@ -763,7 +765,7 @@ namespace tb { m_weight_multiply(1.0), m_update_frequency(20), m_next_update(20) { - set_strategy(ctx.get_params().tab_selection()); + set_strategy(ctx.tab_selection()); } void init(rules const& rs) { @@ -1107,16 +1109,16 @@ namespace tb { m_S1.apply(2, delta, expr_offset(tgt.get_constraint(), 0), tmp); m_S1.apply(2, delta, expr_offset(src.get_constraint(), 1), tmp2); constraint = m.mk_and(tmp, tmp2); - ptr_vector vars; // perform trival quantifier-elimination: uint_set index_set; - get_free_vars(head, vars); + expr_free_vars fv; + fv(head); for (unsigned i = 0; i < predicates.size(); ++i) { - get_free_vars(predicates[i].get(), vars); + fv.accumulate(predicates[i].get()); } - for (unsigned i = 0; i < vars.size(); ++i) { - if (vars[i]) { + for (unsigned i = 0; i < fv.size(); ++i) { + if (fv[i]) { index_set.insert(i); } } @@ -1127,7 +1129,7 @@ namespace tb { // initialize rule. result->init(head, predicates, constraint); - vars.reset(); + ptr_vector vars; result->get_free_vars(vars); bool change = false; var_ref w(m); diff --git a/src/muz/transforms/dl_mk_array_blast.cpp b/src/muz/transforms/dl_mk_array_blast.cpp index 641d40779..fb860f2ac 100644 --- a/src/muz/transforms/dl_mk_array_blast.cpp +++ b/src/muz/transforms/dl_mk_array_blast.cpp @@ -294,7 +294,7 @@ namespace datalog { if (m_simplifier.transform_rule(new_rules.last(), new_rule)) { if (r.get_proof()) { scoped_proof _sc(m); - r.to_formula(fml1); + rm.to_formula(r, fml1); p = m.mk_rewrite(fml1, fml2); p = m.mk_modus_ponens(r.get_proof(), p); new_rule->set_proof(m, p); diff --git a/src/muz/transforms/dl_mk_bit_blast.cpp b/src/muz/transforms/dl_mk_bit_blast.cpp index fd1dbb205..8f4c840eb 100644 --- a/src/muz/transforms/dl_mk_bit_blast.cpp +++ b/src/muz/transforms/dl_mk_bit_blast.cpp @@ -225,7 +225,6 @@ namespace datalog { mk_interp_tail_simplifier m_simplifier; bit_blaster_rewriter m_blaster; expand_mkbv m_rewriter; - bool blast(rule *r, expr_ref& fml) { proof_ref pr(m); @@ -235,7 +234,7 @@ namespace datalog { if (!m_simplifier.transform_rule(r, r2)) { r2 = r; } - r2->to_formula(fml1); + m_context.get_rule_manager().to_formula(*r2.get(), fml1); m_blaster(fml1, fml2, pr); m_rewriter(fml2, fml3); TRACE("dl", tout << mk_pp(fml, m) << " -> " << mk_pp(fml2, m) << " -> " << mk_pp(fml3, m) << "\n";); @@ -263,7 +262,7 @@ namespace datalog { rule_set * operator()(rule_set const & source) { // TODO pc - if (!m_context.bit_blast()) { + if (!m_context.xform_bit_blast()) { return 0; } rule_manager& rm = m_context.get_rule_manager(); @@ -274,7 +273,7 @@ namespace datalog { m_rewriter.m_cfg.set_dst(result); for (unsigned i = 0; !m_context.canceled() && i < sz; ++i) { rule * r = source.get_rule(i); - r->to_formula(fml); + rm.to_formula(*r, fml); if (blast(r, fml)) { proof_ref pr(m); if (r->get_proof()) { diff --git a/src/muz/transforms/dl_mk_coalesce.cpp b/src/muz/transforms/dl_mk_coalesce.cpp index ac7a58d8d..7476a5655 100644 --- a/src/muz/transforms/dl_mk_coalesce.cpp +++ b/src/muz/transforms/dl_mk_coalesce.cpp @@ -134,9 +134,9 @@ namespace datalog { is_neg.push_back(false); res = rm.mk(head, tail.size(), tail.c_ptr(), is_neg.c_ptr(), tgt->name()); if (m_ctx.generate_proof_trace()) { - src.to_formula(fml1); - tgt->to_formula(fml2); - res->to_formula(fml); + rm.to_formula(src, fml1); + rm.to_formula(*tgt.get(),fml2); + rm.to_formula(*res.get(),fml); #if 0 sort* ps = m.mk_proof_sort(); sort* domain[3] = { ps, ps, m.mk_bool_sort() }; diff --git a/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp b/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp index b01b4326c..ca3042ff5 100644 --- a/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp +++ b/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp @@ -491,9 +491,10 @@ namespace datalog { bool mk_interp_tail_simplifier::transform_rule(rule * r0, rule_ref & res) { - rule_ref r(r0, m_context.get_rule_manager()); + rule_manager& rm = m_context.get_rule_manager(); + rule_ref r(r0, rm); - if (r->has_quantifiers()) { + if (rm.has_quantifiers(*r)) { res = r; return true; } diff --git a/src/muz/transforms/dl_mk_quantifier_instantiation.cpp b/src/muz/transforms/dl_mk_quantifier_instantiation.cpp index fcb8d7b85..95d3e8e73 100644 --- a/src/muz/transforms/dl_mk_quantifier_instantiation.cpp +++ b/src/muz/transforms/dl_mk_quantifier_instantiation.cpp @@ -238,7 +238,7 @@ namespace datalog { proof* p1 = r.get_proof(); for (unsigned i = 0; i < added_rules.get_num_rules(); ++i) { rule* r2 = added_rules.get_rule(i); - r2->to_formula(fml); + rm.to_formula(*r2, fml); pr = m.mk_modus_ponens(m.mk_def_axiom(m.mk_implies(m.get_fact(p1), fml)), p1); r2->set_proof(m, pr); } @@ -252,9 +252,10 @@ namespace datalog { } bool has_quantifiers = false; unsigned sz = source.get_num_rules(); + rule_manager& rm = m_ctx.get_rule_manager(); for (unsigned i = 0; !has_quantifiers && i < sz; ++i) { rule& r = *source.get_rule(i); - has_quantifiers = has_quantifiers || r.has_quantifiers(); + has_quantifiers = has_quantifiers || rm.has_quantifiers(r); if (r.has_negation()) { return 0; } diff --git a/src/muz/transforms/dl_mk_rule_inliner.cpp b/src/muz/transforms/dl_mk_rule_inliner.cpp index 522bd2e86..7dabece2f 100644 --- a/src/muz/transforms/dl_mk_rule_inliner.cpp +++ b/src/muz/transforms/dl_mk_rule_inliner.cpp @@ -179,7 +179,7 @@ namespace datalog { if (m_context.generate_proof_trace()) { expr_ref_vector s1 = m_unifier.get_rule_subst(tgt, true); expr_ref_vector s2 = m_unifier.get_rule_subst(src, false); - datalog::resolve_rule(tgt, src, tail_index, s1, s2, *res.get()); + datalog::resolve_rule(m_rm, tgt, src, tail_index, s1, s2, *res.get()); } return true; } @@ -644,7 +644,8 @@ namespace datalog { tout << " num unifiers: " << m_unifiers.size(); tout << " num positions: " << m_positions.find(e).size() << "\n"; output_predicate(m_context, to_app(e), tout); tout << "\n";); - return true; + // stop visitor when we have more than 1 unifier, since that's all we want. + return m_unifiers.size() <= 1; } void mk_rule_inliner::visitor::reset(unsigned sz) { @@ -754,7 +755,7 @@ namespace datalog { valid.reset(); valid.resize(sz, true); - bool allow_branching = m_context.get_params().inline_linear_branch(); + bool allow_branching = m_context.get_params().xform_inline_linear_branch(); for (unsigned i = 0; i < sz; ++i) { @@ -866,7 +867,7 @@ namespace datalog { scoped_ptr res = alloc(rule_set, m_context); - if (m_context.get_params().inline_eager()) { + if (m_context.get_params().xform_inline_eager()) { TRACE("dl", source.display(tout << "before eager inlining\n");); plan_inlining(source); something_done = transform_rules(source, *res); @@ -884,7 +885,7 @@ namespace datalog { res = alloc(rule_set, source); } - if (m_context.get_params().inline_linear() && inline_linear(res)) { + if (m_context.get_params().xform_inline_linear() && inline_linear(res)) { something_done = true; } diff --git a/src/muz/transforms/dl_mk_separate_negated_tails.cpp b/src/muz/transforms/dl_mk_separate_negated_tails.cpp index 782e1011d..9a78c0d4d 100644 --- a/src/muz/transforms/dl_mk_separate_negated_tails.cpp +++ b/src/muz/transforms/dl_mk_separate_negated_tails.cpp @@ -37,10 +37,10 @@ namespace datalog { void mk_separate_negated_tails::get_private_vars(rule const& r, unsigned j) { m_vars.reset(); m_fv.reset(); - get_free_vars(r.get_head(), m_fv); + m_fv(r.get_head()); for (unsigned i = 0; i < r.get_tail_size(); ++i) { if (i != j) { - get_free_vars(r.get_tail(i), m_fv); + m_fv.accumulate(r.get_tail(i)); } } @@ -49,7 +49,7 @@ namespace datalog { expr* v = p->get_arg(i); if (is_var(v)) { unsigned idx = to_var(v)->get_idx(); - if (idx >= m_fv.size() || !m_fv[idx]) { + if (!m_fv.contains(idx)) { m_vars.push_back(v); } } diff --git a/src/muz/transforms/dl_mk_separate_negated_tails.h b/src/muz/transforms/dl_mk_separate_negated_tails.h index 8cd806f43..03a52c997 100644 --- a/src/muz/transforms/dl_mk_separate_negated_tails.h +++ b/src/muz/transforms/dl_mk_separate_negated_tails.h @@ -42,7 +42,7 @@ namespace datalog { rule_manager& rm; context & m_ctx; ptr_vector m_vars; - ptr_vector m_fv; + expr_free_vars m_fv; bool has_private_vars(rule const& r, unsigned j); void get_private_vars(rule const& r, unsigned j); diff --git a/src/muz/transforms/dl_mk_slice.cpp b/src/muz/transforms/dl_mk_slice.cpp index 0df75324d..2a49d534e 100644 --- a/src/muz/transforms/dl_mk_slice.cpp +++ b/src/muz/transforms/dl_mk_slice.cpp @@ -120,7 +120,7 @@ namespace datalog { obj_map::iterator end = m_rule2slice.end(); expr_ref fml(m); for (; it != end; ++it) { - it->m_value->to_formula(fml); + rm.to_formula(*it->m_value, fml); m_pinned_exprs.push_back(fml); TRACE("dl", tout << "orig: " << mk_pp(fml, m) << "\n"; @@ -238,7 +238,7 @@ namespace datalog { r3->display(m_ctx, tout << "res:");); r1 = r3; } - r1->to_formula(concl); + rm.to_formula(*r1.get(), concl); proof* new_p = m.mk_hyper_resolve(premises.size(), premises.c_ptr(), concl, positions, substs); m_pinned_exprs.push_back(new_p); m_pinned_rules.push_back(r1.get()); @@ -676,10 +676,10 @@ namespace datalog { } void mk_slice::add_free_vars(uint_set& result, expr* e) { - ptr_vector sorts; - get_free_vars(e, sorts); - for (unsigned i = 0; i < sorts.size(); ++i) { - if (sorts[i]) { + expr_free_vars fv; + fv(e); + for (unsigned i = 0; i < fv.size(); ++i) { + if (fv[i]) { result.insert(i); } } @@ -773,14 +773,11 @@ namespace datalog { init_vars(r); app_ref_vector tail(m); app_ref head(m); - ptr_vector sorts; update_predicate(r.get_head(), head); - get_free_vars(head.get(), sorts); for (unsigned i = 0; i < r.get_uninterpreted_tail_size(); ++i) { app_ref t(m); update_predicate(r.get_tail(i), t); tail.push_back(t); - get_free_vars(t, sorts); } expr_ref_vector conjs = get_tail_conjs(r); @@ -816,9 +813,10 @@ namespace datalog { } } - rule_set * mk_slice::operator()(rule_set const & src) { + rule_set * mk_slice::operator()(rule_set const & src) { + rule_manager& rm = m_ctx.get_rule_manager(); for (unsigned i = 0; i < src.get_num_rules(); ++i) { - if (src.get_rule(i)->has_quantifiers()) { + if (rm.has_quantifiers(*src.get_rule(i))) { return 0; } } diff --git a/src/muz/transforms/dl_mk_unfold.cpp b/src/muz/transforms/dl_mk_unfold.cpp index a9357f88a..cc460bca1 100644 --- a/src/muz/transforms/dl_mk_unfold.cpp +++ b/src/muz/transforms/dl_mk_unfold.cpp @@ -43,7 +43,7 @@ namespace datalog { m_unify.apply(r, tail_idx, r2, new_rule)) { expr_ref_vector s1 = m_unify.get_rule_subst(r, true); expr_ref_vector s2 = m_unify.get_rule_subst(r2, false); - resolve_rule(r, r2, tail_idx, s1, s2, *new_rule.get()); + resolve_rule(rm, r, r2, tail_idx, s1, s2, *new_rule.get()); expand_tail(*new_rule.get(), tail_idx+r2.get_uninterpreted_tail_size(), src, dst); } } diff --git a/src/muz/transforms/dl_transforms.cpp b/src/muz/transforms/dl_transforms.cpp index 9a4667f2c..db62c2ec6 100644 --- a/src/muz/transforms/dl_transforms.cpp +++ b/src/muz/transforms/dl_transforms.cpp @@ -44,6 +44,11 @@ namespace datalog { transf.register_plugin(alloc(datalog::mk_coi_filter, ctx)); transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, ctx)); + if (ctx.get_params().xform_quantify_arrays()) { + transf.register_plugin(alloc(datalog::mk_quantifier_abstraction, ctx, 38000)); + } + transf.register_plugin(alloc(datalog::mk_quantifier_instantiation, ctx, 37000)); + transf.register_plugin(alloc(datalog::mk_subsumption_checker, ctx, 35005)); transf.register_plugin(alloc(datalog::mk_rule_inliner, ctx, 35000)); transf.register_plugin(alloc(datalog::mk_coi_filter, ctx, 34990)); @@ -63,21 +68,15 @@ namespace datalog { transf.register_plugin(alloc(datalog::mk_rule_inliner, ctx, 34890)); transf.register_plugin(alloc(datalog::mk_subsumption_checker, ctx, 34880)); - - if (ctx.get_params().quantify_arrays()) { - transf.register_plugin(alloc(datalog::mk_quantifier_abstraction, ctx, 33000)); - transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 32500)); - } - transf.register_plugin(alloc(datalog::mk_quantifier_instantiation, ctx, 32000)); - transf.register_plugin(alloc(datalog::mk_bit_blast, ctx, 35000)); - if (!ctx.get_params().quantify_arrays()) - transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000)); transf.register_plugin(alloc(datalog::mk_karr_invariants, ctx, 36010)); - if (ctx.get_params().magic()) { + transf.register_plugin(alloc(datalog::mk_scale, ctx, 36030)); + if (!ctx.get_params().xform_quantify_arrays()) { + transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000)); + } + if (ctx.get_params().xform_magic()) { transf.register_plugin(alloc(datalog::mk_magic_symbolic, ctx, 36020)); } - transf.register_plugin(alloc(datalog::mk_scale, ctx, 36030)); ctx.transform_rules(transf); } } diff --git a/src/opt/bcd2.cpp b/src/opt/bcd2.cpp new file mode 100644 index 000000000..766e0d84a --- /dev/null +++ b/src/opt/bcd2.cpp @@ -0,0 +1,406 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + bcd2.cpp + +Abstract: + + bcd2 based MaxSAT. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-17 + +Notes: + +--*/ +#include "bcd2.h" +#include "pb_decl_plugin.h" +#include "uint_set.h" +#include "ast_pp.h" + + +namespace opt { + // ------------------------------------------------------ + // Morgado, Heras, Marques-Silva 2013 + // (initial version without model-based optimizations) + // + class bcd2 : public maxsmt_solver_base { + struct wcore { + expr* m_r; + unsigned_vector m_R; + rational m_lower; + rational m_mid; + rational m_upper; + }; + typedef obj_hashtable expr_set; + + pb_util pb; + expr_ref_vector m_soft_aux; + obj_map m_relax2index; // expr |-> index + obj_map m_soft2index; // expr |-> index + expr_ref_vector m_trail; + expr_ref_vector m_soft_constraints; + expr_set m_asm_set; + vector m_cores; + vector m_sigmas; + rational m_den; // least common multiplier of original denominators + bool m_enable_lazy; // enable adding soft constraints lazily (called 'mgbcd2') + unsigned_vector m_lazy_soft; // soft constraints to add lazily. + + void set2asms(expr_set const& set, expr_ref_vector & es) const { + es.reset(); + expr_set::iterator it = set.begin(), end = set.end(); + for (; it != end; ++it) { + es.push_back(m.mk_not(*it)); + } + } + void bcd2_init_soft(weights_t& weights, expr_ref_vector const& soft) { + + // normalize weights to be integral: + m_den = rational::one(); + for (unsigned i = 0; i < m_weights.size(); ++i) { + m_den = lcm(m_den, denominator(m_weights[i])); + } + if (!m_den.is_one()) { + for (unsigned i = 0; i < m_weights.size(); ++i) { + m_weights[i] = m_den*m_weights[i]; + SASSERT(m_weights[i].is_int()); + } + } + } + void init_bcd() { + m_trail.reset(); + m_asm_set.reset(); + m_cores.reset(); + m_sigmas.reset(); + m_lazy_soft.reset(); + for (unsigned i = 0; i < m_soft.size(); ++i) { + m_sigmas.push_back(m_weights[i]); + m_soft_aux.push_back(mk_fresh()); + if (m_enable_lazy) { + m_lazy_soft.push_back(i); + } + else { + enable_soft_constraint(i); + } + } + m_upper += rational(1); + } + + void process_sat() { + svector assignment; + update_assignment(assignment); + if (check_lazy_soft(assignment)) { + update_sigmas(); + } + } + + public: + bcd2(context& c, + weights_t& ws, expr_ref_vector const& soft): + maxsmt_solver_base(c, ws, soft), + pb(m), + m_soft_aux(m), + m_trail(m), + m_soft_constraints(m), + m_enable_lazy(true) { + bcd2_init_soft(ws, soft); + } + + virtual ~bcd2() {} + + virtual lbool operator()() { + expr_ref fml(m), r(m); + lbool is_sat = l_undef; + expr_ref_vector asms(m); + init(); + init_bcd(); + if (m_cancel) { + normalize_bounds(); + return l_undef; + } + process_sat(); + while (m_lower < m_upper) { + trace_bounds("bcd2"); + assert_soft(); + solver::scoped_push _scope2(s()); + TRACE("opt", display(tout);); + assert_cores(); + set2asms(m_asm_set, asms); + if (m_cancel) { + normalize_bounds(); + return l_undef; + } + is_sat = s().check_sat(asms.size(), asms.c_ptr()); + switch(is_sat) { + case l_undef: + normalize_bounds(); + return l_undef; + case l_true: + process_sat(); + break; + case l_false: { + ptr_vector unsat_core; + uint_set subC, soft; + s().get_unsat_core(unsat_core); + core2indices(unsat_core, subC, soft); + SASSERT(unsat_core.size() == subC.num_elems() + soft.num_elems()); + if (soft.num_elems() == 0 && subC.num_elems() == 1) { + unsigned s = *subC.begin(); + wcore& c_s = m_cores[s]; + c_s.m_lower = refine(c_s.m_R, c_s.m_mid); + c_s.m_mid = div(c_s.m_lower + c_s.m_upper, rational(2)); + } + else { + wcore c_s; + rational delta = min_of_delta(subC); + rational lower = sum_of_lower(subC); + union_Rs(subC, c_s.m_R); + r = mk_fresh(); + relax(subC, soft, c_s.m_R, delta); + c_s.m_lower = refine(c_s.m_R, lower + delta - rational(1)); + c_s.m_upper = rational::one(); + c_s.m_upper += sum_of_sigmas(c_s.m_R); + c_s.m_mid = div(c_s.m_lower + c_s.m_upper, rational(2)); + c_s.m_r = r; + m_asm_set.insert(r); + subtract(m_cores, subC); + m_relax2index.insert(r, m_cores.size()); + m_cores.push_back(c_s); + } + break; + } + } + m_lower = compute_lower(); + } + normalize_bounds(); + return l_true; + } + + + private: + + void enable_soft_constraint(unsigned i) { + expr_ref fml(m); + expr* r = m_soft_aux[i].get(); + m_soft2index.insert(r, i); + fml = m.mk_or(r, m_soft[i]); + m_soft_constraints.push_back(fml); + m_asm_set.insert(r); + SASSERT(m_weights[i].is_int()); + } + + void assert_soft() { + for (unsigned i = 0; i < m_soft_constraints.size(); ++i) { + s().assert_expr(m_soft_constraints[i].get()); + } + m_soft_constraints.reset(); + } + + bool check_lazy_soft(svector const& assignment) { + bool all_satisfied = true; + for (unsigned i = 0; i < m_lazy_soft.size(); ++i) { + unsigned j = m_lazy_soft[i]; + if (!assignment[j]) { + enable_soft_constraint(j); + m_lazy_soft[i] = m_lazy_soft.back(); + m_lazy_soft.pop_back(); + --i; + all_satisfied = false; + } + } + return all_satisfied; + } + + void normalize_bounds() { + m_lower /= m_den; + m_upper /= m_den; + } + + expr* mk_fresh() { + expr* r = mk_fresh_bool("r"); + m_trail.push_back(r); + return r; + } + + void update_assignment(svector& new_assignment) { + expr_ref val(m); + rational new_upper(0); + model_ref model; + new_assignment.reset(); + s().get_model(model); + for (unsigned i = 0; i < m_soft.size(); ++i) { + VERIFY(model->eval(m_soft[i], val)); + new_assignment.push_back(m.is_true(val)); + if (!new_assignment[i]) { + new_upper += m_weights[i]; + } + } + if (new_upper < m_upper) { + m_upper = new_upper; + m_model = model; + m_assignment.reset(); + m_assignment.append(new_assignment); + } + } + + void update_sigmas() { + for (unsigned i = 0; i < m_cores.size(); ++i) { + wcore& c_i = m_cores[i]; + unsigned_vector const& R = c_i.m_R; + c_i.m_upper.reset(); + for (unsigned j = 0; j < R.size(); ++j) { + unsigned r_j = R[j]; + if (!m_assignment[r_j]) { + c_i.m_upper += m_weights[r_j]; + m_sigmas[r_j] = m_weights[r_j]; + } + else { + m_sigmas[r_j].reset(); + } + } + c_i.m_mid = div(c_i.m_lower + c_i.m_upper, rational(2)); + } + } + + /** + * Minimum of two (positive) numbers. Zero is treated as +infinity. + */ + rational min_z(rational const& a, rational const& b) { + if (a.is_zero()) return b; + if (b.is_zero()) return a; + if (a < b) return a; + return b; + } + + rational min_of_delta(uint_set const& subC) { + rational delta(0); + for (uint_set::iterator it = subC.begin(); it != subC.end(); ++it) { + unsigned j = *it; + wcore const& core = m_cores[j]; + rational new_delta = rational(1) + core.m_upper - core.m_mid; + SASSERT(new_delta.is_pos()); + delta = min_z(delta, new_delta); + } + return delta; + } + + rational sum_of_lower(uint_set const& subC) { + rational lower(0); + for (uint_set::iterator it = subC.begin(); it != subC.end(); ++it) { + lower += m_cores[*it].m_lower; + } + return lower; + } + + rational sum_of_sigmas(unsigned_vector const& R) { + rational sum(0); + for (unsigned i = 0; i < R.size(); ++i) { + sum += m_sigmas[R[i]]; + } + return sum; + } + void union_Rs(uint_set const& subC, unsigned_vector& R) { + for (uint_set::iterator it = subC.begin(); it != subC.end(); ++it) { + R.append(m_cores[*it].m_R); + } + } + rational compute_lower() { + rational result(0); + for (unsigned i = 0; i < m_cores.size(); ++i) { + result += m_cores[i].m_lower; + } + return result; + } + void subtract(vector& cores, uint_set const& subC) { + unsigned j = 0; + for (unsigned i = 0; i < cores.size(); ++i) { + if (subC.contains(i)) { + m_asm_set.remove(cores[i].m_r); + } + else { + if (j != i) { + cores[j] = cores[i]; + } + ++j; + } + } + cores.resize(j); + for (unsigned i = 0; i < cores.size(); ++i) { + m_relax2index.insert(cores[i].m_r, i); + } + } + void core2indices(ptr_vector const& core, uint_set& subC, uint_set& soft) { + for (unsigned i = 0; i < core.size(); ++i) { + unsigned j; + expr* a; + VERIFY(m.is_not(core[i], a)); + if (m_relax2index.find(a, j)) { + subC.insert(j); + } + else { + VERIFY(m_soft2index.find(a, j)); + soft.insert(j); + } + } + } + rational refine(unsigned_vector const& idx, rational v) { + return v + rational(1); + } + void relax(uint_set& subC, uint_set& soft, unsigned_vector& R, rational& delta) { + for (uint_set::iterator it = soft.begin(); it != soft.end(); ++it) { + R.push_back(*it); + delta = min_z(delta, m_weights[*it]); + m_asm_set.remove(m_soft_aux[*it].get()); + } + } + void assert_cores() { + for (unsigned i = 0; i < m_cores.size(); ++i) { + assert_core(m_cores[i]); + } + } + void assert_core(wcore const& core) { + expr_ref fml(m); + vector ws; + ptr_vector rs; + rational w(0); + for (unsigned j = 0; j < core.m_R.size(); ++j) { + unsigned idx = core.m_R[j]; + ws.push_back(m_weights[idx]); + w += ws.back(); + rs.push_back(m_soft_aux[idx].get()); + } + w.neg(); + w += core.m_mid; + ws.push_back(w); + rs.push_back(core.m_r); + fml = pb.mk_le(ws.size(), ws.c_ptr(), rs.c_ptr(), core.m_mid); + s().assert_expr(fml); + } + void display(std::ostream& out) { + out << "[" << m_lower << ":" << m_upper << "]\n"; + s().display(out); + out << "\n"; + for (unsigned i = 0; i < m_cores.size(); ++i) { + wcore const& c = m_cores[i]; + out << mk_pp(c.m_r, m) << ": "; + for (unsigned j = 0; j < c.m_R.size(); ++j) { + out << c.m_R[j] << " (" << m_sigmas[c.m_R[j]] << ") "; + } + out << "[" << c.m_lower << ":" << c.m_mid << ":" << c.m_upper << "]\n"; + } + for (unsigned i = 0; i < m_soft.size(); ++i) { + out << mk_pp(m_soft[i], m) << " " << m_weights[i] << "\n"; + } + } + }; + + maxsmt_solver_base* mk_bcd2( + context& c, weights_t& ws, expr_ref_vector const& soft) { + return alloc(bcd2, c, ws, soft); + } + +} diff --git a/src/opt/bcd2.h b/src/opt/bcd2.h new file mode 100644 index 000000000..79d528e20 --- /dev/null +++ b/src/opt/bcd2.h @@ -0,0 +1,28 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + bcd2.h + +Abstract: + + Bcd2 based MaxSAT. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-17 + +Notes: + +--*/ + +#ifndef _BCD2_H_ +#define _BCD2_H_ + +#include "maxsmt.h" + +namespace opt { + maxsmt_solver_base* mk_bcd2(context& c, weights_t& ws, expr_ref_vector const& soft); +} +#endif diff --git a/src/opt/fu_malik.cpp b/src/opt/fu_malik.cpp new file mode 100644 index 000000000..6d2386b96 --- /dev/null +++ b/src/opt/fu_malik.cpp @@ -0,0 +1,237 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + fu_malik.cpp + +Abstract: + Fu & Malik built-in optimization method. + Adapted from sample code in C. + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-15 + +Notes: + +--*/ + +#include "fu_malik.h" +#include "qfbv_tactic.h" +#include "tactic2solver.h" +#include "goal.h" +#include "probe.h" +#include "tactic.h" +#include "ast_pp.h" +#include "model_smt2_pp.h" +#include "opt_context.h" + +/** + \brief Fu & Malik procedure for MaxSAT. This procedure is based on + unsat core extraction and the at-most-one constraint. + + Return the number of soft-constraints that can be + satisfied. Return -1 if the hard-constraints cannot be + satisfied. That is, the formula cannot be satisfied even if all + soft-constraints are ignored. + + For more information on the Fu & Malik procedure: + + Z. Fu and S. Malik, On solving the partial MAX-SAT problem, in International + Conference on Theory and Applications of Satisfiability Testing, 2006. +*/ +namespace opt { + + class fu_malik : public maxsmt_solver_base { + filter_model_converter& m_fm; + expr_ref_vector m_aux_soft; + expr_ref_vector m_aux; + model_ref m_model; + + public: + fu_malik(context& c, weights_t& ws, expr_ref_vector const& soft): + maxsmt_solver_base(c, ws, soft), + m_fm(c.fm()), + m_aux_soft(soft), + m_aux(m) + { + m_upper = rational(m_aux_soft.size() + 1); + m_lower.reset(); + m_assignment.resize(m_aux_soft.size(), false); + } + + /** + \brief One step of the Fu&Malik algorithm. + + Input: soft constraints + aux-vars (aka answer literals) + Output: done/not-done when not done return updated set of soft-constraints and aux-vars. + - if SAT --> terminates + - if UNSAT + * compute unsat core + * add blocking variable to soft-constraints in the core + - replace soft-constraint with the one with the blocking variable + - we should also add an aux-var + - replace aux-var with a new one + * add at-most-one constraint with blocking + */ + + typedef obj_hashtable expr_set; + + void set2vector(expr_set const& set, expr_ref_vector & es) const { + es.reset(); + expr_set::iterator it = set.begin(), end = set.end(); + for (; it != end; ++it) { + es.push_back(*it); + } + } + + void collect_statistics(statistics& st) const { + st.update("opt-fm-num-steps", m_aux_soft.size() + 2 - m_upper.get_unsigned()); + } + + void set_union(expr_set const& set1, expr_set const& set2, expr_set & set) const { + set.reset(); + expr_set::iterator it = set1.begin(), end = set1.end(); + for (; it != end; ++it) { + set.insert(*it); + } + it = set2.begin(); + end = set2.end(); + for (; it != end; ++it) { + set.insert(*it); + } + } + + lbool step() { + IF_VERBOSE(1, verbose_stream() << "(opt.max_sat step " << m_aux_soft.size() + 2 - m_upper.get_unsigned() << ")\n";); + expr_ref_vector assumptions(m), block_vars(m); + for (unsigned i = 0; i < m_aux_soft.size(); ++i) { + assumptions.push_back(m.mk_not(m_aux[i].get())); + } + lbool is_sat = s().check_sat(assumptions.size(), assumptions.c_ptr()); + if (is_sat != l_false) { + return is_sat; + } + + ptr_vector core; + s().get_unsat_core(core); + + SASSERT(!core.empty()); + + // Update soft-constraints and aux_vars + for (unsigned i = 0; i < m_aux_soft.size(); ++i) { + + bool found = false; + for (unsigned j = 0; !found && j < core.size(); ++j) { + found = assumptions[i].get() == core[j]; + } + if (!found) { + continue; + } + app_ref block_var(m), tmp(m); + block_var = m.mk_fresh_const("block_var", m.mk_bool_sort()); + m_aux[i] = m.mk_fresh_const("aux", m.mk_bool_sort()); + m_fm.insert(block_var->get_decl()); + m_fm.insert(to_app(m_aux[i].get())->get_decl()); + m_aux_soft[i] = m.mk_or(m_aux_soft[i].get(), block_var); + block_vars.push_back(block_var); + tmp = m.mk_or(m_aux_soft[i].get(), m_aux[i].get()); + s().assert_expr(tmp); + } + SASSERT (!block_vars.empty()); + assert_at_most_one(block_vars); + IF_VERBOSE(1, verbose_stream() << "(opt.max_sat # of non-blocked soft constraints: " << m_aux_soft.size() - block_vars.size() << ")\n";); + return l_false; + } + + void assert_at_most_one(expr_ref_vector const& block_vars) { + expr_ref has_one(m), has_zero(m), at_most_one(m); + mk_at_most_one(block_vars.size(), block_vars.c_ptr(), has_one, has_zero); + at_most_one = m.mk_or(has_one, has_zero); + s().assert_expr(at_most_one); + } + + void mk_at_most_one(unsigned n, expr* const * vars, expr_ref& has_one, expr_ref& has_zero) { + SASSERT(n != 0); + if (n == 1) { + has_one = vars[0]; + has_zero = m.mk_not(vars[0]); + } + else { + unsigned mid = n/2; + expr_ref has_one1(m), has_one2(m), has_zero1(m), has_zero2(m); + mk_at_most_one(mid, vars, has_one1, has_zero1); + mk_at_most_one(n-mid, vars+mid, has_one2, has_zero2); + has_one = m.mk_or(m.mk_and(has_one1, has_zero2), m.mk_and(has_one2, has_zero1)); + has_zero = m.mk_and(has_zero1, has_zero2); + } + } + + + // TBD: bug when cancel flag is set, fu_malik returns is_sat == l_true instead of l_undef + virtual lbool operator()() { + lbool is_sat = l_true; + if (m_aux_soft.empty()) { + return is_sat; + } + solver::scoped_push _sp(s()); + expr_ref tmp(m); + + TRACE("opt", + tout << "soft constraints:\n"; + for (unsigned i = 0; i < m_aux_soft.size(); ++i) { + tout << mk_pp(m_aux_soft[i].get(), m) << "\n"; + }); + + for (unsigned i = 0; i < m_aux_soft.size(); ++i) { + m_aux.push_back(m.mk_fresh_const("p", m.mk_bool_sort())); + m_fm.insert(to_app(m_aux.back())->get_decl()); + tmp = m.mk_or(m_aux_soft[i].get(), m_aux[i].get()); + s().assert_expr(tmp); + } + + do { + is_sat = step(); + --m_upper; + } + while (is_sat == l_false); + + if (is_sat == l_true) { + // Get a list satisfying m_aux_soft + s().get_model(m_model); + m_lower = m_upper; + m_assignment.reset(); + for (unsigned i = 0; i < m_soft.size(); ++i) { + expr_ref val(m); + VERIFY(m_model->eval(m_soft[i], val)); + TRACE("opt", tout << val << "\n";); + m_assignment.push_back(m.is_true(val)); + } + TRACE("opt", tout << "maxsat cost: " << m_upper << "\n"; + model_smt2_pp(tout, m, *m_model, 0);); + } + // We are done and soft_constraints has + // been updated with the max-sat assignment. + return is_sat; + } + + virtual void get_model(model_ref& mdl) { + mdl = m_model.get(); + } + + virtual rational get_lower() const { + return rational(m_aux_soft.size())-m_upper; + } + + virtual rational get_upper() const { + return rational(m_aux_soft.size())-m_lower; + } + }; + + maxsmt_solver_base* mk_fu_malik(context& c, weights_t & ws, expr_ref_vector const& soft) { + return alloc(fu_malik, c, ws, soft); + } + +}; + diff --git a/src/opt/fu_malik.h b/src/opt/fu_malik.h new file mode 100644 index 000000000..5eea9fc49 --- /dev/null +++ b/src/opt/fu_malik.h @@ -0,0 +1,37 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + fu_malik.h + +Abstract: + + Fu&Malik built-in optimization method. + Adapted from sample code in C. + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-15 + +Notes: + + Takes solver with hard constraints added. + Returns a maximal satisfying subset of soft_constraints + that are still consistent with the solver state. + +--*/ +#ifndef _OPT_FU_MALIK_H_ +#define _OPT_FU_MALIK_H_ + +#include "opt_solver.h" +#include "maxsmt.h" + +namespace opt { + + maxsmt_solver_base* mk_fu_malik(context& c, weights_t & ws, expr_ref_vector const& soft); + + +}; + +#endif diff --git a/src/opt/hitting_sets.cpp b/src/opt/hitting_sets.cpp new file mode 100644 index 000000000..37b800428 --- /dev/null +++ b/src/opt/hitting_sets.cpp @@ -0,0 +1,1092 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + hitting_sets.h + +Abstract: + + Hitting set approximations. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-06-06 + +Notes: + +--*/ +#include "vector.h" +#include "util.h" +#include "hitting_sets.h" +#include "simplex.h" +#include "sparse_matrix_def.h" +#include "simplex_def.h" + +typedef simplex::simplex Simplex; +typedef simplex::sparse_matrix sparse_matrix; + + +namespace opt { + + struct hitting_sets::imp { + class justification { + public: + enum kind_t { AXIOM, DECISION, CLAUSE }; + private: + kind_t m_kind; + unsigned m_value; + bool m_pos; + public: + explicit justification(kind_t k):m_kind(k), m_value(0), m_pos(false) {} + explicit justification(unsigned v, bool pos):m_kind(CLAUSE), m_value(v), m_pos(pos) {} + justification(justification const& other): + m_kind(other.m_kind), m_value(other.m_value), m_pos(other.m_pos) {} + justification& operator=(justification const& other) { + m_kind = other.m_kind; + m_value = other.m_value; + m_pos = other.m_pos; + return *this; + } + unsigned clause() const { return m_value; } + bool is_axiom() const { return m_kind == AXIOM; } + bool is_decision() const { return m_kind == DECISION; } + bool is_clause() const { return m_kind == CLAUSE; } + kind_t kind() const { return m_kind; } + bool pos() const { return m_pos; } + }; + + class set { + unsigned m_num_elems; + unsigned m_elems[0]; + set(): m_num_elems(0) {} + public: + + static set* mk(small_object_allocator& alloc, unsigned sz, unsigned const* elems) { + unsigned size = (sz+1)*sizeof(unsigned); + void * mem = alloc.allocate(size); + set* result = new (mem) set(); + result->m_num_elems = sz; + memcpy(result->m_elems, elems, sizeof(unsigned)*sz); + return result; + } + + inline unsigned operator[](unsigned idx) const { + SASSERT(idx < m_num_elems); + return m_elems[idx]; + } + + inline unsigned& operator[](unsigned idx) { + SASSERT(idx < m_num_elems); + return m_elems[idx]; + } + + unsigned size() const { return m_num_elems; } + + unsigned alloc_size() const { return (m_num_elems + 1)*sizeof(unsigned); } + + bool empty() const { return 0 == size(); } + }; + + volatile bool m_cancel; + rational m_lower; + rational m_upper; + vector m_weights; + vector m_weights_inv; + rational m_max_weight; + rational m_denominator; + small_object_allocator m_alloc; + ptr_vector m_T; + ptr_vector m_F; + svector m_value; + svector m_model; + vector m_tuse_list; + vector m_fuse_list; + + // Custom CDCL solver. + svector m_justification; + vector m_twatch; + vector m_fwatch; + unsigned_vector m_level; + unsigned_vector m_trail; // trail of assigned literals + unsigned m_qhead; // queue head + justification m_conflict_j; // conflict justification + unsigned m_conflict_l; // conflict literal + bool m_inconsistent; + unsigned m_scope_lvl; + rational m_weight; // current weight of assignment. + unsigned_vector m_indices; + unsigned_vector m_scores; + vector m_scored_weights; + svector m_score_updated; + bool m_enable_simplex; + struct compare_scores { + imp* m_imp; + compare_scores(imp* i):m_imp(i) {} + bool operator()(int v1, int v2) const { + return m_imp->m_scored_weights[v1] > m_imp->m_scored_weights[v2]; + } + }; + compare_scores m_compare_scores; + heap m_heap; + svector m_mark; + struct scope { + unsigned m_trail_lim; + }; + vector m_scopes; + unsigned_vector m_lemma; + unsigned m_conflict_lvl; + + // simplex + unsynch_mpz_manager m; + Simplex m_simplex; + unsigned m_weights_var; + + static unsigned const null_idx = UINT_MAX; + + imp(): + m_cancel(false), + m_max_weight(0), + m_denominator(1), + m_alloc("hitting-sets"), + m_weights_var(0), + m_qhead(0), + m_scope_lvl(0), + m_conflict_j(justification(justification::AXIOM)), + m_inconsistent(false), + m_compare_scores(this), + m_heap(0, m_compare_scores) { + m_enable_simplex = true; + + } + ~imp() { + for (unsigned i = 0; i < m_T.size(); ++i) { + m_alloc.deallocate(m_T[i]->alloc_size(), m_T[i]); + } + for (unsigned i = 0; i < m_F.size(); ++i) { + m_alloc.deallocate(m_F[i]->alloc_size(), m_F[i]); + } + } + + void add_weight(rational const& w) { + SASSERT(w.is_pos()); + unsigned var = m_weights.size(); + m_simplex.ensure_var(var); + m_simplex.set_lower(var, mpq_inf(mpq(0),mpq(0))); + m_simplex.set_upper(var, mpq_inf(mpq(1),mpq(0))); + m_weights.push_back(w); + m_weights_inv.push_back(rational::one()); + m_value.push_back(l_undef); + m_justification.push_back(justification(justification::DECISION)); + m_tuse_list.push_back(unsigned_vector()); + m_fuse_list.push_back(unsigned_vector()); + m_twatch.push_back(unsigned_vector()); + m_fwatch.push_back(unsigned_vector()); + m_level.push_back(0); + m_indices.push_back(var); + m_model.push_back(l_undef); + m_mark.push_back(false); + m_scores.push_back(0); + m_scored_weights.push_back(rational(0)); + m_score_updated.push_back(true); + m_max_weight += w; + } + + justification add_exists_false(unsigned sz, unsigned const* S) { + return add_exists(sz, S, true); + } + + justification add_exists_true(unsigned sz, unsigned const* S) { + return add_exists(sz, S, false); + } + + justification add_exists(unsigned sz, unsigned const* S, bool sign) { + vector& use_list = sign?m_fuse_list:m_tuse_list; + lbool val = sign?l_false:l_true; + justification j(justification::AXIOM); + ptr_vector& Sets = sign?m_F:m_T; + vector& watch = sign?m_fwatch:m_twatch; + init_weights(); + if (sz == 0) { + set_conflict(0, justification(justification::AXIOM)); + } + else if (sz == 1) { + IF_VERBOSE(2, verbose_stream() << "unit literal : " << S[0] << " " << val << "\n";); + assign(S[0], val, justification(justification::AXIOM)); + } + else { + unsigned clause_id = Sets.size(); + for (unsigned i = 0; i < sz; ++i) { + use_list[S[i]].push_back(clause_id); + } + j = justification(clause_id, !sign); + watch[S[0]].push_back(clause_id); + watch[S[1]].push_back(clause_id); + Sets.push_back(set::mk(m_alloc, sz, S)); + if (!sign) { + pop(scope_lvl()); + inc_score(clause_id); + } + TRACE("opt", display(tout, j);); + IF_VERBOSE(2, if (!sign) display(verbose_stream(), j);); + if (!sign && m_enable_simplex) { + add_simplex_row(!sign, sz, S); + } + } + return j; + } + + lbool compute_lower() { + m_lower.reset(); + rational w1 = L1(); + rational w2 = L2(); + rational w3 = L3(); + if (w1 > m_lower) m_lower = w1; + if (w2 > m_lower) m_lower = w2; + if (w3 > m_lower) m_lower = w3; + return l_true; + } + + lbool compute_upper() { + m_upper = m_max_weight; + unsigned fsz = m_F.size(); + lbool r = search(); + pop(scope_lvl()); + + + IF_VERBOSE(1, verbose_stream() << "(hsmax.negated-size: " << fsz << ")\n";); +#if 0 + // garbage collect agressively on exit. + // all learned clases for negative branches are + // pruned. + for (unsigned i = fsz; i < m_F.size(); ++i) { + m_alloc.deallocate(m_F[i]->alloc_size(), m_F[i]); + } + m_F.resize(fsz); + for (unsigned i = 0; i < m_fuse_list.size(); ++i) { + unsigned_vector & uses = m_fuse_list[i]; + while (!uses.empty() && uses.back() >= fsz) uses.pop_back(); + unsigned_vector & watch = m_fwatch[i]; + unsigned j = 0, k = 0; + for (; j < watch.size(); ++j) { + if (watch[j] < fsz) { + watch[k] = watch[j]; + ++k; + } + } + watch.resize(k); + } +#endif + return r; + } + + rational get_lower() { + return m_lower/m_denominator; + } + + rational get_upper() { + return m_upper/m_denominator; + } + + void set_upper(rational const& r) { + m_max_weight = r*m_denominator; + } + + bool get_value(unsigned idx) { + return + idx < m_model.size() && + m_model[idx] == l_true; + } + + void set_cancel(bool f) { + m_cancel = f; + m_simplex.set_cancel(f); + } + + void collect_statistics(::statistics& st) const { + m_simplex.collect_statistics(st); + } + + void reset() { + m_lower.reset(); + m_upper = m_max_weight; + } + + void init_weights() { + if (m_weights_var != 0) { + return; + } + m_weights_var = m_weights.size(); + unsigned_vector vars; + scoped_mpz_vector coeffs(m); + + // normalize weights to integral. + rational d(1); + for (unsigned i = 0; i < m_weights.size(); ++i) { + d = lcm(d, denominator(m_weights[i])); + } + m_denominator = d; + if (!d.is_one()) { + for (unsigned i = 0; i < m_weights.size(); ++i) { + m_weights[i] *= d; + } + } + rational lc(1); + for (unsigned i = 0; i < m_weights.size(); ++i) { + lc = lcm(lc, m_weights[i]); + } + for (unsigned i = 0; i < m_weights.size(); ++i) { + m_weights_inv[i] = lc/m_weights[i]; + } + + m_heap.set_bounds(m_weights.size()); + for (unsigned i = 0; i < m_weights.size(); ++i) { + m_heap.insert(i); + } + update_heap(); + + // set up Simplex objective function. + for (unsigned i = 0; i < m_weights.size(); ++i) { + vars.push_back(i); + coeffs.push_back(m_weights[i].to_mpq().numerator()); + } + m_simplex.ensure_var(m_weights_var); + vars.push_back(m_weights_var); + coeffs.push_back(mpz(-1)); + m_simplex.add_row(m_weights_var, coeffs.size(), vars.c_ptr(), coeffs.c_ptr()); + + } + + void display(std::ostream& out) const { + out << "inconsistent: " << m_inconsistent << "\n"; + out << "weight: " << m_weight << "\n"; + for (unsigned i = 0; i < m_weights.size(); ++i) { + out << i << ": " << value(i) << " w: " << m_weights[i] << " s: " << m_scores[i] << "\n"; + } + for (unsigned i = 0; i < m_T.size(); ++i) { + display(out << "+" << i << ": ", *m_T[i]); + } + for (unsigned i = 0; i < m_F.size(); ++i) { + display(out << "-" << i << ": ", *m_F[i]); + } + out << "watch lists:\n"; + for (unsigned i = 0; i < m_fwatch.size(); ++i) { + out << i << ": "; + for (unsigned j = 0; j < m_twatch[i].size(); ++j) { + out << "+" << m_twatch[i][j] << " "; + } + for (unsigned j = 0; j < m_fwatch[i].size(); ++j) { + out << "-" << m_fwatch[i][j] << " "; + } + out << "\n"; + } + out << "trail\n"; + for (unsigned i = 0; i < m_trail.size(); ++i) { + unsigned idx = m_trail[i]; + out << (m_justification[idx].is_decision()?"d":"") << idx << " "; + } + out << "\n"; + } + + void display(std::ostream& out, set const& S) const { + for (unsigned i = 0; i < S.size(); ++i) { + out << S[i] << " "; + } + out << "\n"; + } + + void display(std::ostream& out, justification const& j) const { + switch(j.kind()) { + case justification::AXIOM: + out << "axiom\n"; + break; + case justification::DECISION: + out << "decision\n"; + break; + case justification::CLAUSE: { + out << "clause: "; + set const& S = j.pos()?(*m_T[j.clause()]):(*m_F[j.clause()]); + for (unsigned i = 0; i < S.size(); ++i) { + out << S[i] << " "; + } + out << "\n"; + } + } + } + + void display_lemma(std::ostream& out) { + out << "lemma: "; + for (unsigned i = 0; i < m_lemma.size(); ++i) { + out << m_lemma[i] << " "; + } + out << "\n"; + } + + struct scoped_push { + imp& s; + scoped_push(imp& s):s(s) { s.push(); } + ~scoped_push() { s.pop(1); } + }; + + struct value_lt { + vector const& weights; + value_lt(vector const& weights): + weights(weights) {} + bool operator()(int v1, int v2) const { + return weights[v1] > weights[v2]; + } + }; + + void inc_score(unsigned clause_id) { + set const& S = *m_T[clause_id]; + if (!has_selected(S)) { + for (unsigned j = 0; j < S.size(); ++j) { + ++m_scores[S[j]]; + m_score_updated[S[j]] = true; + } + } + } + + void dec_score(unsigned clause_id) { + set const& S = *m_T[clause_id]; + if (!has_selected(S)) { + for (unsigned j = 0; j < S.size(); ++j) { + SASSERT(m_scores[S[j]] > 0); + --m_scores[S[j]]; + m_score_updated[S[j]] = true; + } + } + } + + void update_score(unsigned idx, bool inc) { + unsigned_vector const& uses = m_tuse_list[idx]; + for (unsigned i = 0; i < uses.size(); ++i) { + if (inc) { + inc_score(uses[i]); + } + else { + dec_score(uses[i]); + } + } + } + + rational L1() { + rational w(m_weight); + scoped_push _sc(*this); + for (unsigned i = 0; !canceled() && i < m_T.size(); ++i) { + set const& S = *m_T[i]; + SASSERT(!S.empty()); + if (!has_selected(S)) { + w += m_weights[select_min(S)]; + for (unsigned j = 0; j < S.size(); ++j) { + assign(S[j], l_true, justification(justification::DECISION)); + } + } + } + return w; + } + + void update_heap() { + for (unsigned i = 0; i < m_scored_weights.size(); ++i) { + if (m_score_updated[i]) { + rational const& old_w = m_scored_weights[i]; + rational new_w = rational(m_scores[i])*m_weights_inv[i]; + if (new_w > old_w) { + m_scored_weights[i] = new_w; + //m_heap.decreased(i); + } + else if (new_w < old_w) { + m_scored_weights[i] = new_w; + //m_heap.increased(i); + } + m_score_updated[i] = false; + } + } + } + + rational L2() { + rational w(m_weight); + scoped_push _sc(*this); + int n = 0; + for (unsigned i = 0; i < m_T.size(); ++i) { + if (!has_selected(*m_T[i])) ++n; + } + + update_heap(); + value_lt lt(m_scored_weights); + std::sort(m_indices.begin(), m_indices.end(), lt); + for(unsigned i = 0; i < m_indices.size() && n > 0; ++i) { + // deg(c) = score(c) + // wt(c) = m_weights[c] + + unsigned idx = m_indices[i]; + if (m_scores[idx] == 0) { + break; + } + if (m_scores[idx] < static_cast(n) || m_weights[idx].is_one()) { + w += m_weights[idx]; + } + else { + w += div((rational(n)*m_weights[idx]), rational(m_scores[idx])); + } + n -= m_scores[idx]; + } + return w; + } + + rational L3() { + TRACE("simplex", m_simplex.display(tout);); + VERIFY(l_true == m_simplex.make_feasible()); + TRACE("simplex", m_simplex.display(tout);); + VERIFY(l_true == m_simplex.minimize(m_weights_var)); + mpq_inf const& val = m_simplex.get_value(m_weights_var); + unsynch_mpq_inf_manager mg; + unsynch_mpq_manager& mq = mg.get_mpq_manager(); + scoped_mpq c(mq); + mg.ceil(val, c); + rational w(c); + CTRACE("simplex", + w >= m_weight, tout << w << " " << m_weight << " !!!!\n"; + display(tout);); + SASSERT(w >= m_weight); + return w; + } + + void add_simplex_row(bool is_some_true, unsigned sz, unsigned const* S) { + unsigned_vector vars; + scoped_mpz_vector coeffs(m); + for (unsigned i = 0; i < sz; ++i) { + vars.push_back(S[i]); + coeffs.push_back(mpz(1)); + } + unsigned base_var = m_F.size() + m_T.size() + m_weights.size(); + m_simplex.ensure_var(base_var); + vars.push_back(base_var); + coeffs.push_back(mpz(-1)); + // S - base_var = 0 + if (is_some_true) { + // base_var >= 1 + m_simplex.set_lower(base_var, mpq_inf(mpq(1),mpq(0))); + } + else { + // base_var <= sz-1 + m_simplex.set_upper(base_var, mpq_inf(mpq(sz-1),mpq(0))); + } + m_simplex.add_row(base_var, coeffs.size(), vars.c_ptr(), coeffs.c_ptr()); + } + + unsigned select_min(set const& S) { + unsigned result = S[0]; + for (unsigned i = 1; i < S.size(); ++i) { + if (m_weights[result] > m_weights[S[i]]) { + result = S[i]; + } + } + return result; + } + + bool have_selected(lbool val, ptr_vector const& Sets, unsigned& i) { + for (i = 0; i < Sets.size(); ++i) { + if (!has_selected(val, *Sets[i])) return false; + } + return true; + } + + void set_undef_to_false() { + for (unsigned i = 0; i < m_model.size(); ++i) { + if (m_model[i] == l_undef) { + m_model[i] = l_false; + } + } + } + + bool values_satisfy_Fs(unsigned& i) { + unsigned j = 0; + for (i = 0; i < m_F.size(); ++i) { + set const& F = *m_F[i]; + for (j = 0; j < F.size(); ++j) { + if (m_model[F[j]] == l_false) { + break; + } + } + if (F.size() == j) { + break; + } + } + return i == m_F.size(); + } + + bool has_selected(set const& S) { + return has_selected(l_true, S); + } + + bool has_unselected(set const& S) { + return has_selected(l_false, S); + } + + bool has_unset(set const& S) { + return has_selected(l_undef, S); + } + + bool has_selected(lbool val, set const& S) { + for (unsigned i = 0; i < S.size(); ++i) { + if (val == value(S[i])) { + return true; + } + } + return false; + } + + // (greedy) CDCL learner for hitting sets. + + inline unsigned scope_lvl() const { return m_scope_lvl; } + inline bool inconsistent() const { return m_inconsistent; } + inline bool canceled() const { return m_cancel; } + inline unsigned lvl(unsigned idx) const { return m_level[idx]; } + inline lbool value(unsigned idx) const { return m_value[idx]; } + + inline bool is_marked(unsigned v) const { return m_mark[v] != 0; } + inline void mark(unsigned v) { SASSERT(!is_marked(v)); m_mark[v] = true; } + inline void reset_mark(unsigned v) { SASSERT(is_marked(v)); m_mark[v] = false; } + + void push() { + SASSERT(!inconsistent()); + ++m_scope_lvl; + m_scopes.push_back(scope()); + scope& s = m_scopes.back(); + s.m_trail_lim = m_trail.size(); + } + + void pop(unsigned n) { + if (n > 0) { + m_inconsistent = false; + m_scope_lvl = scope_lvl() - n; + unassign(m_scopes[scope_lvl()].m_trail_lim); + m_scopes.shrink(scope_lvl()); + } + } + + void assign(unsigned idx, lbool val, justification const& justification) { + if (val == l_true) { + m_weight += m_weights[idx]; + update_score(idx, false); + if (m_enable_simplex) { + m_simplex.set_lower(idx, mpq_inf(mpq(1),mpq(0))); + } + } + SASSERT(val != l_true || m_scores[idx] == 0); + m_value[idx] = val; + m_justification[idx] = justification; + m_trail.push_back(idx); + m_level[idx] = scope_lvl(); + TRACE("opt", tout << idx << " := " << val << " scope: " << scope_lvl() << " w: " << m_weight << "\n";); + } + + + svector m_replay_idx; + svector m_replay_val; + void unassign(unsigned sz) { + for (unsigned j = sz; j < m_trail.size(); ++j) { + unsigned idx = m_trail[j]; + lbool val = value(idx); + m_value[idx] = l_undef; + if (val == l_true) { + m_weight -= m_weights[idx]; + update_score(idx, true); + if (m_enable_simplex) { + m_simplex.set_lower(idx, mpq_inf(mpq(0),mpq(0))); + } + } + if (m_justification[idx].is_axiom()) { + m_replay_idx.push_back(idx); + m_replay_val.push_back(val); + } + } + TRACE("opt", tout << m_weight << "\n";); + m_trail.shrink(sz); + m_qhead = sz; + for (unsigned i = m_replay_idx.size(); i > 0; ) { + --i; + unsigned idx = m_replay_idx[i]; + lbool val = m_replay_val[i]; + assign(idx, val, justification(justification::AXIOM)); + } + m_replay_idx.reset(); + m_replay_val.reset(); + } + + + lbool search() { + TRACE("opt", display(tout);); + pop(scope_lvl()); + while (true) { + while (true) { + propagate(); + if (canceled()) return l_undef; + if (!inconsistent()) break; + if (!resolve_conflict()) return l_false; + SASSERT(!inconsistent()); + } + if (!decide()) { + SASSERT(validate_model()); + m_model.reset(); + m_model.append(m_value); + m_upper = m_weight; + // SASSERT(m_weight < m_max_weight); + return l_true; + } + } + } + + bool validate_model() { + for (unsigned i = 0; i < m_T.size(); ++i) { + set const& S = *m_T[i]; + bool found = false; + for (unsigned j = 0; !found && j < S.size(); ++j) { + found = value(S[j]) == l_true; + } + CTRACE("opt", !found, + display(tout << "not found: " << i << "\n", S); + display(tout);); + SASSERT(found); + } + for (unsigned i = 0; i < m_F.size(); ++i) { + set const& S = *m_F[i]; + bool found = false; + for (unsigned j = 0; !found && j < S.size(); ++j) { + found = value(S[j]) != l_true; + } + CTRACE("opt", !found, + display(tout << "not found: " << i << "\n", S); + display(tout);); + SASSERT(found); + } + + return true; + } + + bool invariant() { + for (unsigned i = 0; i < m_fwatch.size(); ++i) { + for (unsigned j = 0; j < m_fwatch[i].size(); ++j) { + set const& S = *m_F[m_fwatch[i][j]]; + SASSERT(S[0] == i || S[1] == i); + } + } + for (unsigned i = 0; i < m_twatch.size(); ++i) { + for (unsigned j = 0; j < m_twatch[i].size(); ++j) { + set const& S = *m_T[m_twatch[i][j]]; + SASSERT(S[0] == i || S[1] == i); + } + } + return true; + } + + bool resolve_conflict() { + while (true) { + if (!resolve_conflict_core()) return false; + if (!inconsistent()) return true; + } + } + + unsigned get_max_lvl(unsigned conflict_l, justification const& conflict_j) { + if (scope_lvl() == 0) return 0; + unsigned r = lvl(conflict_l); + if (conflict_j.is_clause()) { + unsigned clause = conflict_j.clause(); + ptr_vector const& S = conflict_j.pos()?m_T:m_F; + r = std::max(r, lvl((*S[clause])[0])); + r = std::max(r, lvl((*S[clause])[1])); + } + return r; + } + + bool resolve_conflict_core() { + SASSERT(inconsistent()); + TRACE("opt", display(tout);); + unsigned conflict_l = m_conflict_l; + justification conflict_j(m_conflict_j); + if (conflict_j.is_axiom()) { + return false; + } + m_conflict_lvl = get_max_lvl(conflict_l, conflict_j); + if (m_conflict_lvl == 0) { + return false; + } + unsigned idx = skip_above_conflict_level(); + unsigned num_marks = 0; + m_lemma.reset(); + m_lemma.push_back(0); + process_antecedent(conflict_l, num_marks); + do { + TRACE("opt", tout << "conflict literal: " << conflict_l << "\n"; + display(tout, conflict_j);); + if (conflict_j.is_clause()) { + unsigned cl = conflict_j.clause(); + unsigned i = 0; + SASSERT(value(conflict_l) != l_undef); + set const& T = conflict_j.pos()?(*m_T[cl]):(*m_F[cl]); + if (T[0] == conflict_l) { + i = 1; + } + else { + SASSERT(T[1] == conflict_l); + process_antecedent(T[0], num_marks); + i = 2; + } + unsigned sz = T.size(); + for (; i < sz; ++i) { + process_antecedent(T[i], num_marks); + } + } + else if (conflict_j.is_decision()) { + --num_marks; + SASSERT(num_marks == 0); + break; + } + else if (conflict_j.is_axiom()) { + IF_VERBOSE(0, verbose_stream() << "axiom " << conflict_l << " " << value(conflict_l) << " " << num_marks << "\n";); + --num_marks; + SASSERT(num_marks == 0); + break; + } + while (true) { + unsigned l = m_trail[idx]; + if (is_marked(l)) break; + SASSERT(idx > 0); + --idx; + } + conflict_l = m_trail[idx]; + conflict_j = m_justification[conflict_l]; + --idx; + --num_marks; + if (num_marks == 0 && value(conflict_l) == l_false) { + ++num_marks; + } + reset_mark(conflict_l); + } + while (num_marks > 0); + m_lemma[0] = conflict_l; + TRACE("opt", display_lemma(tout);); + SASSERT(value(conflict_l) == l_true); + unsigned new_scope_lvl = 0; + for (unsigned i = 1; i < m_lemma.size(); ++i) { + SASSERT(l_true == value(m_lemma[i])); + new_scope_lvl = std::max(new_scope_lvl, lvl(m_lemma[i])); + reset_mark(m_lemma[i]); + } + pop(scope_lvl() - new_scope_lvl); + SASSERT(l_undef == value(conflict_l)); + justification j = add_exists_false(m_lemma.size(), m_lemma.c_ptr()); + if (!j.is_axiom()) assign(conflict_l, l_false, j); + return true; + } + + + void process_antecedent(unsigned antecedent, unsigned& num_marks) { + unsigned alvl = lvl(antecedent); + SASSERT(alvl <= m_conflict_lvl); + if (!is_marked(antecedent) && alvl > 0 && !m_justification[antecedent].is_axiom()) { + mark(antecedent); + if (alvl == m_conflict_lvl || value(antecedent) == l_false) { + ++num_marks; + } + else { + m_lemma.push_back(antecedent); + } + } + } + + unsigned skip_above_conflict_level() { + unsigned idx = m_trail.size(); + if (idx == 0) { + return idx; + } + idx--; + // skip literals from levels above the conflict level + while (lvl(m_trail[idx]) > m_conflict_lvl) { + SASSERT(idx > 0); + idx--; + } + return idx; + } + + void set_conflict(unsigned idx, justification const& justification) { + if (!inconsistent()) { + TRACE("opt", tout << "conflict: " << idx << "\n";); + m_inconsistent = true; + m_conflict_j = justification; + m_conflict_l = idx; + } + } + + unsigned next_var() { + update_heap(); + + value_lt lt(m_scored_weights); + std::sort(m_indices.begin(), m_indices.end(), lt); + unsigned idx = m_indices[0]; + if (m_scores[idx] == 0) return UINT_MAX; + return idx; +#if 0 + int min_val = m_heap.min_value(); + if (min_val == -1) { + return UINT_MAX; + } + SASSERT(0 <= min_val && static_cast(min_val) < m_weights.size()); + if (m_scores[min_val] == 0) { + return UINT_MAX; + } + return static_cast(min_val); +#endif + } + + bool decide() { + unsigned idx = next_var(); + if (idx == UINT_MAX) { + return false; + } + else { + push(); + TRACE("opt", tout << "decide " << idx << "\n";); + assign(idx, l_true, justification(justification::DECISION)); + return true; + } + } + + void propagate() { + TRACE("opt", display(tout);); + SASSERT(invariant()); + while (m_qhead < m_trail.size() && !inconsistent() && !canceled()) { + unsigned idx = m_trail[m_qhead]; + ++m_qhead; + switch (value(idx)) { + case l_undef: + UNREACHABLE(); + break; + case l_true: + propagate(idx, l_false, m_fwatch, m_F); + break; + case l_false: + propagate(idx, l_true, m_twatch, m_T); + break; + } + } + prune_branch(); + } + + void propagate(unsigned idx, lbool good_val, vector& watch, ptr_vector& Fs) + { + TRACE("opt", tout << idx << " " << value(idx) << "\n";); + unsigned_vector& w = watch[idx]; + unsigned sz = w.size(); + lbool bad_val = ~good_val; + SASSERT(value(idx) == bad_val); + unsigned l = 0; + for (unsigned i = 0; i < sz && !canceled(); ++i, ++l) { + unsigned clause_id = w[i]; + set& F = *Fs[clause_id]; + SASSERT(F.size() >= 2); + bool k1 = (F[0] != idx); + bool k2 = !k1; + SASSERT(F[k1] == idx); + SASSERT(value(F[k1]) == bad_val); + if (value(F[k2]) == good_val) { + w[l] = w[i]; + continue; + } + bool found = false; + unsigned sz2 = F.size(); + for (unsigned j = 2; !found && j < sz2; ++j) { + unsigned idx2 = F[j]; + if (value(idx2) != bad_val) { + found = true; + std::swap(F[k1], F[j]); + --l; + watch[idx2].push_back(clause_id); + } + } + if (!found) { + if (value(F[k2]) == bad_val) { + set_conflict(F[k2], justification(clause_id, good_val == l_true)); + if (i == l) { + l = sz; + } + else { + for (; i < sz; ++i, ++l) { + w[l] = w[i]; + } + } + break; + } + else { + SASSERT(value(F[k2]) == l_undef); + assign(F[k2], good_val, justification(clause_id, good_val == l_true)); + w[l] = w[i]; + } + } + } + watch[idx].shrink(l); + SASSERT(invariant()); + TRACE("opt", tout << idx << " " << value(idx) << "\n";); + SASSERT(value(idx) == bad_val); + } + + bool infeasible_lookahead() { + if (m_enable_simplex && L3() >= m_max_weight) { + return true; + } + return + (L1() >= m_max_weight) || + (L2() >= m_max_weight); + } + + void prune_branch() { + if (inconsistent() || !infeasible_lookahead()) { + return; + } + + IF_VERBOSE(4, verbose_stream() << "(hs.prune-branch " << m_weight << ")\n";); + m_lemma.reset(); + unsigned i = 0; + rational w(0); + for (; i < m_trail.size() && w < m_max_weight; ++i) { + unsigned idx = m_trail[i]; + if (m_justification[idx].is_decision()) { + SASSERT(value(idx) == l_true); + m_lemma.push_back(idx); + w += m_weights[idx]; + } + } + // undo the lower bounds. + TRACE("opt", + tout << "prune branch: " << m_weight << " "; + display_lemma(tout); + display(tout); + ); + justification j = add_exists_false(m_lemma.size(), m_lemma.c_ptr()); + unsigned idx = m_lemma.empty()?0:m_lemma[0]; + set_conflict(idx, j); + } + + // TBD: derive strong inequalities and add them to Simplex. + // x_i1 + .. + x_ik >= k-1 for each subset k from set n: x_1 + .. + x_n >= k + }; + + + hitting_sets::hitting_sets() { m_imp = alloc(imp); } + hitting_sets::~hitting_sets() { dealloc(m_imp); } + void hitting_sets::add_weight(rational const& w) { m_imp->add_weight(w); } + void hitting_sets::add_exists_true(unsigned sz, unsigned const* elems) { m_imp->add_exists_true(sz, elems); } + void hitting_sets::add_exists_false(unsigned sz, unsigned const* elems) { m_imp->add_exists_false(sz, elems); } + lbool hitting_sets::compute_lower() { return m_imp->compute_lower(); } + lbool hitting_sets::compute_upper() { return m_imp->compute_upper(); } + rational hitting_sets::get_lower() { return m_imp->get_lower(); } + rational hitting_sets::get_upper() { return m_imp->get_upper(); } + void hitting_sets::set_upper(rational const& r) { return m_imp->set_upper(r); } + bool hitting_sets::get_value(unsigned idx) { return m_imp->get_value(idx); } + void hitting_sets::set_cancel(bool f) { m_imp->set_cancel(f); } + void hitting_sets::collect_statistics(::statistics& st) const { m_imp->collect_statistics(st); } + void hitting_sets::reset() { m_imp->reset(); } + + +}; diff --git a/src/opt/hitting_sets.h b/src/opt/hitting_sets.h new file mode 100644 index 000000000..58de8c518 --- /dev/null +++ b/src/opt/hitting_sets.h @@ -0,0 +1,51 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + hitting_sets.h + +Abstract: + + Hitting set approximations. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-06-06 + +Notes: + +--*/ +#ifndef _HITTING_SETS_H_ +#define _HITTING_SETS_H_ + +#include "rational.h" +#include "statistics.h" +#include "lbool.h" + +namespace opt { + + class hitting_sets { + struct imp; + imp* m_imp; + public: + hitting_sets(); + ~hitting_sets(); + void add_weight(rational const& w); + void add_exists_true(unsigned sz, unsigned const* elems); + void add_exists_false(unsigned sz, unsigned const* elems); + lbool compute_lower(); + lbool compute_upper(); + void set_upper(rational const& r); + rational get_lower(); + rational get_upper(); + bool get_value(unsigned idx); + void set_cancel(bool f); + void collect_statistics(::statistics& st) const; + void reset(); + }; + + +}; + +#endif diff --git a/src/opt/inc_sat_solver.cpp b/src/opt/inc_sat_solver.cpp new file mode 100644 index 000000000..65264e0d9 --- /dev/null +++ b/src/opt/inc_sat_solver.cpp @@ -0,0 +1,425 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + inc_sat_solver.cpp + +Abstract: + + incremental solver based on SAT core. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-7-30 + +Notes: + +--*/ + +#include "solver.h" +#include "tactical.h" +#include "sat_solver.h" +#include "tactic2solver.h" +#include "nnf_tactic.h" +#include "aig_tactic.h" +#include "propagate_values_tactic.h" +#include "max_bv_sharing_tactic.h" +#include "card2bv_tactic.h" +#include "bit_blaster_tactic.h" +#include "simplify_tactic.h" +#include "goal2sat.h" +#include "ast_pp.h" +#include "model_smt2_pp.h" + +// incremental SAT solver. +class inc_sat_solver : public solver { + ast_manager& m; + sat::solver m_solver; + goal2sat m_goal2sat; + params_ref m_params; + bool m_optimize_model; // parameter + expr_ref_vector m_fmls; + unsigned_vector m_fmls_lim; + unsigned_vector m_fmls_head_lim; + unsigned m_fmls_head; + expr_ref_vector m_core; + atom2bool_var m_map; + model_ref m_model; + model_converter_ref m_mc; + tactic_ref m_preprocess; + unsigned m_num_scopes; + sat::literal_vector m_asms; + goal_ref_buffer m_subgoals; + proof_converter_ref m_pc; + model_converter_ref m_mc2; + expr_dependency_ref m_dep_core; + expr_ref_vector m_soft; + vector m_weights; + bool m_soft_assumptions; + + + typedef obj_map dep2asm_t; +public: + inc_sat_solver(ast_manager& m, params_ref const& p): + m(m), m_solver(p,0), + m_params(p), m_optimize_model(false), + m_fmls(m), + m_fmls_head(0), + m_core(m), + m_map(m), + m_num_scopes(0), + m_dep_core(m), + m_soft(m), + m_soft_assumptions(false) { + m_params.set_bool("elim_vars", false); + m_solver.updt_params(m_params); + params_ref simp2_p = p; + simp2_p.set_bool("som", true); + simp2_p.set_bool("pull_cheap_ite", true); + simp2_p.set_bool("push_ite_bv", false); + simp2_p.set_bool("local_ctx", true); + simp2_p.set_uint("local_ctx_limit", 10000000); + simp2_p.set_bool("flat", true); // required by som + simp2_p.set_bool("hoist_mul", false); // required by som + m_preprocess = + and_then(mk_card2bv_tactic(m, m_params), + //mk_simplify_tactic(m), + //mk_propagate_values_tactic(m), + using_params(mk_simplify_tactic(m), simp2_p), + mk_max_bv_sharing_tactic(m), + mk_bit_blaster_tactic(m), + mk_aig_tactic(), + using_params(mk_simplify_tactic(m), simp2_p)); + } + + virtual ~inc_sat_solver() {} + + virtual void set_progress_callback(progress_callback * callback) {} + + virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) { + m_solver.pop_to_base_level(); + dep2asm_t dep2asm; + m_model = 0; + lbool r = internalize_formulas(); + if (r != l_true) return r; + r = internalize_assumptions(num_assumptions, assumptions, dep2asm); + if (r != l_true) return r; + extract_assumptions(dep2asm, m_asms); + + r = initialize_soft_constraints(); + if (r != l_true) return r; + + r = m_solver.check(m_asms.size(), m_asms.c_ptr()); + switch (r) { + case l_true: + if (num_assumptions > 0) { + check_assumptions(dep2asm); + } + break; + case l_false: + // TBD: expr_dependency core is not accounted for. + if (num_assumptions > 0) { + extract_core(dep2asm); + } + break; + default: + break; + } + return r; + } + virtual void set_cancel(bool f) { + m_goal2sat.set_cancel(f); + m_solver.set_cancel(f); + if (f) m_preprocess->cancel(); else m_preprocess->reset_cancel(); + } + virtual void push() { + internalize_formulas(); + m_solver.user_push(); + ++m_num_scopes; + m_fmls_lim.push_back(m_fmls.size()); + m_fmls_head_lim.push_back(m_fmls_head); + } + virtual void pop(unsigned n) { + if (n < m_num_scopes) { // allow inc_sat_solver to + n = m_num_scopes; // take over for another solver. + } + SASSERT(n >= m_num_scopes); + m_solver.user_pop(n); + m_num_scopes -= n; + while (n > 0) { + m_fmls_head = m_fmls_head_lim.back(); + m_fmls.resize(m_fmls_lim.back()); + m_fmls_lim.pop_back(); + m_fmls_head_lim.pop_back(); + --n; + } + } + virtual unsigned get_scope_level() const { + return m_num_scopes; + } + virtual void assert_expr(expr * t, expr * a) { + if (a) { + assert_expr(m.mk_implies(a, t)); + } + else { + assert_expr(t); + } + } + virtual void assert_expr(expr * t) { + TRACE("opt", tout << mk_pp(t, m) << "\n";); + m_fmls.push_back(t); + } + virtual void set_produce_models(bool f) {} + virtual void collect_param_descrs(param_descrs & r) { + goal2sat::collect_param_descrs(r); + sat::solver::collect_param_descrs(r); + } + virtual void updt_params(params_ref const & p) { + m_params = p; + m_params.set_bool("elim_vars", false); + m_solver.updt_params(m_params); + m_soft_assumptions = m_params.get_bool("soft_assumptions", false); + m_optimize_model = m_params.get_bool("optimize_model", false); + } + virtual void collect_statistics(statistics & st) const { + m_preprocess->collect_statistics(st); + m_solver.collect_statistics(st); + } + virtual void get_unsat_core(ptr_vector & r) { + r.reset(); + r.append(m_core.size(), m_core.c_ptr()); + } + virtual void get_model(model_ref & m) { + if (!m_model.get()) { + extract_model(); + } + m = m_model; + } + virtual proof * get_proof() { + UNREACHABLE(); + return 0; + } + virtual std::string reason_unknown() const { + return "no reason given"; + } + virtual void get_labels(svector & r) { + UNREACHABLE(); + } + virtual unsigned get_num_assertions() const { + return m_fmls.size(); + } + virtual expr * get_assertion(unsigned idx) const { + return m_fmls[idx]; + } + void set_soft(unsigned sz, expr*const* soft, rational const* weights) { + m_soft.reset(); + m_weights.reset(); + m_soft.append(sz, soft); + m_weights.append(sz, weights); + } + +private: + + lbool initialize_soft_constraints() { + dep2asm_t dep2asm; + if (m_soft.empty()) { + return l_true; + } + expr_ref_vector soft(m_soft); + for (unsigned i = 0; i < soft.size(); ++i) { + expr* e = soft[i].get(), *e1; + if (is_uninterp_const(e) || (m.is_not(e, e1) && is_uninterp_const(e1))) { + continue; + } + expr_ref asum(m), fml(m); + asum = m.mk_fresh_const("soft", m.mk_bool_sort()); + fml = m.mk_iff(asum, e); + m_fmls.push_back(fml); + soft[i] = asum; + } + m_soft.reset(); + lbool r = internalize_formulas(); + if (r != l_true) return r; + r = internalize_assumptions(soft.size(), soft.c_ptr(), dep2asm); + if (r != l_true) return r; + sat::literal_vector lits; + svector weights; + sat::literal lit; + for (unsigned i = 0; i < soft.size(); ++i) { + weights.push_back(m_weights[i].get_double()); + expr* s = soft[i].get(); + if (!dep2asm.find(s, lit)) { + IF_VERBOSE(0, + verbose_stream() << "not found: " << mk_pp(s, m) << "\n"; + dep2asm_t::iterator it = dep2asm.begin(); + dep2asm_t::iterator end = dep2asm.end(); + for (; it != end; ++it) { + verbose_stream() << mk_pp(it->m_key, m) << " " << it->m_value << "\n"; + } + UNREACHABLE();); + } + lits.push_back(lit); + } + m_solver.initialize_soft(lits.size(), lits.c_ptr(), weights.c_ptr()); + return r; + } + + lbool internalize_goal(goal_ref& g, dep2asm_t& dep2asm) { + m_mc2.reset(); + m_pc.reset(); + m_dep_core.reset(); + m_subgoals.reset(); + SASSERT(g->models_enabled()); + SASSERT(!g->proofs_enabled()); + TRACE("opt", g->display(tout);); + try { + (*m_preprocess)(g, m_subgoals, m_mc2, m_pc, m_dep_core); + } + catch (tactic_exception & ex) { + IF_VERBOSE(0, verbose_stream() << "exception in tactic " << ex.msg() << "\n";); + return l_undef; + } + m_mc = concat(m_mc.get(), m_mc2.get()); + if (m_subgoals.size() != 1) { + IF_VERBOSE(0, verbose_stream() << "size of subgoals is not 1, it is: " << m_subgoals.size() << "\n";); + return l_undef; + } + g = m_subgoals[0]; + TRACE("opt", g->display_with_dependencies(tout);); + m_goal2sat(*g, m_params, m_solver, m_map, dep2asm, true); + return l_true; + } + + lbool internalize_assumptions(unsigned sz, expr* const* asms, dep2asm_t& dep2asm) { + if (sz == 0) { + return l_true; + } + goal_ref g = alloc(goal, m, true, true); // models and cores are enabled. + for (unsigned i = 0; i < sz; ++i) { + g->assert_expr(asms[i], m.mk_leaf(asms[i])); + } + return internalize_goal(g, dep2asm); + } + + lbool internalize_formulas() { + if (m_fmls_head == m_fmls.size()) { + return l_true; + } + dep2asm_t dep2asm; + goal_ref g = alloc(goal, m, true, false); // models, maybe cores are enabled + for (; m_fmls_head < m_fmls.size(); ++m_fmls_head) { + g->assert_expr(m_fmls[m_fmls_head].get()); + } + return internalize_goal(g, dep2asm); + } + + void extract_assumptions(dep2asm_t& dep2asm, sat::literal_vector& asms) { + asms.reset(); + dep2asm_t::iterator it = dep2asm.begin(), end = dep2asm.end(); + for (; it != end; ++it) { + asms.push_back(it->m_value); + } + //IF_VERBOSE(0, verbose_stream() << asms << "\n";); + } + + void extract_core(dep2asm_t& dep2asm) { + u_map asm2dep; + dep2asm_t::iterator it = dep2asm.begin(), end = dep2asm.end(); + for (; it != end; ++it) { + asm2dep.insert(it->m_value.index(), it->m_key); + } + sat::literal_vector const& core = m_solver.get_core(); + TRACE("opt", + dep2asm_t::iterator it = dep2asm.begin(); + dep2asm_t::iterator end = dep2asm.end(); + for (; it != end; ++it) { + tout << mk_pp(it->m_key, m) << " |-> " << sat::literal(it->m_value) << "\n"; + } + tout << "core: "; + for (unsigned i = 0; i < core.size(); ++i) { + tout << core[i] << " "; + } + tout << "\n"; + ); + + m_core.reset(); + for (unsigned i = 0; i < core.size(); ++i) { + expr* e; + VERIFY(asm2dep.find(core[i].index(), e)); + m_core.push_back(e); + } + + + } + + void check_assumptions(dep2asm_t& dep2asm) { + sat::model const & ll_m = m_solver.get_model(); + dep2asm_t::iterator it = dep2asm.begin(), end = dep2asm.end(); + for (; it != end; ++it) { + sat::literal lit = it->m_value; + if (!m_soft_assumptions && sat::value_at(lit, ll_m) != l_true) { + IF_VERBOSE(0, verbose_stream() << mk_pp(it->m_key, m) << " does not evaluate to true\n"; + verbose_stream() << m_asms << "\n"; + m_solver.display_assignment(verbose_stream()); + m_solver.display(verbose_stream());); + throw default_exception("bad state"); + } + } + } + + void extract_model() { + TRACE("sat", tout << "retrieve model\n";); + if (!m_solver.model_is_current()) { + m_model = 0; + return; + } + sat::model const & ll_m = m_solver.get_model(); + model_ref md = alloc(model, m); + atom2bool_var::iterator it = m_map.begin(); + atom2bool_var::iterator end = m_map.end(); + for (; it != end; ++it) { + expr * n = it->m_key; + if (is_app(n) && to_app(n)->get_num_args() > 0) { + continue; + } + sat::bool_var v = it->m_value; + switch (sat::value_at(v, ll_m)) { + case l_true: + md->register_decl(to_app(n)->get_decl(), m.mk_true()); + break; + case l_false: + md->register_decl(to_app(n)->get_decl(), m.mk_false()); + break; + default: + break; + } + } + m_model = md; + if (m_mc) { + (*m_mc)(m_model); + } + SASSERT(m_model); + + DEBUG_CODE( + for (unsigned i = 0; i < m_fmls.size(); ++i) { + expr_ref tmp(m); + VERIFY(m_model->eval(m_fmls[i].get(), tmp)); + CTRACE("opt", !m.is_true(tmp), + tout << "Evaluation failed: " << mk_pp(m_fmls[i].get(), m) + << " to " << tmp << "\n"; + model_smt2_pp(tout, m, *(m_model.get()), 0);); + SASSERT(m.is_true(tmp)); + }); + } +}; + + +solver* mk_inc_sat_solver(ast_manager& m, params_ref& p) { + return alloc(inc_sat_solver, m, p); +} + +void set_soft_inc_sat(solver* _s, unsigned sz, expr*const* soft, rational const* weights) { + inc_sat_solver* s = dynamic_cast(_s); + s->set_soft(sz, soft, weights); +} diff --git a/src/opt/inc_sat_solver.h b/src/opt/inc_sat_solver.h new file mode 100644 index 000000000..8bb4c288a --- /dev/null +++ b/src/opt/inc_sat_solver.h @@ -0,0 +1,29 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + inc_sat_solver.h + +Abstract: + + incremental solver based on SAT core. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-7-30 + +Notes: + +--*/ + +#ifndef _HS_INC_SAT_SOLVER_H_ +#define _HS_INC_SAT_SOLVER_H_ + +#include "solver.h" + +solver* mk_inc_sat_solver(ast_manager& m, params_ref& p); + +void set_soft_inc_sat(solver* s, unsigned sz, expr*const* soft, rational const* weights); + +#endif diff --git a/src/opt/maxhs.cpp b/src/opt/maxhs.cpp new file mode 100644 index 000000000..6d4a7b8bf --- /dev/null +++ b/src/opt/maxhs.cpp @@ -0,0 +1,561 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + maxhs.cpp + +Abstract: + + maxhs based MaxSAT. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-17 + +Notes: + +--*/ +#include "optsmt.h" +#include "hitting_sets.h" +#include "stopwatch.h" +#include "ast_pp.h" +#include "model_smt2_pp.h" +#include "uint_set.h" +#include "maxhs.h" +#include "opt_context.h" + +namespace opt { + + class scoped_stopwatch { + double& m_time; + stopwatch m_watch; + public: + scoped_stopwatch(double& time): m_time(time) { + m_watch.start(); + } + ~scoped_stopwatch() { + m_watch.stop(); + m_time += m_watch.get_seconds(); + } + }; + + + // ---------------------------------- + // MaxSatHS+MSS + // variant of MaxSAT-HS (Algorithm 9) + // that also refines upper bound during progressive calls + // to the underlying optimization solver for the soft constraints. + // + + class maxhs : public maxsmt_solver_base { + struct stats { + stats() { reset(); } + void reset() { memset(this, 0, sizeof(*this)); } + unsigned m_num_iterations; + unsigned m_num_core_reductions_success; + unsigned m_num_core_reductions_failure; + unsigned m_num_model_expansions_success; + unsigned m_num_model_expansions_failure; + double m_core_reduction_time; + double m_model_expansion_time; + double m_aux_sat_time; + double m_disjoint_cores_time; + }; + + hitting_sets m_hs; + expr_ref_vector m_aux; // auxiliary (indicator) variables. + obj_map m_aux2index; // expr |-> index + unsigned_vector m_core_activity; // number of times soft constraint is used in a core. + svector m_seed; // clause selected in current model. + svector m_aux_active; // active soft clauses. + ptr_vector m_asms; // assumptions (over aux) + stats m_stats; + bool m_at_lower_bound; + + + public: + maxhs(context& c, weights_t& ws, expr_ref_vector const& soft): + maxsmt_solver_base(c, ws, soft), + m_aux(m), + m_at_lower_bound(false) { + } + virtual ~maxhs() {} + + virtual void set_cancel(bool f) { + maxsmt_solver_base::set_cancel(f); + m_hs.set_cancel(f); + } + + virtual void collect_statistics(statistics& st) const { + maxsmt_solver_base::collect_statistics(st); + m_hs.collect_statistics(st); + st.update("maxhs-num-iterations", m_stats.m_num_iterations); + st.update("maxhs-num-core-reductions-n", m_stats.m_num_core_reductions_failure); + st.update("maxhs-num-core-reductions-y", m_stats.m_num_core_reductions_success); + st.update("maxhs-num-model-expansions-n", m_stats.m_num_model_expansions_failure); + st.update("maxhs-num-model-expansions-y", m_stats.m_num_model_expansions_success); + st.update("maxhs-core-reduction-time", m_stats.m_core_reduction_time); + st.update("maxhs-model-expansion-time", m_stats.m_model_expansion_time); + st.update("maxhs-aux-sat-time", m_stats.m_aux_sat_time); + st.update("maxhs-disj-core-time", m_stats.m_disjoint_cores_time); + } + + lbool operator()() { + ptr_vector hs; + init(); + init_local(); + if (!disjoint_cores(hs)) { + return l_undef; + } + seed2assumptions(); + while (m_lower < m_upper) { + ++m_stats.m_num_iterations; + trace_bounds("maxhs"); + TRACE("opt", tout << "(maxhs [" << m_lower << ":" << m_upper << "])\n";); + if (m_cancel) { + return l_undef; + } + + lbool core_found = generate_cores(hs); + switch(core_found) { + case l_undef: + return l_undef; + case l_true: { + lbool is_sat = next_seed(); + switch(is_sat) { + case l_true: + seed2hs(false, hs); + break; + case l_false: + TRACE("opt", tout << "no more seeds\n";); + IF_VERBOSE(1, verbose_stream() << "(opt.maxhs.no-more-seeds)\n";); + m_lower = m_upper; + return l_true; + case l_undef: + return l_undef; + } + break; + } + case l_false: + IF_VERBOSE(1, verbose_stream() << "(opt.maxhs.no-more-cores)\n";); + TRACE("opt", tout << "no more cores\n";); + m_lower = m_upper; + return l_true; + } + } + return l_true; + } + + private: + + unsigned num_soft() const { return m_soft.size(); } + + void init_local() { + unsigned sz = num_soft(); + app_ref fml(m), obj(m); + expr_ref_vector sum(m); + m_asms.reset(); + m_seed.reset(); + m_aux.reset(); + m_aux_active.reset(); + m_aux2index.reset(); + m_core_activity.reset(); + for (unsigned i = 0; i < sz; ++i) { + bool tt = is_true(m_model, m_soft[i]); + m_seed.push_back(tt); + m_aux. push_back(mk_fresh(m.mk_bool_sort())); + m_aux_active.push_back(false); + m_core_activity.push_back(0); + m_aux2index.insert(m_aux.back(), i); + if (tt) { + m_asms.push_back(m_aux.back()); + ensure_active(i); + } + } + + for (unsigned i = 0; i < m_weights.size(); ++i) { + m_hs.add_weight(m_weights[i]); + } + TRACE("opt", print_seed(tout);); + } + + + void hs2seed(ptr_vector const& hs) { + for (unsigned i = 0; i < num_soft(); ++i) { + m_seed[i] = true; + } + for (unsigned i = 0; i < hs.size(); ++i) { + m_seed[m_aux2index.find(hs[i])] = false; + } + TRACE("opt", + print_asms(tout << "hitting set: ", hs); + print_seed(tout);); + } + + void seed2hs(bool pos, ptr_vector& hs) { + hs.reset(); + for (unsigned i = 0; i < num_soft(); ++i) { + if (pos == m_seed[i]) { + hs.push_back(m_aux[i].get()); + } + } + TRACE("opt", + print_asms(tout << "hitting set: ", hs); + print_seed(tout);); + + } + + void seed2assumptions() { + seed2hs(true, m_asms); + } + + + // + // Find disjoint cores for soft constraints. + // + bool disjoint_cores(ptr_vector& hs) { + scoped_stopwatch _sw(m_stats.m_disjoint_cores_time); + m_asms.reset(); + svector active(num_soft(), true); + rational lower(0); + update_assumptions(active, lower, hs); + SASSERT(lower.is_zero()); + while (true) { + lbool is_sat = s().check_sat(m_asms.size(), m_asms.c_ptr()); + switch (is_sat) { + case l_true: + if (lower > m_lower) { + m_lower = lower; + } + return true; + case l_false: + if (!shrink()) return false; + block_up(); + update_assumptions(active, lower, hs); + break; + case l_undef: + return false; + } + } + } + + void update_assumptions(svector& active, rational& lower, ptr_vector& hs) { + rational arg_min(0); + expr* e = 0; + for (unsigned i = 0; i < m_asms.size(); ++i) { + unsigned index = m_aux2index.find(m_asms[i]); + active[index] = false; + if (arg_min.is_zero() || arg_min > m_weights[index]) { + arg_min = m_weights[index]; + e = m_asms[i]; + } + } + if (e) { + hs.push_back(e); + lower += arg_min; + } + m_asms.reset(); + for (unsigned i = 0; i < num_soft(); ++i) { + if (active[i]) { + m_asms.push_back(m_aux[i].get()); + ensure_active(i); + } + } + } + + // + // Auxiliary Algorithm 10 for producing cores. + // + lbool generate_cores(ptr_vector& hs) { + bool core = !m_at_lower_bound; + while (true) { + hs2seed(hs); + lbool is_sat = check_subset(); + switch(is_sat) { + case l_undef: + return l_undef; + case l_true: + if (!grow()) return l_undef; + block_down(); + return core?l_true:l_false; + case l_false: + core = true; + if (!shrink()) return l_undef; + block_up(); + find_non_optimal_hitting_set(hs); + break; + } + } + } + + struct lt_activity { + maxhs& hs; + lt_activity(maxhs& hs):hs(hs) {} + bool operator()(expr* a, expr* b) const { + unsigned w1 = hs.m_core_activity[hs.m_aux2index.find(a)]; + unsigned w2 = hs.m_core_activity[hs.m_aux2index.find(b)]; + return w1 < w2; + } + }; + + // + // produce the non-optimal hitting set by using the 10% heuristic. + // of most active cores constraints. + // m_asms contains the current core. + // + void find_non_optimal_hitting_set(ptr_vector& hs) { + std::sort(m_asms.begin(), m_asms.end(), lt_activity(*this)); + for (unsigned i = m_asms.size(); i > 9*m_asms.size()/10;) { + --i; + hs.push_back(m_asms[i]); + } + } + + // + // retrieve the next seed that satisfies state of hs. + // state of hs must be satisfiable before optimization is called. + // + lbool next_seed() { + scoped_stopwatch _sw(m_stats.m_aux_sat_time); + TRACE("opt", tout << "\n";); + + // min c_i*(not x_i) for x_i are soft clauses. + // max c_i*x_i for x_i are soft clauses + + m_at_lower_bound = false; + + lbool is_sat = m_hs.compute_upper(); + + if (is_sat == l_true) { + is_sat = m_hs.compute_lower(); + } + if (is_sat == l_true) { + m_at_lower_bound = m_hs.get_upper() == m_hs.get_lower(); + if (m_hs.get_lower() > m_lower) { + m_lower = m_hs.get_lower(); + } + for (unsigned i = 0; i < num_soft(); ++i) { + m_seed[i] = is_active(i) && !m_hs.get_value(i); + } + TRACE("opt", print_seed(tout);); + } + return is_sat; + } + + // + // check assignment returned by HS with the original + // hard constraints. + // + lbool check_subset() { + TRACE("opt", tout << "\n";); + m_asms.reset(); + for (unsigned i = 0; i < num_soft(); ++i) { + if (m_seed[i]) { + m_asms.push_back(m_aux[i].get()); + ensure_active(i); + } + } + return s().check_sat(m_asms.size(), m_asms.c_ptr()); + } + + // + // extend the current assignment to one that + // satisfies as many soft constraints as possible. + // update the upper bound based on this assignment + // + bool grow() { + scoped_stopwatch _sw(m_stats.m_model_expansion_time); + model_ref mdl; + s().get_model(mdl); + for (unsigned i = 0; i < num_soft(); ++i) { + ensure_active(i); + m_seed[i] = false; + } + for (unsigned i = 0; i < m_asms.size(); ++i) { + m_seed[m_aux2index.find(m_asms[i])] = true; + } + + for (unsigned i = 0; i < num_soft(); ++i) { + if (m_seed[i]) { + // already an assumption + } + else if (is_true(mdl, m_soft[i])) { + m_seed[i] = true; + m_asms.push_back(m_aux[i].get()); + } + else { + m_asms.push_back(m_aux[i].get()); + lbool is_sat = s().check_sat(m_asms.size(), m_asms.c_ptr()); + switch(is_sat) { + case l_undef: + return false; + case l_false: + ++m_stats.m_num_model_expansions_failure; + m_asms.pop_back(); + break; + case l_true: + ++m_stats.m_num_model_expansions_success; + s().get_model(mdl); + m_seed[i] = true; + break; + } + } + } + rational upper(0); + for (unsigned i = 0; i < num_soft(); ++i) { + if (!m_seed[i]) { + upper += m_weights[i]; + } + } + if (upper < m_upper) { + m_upper = upper; + m_hs.set_upper(upper); + m_model = mdl; + m_assignment.reset(); + m_assignment.append(m_seed); + TRACE("opt", + tout << "new upper: " << m_upper << "\n"; + model_smt2_pp(tout, m, *(mdl.get()), 0);); + } + DEBUG_CODE( + for (unsigned i = 0; i < num_soft(); ++i) { + SASSERT(is_true(mdl, m_soft[i]) == m_seed[i]); + }); + + return true; + } + + // + // remove soft constraints from the current core. + // + bool shrink() { + scoped_stopwatch _sw(m_stats.m_core_reduction_time); + m_asms.reset(); + s().get_unsat_core(m_asms); + TRACE("opt", print_asms(tout, m_asms);); + obj_map asm2index; + for (unsigned i = 0; i < m_asms.size(); ++i) { + asm2index.insert(m_asms[i], i); + } + obj_map::iterator it = asm2index.begin(), end = asm2index.end(); + for (; it != end; ++it) { + unsigned i = it->m_value; + if (i < m_asms.size()) { + expr* tmp = m_asms[i]; + expr* back = m_asms.back(); + m_asms[i] = back; + m_asms.pop_back(); + lbool is_sat = s().check_sat(m_asms.size(), m_asms.c_ptr()); + TRACE("opt", tout << "checking: " << mk_pp(tmp, m) << ": " << is_sat << "\n";); + switch(is_sat) { + case l_true: + ++m_stats.m_num_core_reductions_failure; + // put back literal into core + m_asms.push_back(back); + m_asms[i] = tmp; + break; + case l_false: + // update the core + m_asms.reset(); + ++m_stats.m_num_core_reductions_success; + s().get_unsat_core(m_asms); + TRACE("opt", print_asms(tout, m_asms);); + update_index(asm2index); + break; + case l_undef: + return false; + } + } + } + return true; + } + + void print_asms(std::ostream& out, ptr_vector const& asms) { + for (unsigned j = 0; j < asms.size(); ++j) { + out << mk_pp(asms[j], m) << " "; + } + out << "\n"; + } + + void print_seed(std::ostream& out) { + out << "seed: "; + for (unsigned i = 0; i < num_soft(); ++i) { + out << (m_seed[i]?"1":"0"); + } + out << "\n"; + } + + // + // must include some literal not from asms. + // (furthermore, update upper bound constraint in HS) + // + void block_down() { + uint_set indices; + unsigned_vector c_indices; + for (unsigned i = 0; i < m_asms.size(); ++i) { + indices.insert(m_aux2index.find(m_asms[i])); + } + for (unsigned i = 0; i < num_soft(); ++i) { + if (!indices.contains(i)) { + c_indices.push_back(i); + } + } + m_hs.add_exists_false(c_indices.size(), c_indices.c_ptr()); + } + + // should exclude some literal from core. + void block_up() { + unsigned_vector indices; + for (unsigned i = 0; i < m_asms.size(); ++i) { + unsigned index = m_aux2index.find(m_asms[i]); + m_core_activity[index]++; + indices.push_back(index); + } + m_hs.add_exists_true(indices.size(), indices.c_ptr()); + } + + void update_index(obj_map& asm2index) { + obj_map::iterator it = asm2index.begin(), end = asm2index.end(); + for (; it != end; ++it) { + it->m_value = UINT_MAX; + } + for (unsigned i = 0; i < m_asms.size(); ++i) { + asm2index.find(m_asms[i]) = i; + } + } + + app_ref mk_fresh(sort* s) { + app_ref r(m); + r = m.mk_fresh_const("r", s); + m_c.fm().insert(r->get_decl()); + return r; + } + + bool is_true(model_ref& mdl, expr* e) { + expr_ref val(m); + VERIFY(mdl->eval(e, val)); + return m.is_true(val); + } + + bool is_active(unsigned i) const { + return m_aux_active[i]; + } + + void ensure_active(unsigned i) { + if (!is_active(i)) { + expr_ref fml(m); + fml = m.mk_implies(m_aux[i].get(), m_soft[i]); + s().assert_expr(fml); + m_aux_active[i] = true; + } + } + + }; + + maxsmt_solver_base* mk_maxhs( + context& c, weights_t& ws, expr_ref_vector const& soft) { + return alloc(maxhs, c, ws, soft); + } + +} diff --git a/src/opt/maxhs.h b/src/opt/maxhs.h new file mode 100644 index 000000000..f31cbce9f --- /dev/null +++ b/src/opt/maxhs.h @@ -0,0 +1,29 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + maxhs.h + +Abstract: + + HS-max based MaxSAT. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-17 + +Notes: + +--*/ + +#ifndef _HS_MAX_H_ +#define _HS_MAX_H_ + +#include "maxsmt.h" + +namespace opt { + maxsmt_solver_base* mk_maxhs(context& c, + weights_t& ws, expr_ref_vector const& soft); +} +#endif diff --git a/src/opt/maxres.cpp b/src/opt/maxres.cpp new file mode 100644 index 000000000..c9b52f370 --- /dev/null +++ b/src/opt/maxres.cpp @@ -0,0 +1,799 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + maxsres.cpp + +Abstract: + + MaxRes (weighted) max-sat algorithms: + + - mus: max-sat algorithm by Nina and Bacchus, AAAI 2014. + - mus-mss: based on dual refinement of bounds. + + MaxRes is a core-guided approach to maxsat. + MusMssMaxRes extends the core-guided approach by + leveraging both cores and satisfying assignments + to make progress towards a maximal satisfying assignment. + + Given a (minimal) unsatisfiable core for the soft + constraints the approach works like max-res. + Given a (maximal) satisfying subset of the soft constraints + the approach updates the upper bound if the current assignment + improves the current best assignmet. + Furthermore, take the soft constraints that are complements + to the current satisfying subset. + E.g, if F are the hard constraints and + s1,...,sn, t1,..., tm are the soft clauses and + F & s1 & ... & sn is satisfiable, then the complement + of of the current satisfying subset is t1, .., tm. + Update the hard constraint: + F := F & (t1 or ... or tm) + Replace t1, .., tm by m-1 new soft clauses: + t1 & t2, t3 & (t1 or t2), t4 & (t1 or t2 or t3), ..., tn & (t1 or ... t_{n-1}) + Claim: + If k of these soft clauses are satisfied, then k+1 of + the previous soft clauses are satisfied. + If k of these soft clauses are false in the satisfying assignment + for the updated F, then k of the original soft clauses are also false + under the assignment. + In summary: any assignment to the new clauses that satsfies F has the + same cost. + Claim: + If there are no satisfying assignments to F, then the current best assignment + is the optimum. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-20-7 + +Notes: + +--*/ + +#include "solver.h" +#include "maxsmt.h" +#include "maxres.h" +#include "ast_pp.h" +#include "mus.h" +#include "mss.h" +#include "inc_sat_solver.h" +#include "opt_context.h" +#include "pb_decl_plugin.h" +#include "opt_params.hpp" +#include "ast_util.h" +#include "smt_solver.h" + +using namespace opt; + +class maxres : public maxsmt_solver_base { +public: + enum strategy_t { + s_primal, + s_primal_dual + }; +private: + struct stats { + unsigned m_num_cores; + unsigned m_num_cs; + stats() { reset(); } + void reset() { + memset(this, 0, sizeof(*this)); + } + }; + stats m_stats; + expr_ref_vector m_B; + expr_ref_vector m_asms; + expr_ref_vector m_defs; + obj_map m_asm2weight; + ptr_vector m_new_core; + mus m_mus; + mss m_mss; + expr_ref_vector m_trail; + strategy_t m_st; + rational m_max_upper; + bool m_found_feasible_optimum; + bool m_hill_climb; // prefer large weight soft clauses for cores + unsigned m_last_index; // last index used during hill-climbing + bool m_add_upper_bound_block; // restrict upper bound with constraint + unsigned m_max_num_cores; // max number of cores per round. + unsigned m_max_core_size; // max core size per round. + bool m_maximize_assignment; // maximize assignment to find MCS + unsigned m_max_correction_set_size;// maximal set of correction set that is tolerated. + bool m_wmax; // Block upper bound using wmax + // this option is disabled if SAT core is used. + + typedef ptr_vector exprs; + +public: + maxres(context& c, + weights_t& ws, expr_ref_vector const& soft, + strategy_t st): + maxsmt_solver_base(c, ws, soft), + m_B(m), m_asms(m), m_defs(m), + m_mus(c.get_solver(), m), + m_mss(c.get_solver(), m), + m_trail(m), + m_st(st), + m_found_feasible_optimum(false), + m_hill_climb(true), + m_last_index(0), + m_add_upper_bound_block(false), + m_max_num_cores(UINT_MAX), + m_max_core_size(3), + m_maximize_assignment(false), + m_max_correction_set_size(3) + { + } + + virtual ~maxres() {} + + bool is_literal(expr* l) { + return + is_uninterp_const(l) || + (m.is_not(l, l) && is_uninterp_const(l)); + } + + + + void add_soft(expr* e, rational const& w) { + TRACE("opt", tout << mk_pp(e, m) << "\n";); + expr_ref asum(m), fml(m); + app_ref cls(m); + rational weight(0); + if (m_asm2weight.find(e, weight)) { + weight += w; + m_asm2weight.insert(e, weight); + m_upper += w; + return; + } + if (is_literal(e)) { + asum = e; + } + else { + asum = mk_fresh_bool("soft"); + fml = m.mk_iff(asum, e); + s().assert_expr(fml); + } + new_assumption(asum, w); + m_upper += w; + } + + void new_assumption(expr* e, rational const& w) { + IF_VERBOSE(3, verbose_stream() << "new assumption " << mk_pp(e, m) << " " << w << "\n";); + TRACE("opt", tout << "insert: " << mk_pp(e, m) << " : " << w << "\n";); + m_asm2weight.insert(e, w); + m_asms.push_back(e); + m_trail.push_back(e); + } + + lbool mus_solver() { + init(); + init_local(); + trace_bounds("maxres"); + while (m_lower < m_upper) { + TRACE("opt", + display_vec(tout, m_asms); + s().display(tout); + tout << "\n"; + display(tout); + ); + lbool is_sat = check_sat_hill_climb(m_asms); + if (m_cancel) { + return l_undef; + } + switch (is_sat) { + case l_true: + found_optimum(); + return l_true; + case l_false: + is_sat = process_unsat(); + if (is_sat != l_true) return is_sat; + break; + case l_undef: + return l_undef; + default: + break; + } + } + trace_bounds("maxres"); + return l_true; + } + + lbool primal_dual_solver() { + init(); + init_local(); + set_soft_assumptions(); + lbool is_sat = l_true; + trace_bounds("max_res"); + exprs cs; + while (m_lower < m_upper) { +#if 0 + expr_ref_vector asms(m_asms); + sort_assumptions(asms); + is_sat = s().check_sat(asms.size(), asms.c_ptr()); +#else + is_sat = check_sat_hill_climb(m_asms); +#endif + if (m_cancel) { + return l_undef; + } + switch (is_sat) { + case l_true: + get_current_correction_set(cs); + IF_VERBOSE(2, display_vec(verbose_stream() << "correction set: ", cs);); + if (cs.empty()) { + m_found_feasible_optimum = m_model.get() != 0; + m_lower = m_upper; + } + else { + process_sat(cs); + } + break; + case l_false: + is_sat = process_unsat(); + if (is_sat != l_true) return is_sat; + break; + case l_undef: + return l_undef; + default: + break; + } + } + trace_bounds("maxres"); + return l_true; + } + + + lbool check_sat_hill_climb(expr_ref_vector& asms1) { + expr_ref_vector asms(asms1); + lbool is_sat = l_true; + if (m_hill_climb) { + /** + Give preference to cores that have large minmal values. + */ + sort_assumptions(asms); + + m_last_index = std::min(m_last_index, asms.size()-1); + m_last_index = 0; + unsigned index = m_last_index>0?m_last_index-1:0; + m_last_index = 0; + bool first = index > 0; + SASSERT(index < asms.size() || asms.empty()); + while (index < asms.size() && is_sat == l_true) { + while (!first && asms.size() > 20*(index - m_last_index) && index < asms.size()) { + index = next_index(asms, index); + } + first = false; + IF_VERBOSE(3, verbose_stream() << "weight: " << get_weight(asms[0].get()) << " " << get_weight(asms[index-1].get()) << " num soft: " << index << "\n";); + m_last_index = index; + is_sat = s().check_sat(index, asms.c_ptr()); + } + } + else { + is_sat = s().check_sat(asms.size(), asms.c_ptr()); + } + return is_sat; + } + + void found_optimum() { + IF_VERBOSE(1, verbose_stream() << "found optimum\n";); + s().get_model(m_model); + DEBUG_CODE( + for (unsigned i = 0; i < m_asms.size(); ++i) { + SASSERT(is_true(m_asms[i].get())); + }); + rational upper(0); + for (unsigned i = 0; i < m_soft.size(); ++i) { + m_assignment[i] = is_true(m_soft[i]); + if (!m_assignment[i]) upper += m_weights[i]; + } + SASSERT(upper == m_lower); + m_upper = m_lower; + m_found_feasible_optimum = true; + } + + + virtual lbool operator()() { + m_defs.reset(); + switch(m_st) { + case s_primal: + return mus_solver(); + case s_primal_dual: + return primal_dual_solver(); + } + return l_undef; + } + + virtual void collect_statistics(statistics& st) const { + st.update("maxres-cores", m_stats.m_num_cores); + st.update("maxres-correction-sets", m_stats.m_num_cs); + } + + lbool get_cores(vector& cores) { + // assume m_s is unsat. + lbool is_sat = l_false; + expr_ref_vector asms(m_asms); + cores.reset(); + exprs core; + while (is_sat == l_false) { + core.reset(); + s().get_unsat_core(core); + //verify_core(core); + model_ref mdl; + get_mus_model(mdl); + is_sat = minimize_core(core); + ++m_stats.m_num_cores; + if (is_sat != l_true) { + break; + } + if (core.empty()) { + cores.reset(); + m_lower = m_upper; + return l_true; + } + cores.push_back(core); + if (core.size() >= m_max_core_size) { + break; + } + if (cores.size() >= m_max_num_cores) { + break; + } + remove_soft(core, asms); + is_sat = check_sat_hill_climb(asms); + } + TRACE("opt", + tout << "num cores: " << cores.size() << "\n"; + for (unsigned i = 0; i < cores.size(); ++i) { + display_vec(tout, cores[i]); + } + tout << "num satisfying: " << asms.size() << "\n";); + + return is_sat; + } + + void get_current_correction_set(exprs& cs) { + model_ref mdl; + s().get_model(mdl); + update_assignment(mdl.get()); + get_current_correction_set(mdl.get(), cs); + } + + void get_current_correction_set(model* mdl, exprs& cs) { + ++m_stats.m_num_cs; + cs.reset(); + if (!mdl) return; + for (unsigned i = 0; i < m_asms.size(); ++i) { + if (is_false(mdl, m_asms[i].get())) { + cs.push_back(m_asms[i].get()); + } + } + TRACE("opt", display_vec(tout << "new correction set: ", cs);); + } + + struct compare_asm { + maxres& mr; + compare_asm(maxres& mr):mr(mr) {} + bool operator()(expr* a, expr* b) const { + return mr.get_weight(a) > mr.get_weight(b); + } + }; + + void sort_assumptions(expr_ref_vector& _asms) { + compare_asm comp(*this); + exprs asms(_asms.size(), _asms.c_ptr()); + expr_ref_vector trail(_asms); + std::sort(asms.begin(), asms.end(), comp); + _asms.reset(); + _asms.append(asms.size(), asms.c_ptr()); + DEBUG_CODE( + for (unsigned i = 0; i + 1 < asms.size(); ++i) { + SASSERT(get_weight(asms[i]) >= get_weight(asms[i+1])); + }); + } + + unsigned next_index(expr_ref_vector const& asms, unsigned index) { + if (index < asms.size()) { + rational w = get_weight(asms[index]); + ++index; + for (; index < asms.size() && w == get_weight(asms[index]); ++index); + } + return index; + } + + void process_sat(exprs const& corr_set) { + expr_ref fml(m), tmp(m); + TRACE("opt", display_vec(tout << "corr_set: ", corr_set);); + remove_core(corr_set); + rational w = split_core(corr_set); + cs_max_resolve(corr_set, w); + IF_VERBOSE(2, verbose_stream() << "(opt.maxres.correction-set " << corr_set.size() << ")\n";); + } + + lbool process_unsat() { + vector cores; + lbool is_sat = get_cores(cores); + if (is_sat != l_true) { + return is_sat; + } + if (cores.empty()) { + return l_false; + } + else { + process_unsat(cores); + return l_true; + } + } + + unsigned max_core_size(vector const& cores) { + unsigned result = 0; + for (unsigned i = 0; i < cores.size(); ++i) { + result = std::max(cores[i].size(), result); + } + return result; + } + + void process_unsat(vector const& cores) { + for (unsigned i = 0; i < cores.size(); ++i) { + process_unsat(cores[i]); + } + } + + void process_unsat(exprs const& core) { + expr_ref fml(m); + remove_core(core); + SASSERT(!core.empty()); + rational w = split_core(core); + TRACE("opt", display_vec(tout << "minimized core: ", core);); + max_resolve(core, w); + fml = mk_not(m, mk_and(m, m_B.size(), m_B.c_ptr())); + s().assert_expr(fml); + m_lower += w; + trace_bounds("maxres"); + } + + bool get_mus_model(model_ref& mdl) { + rational w(0); + if (m_c.sat_enabled()) { + // SAT solver core extracts some model + // during unsat core computation. + mdl = 0; + s().get_model(mdl); + } + else { + w = m_mus.get_best_model(mdl); + } + if (mdl.get() && w < m_upper) { + update_assignment(mdl.get()); + } + return 0 != mdl.get(); + } + + lbool minimize_core(exprs& core) { + if (m_c.sat_enabled() || core.empty()) { + return l_true; + } + m_mus.reset(); + for (unsigned i = 0; i < core.size(); ++i) { + m_mus.add_soft(core[i]); + } + unsigned_vector mus_idx; + lbool is_sat = m_mus.get_mus(mus_idx); + if (is_sat != l_true) { + return is_sat; + } + m_new_core.reset(); + for (unsigned i = 0; i < mus_idx.size(); ++i) { + m_new_core.push_back(core[mus_idx[i]]); + } + core.reset(); + core.append(m_new_core); + return l_true; + } + + rational get_weight(expr* e) const { + return m_asm2weight.find(e); + } + + void sls() { + vector ws; + for (unsigned i = 0; i < m_asms.size(); ++i) { + ws.push_back(get_weight(m_asms[i].get())); + } + enable_sls(m_asms, ws); + } + + rational split_core(exprs const& core) { + if (core.empty()) return rational(0); + // find the minimal weight: + rational w = get_weight(core[0]); + for (unsigned i = 1; i < core.size(); ++i) { + w = std::min(w, get_weight(core[i])); + } + // add fresh soft clauses for weights that are above w. + for (unsigned i = 0; i < core.size(); ++i) { + rational w2 = get_weight(core[i]); + if (w2 > w) { + rational w3 = w2 - w; + new_assumption(core[i], w3); + } + } + return w; + } + + void display_vec(std::ostream& out, exprs const& exprs) { + display_vec(out, exprs.size(), exprs.c_ptr()); + } + + void display_vec(std::ostream& out, expr_ref_vector const& exprs) { + display_vec(out, exprs.size(), exprs.c_ptr()); + } + + void display_vec(std::ostream& out, unsigned sz, expr* const* args) const { + for (unsigned i = 0; i < sz; ++i) { + out << mk_pp(args[i], m) << " : " << get_weight(args[i]) << " "; + } + out << "\n"; + } + + void display(std::ostream& out) { + for (unsigned i = 0; i < m_asms.size(); ++i) { + expr* a = m_asms[i].get(); + out << mk_pp(a, m) << " : " << get_weight(a) << "\n"; + } + } + + void max_resolve(exprs const& core, rational const& w) { + SASSERT(!core.empty()); + expr_ref fml(m), asum(m); + app_ref cls(m), d(m), dd(m); + m_B.reset(); + m_B.append(core.size(), core.c_ptr()); + // + // d_0 := true + // d_i := b_{i-1} and d_{i-1} for i = 1...sz-1 + // soft (b_i or !d_i) + // == (b_i or !(!b_{i-1} or d_{i-1})) + // == (b_i or b_0 & b_1 & ... & b_{i-1}) + // + // Soft constraint is satisfied if previous soft constraint + // holds or if it is the first soft constraint to fail. + // + // Soundness of this rule can be established using MaxRes + // + for (unsigned i = 1; i < core.size(); ++i) { + expr* b_i = m_B[i-1].get(); + expr* b_i1 = m_B[i].get(); + if (i == 1) { + d = to_app(b_i); + } + else if (i == 2) { + d = m.mk_and(b_i, d); + m_trail.push_back(d); + } + else { + dd = mk_fresh_bool("d"); + fml = m.mk_implies(dd, d); + s().assert_expr(fml); + m_defs.push_back(fml); + fml = m.mk_implies(dd, b_i); + s().assert_expr(fml); + m_defs.push_back(fml); + d = dd; + } + asum = mk_fresh_bool("a"); + cls = m.mk_or(b_i1, d); + fml = m.mk_implies(asum, cls); + new_assumption(asum, w); + s().assert_expr(fml); + m_defs.push_back(fml); + } + } + + // cs is a correction set (a complement of a (maximal) satisfying assignment). + void cs_max_resolve(exprs const& cs, rational const& w) { + if (cs.empty()) return; + TRACE("opt", display_vec(tout << "correction set: ", cs);); + expr_ref fml(m), asum(m); + app_ref cls(m), d(m), dd(m); + m_B.reset(); + m_B.append(cs.size(), cs.c_ptr()); + d = m.mk_false(); + // + // d_0 := false + // d_i := b_{i-1} or d_{i-1} for i = 1...sz-1 + // soft (b_i and d_i) + // == (b_i and (b_0 or b_1 or ... or b_{i-1})) + // + // asm => b_i + // asm => d_{i-1} or b_{i-1} + // d_i => d_{i-1} or b_{i-1} + // + for (unsigned i = 1; i < cs.size(); ++i) { + expr* b_i = m_B[i-1].get(); + expr* b_i1 = m_B[i].get(); + cls = m.mk_or(b_i, d); + if (i > 2) { + d = mk_fresh_bool("d"); + fml = m.mk_implies(d, cls); + s().assert_expr(fml); + m_defs.push_back(fml); + } + else { + d = cls; + } + asum = mk_fresh_bool("a"); + fml = m.mk_implies(asum, b_i1); + s().assert_expr(fml); + m_defs.push_back(fml); + fml = m.mk_implies(asum, cls); + s().assert_expr(fml); + m_defs.push_back(fml); + new_assumption(asum, w); + } + fml = m.mk_or(m_B.size(), m_B.c_ptr()); + s().assert_expr(fml); + } + + void update_assignment(model* mdl) { + rational upper(0); + expr_ref tmp(m); + for (unsigned i = 0; i < m_soft.size(); ++i) { + if (!is_true(mdl, m_soft[i])) { + upper += m_weights[i]; + } + } + if (upper >= m_upper) { + return; + } + m_model = mdl; + + for (unsigned i = 0; i < m_soft.size(); ++i) { + m_assignment[i] = is_true(m_soft[i]); + } + m_upper = upper; + DEBUG_CODE(verify_assignment();); + trace_bounds("maxres"); + + add_upper_bound_block(); + } + + void add_upper_bound_block() { + if (!m_add_upper_bound_block) return; + pb_util u(m); + expr_ref_vector nsoft(m); + expr_ref fml(m); + for (unsigned i = 0; i < m_soft.size(); ++i) { + nsoft.push_back(mk_not(m, m_soft[i])); + } + fml = u.mk_lt(nsoft.size(), m_weights.c_ptr(), nsoft.c_ptr(), m_upper); + s().assert_expr(fml); + } + + bool is_true(model* mdl, expr* e) { + expr_ref tmp(m); + VERIFY(mdl->eval(e, tmp)); + return m.is_true(tmp); + } + + bool is_false(model* mdl, expr* e) { + expr_ref tmp(m); + VERIFY(mdl->eval(e, tmp)); + return m.is_false(tmp); + } + + bool is_true(expr* e) { + return is_true(m_model.get(), e); + } + + void remove_soft(exprs const& core, expr_ref_vector& asms) { + for (unsigned i = 0; i < asms.size(); ++i) { + if (core.contains(asms[i].get())) { + asms[i] = asms.back(); + asms.pop_back(); + --i; + } + } + } + + void remove_core(exprs const& core) { + remove_soft(core, m_asms); + } + + virtual void set_cancel(bool f) { + maxsmt_solver_base::set_cancel(f); + m_mus.set_cancel(f); + } + + virtual void updt_params(params_ref& p) { + maxsmt_solver_base::updt_params(p); + opt_params _p(p); + + m_hill_climb = _p.maxres_hill_climb(); + m_add_upper_bound_block = _p.maxres_add_upper_bound_block(); + m_max_num_cores = _p.maxres_max_num_cores(); + m_max_core_size = _p.maxres_max_core_size(); + m_maximize_assignment = _p.maxres_maximize_assignment(); + m_max_correction_set_size = _p.maxres_max_correction_set_size(); + m_wmax = _p.maxres_wmax(); + } + + void init_local() { + m_upper.reset(); + m_lower.reset(); + m_trail.reset(); + for (unsigned i = 0; i < m_soft.size(); ++i) { + add_soft(m_soft[i], m_weights[i]); + } + m_max_upper = m_upper; + m_found_feasible_optimum = false; + m_last_index = 0; + add_upper_bound_block(); + } + + virtual void commit_assignment() { + if (m_found_feasible_optimum) { + TRACE("opt", tout << "Committing feasible solution\n"; + tout << m_defs; + tout << m_asms; + ); + for (unsigned i = 0; i < m_defs.size(); ++i) { + s().assert_expr(m_defs[i].get()); + } + for (unsigned i = 0; i < m_asms.size(); ++i) { + s().assert_expr(m_asms[i].get()); + } + } + else { + maxsmt_solver_base::commit_assignment(); + } + } + + void verify_core(exprs const& core) { + IF_VERBOSE(3, verbose_stream() << "verify core\n";); + ref smt_solver = mk_smt_solver(m, m_params, symbol()); + for (unsigned i = 0; i < s().get_num_assertions(); ++i) { + smt_solver->assert_expr(s().get_assertion(i)); + } + for (unsigned i = 0; i < core.size(); ++i) { + smt_solver->assert_expr(core[i]); + } + lbool is_sat = smt_solver->check_sat(0, 0); + if (is_sat == l_true) { + IF_VERBOSE(0, verbose_stream() << "not a core\n";); + } + } + + void verify_assignment() { + IF_VERBOSE(1, verbose_stream() << "verify assignment\n";); + ref smt_solver = mk_smt_solver(m, m_params, symbol()); + for (unsigned i = 0; i < s().get_num_assertions(); ++i) { + smt_solver->assert_expr(s().get_assertion(i)); + } + expr_ref n(m); + for (unsigned i = 0; i < m_soft.size(); ++i) { + n = m_soft[i]; + if (!m_assignment[i]) { + n = mk_not(m, n); + } + smt_solver->assert_expr(n); + } + lbool is_sat = smt_solver->check_sat(0, 0); + if (is_sat == l_false) { + IF_VERBOSE(0, verbose_stream() << "assignment is infeasible\n";); + } + } + +}; + +opt::maxsmt_solver_base* opt::mk_maxres( + context& c, weights_t& ws, expr_ref_vector const& soft) { + return alloc(maxres, c, ws, soft, maxres::s_primal); +} + +opt::maxsmt_solver_base* opt::mk_primal_dual_maxres( + context& c, weights_t& ws, expr_ref_vector const& soft) { + return alloc(maxres, c, ws, soft, maxres::s_primal_dual); +} + diff --git a/src/opt/maxres.h b/src/opt/maxres.h new file mode 100644 index 000000000..c942b655e --- /dev/null +++ b/src/opt/maxres.h @@ -0,0 +1,31 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + maxsres.h + +Abstract: + + MaxRes (weighted) max-sat algorithm by Nina and Bacchus, AAAI 2014. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-20-7 + +Notes: + +--*/ + +#ifndef _MAXRES_H_ +#define _MAXRES_H_ + +namespace opt { + + maxsmt_solver_base* mk_maxres(context& c, weights_t & ws, expr_ref_vector const& soft); + + maxsmt_solver_base* mk_primal_dual_maxres(context& c, weights_t & ws, expr_ref_vector const& soft); + +}; + +#endif diff --git a/src/opt/maxsls.cpp b/src/opt/maxsls.cpp new file mode 100644 index 000000000..fc9c71607 --- /dev/null +++ b/src/opt/maxsls.cpp @@ -0,0 +1,62 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + maxsls.cpp + +Abstract: + + Weighted SLS MAXSAT module + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-17 + +Notes: + +--*/ + +#include "maxsls.h" +#include "ast_pp.h" +#include "model_smt2_pp.h" + + +namespace opt { + + class sls : public maxsmt_solver_base { + public: + sls(context& c, weights_t& ws, expr_ref_vector const& soft): + maxsmt_solver_base(c, ws, soft) { + } + virtual ~sls() {} + lbool operator()() { + IF_VERBOSE(1, verbose_stream() << "(opt.sls)\n";); + init(); + set_enable_sls(true); + enable_sls(m_soft, m_weights); + lbool is_sat = s().check_sat(0, 0); + if (is_sat == l_true) { + s().get_model(m_model); + m_upper.reset(); + for (unsigned i = 0; i < m_soft.size(); ++i) { + expr_ref tmp(m); + m_model->eval(m_soft[i], tmp, true); + m_assignment[i] = m.is_true(tmp); + if (!m_assignment[i]) { + m_upper += m_weights[i]; + } + } + } + return is_sat; + } + + }; + + maxsmt_solver_base* mk_sls( + context& c, weights_t& ws, expr_ref_vector const& soft) { + return alloc(sls, c, ws, soft); + } + + +}; diff --git a/src/opt/maxsls.h b/src/opt/maxsls.h new file mode 100644 index 000000000..c4314171f --- /dev/null +++ b/src/opt/maxsls.h @@ -0,0 +1,35 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + maxsls.h + +Abstract: + + Weighted SLS MAXSAT module + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-17 + +Notes: + + Partial, one-round SLS optimizer. Finds the first + local maximum given a resource bound and returns. + +--*/ +#ifndef _OPT_SLS_MAX_SAT_H_ +#define _OPT_SLS_MAX_SAT_H_ + +#include "maxsmt.h" + +namespace opt { + + + maxsmt_solver_base* mk_sls(context& c, weights_t& ws, expr_ref_vector const& soft); + + +}; + +#endif diff --git a/src/opt/maxsmt.cpp b/src/opt/maxsmt.cpp new file mode 100644 index 000000000..710f10d48 --- /dev/null +++ b/src/opt/maxsmt.cpp @@ -0,0 +1,323 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + maxsmt.cpp + +Abstract: + + MaxSMT optimization context. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-7 + +Notes: + +--*/ + +#include +#include "maxsmt.h" +#include "fu_malik.h" +#include "maxres.h" +#include "maxhs.h" +#include "bcd2.h" +#include "wmax.h" +#include "maxsls.h" +#include "ast_pp.h" +#include "uint_set.h" +#include "opt_context.h" +#include "theory_wmaxsat.h" +#include "ast_util.h" +#include "pb_decl_plugin.h" + + +namespace opt { + + maxsmt_solver_base::maxsmt_solver_base( + context& c, vector const& ws, expr_ref_vector const& soft): + m(c.get_manager()), + m_c(c), + m_cancel(false), + m_soft(soft), + m_weights(ws), + m_assertions(m) { + c.get_base_model(m_model); + SASSERT(m_model); + updt_params(c.params()); + } + + void maxsmt_solver_base::updt_params(params_ref& p) { + m_params.copy(p); + } + + solver& maxsmt_solver_base::s() { + return m_c.get_solver(); + } + + void maxsmt_solver_base::commit_assignment() { + expr_ref tmp(m); + rational k(0); + for (unsigned i = 0; i < m_soft.size(); ++i) { + if (get_assignment(i)) { + k += m_weights[i]; + } + } + pb_util pb(m); + tmp = pb.mk_ge(m_weights.size(), m_weights.c_ptr(), m_soft.c_ptr(), k); + TRACE("opt", tout << tmp << "\n";); + s().assert_expr(tmp); + } + + void maxsmt_solver_base::init() { + m_lower.reset(); + m_upper.reset(); + m_assignment.reset(); + for (unsigned i = 0; i < m_weights.size(); ++i) { + expr_ref val(m); + VERIFY(m_model->eval(m_soft[i], val)); + m_assignment.push_back(m.is_true(val)); + if (!m_assignment.back()) { + m_upper += m_weights[i]; + } + } + + TRACE("opt", + tout << "upper: " << m_upper << " assignments: "; + for (unsigned i = 0; i < m_weights.size(); ++i) { + tout << (m_assignment[i]?"T":"F"); + } + tout << "\n";); + } + + void maxsmt_solver_base::set_mus(bool f) { + params_ref p; + p.set_bool("minimize_core", f); + s().updt_params(p); + } + + void maxsmt_solver_base::enable_sls(expr_ref_vector const& soft, vector const& ws) { + m_c.enable_sls(soft, ws); + } + + void maxsmt_solver_base::set_enable_sls(bool f) { + m_c.set_enable_sls(f); + } + + void maxsmt_solver_base::set_soft_assumptions() { + m_c.set_soft_assumptions(); + } + + app* maxsmt_solver_base::mk_fresh_bool(char const* name) { + app* result = m.mk_fresh_const(name, m.mk_bool_sort()); + m_c.fm().insert(result->get_decl()); + return result; + } + + smt::theory_wmaxsat* maxsmt_solver_base::get_wmax_theory() const { + smt::theory_id th_id = m.get_family_id("weighted_maxsat"); + smt::theory* th = m_c.smt_context().get_theory(th_id); + if (th) { + return dynamic_cast(th); + } + else { + return 0; + } + } + + smt::theory_wmaxsat* maxsmt_solver_base::ensure_wmax_theory() { + smt::theory_wmaxsat* wth = get_wmax_theory(); + if (wth) { + wth->reset_local(); + } + else { + wth = alloc(smt::theory_wmaxsat, m, m_c.fm()); + m_c.smt_context().register_plugin(wth); + } + return wth; + } + + maxsmt_solver_base::scoped_ensure_theory::scoped_ensure_theory(maxsmt_solver_base& s) { + m_wth = s.ensure_wmax_theory(); + } + maxsmt_solver_base::scoped_ensure_theory::~scoped_ensure_theory() { + //m_wth->reset_local(); + } + smt::theory_wmaxsat& maxsmt_solver_base::scoped_ensure_theory::operator()() { return *m_wth; } + + void maxsmt_solver_base::trace_bounds(char const * solver) { + IF_VERBOSE(1, + rational l = m_adjust_value(m_lower); + rational u = m_adjust_value(m_upper); + if (l > u) std::swap(l, u); + verbose_stream() << "(opt." << solver << " [" << l << ":" << u << "])\n";); + } + + + + maxsmt::maxsmt(context& c): + m(c.get_manager()), m_c(c), m_cancel(false), + m_soft_constraints(m), m_answer(m) {} + + lbool maxsmt::operator()() { + lbool is_sat; + m_msolver = 0; + symbol const& maxsat_engine = m_c.maxsat_engine(); + IF_VERBOSE(1, verbose_stream() << "(maxsmt)\n";); + TRACE("opt", tout << "maxsmt\n";); + if (m_soft_constraints.empty()) { + TRACE("opt", tout << "no constraints\n";); + m_msolver = 0; + is_sat = s().check_sat(0, 0); + } + else if (maxsat_engine == symbol("maxres")) { + m_msolver = mk_maxres(m_c, m_weights, m_soft_constraints); + } + else if (maxsat_engine == symbol("pd-maxres")) { + m_msolver = mk_primal_dual_maxres(m_c, m_weights, m_soft_constraints); + } + else if (maxsat_engine == symbol("bcd2")) { + m_msolver = mk_bcd2(m_c, m_weights, m_soft_constraints); + } + else if (maxsat_engine == symbol("maxhs")) { + m_msolver = mk_maxhs(m_c, m_weights, m_soft_constraints); + } + else if (maxsat_engine == symbol("sls")) { + // NB: this is experimental one-round version of SLS + m_msolver = mk_sls(m_c, m_weights, m_soft_constraints); + } + else if (is_maxsat_problem(m_weights) && maxsat_engine == symbol("fu_malik")) { + m_msolver = mk_fu_malik(m_c, m_weights, m_soft_constraints); + } + else { + if (maxsat_engine != symbol::null && maxsat_engine != symbol("wmax")) { + warning_msg("solver %s is not recognized, using default 'wmax'", + maxsat_engine.str().c_str()); + } + m_msolver = mk_wmax(m_c, m_weights, m_soft_constraints); + } + + if (m_msolver) { + m_msolver->updt_params(m_params); + m_msolver->set_adjust_value(m_adjust_value); + is_sat = (*m_msolver)(); + if (is_sat != l_false) { + m_msolver->get_model(m_model); + } + } + + IF_VERBOSE(1, verbose_stream() << "is-sat: " << is_sat << "\n"; + if (is_sat == l_true) { + verbose_stream() << "Satisfying soft constraints\n"; + display_answer(verbose_stream()); + }); + + DEBUG_CODE(if (is_sat == l_true) verify_assignment();); + + return is_sat; + } + + void maxsmt::verify_assignment() { + // TBD: have to use a different solver + // because we don't push local scope any longer. + return; + } + + bool maxsmt::get_assignment(unsigned idx) const { + if (m_msolver) { + return m_msolver->get_assignment(idx); + } + else { + return true; + } + } + + rational maxsmt::get_lower() const { + rational r = m_lower; + if (m_msolver) { + rational q = m_msolver->get_lower(); + if (q > r) r = q; + } + return m_adjust_value(r); + } + + rational maxsmt::get_upper() const { + rational r = m_upper; + if (m_msolver) { + rational q = m_msolver->get_upper(); + if (q < r) r = q; + } + return m_adjust_value(r); + } + + void maxsmt::update_lower(rational const& r) { + m_lower = r; + } + + void maxsmt::update_upper(rational const& r) { + m_upper = r; + } + + void maxsmt::get_model(model_ref& mdl) { + mdl = m_model.get(); + } + + void maxsmt::commit_assignment() { + if (m_msolver) { + m_msolver->commit_assignment(); + } + } + + void maxsmt::add(expr* f, rational const& w) { + TRACE("opt", tout << mk_pp(f, m) << " weight: " << w << "\n";); + SASSERT(m.is_bool(f)); + SASSERT(w.is_pos()); + m_soft_constraints.push_back(f); + m_weights.push_back(w); + m_upper += w; + } + + void maxsmt::display_answer(std::ostream& out) const { + for (unsigned i = 0; i < m_soft_constraints.size(); ++i) { + out << mk_pp(m_soft_constraints[i], m) + << (get_assignment(i)?" |-> true\n":" |-> false\n"); + } + } + + void maxsmt::set_cancel(bool f) { + m_cancel = f; + + if (m_msolver) { + m_msolver->set_cancel(f); + } + } + + bool maxsmt::is_maxsat_problem(vector const& ws) const { + for (unsigned i = 0; i < ws.size(); ++i) { + if (!ws[i].is_one()) { + return false; + } + } + return true; + } + + void maxsmt::updt_params(params_ref& p) { + m_params.append(p); + if (m_msolver) { + m_msolver->updt_params(p); + } + } + + void maxsmt::collect_statistics(statistics& st) const { + if (m_msolver) { + m_msolver->collect_statistics(st); + } + } + + solver& maxsmt::s() { + return m_c.get_solver(); + } + + +}; diff --git a/src/opt/maxsmt.h b/src/opt/maxsmt.h new file mode 100644 index 000000000..356a2d50b --- /dev/null +++ b/src/opt/maxsmt.h @@ -0,0 +1,156 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + maxsmt.h + +Abstract: + + MaxSMT optimization context. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-7 + +Notes: + +--*/ +#ifndef _OPT_MAXSMT_H_ +#define _OPT_MAXSMT_H_ + +#include"ast.h" +#include"params.h" +#include"solver.h" +#include"filter_model_converter.h" +#include"statistics.h" +#include"smt_context.h" +#include"smt_theory.h" +#include"theory_wmaxsat.h" +#include"opt_solver.h" + +namespace opt { + + typedef vector const weights_t; + + class context; + + class maxsmt_solver { + protected: + adjust_value m_adjust_value; + public: + virtual ~maxsmt_solver() {} + virtual lbool operator()() = 0; + virtual rational get_lower() const = 0; + virtual rational get_upper() const = 0; + virtual bool get_assignment(unsigned index) const = 0; + virtual void set_cancel(bool f) = 0; + virtual void collect_statistics(statistics& st) const = 0; + virtual void get_model(model_ref& mdl) = 0; + virtual void updt_params(params_ref& p) = 0; + void set_adjust_value(adjust_value& adj) { m_adjust_value = adj; } + + }; + + // --------------------------------------------- + // base class with common utilities used + // by maxsmt solvers + // + class maxsmt_solver_base : public maxsmt_solver { + protected: + ast_manager& m; + context& m_c; + volatile bool m_cancel; + const expr_ref_vector m_soft; + vector m_weights; + expr_ref_vector m_assertions; + rational m_lower; + rational m_upper; + model_ref m_model; + svector m_assignment; // truth assignment to soft constraints + params_ref m_params; // config + + public: + maxsmt_solver_base(context& c, weights_t& ws, expr_ref_vector const& soft); + + virtual ~maxsmt_solver_base() {} + virtual rational get_lower() const { return m_lower; } + virtual rational get_upper() const { return m_upper; } + virtual bool get_assignment(unsigned index) const { return m_assignment[index]; } + virtual void set_cancel(bool f) { m_cancel = f; if (f) s().cancel(); else s().reset_cancel(); } + virtual void collect_statistics(statistics& st) const { } + virtual void get_model(model_ref& mdl) { mdl = m_model.get(); } + virtual void commit_assignment(); + void set_model() { s().get_model(m_model); } + virtual void updt_params(params_ref& p); + solver& s(); + void init(); + void set_mus(bool f); + app* mk_fresh_bool(char const* name); + + class smt::theory_wmaxsat* get_wmax_theory() const; + smt::theory_wmaxsat* ensure_wmax_theory(); + class scoped_ensure_theory { + smt::theory_wmaxsat* m_wth; + public: + scoped_ensure_theory(maxsmt_solver_base& s); + ~scoped_ensure_theory(); + smt::theory_wmaxsat& operator()(); + }; + + + protected: + void enable_sls(expr_ref_vector const& soft, weights_t& ws); + void set_enable_sls(bool f); + void set_soft_assumptions(); + void trace_bounds(char const* solver); + + }; + + /** + Takes solver with hard constraints added. + Returns modified soft constraints that are maximal assignments. + */ + + class maxsmt { + ast_manager& m; + context& m_c; + scoped_ptr m_msolver; + volatile bool m_cancel; + expr_ref_vector m_soft_constraints; + expr_ref_vector m_answer; + vector m_weights; + rational m_lower; + rational m_upper; + adjust_value m_adjust_value; + model_ref m_model; + params_ref m_params; + public: + maxsmt(context& c); + lbool operator()(); + void set_cancel(bool f); + void updt_params(params_ref& p); + void add(expr* f, rational const& w); + void set_adjust_value(adjust_value& adj) { m_adjust_value = adj; } + unsigned size() const { return m_soft_constraints.size(); } + expr* operator[](unsigned idx) const { return m_soft_constraints[idx]; } + rational weight(unsigned idx) const { return m_weights[idx]; } + void commit_assignment(); + rational get_value() const; + rational get_lower() const; + rational get_upper() const; + void update_lower(rational const& r); + void update_upper(rational const& r); + void get_model(model_ref& mdl); + bool get_assignment(unsigned index) const; + void display_answer(std::ostream& out) const; + void collect_statistics(statistics& st) const; + private: + bool is_maxsat_problem(weights_t& ws) const; + void verify_assignment(); + solver& s(); + }; + +}; + +#endif diff --git a/src/opt/mss.cpp b/src/opt/mss.cpp new file mode 100644 index 000000000..9d44180a6 --- /dev/null +++ b/src/opt/mss.cpp @@ -0,0 +1,288 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + mss.cpp + +Abstract: + + MSS/MCS extraction. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-2-8 + +Notes: + + +--*/ + +#include "solver.h" +#include "mss.h" +#include "ast_pp.h" +#include "model_smt2_pp.h" + +namespace opt { + + + mss::mss(solver& s, ast_manager& m): m_s(s), m(m), m_cancel(false) { + } + + mss::~mss() { + } + + bool mss::check_result() { + lbool is_sat = m_s.check_sat(m_mss.size(), m_mss.c_ptr()); + if (is_sat == l_undef) return true; + SASSERT(m_mss.empty() || is_sat == l_true); + if (is_sat == l_false) return false; + expr_set::iterator it = m_mcs.begin(), end = m_mcs.end(); + for (; it != end; ++it) { + m_mss.push_back(*it); + is_sat = m_s.check_sat(m_mss.size(), m_mss.c_ptr()); + m_mss.pop_back(); + if (is_sat == l_undef) return true; + SASSERT(is_sat == l_false); + if (is_sat == l_true) return false; + } + return true; + } + + void mss::initialize(exprs& literals) { + expr* n; + expr_set lits, core_lits; + for (unsigned i = 0; i < literals.size(); ++i) { + n = literals[i]; + lits.insert(n); + m.is_not(n, n); + if (!is_uninterp_const(n)) { + throw default_exception("arguments have to be uninterpreted literals"); + } + } + exprs rest_core; + expr_ref tmp(m); + // + // the last core is a dummy core. It contains literals that + // did not occur in previous cores and did not evaluate to true + // in the current model. + // + for (unsigned i = 0; i < m_cores.size(); ++i) { + exprs const& core = m_cores[i]; + for (unsigned j = 0; j < core.size(); ++j) { + expr* n = core[j]; + if (!core_lits.contains(n)) { + core_lits.insert(n); + VERIFY(m_model->eval(n, tmp)); + if (m.is_true(tmp)) { + add_mss(n); + } + else { + m_todo.push_back(n); + } + } + } + } + for (unsigned i = 0; i < literals.size(); ++i) { + expr* n = literals[i]; + if (!core_lits.contains(n)) { + VERIFY(m_model->eval(n, tmp)); + if (m.is_true(tmp)) { + m_mss.push_back(n); + } + else { + rest_core.push_back(n); + core_lits.insert(n); + m_todo.push_back(n); + } + } + } + m_cores.push_back(rest_core); + } + + void mss::add_mss(expr* n) { + if (!m_mss_set.contains(n)) { + m_mss_set.insert(n); + m_mss.push_back(n); + } + } + + void mss::update_core(exprs& core) { + unsigned j = 0; + for (unsigned i = 0; i < core.size(); ++i) { + expr* n = core[i]; + if (!m_mss_set.contains(n)) { + if (i != j) { + core[j] = core[i]; + } + ++j; + } + } + core.resize(j); + } + + void mss::update_mss() { + expr_ref tmp(m); + unsigned j = 0; + for (unsigned i = 0; i < m_todo.size(); ++i) { + expr* n = m_todo[i]; + SASSERT(!m_mss_set.contains(n)); + if (m_mcs.contains(n)) { + continue; // remove from cores. + } + VERIFY(m_model->eval(n, tmp)); + if (m.is_true(tmp)) { + add_mss(n); + } + else { + if (j != i) { + m_todo[j] = m_todo[i]; + } + ++j; + } + } + m_todo.resize(j); + } + + lbool mss::operator()(model* initial_model, vector const& _cores, exprs& literals, exprs& mcs) { + m_mss.reset(); + m_todo.reset(); + m_model = initial_model; + m_cores.reset(); + SASSERT(m_model); + m_cores.append(_cores); + initialize(literals); + TRACE("opt", + display_vec(tout << "lits: ", literals.size(), literals.c_ptr()); + display(tout);); + lbool is_sat = l_true; + for (unsigned i = 0; is_sat == l_true && i < m_cores.size(); ++i) { + bool has_mcs = false; + bool is_last = i + 1 < m_cores.size(); + SASSERT(check_invariant()); + update_core(m_cores[i]); // remove members of mss + is_sat = process_core(1, m_cores[i], has_mcs, is_last); + } + if (is_sat == l_true) { + SASSERT(check_invariant()); + TRACE("opt", display(tout);); + literals.reset(); + literals.append(m_mss); + mcs.reset(); + expr_set::iterator it = m_mcs.begin(), end = m_mcs.end(); + for (; it != end; ++it) { + mcs.push_back(*it); + } + SASSERT(check_result()); + } + m_mcs.reset(); + m_mss_set.reset(); + IF_VERBOSE(2, display_vec(verbose_stream() << "mcs: ", mcs.size(), mcs.c_ptr());); + return is_sat; + } + + + // + // at least one literal in core is false in current model. + // pick literals in core that are not yet in mss. + // + lbool mss::process_core(unsigned sz, exprs& core, bool& has_mcs, bool is_last) { + SASSERT(sz > 0); + if (core.empty()) { + return l_true; + } + if (m_cancel) { + return l_undef; + } + if (sz == 1 && core.size() == 1 && is_last && !has_mcs) { + // there has to be at least one false + // literal in the core. + TRACE("opt", tout << "mcs: " << mk_pp(core[0], m) << "\n";); + m_mcs.insert(core[0]); + return l_true; + } + sz = std::min(sz, core.size()); + TRACE("opt", display_vec(tout << "process (total " << core.size() << ") :", sz, core.c_ptr());); + unsigned sz_save = m_mss.size(); + m_mss.append(sz, core.c_ptr()); + lbool is_sat = m_s.check_sat(m_mss.size(), m_mss.c_ptr()); + IF_VERBOSE(3, display_vec(verbose_stream() << "mss: ", m_mss.size(), m_mss.c_ptr());); + m_mss.resize(sz_save); + switch (is_sat) { + case l_true: + m_s.get_model(m_model); + update_mss(); + DEBUG_CODE( + for (unsigned i = 0; i < sz; ++i) { + SASSERT(m_mss_set.contains(core[i])); + }); + update_core(core); + return process_core(2*sz, core, has_mcs, is_last); + case l_false: + if (sz == 1) { + has_mcs = true; + m_mcs.insert(core[0]); + core[0] = core.back(); + core.pop_back(); + } + else { + exprs core2; + core2.append(core.size()-sz, core.c_ptr()+sz); + core.resize(sz); + is_sat = process_core(sz, core2, has_mcs, false); + if (is_sat != l_true) { + return is_sat; + } + update_core(core); + } + return process_core(1, core, has_mcs, is_last); + case l_undef: + return l_undef; + } + + return l_true; + } + + void mss::display_vec(std::ostream& out, unsigned sz, expr* const* args) const { + for (unsigned i = 0; i < sz; ++i) { + out << mk_pp(args[i], m) << " "; + } + out << "\n"; + } + + void mss::display(std::ostream& out) const { + for (unsigned i = 0; i < m_cores.size(); ++i) { + display_vec(out << "core: ", m_cores[i].size(), m_cores[i].c_ptr()); + } + expr_set::iterator it = m_mcs.begin(), end = m_mcs.end(); + out << "mcs:\n"; + for (; it != end; ++it) { + out << mk_pp(*it, m) << "\n"; + } + out << "\n"; + out << "mss:\n"; + for (unsigned i = 0; i < m_mss.size(); ++i) { + out << mk_pp(m_mss[i], m) << "\n"; + } + out << "\n"; + if (m_model) { + model_smt2_pp(out, m, *(m_model.get()), 0); + } + } + + bool mss::check_invariant() const { + if (!m_model) return true; + expr_ref tmp(m); + for (unsigned i = 0; i < m_mss.size(); ++i) { + expr* n = m_mss[i]; + VERIFY(m_model->eval(n, tmp)); + CTRACE("opt", !m.is_true(tmp), tout << mk_pp(n, m) << " |-> " << mk_pp(tmp, m) << "\n";); + SASSERT(!m.is_false(tmp)); + } + return true; + } +} + + + + diff --git a/src/opt/mss.h b/src/opt/mss.h new file mode 100644 index 000000000..02d218e4d --- /dev/null +++ b/src/opt/mss.h @@ -0,0 +1,59 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + mss.h + +Abstract: + + Maximal satisfying subset/minimal correction sets: MSS/MCS + +Author: + + Nikolaj Bjorner (nbjorner) 2014-2-8 + +Notes: + +--*/ +#ifndef _MSS_H_ +#define _MSS_H_ + +namespace opt { + class mss { + solver& m_s; + ast_manager& m; + volatile bool m_cancel; + typedef ptr_vector exprs; + typedef obj_hashtable expr_set; + exprs m_mss; + expr_set m_mcs; + expr_set m_mss_set; + vector m_cores; + exprs m_todo; + model_ref m_model; + public: + mss(solver& s, ast_manager& m); + ~mss(); + + lbool operator()(model* initial_model, vector const& cores, exprs& literals, exprs& mcs); + + void set_cancel(bool f) { m_cancel = f; } + + void get_model(model_ref& mdl) { mdl = m_model; } + + private: + void initialize(exprs& literals); + bool check_result(); + void add_mss(expr* n); + void update_mss(); + void update_core(exprs& core); + lbool process_core(unsigned sz, exprs& core, bool& has_mcs, bool is_last); + void display(std::ostream& out) const; + void display_vec(std::ostream& out, unsigned sz, expr* const* args) const; + bool check_invariant() const; + }; + +}; + +#endif diff --git a/src/opt/mus.cpp b/src/opt/mus.cpp new file mode 100644 index 000000000..0cf9786b2 --- /dev/null +++ b/src/opt/mus.cpp @@ -0,0 +1,213 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + mus.cpp + +Abstract: + + MUS extraction. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-20-7 + +Notes: + + +--*/ + +#include "solver.h" +#include "smt_literal.h" +#include "mus.h" +#include "ast_pp.h" +#include "ast_util.h" + +using namespace opt; + +// + +struct mus::imp { + solver& m_s; + ast_manager& m; + expr_ref_vector m_cls2expr; + obj_map m_expr2cls; + volatile bool m_cancel; + model_ref m_model; + expr_ref_vector m_soft; + vector m_weights; + rational m_weight; + + imp(solver& s, ast_manager& m): + m_s(s), m(m), m_cls2expr(m), m_cancel(false), m_soft(m) + {} + + void reset() { + m_cls2expr.reset(); + m_expr2cls.reset(); + } + + void set_cancel(bool f) { + m_cancel = f; + } + + + unsigned add_soft(expr* cls) { + SASSERT(is_uninterp_const(cls) || m.is_not(cls) && is_uninterp_const(to_app(cls)->get_arg(0))); + unsigned idx = m_cls2expr.size(); + m_expr2cls.insert(cls, idx); + m_cls2expr.push_back(cls); + TRACE("opt", tout << idx << ": " << mk_pp(cls, m) << "\n";); + return idx; + } + + lbool get_mus(unsigned_vector& mus) { + // SASSERT: mus does not have duplicates. + m_model.reset(); + unsigned_vector core; + for (unsigned i = 0; i < m_cls2expr.size(); ++i) { + core.push_back(i); + } + if (core.size() == 1) { + mus.push_back(core.back()); + return l_true; + } + mus.reset(); + expr_ref_vector assumptions(m); + ptr_vector core_exprs; + while (!core.empty()) { + IF_VERBOSE(1, verbose_stream() << "(opt.mus reducing core: " << core.size() << " new core: " << mus.size() << ")\n";); + unsigned cls_id = core.back(); + TRACE("opt", + display_vec(tout << "core: ", core); + display_vec(tout << "mus: ", mus); + ); + core.pop_back(); + expr* cls = m_cls2expr[cls_id].get(); + expr_ref not_cls(m); + not_cls = mk_not(m, cls); + unsigned sz = assumptions.size(); + assumptions.push_back(not_cls); + add_core(core, assumptions); + lbool is_sat = m_s.check_sat(assumptions.size(), assumptions.c_ptr()); + assumptions.resize(sz); + switch (is_sat) { + case l_undef: + return is_sat; + case l_true: + assumptions.push_back(cls); + mus.push_back(cls_id); + update_model(); + break; + default: + core_exprs.reset(); + m_s.get_unsat_core(core_exprs); + if (!core_exprs.contains(not_cls)) { + // core := core_exprs \ mus + core.reset(); + for (unsigned i = 0; i < core_exprs.size(); ++i) { + cls = core_exprs[i]; + cls_id = m_expr2cls.find(cls); + if (!mus.contains(cls_id)) { + core.push_back(cls_id); + } + } + } + break; + } + } +#if 0 + DEBUG_CODE( + assumptions.reset(); + for (unsigned i = 0; i < mus.size(); ++i) { + assumptions.push_back(m_cls2expr[mus[i]].get()); + } + lbool is_sat = m_s.check_sat(assumptions.size(), assumptions.c_ptr()); + SASSERT(is_sat == l_false); + ); +#endif + return l_true; + } + + void add_core(unsigned_vector const& core, expr_ref_vector& assumptions) { + for (unsigned i = 0; i < core.size(); ++i) { + assumptions.push_back(m_cls2expr[core[i]].get()); + } + } + + template + void display_vec(std::ostream& out, T const& v) const { + for (unsigned i = 0; i < v.size(); ++i) { + out << v[i] << " "; + } + out << "\n"; + } + + void set_soft(unsigned sz, expr* const* soft, rational const* weights) { + m_model.reset(); + m_weight.reset(); + m_soft.append(sz, soft); + m_weights.append(sz, weights); + for (unsigned i = 0; i < sz; ++i) { + m_weight += weights[i]; + } + } + + void update_model() { + if (m_soft.empty()) return; + model_ref mdl; + expr_ref tmp(m); + m_s.get_model(mdl); + rational w; + for (unsigned i = 0; i < m_soft.size(); ++i) { + mdl->eval(m_soft[i].get(), tmp); + if (!m.is_true(tmp)) { + w += m_weights[i]; + } + } + if (w < m_weight || !m_model.get()) { + m_model = mdl; + m_weight = w; + } + } + + rational get_best_model(model_ref& mdl) { + mdl = m_model; + return m_weight; + } + + +}; + +mus::mus(solver& s, ast_manager& m) { + m_imp = alloc(imp, s, m); +} + +mus::~mus() { + dealloc(m_imp); +} + +unsigned mus::add_soft(expr* cls) { + return m_imp->add_soft(cls); +} + +lbool mus::get_mus(unsigned_vector& mus) { + return m_imp->get_mus(mus); +} + +void mus::set_cancel(bool f) { + m_imp->set_cancel(f); +} + +void mus::reset() { + m_imp->reset(); +} + +void mus::set_soft(unsigned sz, expr* const* soft, rational const* weights) { + m_imp->set_soft(sz, soft, weights); +} + +rational mus::get_best_model(model_ref& mdl) { + return m_imp->get_best_model(mdl); +} diff --git a/src/opt/mus.h b/src/opt/mus.h new file mode 100644 index 000000000..12cd8b0b2 --- /dev/null +++ b/src/opt/mus.h @@ -0,0 +1,57 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + mus.h + +Abstract: + + Basic MUS extraction + +Author: + + Nikolaj Bjorner (nbjorner) 2014-20-7 + +Notes: + +--*/ +#ifndef _MUS_H_ +#define _MUS_H_ + +namespace opt { + class mus { + struct imp; + imp * m_imp; + public: + mus(solver& s, ast_manager& m); + ~mus(); + /** + Add soft constraint. + + Assume that the solver context enforces that + cls is equivalent to a disjunction of args. + Assume also that cls is a literal. + */ + unsigned add_soft(expr* cls); + + lbool get_mus(unsigned_vector& mus); + + void reset(); + + void set_cancel(bool f); + + /** + Instrument MUS extraction to also provide the minimal + penalty model, if any is found. + The minimal penalty model has the least weight for the + supplied soft constraints. + */ + void set_soft(unsigned sz, expr* const* soft, rational const* weights); + rational get_best_model(model_ref& mdl); + + }; + +}; + +#endif diff --git a/src/opt/opt_cmds.cpp b/src/opt/opt_cmds.cpp new file mode 100644 index 000000000..537f4bf22 --- /dev/null +++ b/src/opt/opt_cmds.cpp @@ -0,0 +1,345 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + opt_cmds.cpp + +Abstract: + Commands for optimization benchmarks + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-14 + +Notes: + + TODO: + + - Add appropriate statistics tracking to opt::context + + - Deal with push/pop (later) + +--*/ +#include "opt_cmds.h" +#include "cmd_context.h" +#include "ast_pp.h" +#include "opt_context.h" +#include "cancel_eh.h" +#include "scoped_ctrl_c.h" +#include "scoped_timer.h" +#include "parametric_cmd.h" +#include "opt_params.hpp" +#include "model_smt2_pp.h" + +static opt::context& get_opt(cmd_context& cmd) { + if (!cmd.get_opt()) { + cmd.set_opt(alloc(opt::context, cmd.m())); + } + return dynamic_cast(*cmd.get_opt()); +} + +class assert_weighted_cmd : public cmd { + unsigned m_idx; + expr* m_formula; + rational m_weight; + symbol m_id; + +public: + assert_weighted_cmd(): + cmd("assert-weighted"), + m_idx(0), + m_formula(0), + m_weight(0) + {} + + virtual ~assert_weighted_cmd() { + } + + virtual void reset(cmd_context & ctx) { + m_idx = 0; + m_formula = 0; + m_id = symbol::null; + } + + virtual char const * get_usage() const { return " "; } + virtual char const * get_descr(cmd_context & ctx) const { return "assert soft constraint with weight"; } + virtual unsigned get_arity() const { return VAR_ARITY; } + + // command invocation + virtual void prepare(cmd_context & ctx) {} + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { + switch(m_idx) { + case 0: return CPK_EXPR; + case 1: return CPK_NUMERAL; + default: return CPK_SYMBOL; + } + } + virtual void set_next_arg(cmd_context & ctx, rational const & val) { + SASSERT(m_idx == 1); + if (!val.is_pos()) { + throw cmd_exception("Invalid weight. Weights must be positive."); + } + m_weight = val; + ++m_idx; + } + + virtual void set_next_arg(cmd_context & ctx, expr * t) { + SASSERT(m_idx == 0); + if (!ctx.m().is_bool(t)) { + throw cmd_exception("Invalid type for expression. Expected Boolean type."); + } + m_formula = t; + ++m_idx; + } + + virtual void set_next_arg(cmd_context & ctx, symbol const& s) { + SASSERT(m_idx > 1); + m_id = s; + ++m_idx; + } + + virtual void failure_cleanup(cmd_context & ctx) { + reset(ctx); + } + + virtual void execute(cmd_context & ctx) { + get_opt(ctx).add_soft_constraint(m_formula, m_weight, m_id); + reset(ctx); + } + + virtual void finalize(cmd_context & ctx) { + } + +}; + + +class assert_soft_cmd : public parametric_cmd { + unsigned m_idx; + expr* m_formula; + +public: + assert_soft_cmd(): + parametric_cmd("assert-soft"), + m_idx(0), + m_formula(0) + {} + + virtual ~assert_soft_cmd() { + } + + virtual void reset(cmd_context & ctx) { + m_idx = 0; + m_formula = 0; + } + + virtual char const * get_usage() const { return " [:weight ] [:id ]"; } + virtual char const * get_main_descr() const { return "assert soft constraint with optional weight and identifier"; } + + // command invocation + virtual void prepare(cmd_context & ctx) { + reset(ctx); + } + + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { + if (m_idx == 0) return CPK_EXPR; + return parametric_cmd::next_arg_kind(ctx); + } + + virtual void init_pdescrs(cmd_context & ctx, param_descrs & p) { + p.insert("weight", CPK_NUMERAL, "(default: 1) penalty of not satisfying constraint."); + p.insert("dweight", CPK_DECIMAL, "(default: 1.0) penalty as double of not satisfying constraint."); + p.insert("id", CPK_SYMBOL, "(default: null) partition identifier for soft constraints."); + } + + virtual void set_next_arg(cmd_context & ctx, expr * t) { + SASSERT(m_idx == 0); + if (!ctx.m().is_bool(t)) { + throw cmd_exception("Invalid type for expression. Expected Boolean type."); + } + m_formula = t; + ++m_idx; + } + + virtual void failure_cleanup(cmd_context & ctx) { + reset(ctx); + } + + virtual void execute(cmd_context & ctx) { + symbol w("weight"); + rational weight = ps().get_rat(symbol("weight"), rational(0)); + if (weight.is_zero()) { + weight = ps().get_rat(symbol("dweight"), rational(0)); + } + if (weight.is_zero()) { + weight = rational::one(); + } + symbol id = ps().get_sym(symbol("id"), symbol::null); + get_opt(ctx).add_soft_constraint(m_formula, weight, id); + reset(ctx); + } + + virtual void finalize(cmd_context & ctx) { + } + +}; + +class min_maximize_cmd : public cmd { + bool m_is_max; + +public: + min_maximize_cmd(bool is_max): + cmd(is_max?"maximize":"minimize"), + m_is_max(is_max) + {} + + virtual void reset(cmd_context & ctx) { } + + virtual char const * get_usage() const { return ""; } + virtual char const * get_descr(cmd_context & ctx) const { return "check sat modulo objective function";} + virtual unsigned get_arity() const { return 1; } + + virtual void prepare(cmd_context & ctx) {} + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_EXPR; } + + virtual void set_next_arg(cmd_context & ctx, expr * t) { + if (!is_app(t)) { + throw cmd_exception("malformed objective term: it cannot be a quantifier or bound variable"); + } + get_opt(ctx).add_objective(to_app(t), m_is_max); + } + + virtual void failure_cleanup(cmd_context & ctx) { + reset(ctx); + } + + virtual void execute(cmd_context & ctx) { + } +}; + +class optimize_cmd : public parametric_cmd { +public: + optimize_cmd(): + parametric_cmd("optimize") + {} + + virtual ~optimize_cmd() { + } + + virtual void init_pdescrs(cmd_context & ctx, param_descrs & p) { + insert_timeout(p); + insert_max_memory(p); + p.insert("print_statistics", CPK_BOOL, "(default: false) print statistics."); + opt::context::collect_param_descrs(p); + } + + virtual char const * get_main_descr() const { return "check sat modulo objective function";} + virtual char const * get_usage() const { return "( )*"; } + virtual void prepare(cmd_context & ctx) { + parametric_cmd::prepare(ctx); + } + virtual void failure_cleanup(cmd_context & ctx) { + reset(ctx); + } + + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { + return parametric_cmd::next_arg_kind(ctx); + } + + + virtual void execute(cmd_context & ctx) { + params_ref p = ctx.params().merge_default_params(ps()); + opt::context& opt = get_opt(ctx); + opt.updt_params(p); + unsigned timeout = p.get_uint("timeout", UINT_MAX); + + ptr_vector::const_iterator it = ctx.begin_assertions(); + ptr_vector::const_iterator end = ctx.end_assertions(); + for (; it != end; ++it) { + opt.add_hard_constraint(*it); + } + lbool r = l_undef; + cancel_eh eh(opt); + { + scoped_ctrl_c ctrlc(eh); + scoped_timer timer(timeout, &eh); + cmd_context::scoped_watch sw(ctx); + try { + r = opt.optimize(); + if (r == l_true && opt.is_pareto()) { + while (r == l_true) { + display_result(ctx); + ctx.regular_stream() << "\n"; + r = opt.optimize(); + } + if (p.get_bool("print_statistics", false)) { + display_statistics(ctx); + } + return; + } + } + catch (z3_error& ex) { + ctx.regular_stream() << "(error: " << ex.msg() << "\")" << std::endl; + } + catch (z3_exception& ex) { + ctx.regular_stream() << "(error: " << ex.msg() << "\")" << std::endl; + } + } + switch(r) { + case l_true: { + ctx.regular_stream() << "sat\n"; + display_result(ctx); + break; + } + case l_false: + ctx.regular_stream() << "unsat\n"; + break; + case l_undef: + ctx.regular_stream() << "unknown\n"; + display_result(ctx); + break; + } + if (p.get_bool("print_statistics", false)) { + display_statistics(ctx); + } + } + + void display_result(cmd_context & ctx) { + params_ref p = ctx.params().merge_default_params(ps()); + opt::context& opt = get_opt(ctx); + opt.display_assignment(ctx.regular_stream()); + opt_params optp(p); + if (optp.print_model()) { + model_ref mdl; + opt.get_model(mdl); + if (mdl) { + ctx.regular_stream() << "(model " << std::endl; + model_smt2_pp(ctx.regular_stream(), ctx, *(mdl.get()), 2); + ctx.regular_stream() << ")" << std::endl; + } + } + } +private: + + void display_statistics(cmd_context& ctx) { + statistics stats; + unsigned long long max_mem = memory::get_max_used_memory(); + unsigned long long mem = memory::get_allocation_size(); + stats.update("time", ctx.get_seconds()); + stats.update("memory", static_cast(mem)/static_cast(1024*1024)); + stats.update("max memory", static_cast(max_mem)/static_cast(1024*1024)); + get_opt(ctx).collect_statistics(stats); + stats.display_smt2(ctx.regular_stream()); + } +}; + + + +void install_opt_cmds(cmd_context & ctx) { + ctx.insert(alloc(assert_weighted_cmd)); + ctx.insert(alloc(assert_soft_cmd)); + ctx.insert(alloc(min_maximize_cmd, true)); + ctx.insert(alloc(min_maximize_cmd, false)); + ctx.insert(alloc(optimize_cmd)); +} + diff --git a/src/opt/opt_cmds.h b/src/opt/opt_cmds.h new file mode 100644 index 000000000..048871987 --- /dev/null +++ b/src/opt/opt_cmds.h @@ -0,0 +1,28 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + opt_cmds.h + +Abstract: + Commands for optimization benchmarks + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-14 + +Notes: + +--*/ +#ifndef _OPT_CMDS_H_ +#define _OPT_CMDS_H_ + +#include "ast.h" + +class cmd_context; + +void install_opt_cmds(cmd_context & ctx); + + +#endif diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp new file mode 100644 index 000000000..5971cceb7 --- /dev/null +++ b/src/opt/opt_context.cpp @@ -0,0 +1,1329 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + opt_context.cpp + +Abstract: + + Facility for running optimization problem. + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-16 + +Notes: + +--*/ + +#include "opt_context.h" +#include "ast_pp.h" +#include "opt_solver.h" +#include "opt_params.hpp" +#include "for_each_expr.h" +#include "goal.h" +#include "tactic.h" +#include "lia2card_tactic.h" +#include "elim01_tactic.h" +#include "solve_eqs_tactic.h" +#include "simplify_tactic.h" +#include "propagate_values_tactic.h" +#include "solve_eqs_tactic.h" +#include "elim_uncnstr_tactic.h" +#include "tactical.h" +#include "model_smt2_pp.h" +#include "card2bv_tactic.h" +#include "nnf_tactic.h" +#include "inc_sat_solver.h" +#include "bv_decl_plugin.h" +#include "pb_decl_plugin.h" +#include "ast_smt_pp.h" +#include "filter_model_converter.h" + +namespace opt { + + void context::scoped_state::push() { + m_hard_lim.push_back(m_hard.size()); + m_objectives_lim.push_back(m_objectives.size()); + m_objectives_term_trail_lim.push_back(m_objectives_term_trail.size()); + } + + void context::scoped_state::pop() { + m_hard.resize(m_hard_lim.back()); + unsigned k = m_objectives_term_trail_lim.back(); + while (m_objectives_term_trail.size() > k) { + unsigned idx = m_objectives_term_trail.back(); + m_objectives[idx].m_terms.pop_back(); + m_objectives[idx].m_weights.pop_back(); + m_objectives_term_trail.pop_back(); + } + m_objectives_term_trail_lim.pop_back(); + k = m_objectives_lim.back(); + while (m_objectives.size() > k) { + objective& obj = m_objectives.back(); + if (obj.m_type == O_MAXSMT) { + m_indices.erase(obj.m_id); + } + m_objectives.pop_back(); + } + m_objectives_lim.pop_back(); + m_hard_lim.pop_back(); + } + + void context::scoped_state::add(expr* hard) { + m_hard.push_back(hard); + } + + void context::scoped_state::set(ptr_vector & hard) { + m_hard.reset(); + m_hard.append(hard.size(), hard.c_ptr()); + } + + unsigned context::scoped_state::add(expr* f, rational const& w, symbol const& id) { + if (w.is_neg()) { + throw default_exception("Negative weight supplied. Weight should be positive"); + } + if (w.is_zero()) { + throw default_exception("Zero weight supplied. Weight should be positive"); + } + if (!m.is_bool(f)) { + throw default_exception("Soft constraint should be Boolean"); + } + if (!m_indices.contains(id)) { + m_objectives.push_back(objective(m, id)); + m_indices.insert(id, m_objectives.size() - 1); + } + SASSERT(m_indices.contains(id)); + unsigned idx = m_indices[id]; + m_objectives[idx].m_terms.push_back(f); + m_objectives[idx].m_weights.push_back(w); + m_objectives_term_trail.push_back(idx); + return idx; + } + + unsigned context::scoped_state::add(app* t, bool is_max) { + app_ref tr(t, m); + if (!m_bv.is_bv(t) && !m_arith.is_int_real(t)) { + throw default_exception("Objective must be bit-vector, integer or real"); + } + unsigned index = m_objectives.size(); + m_objectives.push_back(objective(is_max, tr, index)); + return index; + } + + context::context(ast_manager& m): + m(m), + m_arith(m), + m_bv(m), + m_hard_constraints(m), + m_solver(0), + m_optsmt(m), + m_scoped_state(m), + m_fm(m), + m_objective_refs(m), + m_enable_sat(false), + m_enable_sls(false), + m_is_clausal(false), + m_pp_neat(false) + { + params_ref p; + p.set_bool("model", true); + p.set_bool("unsat_core", true); + updt_params(p); + } + + context::~context() { + reset_maxsmts(); + } + + void context::reset_maxsmts() { + map_t::iterator it = m_maxsmts.begin(), end = m_maxsmts.end(); + for (; it != end; ++it) { + dealloc(it->m_value); + } + m_maxsmts.reset(); + } + + void context::push() { + m_scoped_state.push(); + } + + void context::pop(unsigned n) { + for (unsigned i = 0; i < n; ++i) { + m_scoped_state.pop(); + } + m_model.reset(); + reset_maxsmts(); + m_optsmt.reset(); + m_hard_constraints.reset(); + } + + void context::set_hard_constraints(ptr_vector& fmls) { + m_scoped_state.set(fmls); + m_model.reset(); + } + + void context::add_hard_constraint(expr* f) { + m_scoped_state.add(f); + m_model.reset(); + } + + unsigned context::add_soft_constraint(expr* f, rational const& w, symbol const& id) { + m_model.reset(); + return m_scoped_state.add(f, w, id); + } + + unsigned context::add_objective(app* t, bool is_max) { + m_model.reset(); + return m_scoped_state.add(t, is_max); + } + + void context::import_scoped_state() { + m_optsmt.reset(); + reset_maxsmts(); + m_objectives.reset(); + m_hard_constraints.reset(); + scoped_state& s = m_scoped_state; + for (unsigned i = 0; i < s.m_objectives.size(); ++i) { + objective& obj = s.m_objectives[i]; + m_objectives.push_back(obj); + if (obj.m_type == O_MAXSMT) { + add_maxsmt(obj.m_id); + } + } + m_hard_constraints.append(s.m_hard); + } + + lbool context::optimize() { + if (m_pareto) { + return execute_pareto(); + } + init_solver(); + import_scoped_state(); + normalize(); + internalize(); + update_solver(); + solver& s = get_solver(); + for (unsigned i = 0; i < m_hard_constraints.size(); ++i) { + TRACE("opt", tout << "Hard constraint: " << mk_ismt2_pp(m_hard_constraints[i].get(), m) << std::endl;); + s.assert_expr(m_hard_constraints[i].get()); + } + + IF_VERBOSE(1, verbose_stream() << "(optimize:check-sat)\n";); + lbool is_sat = s.check_sat(0,0); + TRACE("opt", tout << "initial search result: " << is_sat << "\n";); + if (is_sat != l_true) { + m_model = 0; + return is_sat; + } + IF_VERBOSE(1, verbose_stream() << "(optimize:sat)\n";); + s.get_model(m_model); + TRACE("opt", model_smt2_pp(tout, m, *m_model, 0);); + m_optsmt.setup(*m_opt_solver.get()); + update_lower(); + switch (m_objectives.size()) { + case 0: + return is_sat; + case 1: + return execute(m_objectives[0], true, false); + default: { + opt_params optp(m_params); + symbol pri = optp.priority(); + if (pri == symbol("pareto")) { + return execute_pareto(); + } + else if (pri == symbol("box")) { + return execute_box(); + } + else { + return execute_lex(); + } + } + } + } + + void context::get_base_model(model_ref& mdl) { + mdl = m_model; + } + + void context::fix_model(model_ref& mdl) { + if (mdl) { + if (m_model_converter) { + (*m_model_converter)(mdl, 0); + } + m_fm(mdl, 0); + } + } + + void context::set_model(model_ref& mdl) { + m_model = mdl; + fix_model(mdl); + } + + void context::get_model(model_ref& mdl) { + mdl = m_model; + fix_model(mdl); + } + + lbool context::execute_min_max(unsigned index, bool committed, bool scoped, bool is_max) { + if (scoped) get_solver().push(); + lbool result = m_optsmt.lex(index, is_max); + if (result == l_true) m_optsmt.get_model(m_model); + if (scoped) get_solver().pop(1); + if (result == l_true && committed) m_optsmt.commit_assignment(index); + return result; + } + + lbool context::execute_maxsat(symbol const& id, bool committed, bool scoped) { + model_ref tmp; + maxsmt& ms = *m_maxsmts.find(id); + if (scoped) get_solver().push(); + lbool result = ms(); + if (result != l_false && (ms.get_model(tmp), tmp.get())) ms.get_model(m_model); + if (scoped) get_solver().pop(1); + if (result == l_true && committed) ms.commit_assignment(); + return result; + } + + lbool context::execute(objective const& obj, bool committed, bool scoped) { + switch(obj.m_type) { + case O_MAXIMIZE: return execute_min_max(obj.m_index, committed, scoped, true); + case O_MINIMIZE: return execute_min_max(obj.m_index, committed, scoped, false); + case O_MAXSMT: return execute_maxsat(obj.m_id, committed, scoped); + default: UNREACHABLE(); return l_undef; + } + } + + lbool context::execute_lex() { + lbool r = l_true; + IF_VERBOSE(1, verbose_stream() << "(optsmt:lex)\n";); + for (unsigned i = 0; r == l_true && i < m_objectives.size(); ++i) { + bool is_last = i + 1 == m_objectives.size(); + r = execute(m_objectives[i], i + 1 < m_objectives.size(), !is_last); + if (r == l_true && !get_lower_as_num(i).is_finite()) { + return r; + } + if (r == l_true && i + 1 < m_objectives.size()) { + update_lower(); + } + } + DEBUG_CODE(if (r == l_true) validate_lex();); + return r; + } + + lbool context::execute_box() { + lbool r = m_optsmt.box(); + for (unsigned i = 0; r == l_true && i < m_objectives.size(); ++i) { + objective const& obj = m_objectives[i]; + if (obj.m_type == O_MAXSMT) { + solver::scoped_push _sp(get_solver()); + r = execute(obj, false, false); + } + } + return r; + } + + + expr_ref context::mk_le(unsigned i, model_ref& mdl) { + objective const& obj = m_objectives[i]; + expr_ref val(m), result(m), term(m); + mk_term_val(mdl, obj, term, val); + switch (obj.m_type) { + case O_MINIMIZE: + result = mk_ge(term, val); + break; + case O_MAXSMT: + result = mk_ge(term, val); + break; + case O_MAXIMIZE: + result = mk_ge(val, term); + break; + } + return result; + } + + expr_ref context::mk_ge(unsigned i, model_ref& mdl) { + objective const& obj = m_objectives[i]; + expr_ref val(m), result(m), term(m); + mk_term_val(mdl, obj, term, val); + switch (obj.m_type) { + case O_MINIMIZE: + result = mk_ge(val, term); + break; + case O_MAXSMT: + result = mk_ge(val, term); + break; + case O_MAXIMIZE: + result = mk_ge(term, val); + break; + } + return result; + } + + expr_ref context::mk_gt(unsigned i, model_ref& mdl) { + expr_ref result = mk_le(i, mdl); + result = m.mk_not(result); + return result; + } + + void context::mk_term_val(model_ref& mdl, objective const& obj, expr_ref& term, expr_ref& val) { + rational r; + switch (obj.m_type) { + case O_MINIMIZE: + case O_MAXIMIZE: + term = obj.m_term; + break; + case O_MAXSMT: { + unsigned sz = obj.m_terms.size(); + expr_ref_vector sum(m); + expr_ref zero(m); + zero = m_arith.mk_numeral(rational(0), false); + for (unsigned i = 0; i < sz; ++i) { + expr* t = obj.m_terms[i]; + rational const& w = obj.m_weights[i]; + sum.push_back(m.mk_ite(t, m_arith.mk_numeral(w, false), zero)); + } + if (sum.empty()) { + term = zero; + } + else { + term = m_arith.mk_add(sum.size(), sum.c_ptr()); + } + break; + } + } + TRACE("opt", + model_smt2_pp(tout << "Model:\n", m, *mdl, 0); + mdl->eval(term, val); tout << term << " " << val << "\n";); + VERIFY(mdl->eval(term, val) && is_numeral(val, r)); + } + + + expr_ref context::mk_ge(expr* t, expr* s) { + expr_ref result(m); + if (m_bv.is_bv(t)) { + result = m_bv.mk_ule(s, t); + } + else { + result = m_arith.mk_ge(t, s); + } + return result; + } + + void context::yield() { + m_pareto->get_model(m_model); + update_bound(true); + update_bound(false); + } + + lbool context::execute_pareto() { + + if (!m_pareto) { + set_pareto(alloc(gia_pareto, m, *this, m_solver.get(), m_params)); + } + lbool is_sat = (*(m_pareto.get()))(); + if (is_sat != l_true) { + set_pareto(0); + } + if (is_sat == l_true) { + yield(); + } + return is_sat; + } + + void context::display_bounds(std::ostream& out, bounds_t const& b) const { + for (unsigned i = 0; i < m_objectives.size(); ++i) { + objective const& obj = m_objectives[i]; + display_objective(out, obj); + if (obj.m_type == O_MAXIMIZE) { + out << " |-> [" << b[i].first << ":" << b[i].second << "]\n"; + } + else { + out << " |-> [" << -b[i].second << ":" << -b[i].first << "]\n"; + } + } + } + + solver& context::get_solver() { + return *m_solver.get(); + } + + void context::init_solver() { + setup_arith_solver(); + #pragma omp critical (opt_context) + { + m_opt_solver = alloc(opt_solver, m, m_params, m_fm); + m_opt_solver->set_logic(m_logic); + m_solver = m_opt_solver.get(); + } + } + + void context::setup_arith_solver() { + opt_params p(m_params); + if (p.optsmt_engine() == symbol("symba") || + p.optsmt_engine() == symbol("farkas")) { + std::stringstream strm; + strm << AS_OPTINF; + gparams::set("smt.arith.solver", strm.str().c_str()); + } + } + + void context::update_solver() { + if (!m_enable_sat || !probe_bv()) { + return; + } + if (m_maxsat_engine != symbol("maxres") && + m_maxsat_engine != symbol("pd-maxres") && + m_maxsat_engine != symbol("bcd2") && + m_maxsat_engine != symbol("sls")) { + return; + } + m_params.set_bool("minimize_core_partial", true); // false); + m_params.set_bool("minimize_core", true); + m_sat_solver = mk_inc_sat_solver(m, m_params); + unsigned sz = get_solver().get_num_assertions(); + for (unsigned i = 0; i < sz; ++i) { + m_sat_solver->assert_expr(get_solver().get_assertion(i)); + } + #pragma omp critical (opt_context) + { + m_solver = m_sat_solver.get(); + } + } + + void context::set_soft_assumptions() { + if (m_sat_solver.get()) { + m_params.set_bool("soft_assumptions", true); + m_sat_solver->updt_params(m_params); + } + } + + void context::enable_sls(expr_ref_vector const& soft, vector const& weights) { + SASSERT(soft.size() == weights.size()); + if (m_sat_solver.get()) { + set_soft_inc_sat(m_sat_solver.get(), soft.size(), soft.c_ptr(), weights.c_ptr()); + } + if (m_enable_sls && m_sat_solver.get()) { + m_params.set_bool("optimize_model", true); + m_sat_solver->updt_params(m_params); + } + } + + struct context::is_bv { + struct found {}; + ast_manager& m; + pb_util pb; + bv_util bv; + is_bv(ast_manager& m): m(m), pb(m), bv(m) {} + void operator()(var *) { throw found(); } + void operator()(quantifier *) { throw found(); } + void operator()(app *n) { + family_id fid = n->get_family_id(); + if (fid != m.get_basic_family_id() && + fid != pb.get_family_id() && + fid != bv.get_family_id() && + !is_uninterp_const(n)) { + throw found(); + } + } + }; + + bool context::probe_bv() { + expr_fast_mark1 visited; + is_bv proc(m); + try { + for (unsigned i = 0; i < m_objectives.size(); ++i) { + objective & obj = m_objectives[i]; + if (obj.m_type != O_MAXSMT) return false; + maxsmt& ms = *m_maxsmts.find(obj.m_id); + for (unsigned j = 0; j < ms.size(); ++j) { + quick_for_each_expr(proc, visited, ms[j]); + } + } + unsigned sz = get_solver().get_num_assertions(); + for (unsigned i = 0; i < sz; i++) { + quick_for_each_expr(proc, visited, get_solver().get_assertion(i)); + } + } + catch (is_bv::found) { + return false; + } + return true; + } + + struct context::is_propositional_fn { + struct found {}; + ast_manager& m; + is_propositional_fn(ast_manager& m): m(m) {} + void operator()(var *) { throw found(); } + void operator()(quantifier *) { throw found(); } + void operator()(app *n) { + family_id fid = n->get_family_id(); + if (fid != m.get_basic_family_id() && + !is_uninterp_const(n)) { + throw found(); + } + } + }; + + bool context::is_propositional(expr* p) { + expr* np; + if (is_uninterp_const(p) || (m.is_not(p, np) && is_uninterp_const(np))) { + return true; + } + is_propositional_fn proc(m); + expr_fast_mark1 visited; + try { + quick_for_each_expr(proc, visited, p); + } + catch (is_propositional_fn::found) { + return false; + } + return true; + } + + + void context::add_maxsmt(symbol const& id) { + maxsmt* ms = alloc(maxsmt, *this); + ms->updt_params(m_params); + #pragma omp critical (opt_context) + { + m_maxsmts.insert(id, ms); + } + } + + bool context::is_numeral(expr* e, rational & n) const { + unsigned sz; + return m_arith.is_numeral(e, n) || m_bv.is_numeral(e, n, sz); + } + + void context::normalize() { + expr_ref_vector fmls(m); + to_fmls(fmls); + simplify_fmls(fmls); + from_fmls(fmls); + } + + void context::simplify_fmls(expr_ref_vector& fmls) { + if (m_is_clausal) { + return; + } + + goal_ref g(alloc(goal, m, true, false)); + for (unsigned i = 0; i < fmls.size(); ++i) { + g->assert_expr(fmls[i].get()); + } + tactic_ref tac0 = + and_then(mk_simplify_tactic(m), + mk_propagate_values_tactic(m), + mk_solve_eqs_tactic(m), + // NB: mk_elim_uncstr_tactic(m) is not sound with soft constraints + mk_simplify_tactic(m)); + opt_params optp(m_params); + tactic_ref tac2, tac3; + if (optp.elim_01()) { + tac2 = mk_elim01_tactic(m); + tac3 = mk_lia2card_tactic(m); + params_ref lia_p; + lia_p.set_bool("compile_equality", optp.pb_compile_equality()); + tac3->updt_params(lia_p); + set_simplify(and_then(tac0.get(), tac2.get(), tac3.get())); + } + else { + set_simplify(tac0.get()); + } + proof_converter_ref pc; + expr_dependency_ref core(m); + goal_ref_buffer result; + (*m_simplify)(g, result, m_model_converter, pc, core); + SASSERT(result.size() == 1); + goal* r = result[0]; + fmls.reset(); + expr_ref tmp(m); + for (unsigned i = 0; i < r->size(); ++i) { + fmls.push_back(r->form(i)); + } + } + + bool context::is_maximize(expr* fml, app_ref& term, expr*& orig_term, unsigned& index) { + if (is_app(fml) && m_objective_fns.find(to_app(fml)->get_decl(), index) && + m_objectives[index].m_type == O_MAXIMIZE) { + term = to_app(to_app(fml)->get_arg(0)); + orig_term = m_objective_orig.find(to_app(fml)->get_decl()); + return true; + } + return false; + } + + bool context::is_minimize(expr* fml, app_ref& term, expr*& orig_term, unsigned& index) { + if (is_app(fml) && m_objective_fns.find(to_app(fml)->get_decl(), index) && + m_objectives[index].m_type == O_MINIMIZE) { + term = to_app(to_app(fml)->get_arg(0)); + orig_term = m_objective_orig.find(to_app(fml)->get_decl()); + return true; + } + return false; + } + + bool context::is_maxsat(expr* fml, expr_ref_vector& terms, + vector& weights, rational& offset, + bool& neg, symbol& id, unsigned& index) { + if (!is_app(fml)) return false; + neg = false; + app* a = to_app(fml); + if (m_objective_fns.find(a->get_decl(), index) && m_objectives[index].m_type == O_MAXSMT) { + for (unsigned i = 0; i < a->get_num_args(); ++i) { + expr* arg = a->get_arg(i); + if (m.is_true(arg)) { + // skip + } + else if (m.is_false(arg)) { + offset += m_objectives[index].m_weights[i]; + } + else { + terms.push_back(arg); + weights.push_back(m_objectives[index].m_weights[i]); + } + } + id = m_objectives[index].m_id; + return true; + } + app_ref term(m); + expr* orig_term; + offset = rational::zero(); + bool is_max = is_maximize(fml, term, orig_term, index); + bool is_min = !is_max && is_minimize(fml, term, orig_term, index); + if (is_min && get_pb_sum(term, terms, weights, offset)) { + TRACE("opt", tout << "try to convert minimization" << mk_pp(term, m) << "\n";); + // minimize 2*x + 3*y + // <=> + // (assert-soft (not x) 2) + // (assert-soft (not y) 3) + // + for (unsigned i = 0; i < weights.size(); ++i) { + if (weights[i].is_neg()) { + offset += weights[i]; + weights[i].neg(); + } + else { + terms[i] = m.mk_not(terms[i].get()); + } + } + TRACE("opt", + tout << "Convert minimization " << mk_pp(orig_term, m) << "\n"; + tout << "to maxsat: " << term << "\n"; + for (unsigned i = 0; i < weights.size(); ++i) { + tout << mk_pp(terms[i].get(), m) << ": " << weights[i] << "\n"; + } + tout << "offset: " << offset << "\n"; + ); + std::ostringstream out; + out << mk_pp(orig_term, m); + id = symbol(out.str().c_str()); + return true; + } + if (is_max && get_pb_sum(term, terms, weights, offset)) { + TRACE("opt", tout << "try to convert maximization" << mk_pp(term, m) << "\n";); + // maximize 2*x + 3*y - z + // <=> + // (assert-soft x 2) + // (assert-soft y 3) + // (assert-soft (not z) 1) + // offset := 6 + // maximize = offset - penalty + // + for (unsigned i = 0; i < weights.size(); ++i) { + if (weights[i].is_neg()) { + weights[i].neg(); + terms[i] = m.mk_not(terms[i].get()); + } + offset += weights[i]; + } + neg = true; + std::ostringstream out; + out << mk_pp(orig_term, m); + id = symbol(out.str().c_str()); + return true; + } + if ((is_max || is_min) && m_bv.is_bv(term)) { + offset.reset(); + unsigned bv_size = m_bv.get_bv_size(term); + expr_ref val(m); + val = m_bv.mk_numeral(is_max, 1); + for (unsigned i = 0; i < bv_size; ++i) { + rational w = power(rational(2),i); + weights.push_back(w); + terms.push_back(m.mk_eq(val, m_bv.mk_extract(i, i, term))); + if (is_max) { + offset += w; + } + } + neg = is_max; + std::ostringstream out; + out << mk_pp(orig_term, m); + id = symbol(out.str().c_str()); + return true; + } + return false; + } + + expr* context::mk_objective_fn(unsigned index, objective_t ty, unsigned sz, expr*const* args) { + ptr_vector domain; + for (unsigned i = 0; i < sz; ++i) { + domain.push_back(m.get_sort(args[i])); + } + char const* name = ""; + switch(ty) { + case O_MAXIMIZE: name = "maximize"; break; + case O_MINIMIZE: name = "minimize"; break; + case O_MAXSMT: name = "maxsat"; break; + default: break; + } + func_decl* f = m.mk_fresh_func_decl(name,"", domain.size(), domain.c_ptr(), m.mk_bool_sort()); + m_objective_fns.insert(f, index); + m_objective_refs.push_back(f); + if (sz > 0) { + m_objective_orig.insert(f, args[0]); + } + return m.mk_app(f, sz, args); + } + + expr* context::mk_maximize(unsigned index, app* t) { + expr* t_ = t; + return mk_objective_fn(index, O_MAXIMIZE, 1, &t_); + } + + expr* context::mk_minimize(unsigned index, app* t) { + expr* t_ = t; + return mk_objective_fn(index, O_MINIMIZE, 1, &t_); + } + + expr* context::mk_maxsat(unsigned index, unsigned num_fmls, expr* const* fmls) { + return mk_objective_fn(index, O_MAXSMT, num_fmls, fmls); + } + + void context::from_fmls(expr_ref_vector const& fmls) { + TRACE("opt", + for (unsigned i = 0; i < fmls.size(); ++i) { + tout << mk_pp(fmls[i], m) << "\n"; + }); + m_hard_constraints.reset(); + expr* orig_term; + for (unsigned i = 0; i < fmls.size(); ++i) { + expr* fml = fmls[i]; + app_ref tr(m); + expr_ref_vector terms(m); + vector weights; + rational offset(0); + unsigned index; + symbol id; + bool neg; + if (is_maxsat(fml, terms, weights, offset, neg, id, index)) { + objective& obj = m_objectives[index]; + if (obj.m_type != O_MAXSMT) { + // change from maximize/minimize. + obj.m_id = id; + obj.m_type = O_MAXSMT; + obj.m_weights.append(weights); + SASSERT(!m_maxsmts.contains(id)); + add_maxsmt(id); + } + mk_atomic(terms); + SASSERT(obj.m_id == id); + obj.m_terms.reset(); + obj.m_terms.append(terms); + obj.m_adjust_value.set_offset(offset); + obj.m_adjust_value.set_negate(neg); + m_maxsmts.find(id)->set_adjust_value(obj.m_adjust_value); + TRACE("opt", tout << "maxsat: " << id << " offset:" << offset << "\n";); + } + else if (is_maximize(fml, tr, orig_term, index)) { + m_objectives[index].m_term = tr; + } + else if (is_minimize(fml, tr, orig_term, index)) { + m_objectives[index].m_term = tr; + m_objectives[index].m_adjust_value.set_negate(true); + } + else { + m_hard_constraints.push_back(fml); + } + } + } + + /** + To select the proper theory solver we have to ensure that all theory + symbols from soft constraints are reflected in the hard constraints. + + - filter "obj" from generated model. + */ + void context::mk_atomic(expr_ref_vector& terms) { + ref fm; + for (unsigned i = 0; i < terms.size(); ++i) { + expr_ref p(terms[i].get(), m); + app_ref q(m); + if (is_propositional(p)) { + terms[i] = p; + } + else { + q = m.mk_fresh_const("obj", m.mk_bool_sort()); + terms[i] = q; + m_hard_constraints.push_back(m.mk_iff(p, q)); + if (!fm) fm = alloc(filter_model_converter, m); + fm->insert(q->get_decl()); + } + } + if (fm) { + m_model_converter = concat(m_model_converter.get(), fm.get()); + } + } + + void context::to_fmls(expr_ref_vector& fmls) { + m_objective_fns.reset(); + fmls.append(m_hard_constraints); + for (unsigned i = 0; i < m_objectives.size(); ++i) { + objective const& obj = m_objectives[i]; + switch(obj.m_type) { + case O_MINIMIZE: + fmls.push_back(mk_minimize(i, obj.m_term)); + break; + case O_MAXIMIZE: + fmls.push_back(mk_maximize(i, obj.m_term)); + break; + case O_MAXSMT: + fmls.push_back(mk_maxsat(i, obj.m_terms.size(), obj.m_terms.c_ptr())); + break; + } + } + TRACE("opt", + for (unsigned i = 0; i < fmls.size(); ++i) { + tout << mk_pp(fmls[i].get(), m) << "\n"; + }); + } + + void context::internalize() { + for (unsigned i = 0; i < m_objectives.size(); ++i) { + objective & obj = m_objectives[i]; + switch(obj.m_type) { + case O_MINIMIZE: { + app_ref tmp(m); + tmp = m_arith.mk_uminus(obj.m_term); + obj.m_index = m_optsmt.add(tmp); + break; + } + case O_MAXIMIZE: + obj.m_index = m_optsmt.add(obj.m_term); + break; + case O_MAXSMT: { + maxsmt& ms = *m_maxsmts.find(obj.m_id); + for (unsigned j = 0; j < obj.m_terms.size(); ++j) { + ms.add(obj.m_terms[j].get(), obj.m_weights[j]); + } + break; + } + } + } + } + + void context::update_bound(bool is_lower) { + expr_ref val(m); + if (!m_model.get()) return; + for (unsigned i = 0; i < m_objectives.size(); ++i) { + objective const& obj = m_objectives[i]; + rational r; + switch(obj.m_type) { + case O_MINIMIZE: { + bool evaluated = m_model->eval(obj.m_term, val); + TRACE("opt", tout << obj.m_term << " " << val << " " << evaluated << " " << is_numeral(val, r) << "\n";); + if (evaluated && is_numeral(val, r)) { + inf_eps val = inf_eps(obj.m_adjust_value(r)); + TRACE("opt", tout << "adjusted value: " << val << "\n";); + if (is_lower) { + m_optsmt.update_lower(obj.m_index, val); + } + else { + m_optsmt.update_upper(obj.m_index, val); + } + } + break; + } + case O_MAXIMIZE: { + bool evaluated = m_model->eval(obj.m_term, val); + TRACE("opt", tout << obj.m_term << " " << val << "\n";); + if (evaluated && is_numeral(val, r)) { + inf_eps val = inf_eps(obj.m_adjust_value(r)); + TRACE("opt", tout << "adjusted value: " << val << "\n";); + if (is_lower) { + m_optsmt.update_lower(obj.m_index, val); + } + else { + m_optsmt.update_upper(obj.m_index, val); + } + } + break; + } + case O_MAXSMT: { + bool ok = true; + for (unsigned j = 0; ok && j < obj.m_terms.size(); ++j) { + bool evaluated = m_model->eval(obj.m_terms[j], val); + TRACE("opt", tout << mk_pp(obj.m_terms[j], m) << " " << val << "\n";); + if (evaluated) { + if (!m.is_true(val)) { + r += obj.m_weights[j]; + } + } + else { + ok = false; + } + } + if (ok) { + maxsmt& ms = *m_maxsmts.find(obj.m_id); + if (is_lower) { + ms.update_upper(r); + TRACE("opt", tout << r << " " << ms.get_upper() << "\n";); + } + else { + ms.update_lower(r); + TRACE("opt", tout << r << " " << ms.get_lower() << "\n";); + } + } + break; + } + } + } + } + + void context::display(std::ostream& out) { + display_assignment(out); + } + + void context::display_assignment(std::ostream& out) { + for (unsigned i = 0; i < m_scoped_state.m_objectives.size(); ++i) { + objective const& obj = m_scoped_state.m_objectives[i]; + display_objective(out, obj); + if (get_lower_as_num(i) != get_upper_as_num(i)) { + out << " |-> [" << get_lower(i) << ":" << get_upper(i) << "]\n"; + } + else { + out << " |-> " << get_lower(i) << "\n"; + } + } + } + + void context::display_objective(std::ostream& out, objective const& obj) const { + switch(obj.m_type) { + case O_MAXSMT: { + symbol s = obj.m_id; + if (s != symbol::null) { + out << s; + } + break; + } + default: + out << obj.m_term; + break; + } + } + + inf_eps context::get_lower_as_num(unsigned idx) { + if (idx > m_objectives.size()) { + throw default_exception("index out of bounds"); + } + objective const& obj = m_objectives[idx]; + switch(obj.m_type) { + case O_MAXSMT: + return inf_eps(m_maxsmts.find(obj.m_id)->get_lower()); + case O_MINIMIZE: + return obj.m_adjust_value(m_optsmt.get_upper(obj.m_index)); + case O_MAXIMIZE: + return obj.m_adjust_value(m_optsmt.get_lower(obj.m_index)); + default: + UNREACHABLE(); + return inf_eps(); + } + } + + inf_eps context::get_upper_as_num(unsigned idx) { + if (idx > m_objectives.size()) { + throw default_exception("index out of bounds"); + } + objective const& obj = m_objectives[idx]; + switch(obj.m_type) { + case O_MAXSMT: + return inf_eps(m_maxsmts.find(obj.m_id)->get_upper()); + case O_MINIMIZE: + return obj.m_adjust_value(m_optsmt.get_lower(obj.m_index)); + case O_MAXIMIZE: + return obj.m_adjust_value(m_optsmt.get_upper(obj.m_index)); + default: + UNREACHABLE(); + return inf_eps(); + } + } + + expr_ref context::get_lower(unsigned idx) { + return to_expr(get_lower_as_num(idx)); + } + + expr_ref context::get_upper(unsigned idx) { + return to_expr(get_upper_as_num(idx)); + } + + expr_ref context::to_expr(inf_eps const& n) { + rational inf = n.get_infinity(); + rational r = n.get_rational(); + rational eps = n.get_infinitesimal(); + expr_ref_vector args(m); + if (!inf.is_zero()) { + expr* oo = m.mk_const(symbol("oo"), m_arith.mk_int()); + if (inf.is_one()) { + args.push_back(oo); + } + else { + args.push_back(m_arith.mk_mul(m_arith.mk_numeral(inf, inf.is_int()), oo)); + } + } + if (!r.is_zero()) { + args.push_back(m_arith.mk_numeral(r, r.is_int())); + } + if (!eps.is_zero()) { + expr* ep = m.mk_const(symbol("epsilon"), m_arith.mk_real()); + if (eps.is_one()) { + args.push_back(ep); + } + else { + args.push_back(m_arith.mk_mul(m_arith.mk_numeral(eps, eps.is_int()), ep)); + } + } + switch(args.size()) { + case 0: return expr_ref(m_arith.mk_numeral(rational(0), true), m); + case 1: return expr_ref(args[0].get(), m); + default: return expr_ref(m_arith.mk_add(args.size(), args.c_ptr()), m); + } + } + + void context::set_simplify(tactic* tac) { + #pragma omp critical (opt_context) + { + m_simplify = tac; + } + } + + void context::set_pareto(pareto_base* p) { + #pragma omp critical (opt_context) + { + m_pareto = p; + } + } + + void context::set_cancel(bool f) { + #pragma omp critical (opt_context) + { + if (m_solver) { + if (f) m_solver->cancel(); else m_solver->reset_cancel(); + } + if (m_pareto) { + m_pareto->set_cancel(f); + } + if (m_simplify) { + if (f) m_simplify->cancel(); else m_solver->reset_cancel(); + } + map_t::iterator it = m_maxsmts.begin(), end = m_maxsmts.end(); + for (; it != end; ++it) { + it->m_value->set_cancel(f); + } + } + m_optsmt.set_cancel(f); + } + + void context::collect_statistics(statistics& stats) const { + if (m_solver) { + m_solver->collect_statistics(stats); + } + if (m_simplify) { + m_simplify->collect_statistics(stats); + } + map_t::iterator it = m_maxsmts.begin(), end = m_maxsmts.end(); + for (; it != end; ++it) { + it->m_value->collect_statistics(stats); + } + } + + void context::collect_param_descrs(param_descrs & r) { + opt_params::collect_param_descrs(r); + } + + void context::updt_params(params_ref& p) { + m_params.append(p); + if (m_solver) { + m_solver->updt_params(m_params); + } + m_optsmt.updt_params(m_params); + map_t::iterator it = m_maxsmts.begin(), end = m_maxsmts.end(); + for (; it != end; ++it) { + it->m_value->updt_params(m_params); + } + opt_params _p(p); + m_enable_sat = _p.enable_sat(); + m_enable_sls = _p.enable_sls(); + m_maxsat_engine = _p.maxsat_engine(); + m_pp_neat = _p.pp_neat(); + } + + typedef obj_hashtable func_decl_set; + + struct context::free_func_visitor { + ast_manager& m; + func_decl_set m_funcs; + obj_hashtable m_sorts; + expr_mark m_visited; + public: + free_func_visitor(ast_manager& m): m(m) {} + void operator()(var * n) { } + void operator()(app * n) { + if (n->get_family_id() == null_family_id) { + m_funcs.insert(n->get_decl()); + } + sort* s = m.get_sort(n); + if (s->get_family_id() == null_family_id) { + m_sorts.insert(s); + } + } + void operator()(quantifier * n) { } + func_decl_set& funcs() { return m_funcs; } + obj_hashtable& sorts() { return m_sorts; } + + void collect(expr* e) { + for_each_expr(*this, m_visited, e); + } + }; + + std::string context::to_string() const { + smt2_pp_environment_dbg env(m); + ast_smt_pp ll_smt2_pp(m); + free_func_visitor visitor(m); + std::ostringstream out; +#define PP(_e_) ast_smt2_pp(out, _e_, env); +#define PPE(_e_) if (m_pp_neat) ast_smt2_pp(out, _e_, env); else ll_smt2_pp.display_expr_smt2(out, _e_); + for (unsigned i = 0; i < m_scoped_state.m_hard.size(); ++i) { + visitor.collect(m_scoped_state.m_hard[i]); + } + for (unsigned i = 0; i < m_scoped_state.m_objectives.size(); ++i) { + objective const& obj = m_scoped_state.m_objectives[i]; + switch(obj.m_type) { + case O_MAXIMIZE: + case O_MINIMIZE: + visitor.collect(obj.m_term); + break; + case O_MAXSMT: + for (unsigned j = 0; j < obj.m_terms.size(); ++j) { + visitor.collect(obj.m_terms[j]); + } + break; + default: + UNREACHABLE(); + break; + } + } + + obj_hashtable::iterator sit = visitor.sorts().begin(); + obj_hashtable::iterator send = visitor.sorts().end(); + for (; sit != send; ++sit) { + PP(*sit); + } + func_decl_set::iterator it = visitor.funcs().begin(); + func_decl_set::iterator end = visitor.funcs().end(); + for (; it != end; ++it) { + PP(*it); + out << "\n"; + } + for (unsigned i = 0; i < m_scoped_state.m_hard.size(); ++i) { + out << "(assert "; + PPE(m_scoped_state.m_hard[i]); + out << ")\n"; + } + for (unsigned i = 0; i < m_scoped_state.m_objectives.size(); ++i) { + objective const& obj = m_scoped_state.m_objectives[i]; + switch(obj.m_type) { + case O_MAXIMIZE: + out << "(maximize "; + PP(obj.m_term); + out << ")\n"; + break; + case O_MINIMIZE: + out << "(minimize "; + PP(obj.m_term); + out << ")\n"; + break; + case O_MAXSMT: + for (unsigned j = 0; j < obj.m_terms.size(); ++j) { + out << "(assert-soft "; + PP(obj.m_terms[j]); + rational w = obj.m_weights[j]; + if (w.is_int()) { + out << " :weight " << w; + } + else { + out << " :dweight " << w; + } + if (obj.m_id != symbol::null) { + out << " :id " << obj.m_id; + } + out << ")\n"; + } + break; + default: + UNREACHABLE(); + break; + } + } + + param_descrs descrs; + collect_param_descrs(descrs); + m_params.display_smt2(out, "opt", descrs); + + out << "(check-sat)\n"; + return out.str(); + } + + void context::validate_lex() { + rational r1; + expr_ref val(m); + for (unsigned i = 0; i < m_objectives.size(); ++i) { + objective const& obj = m_objectives[i]; + switch(obj.m_type) { + case O_MINIMIZE: + case O_MAXIMIZE: { + inf_eps n = m_optsmt.get_lower(obj.m_index); + if (m_optsmt.objective_is_model_valid(obj.m_index) && + n.get_infinity().is_zero() && + n.get_infinitesimal().is_zero() && + m_model->eval(obj.m_term, val) && + is_numeral(val, r1)) { + rational r2 = n.get_rational(); + if (obj.m_type == O_MINIMIZE) { + r1.neg(); + } + CTRACE("opt", r1 != r2, tout << obj.m_term << " evaluates to " << r1 << " but has objective " << r2 << "\n";); + CTRACE("opt", r1 != r2, model_smt2_pp(tout, m, *m_model, 0);); + SASSERT(r1 == r2); + } + break; + } + case O_MAXSMT: { + maxsmt& ms = *m_maxsmts.find(obj.m_id); + rational value(0); + for (unsigned i = 0; i < obj.m_terms.size(); ++i) { + VERIFY(m_model->eval(obj.m_terms[i], val)); + if (!m.is_true(val)) { + value += obj.m_weights[i]; + } + // TBD: check that optimal was not changed. + } + TRACE("opt", tout << "value " << value << "\n";); + break; + } + } + } + } +} diff --git a/src/opt/opt_context.h b/src/opt/opt_context.h new file mode 100644 index 000000000..ee4ce467a --- /dev/null +++ b/src/opt/opt_context.h @@ -0,0 +1,259 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + opt_context.h + +Abstract: + Facility for running optimization problem. + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-16 + +Notes: + +--*/ +#ifndef _OPT_CONTEXT_H_ +#define _OPT_CONTEXT_H_ + +#include "ast.h" +#include "opt_solver.h" +#include "opt_pareto.h" +#include "optsmt.h" +#include "maxsmt.h" +#include "model_converter.h" +#include "tactic.h" +#include "arith_decl_plugin.h" +#include "bv_decl_plugin.h" +#include "cmd_context.h" + + +namespace opt { + + class opt_solver; + + + class context : public opt_wrapper, public pareto_callback { + struct free_func_visitor; + typedef map map_t; + typedef map map_id; + typedef vector > bounds_t; + enum objective_t { + O_MAXIMIZE, + O_MINIMIZE, + O_MAXSMT + }; + + struct objective { + objective_t m_type; + app_ref m_term; // for maximize, minimize term + expr_ref_vector m_terms; // for maxsmt + vector m_weights; // for maxsmt + adjust_value m_adjust_value; + symbol m_id; // for maxsmt + unsigned m_index; // for maximize/minimize index + + objective(bool is_max, app_ref& t, unsigned idx): + m_type(is_max?O_MAXIMIZE:O_MINIMIZE), + m_term(t), + m_terms(t.get_manager()), + m_id(), + m_index(idx) + { + if (!is_max) { + m_adjust_value.set_negate(true); + } + } + + objective(ast_manager& m, symbol id): + m_type(O_MAXSMT), + m_term(m), + m_terms(m), + m_id(id), + m_index(0) + {} + }; + + class scoped_state { + ast_manager& m; + arith_util m_arith; + bv_util m_bv; + unsigned_vector m_hard_lim; + unsigned_vector m_objectives_lim; + unsigned_vector m_objectives_term_trail; + unsigned_vector m_objectives_term_trail_lim; + map_id m_indices; + + public: + expr_ref_vector m_hard; + vector m_objectives; + + scoped_state(ast_manager& m): + m(m), + m_arith(m), + m_bv(m), + m_hard(m) + {} + void push(); + void pop(); + void add(expr* hard); + void set(ptr_vector & hard); + unsigned add(expr* soft, rational const& weight, symbol const& id); + unsigned add(app* obj, bool is_max); + }; + + ast_manager& m; + arith_util m_arith; + bv_util m_bv; + expr_ref_vector m_hard_constraints; + ref m_opt_solver; + ref m_solver; + ref m_sat_solver; + scoped_ptr m_pareto; + params_ref m_params; + optsmt m_optsmt; + map_t m_maxsmts; + scoped_state m_scoped_state; + vector m_objectives; + model_ref m_model; + model_converter_ref m_model_converter; + filter_model_converter m_fm; + obj_map m_objective_fns; + obj_map m_objective_orig; + func_decl_ref_vector m_objective_refs; + tactic_ref m_simplify; + bool m_enable_sat; + bool m_enable_sls; + bool m_is_clausal; + bool m_pp_neat; + symbol m_maxsat_engine; + symbol m_logic; + public: + context(ast_manager& m); + virtual ~context(); + unsigned add_soft_constraint(expr* f, rational const& w, symbol const& id); + unsigned add_objective(app* t, bool is_max); + void add_hard_constraint(expr* f); + + + virtual void push(); + virtual void pop(unsigned n); + virtual bool empty() { return m_scoped_state.m_objectives.empty(); } + virtual void set_cancel(bool f); + virtual void reset_cancel() { set_cancel(false); } + virtual void cancel() { set_cancel(true); } + virtual void set_hard_constraints(ptr_vector & hard); + virtual lbool optimize(); + virtual void get_model(model_ref& m); + virtual void set_model(model_ref& m); + virtual void fix_model(model_ref& m); + virtual void collect_statistics(statistics& stats) const; + virtual proof* get_proof() { return 0; } + virtual void get_labels(svector & r) {} + virtual void get_unsat_core(ptr_vector & r) {} + virtual std::string reason_unknown() const { return std::string("unknown"); } + + virtual void display_assignment(std::ostream& out); + virtual bool is_pareto() { return m_pareto.get() != 0; } + virtual void set_logic(symbol const& s) { m_logic = s; } + void set_clausal(bool f) { m_is_clausal = f; } + + void display(std::ostream& out); + static void collect_param_descrs(param_descrs & r); + void updt_params(params_ref& p); + params_ref& get_params() { return m_params; } + + expr_ref get_lower(unsigned idx); + expr_ref get_upper(unsigned idx); + + std::string to_string() const; + + + virtual unsigned num_objectives() { return m_objectives.size(); } + virtual expr_ref mk_gt(unsigned i, model_ref& model); + virtual expr_ref mk_ge(unsigned i, model_ref& model); + virtual expr_ref mk_le(unsigned i, model_ref& model); + + smt::context& smt_context() { return m_opt_solver->get_context(); } + filter_model_converter& fm() { return m_fm; } + bool sat_enabled() const { return 0 != m_sat_solver.get(); } + solver& get_solver(); + ast_manager& get_manager() { return this->m; } + params_ref& params() { return m_params; } + void enable_sls(expr_ref_vector const& soft, weights_t& weights); + void set_enable_sls(bool f) { m_enable_sls = f; } + void set_soft_assumptions(); + symbol const& maxsat_engine() const { return m_maxsat_engine; } + void get_base_model(model_ref& m); + + + private: + void validate_feasibility(maxsmt& ms); + + lbool execute(objective const& obj, bool committed, bool scoped); + lbool execute_min_max(unsigned index, bool committed, bool scoped, bool is_max); + lbool execute_maxsat(symbol const& s, bool committed, bool scoped); + lbool execute_lex(); + lbool execute_box(); + lbool execute_pareto(); + expr_ref to_expr(inf_eps const& n); + + void reset_maxsmts(); + void import_scoped_state(); + void normalize(); + void internalize(); + bool is_maximize(expr* fml, app_ref& term, expr*& orig_term, unsigned& index); + bool is_minimize(expr* fml, app_ref& term, expr*& orig_term, unsigned& index); + bool is_maxsat(expr* fml, expr_ref_vector& terms, + vector& weights, rational& offset, bool& neg, + symbol& id, unsigned& index); + expr* mk_maximize(unsigned index, app* t); + expr* mk_minimize(unsigned index, app* t); + expr* mk_maxsat(unsigned index, unsigned num_fmls, expr* const* fmls); + expr* mk_objective_fn(unsigned index, objective_t ty, unsigned sz, expr*const* args); + void to_fmls(expr_ref_vector& fmls); + void from_fmls(expr_ref_vector const& fmls); + void simplify_fmls(expr_ref_vector& fmls); + void mk_atomic(expr_ref_vector& terms); + + void update_lower() { update_bound(true); } + void update_bound(bool is_lower); + + inf_eps get_lower_as_num(unsigned idx); + inf_eps get_upper_as_num(unsigned idx); + + + struct is_bv; + bool probe_bv(); + + struct is_propositional_fn; + bool is_propositional(expr* e); + + void init_solver(); + void update_solver(); + void setup_arith_solver(); + void add_maxsmt(symbol const& id); + void set_simplify(tactic *simplify); + void set_pareto(pareto_base* p); + + bool is_numeral(expr* e, rational& n) const; + + void display_objective(std::ostream& out, objective const& obj) const; + void display_bounds(std::ostream& out, bounds_t const& b) const; + + + void validate_lex(); + + + // pareto + void yield(); + expr_ref mk_ge(expr* t, expr* s); + void mk_term_val(model_ref& mdl, objective const& obj, expr_ref& term, expr_ref& val); + + }; + +} + +#endif diff --git a/src/opt/opt_params.pyg b/src/opt/opt_params.pyg new file mode 100644 index 000000000..059ac0bd2 --- /dev/null +++ b/src/opt/opt_params.pyg @@ -0,0 +1,28 @@ +def_module_params('opt', + description='optimization parameters', + export=True, + params=(('timeout', UINT, UINT_MAX, 'set timeout'), + ('optsmt_engine', SYMBOL, 'basic', "select optimization engine: 'basic', 'farkas', 'symba'"), + ('maxsat_engine', SYMBOL, 'wmax', "select engine for maxsat: 'fu_malik', 'core_maxsat', 'wmax', 'pbmax', 'maxres', 'pd-maxres', 'bcd2', 'wpm2', 'sls', 'maxhs'"), + ('priority', SYMBOL, 'lex', "select how to priortize objectives: 'lex' (lexicographic), 'pareto', or 'box'"), + ('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'), + ('print_model', BOOL, False, 'display model for satisfiable constraints'), + ('enable_sls', BOOL, False, 'enable SLS tuning during weighted maxsast'), + ('enable_sat', BOOL, False, 'enable the new SAT core for propositional constraints'), + ('elim_01', BOOL, True, 'eliminate 01 variables'), + ('pp.neat', BOOL, True, 'use neat (as opposed to less readable, but faster) pretty printer when displaying context'), + ('pb.compile_equality', BOOL, False, 'compile arithmetical equalities into pseudo-Boolean equality (instead of two inequalites)'), + ('maxres.hill_climb', BOOL, True, 'give preference for large weight cores'), + ('maxres.add_upper_bound_block', BOOL, False, 'restict upper bound with constraint'), + ('maxres.max_num_cores', UINT, UINT_MAX, 'maximal number of cores per round'), + ('maxres.max_core_size', UINT, 3, 'break batch of generated cores if size reaches this number'), + ('maxres.maximize_assignment', BOOL, False, 'find an MSS/MCS to improve current assignment'), + ('maxres.max_correction_set_size', UINT, 3, 'allow generating correction set constraints up to maximal size'), + ('maxres.wmax', BOOL, False, 'use weighted theory solver to constrain upper bounds') + + )) + + + + + diff --git a/src/opt/opt_pareto.cpp b/src/opt/opt_pareto.cpp new file mode 100644 index 000000000..e8b295d9f --- /dev/null +++ b/src/opt/opt_pareto.cpp @@ -0,0 +1,105 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + opt_pareto.cpp + +Abstract: + + Pareto front utilities + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-24 + +Notes: + + +--*/ + +#include "opt_pareto.h" +#include "ast_pp.h" +#include "model_smt2_pp.h" + +namespace opt { + + // --------------------- + // GIA pareto algorithm + + lbool gia_pareto::operator()() { + expr_ref fml(m); + lbool is_sat = m_solver->check_sat(0, 0); + if (is_sat == l_true) { + { + solver::scoped_push _s(*m_solver.get()); + while (is_sat == l_true) { + if (m_cancel) { + return l_undef; + } + m_solver->get_model(m_model); + IF_VERBOSE(1, + model_ref mdl(m_model); + cb.fix_model(mdl); + model_smt2_pp(verbose_stream() << "new model:\n", m, *mdl, 0);); + // TBD: we can also use local search to tune solution coordinate-wise. + mk_dominates(); + is_sat = m_solver->check_sat(0, 0); + } + } + if (is_sat == l_undef) { + return l_undef; + } + SASSERT(is_sat == l_false); + is_sat = l_true; + mk_not_dominated_by(); + } + return is_sat; + } + + void pareto_base::mk_dominates() { + unsigned sz = cb.num_objectives(); + expr_ref fml(m); + expr_ref_vector gt(m), fmls(m); + for (unsigned i = 0; i < sz; ++i) { + fmls.push_back(cb.mk_ge(i, m_model)); + gt.push_back(cb.mk_gt(i, m_model)); + } + fmls.push_back(m.mk_or(gt.size(), gt.c_ptr())); + fml = m.mk_and(fmls.size(), fmls.c_ptr()); + IF_VERBOSE(10, verbose_stream() << "dominates: " << fml << "\n";); + TRACE("opt", tout << fml << "\n";); + m_solver->assert_expr(fml); + } + + void pareto_base::mk_not_dominated_by() { + unsigned sz = cb.num_objectives(); + expr_ref fml(m); + expr_ref_vector le(m); + for (unsigned i = 0; i < sz; ++i) { + le.push_back(cb.mk_le(i, m_model)); + } + fml = m.mk_not(m.mk_and(le.size(), le.c_ptr())); + IF_VERBOSE(10, verbose_stream() << "not dominated by: " << fml << "\n";); + TRACE("opt", tout << fml << "\n";); + m_solver->assert_expr(fml); + } + + // --------------------------------- + // OIA algorithm (without filtering) + + lbool oia_pareto::operator()() { + solver::scoped_push _s(*m_solver.get()); + lbool is_sat = m_solver->check_sat(0, 0); + if (m_cancel) { + is_sat = l_undef; + } + if (is_sat == l_true) { + m_solver->get_model(m_model); + mk_not_dominated_by(); + } + return is_sat; + } + +} + diff --git a/src/opt/opt_pareto.h b/src/opt/opt_pareto.h new file mode 100644 index 000000000..ce78e68f3 --- /dev/null +++ b/src/opt/opt_pareto.h @@ -0,0 +1,118 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + opt_pareto.h + +Abstract: + + Pareto front utilities + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-24 + +Notes: + + +--*/ +#ifndef _OPT_PARETO_H_ +#define _OPT_PARETO_H_ + +#include "solver.h" +#include "model.h" + +namespace opt { + + class pareto_callback { + public: + virtual unsigned num_objectives() = 0; + virtual expr_ref mk_gt(unsigned i, model_ref& model) = 0; + virtual expr_ref mk_ge(unsigned i, model_ref& model) = 0; + virtual expr_ref mk_le(unsigned i, model_ref& model) = 0; + virtual void set_model(model_ref& m) = 0; + virtual void fix_model(model_ref& m) = 0; + }; + class pareto_base { + protected: + ast_manager& m; + pareto_callback& cb; + volatile bool m_cancel; + ref m_solver; + params_ref m_params; + model_ref m_model; + public: + pareto_base( + ast_manager & m, + pareto_callback& cb, + solver* s, + params_ref & p): + m(m), + cb(cb), + m_cancel(false), + m_solver(s), + m_params(p) { + } + virtual ~pareto_base() {} + virtual void updt_params(params_ref & p) { + m_solver->updt_params(p); + m_params.copy(p); + } + virtual void collect_param_descrs(param_descrs & r) { + m_solver->collect_param_descrs(r); + } + virtual void collect_statistics(statistics & st) const { + m_solver->collect_statistics(st); + } + virtual void set_cancel(bool f) { + if (f) + m_solver->cancel(); + else + m_solver->reset_cancel(); + m_cancel = f; + } + virtual void display(std::ostream & out) const { + m_solver->display(out); + } + virtual lbool operator()() = 0; + + virtual void get_model(model_ref& mdl) { + mdl = m_model; + } + + protected: + + void mk_dominates(); + + void mk_not_dominated_by(); + }; + class gia_pareto : public pareto_base { + public: + gia_pareto(ast_manager & m, + pareto_callback& cb, + solver* s, + params_ref & p): + pareto_base(m, cb, s, p) { + } + virtual ~gia_pareto() {} + + virtual lbool operator()(); + }; + + // opportunistic improvement algorithm. + class oia_pareto : public pareto_base { + public: + oia_pareto(ast_manager & m, + pareto_callback& cb, + solver* s, + params_ref & p): + pareto_base(m, cb, s, p) { + } + virtual ~oia_pareto() {} + + virtual lbool operator()(); + }; +} + +#endif diff --git a/src/opt/opt_sls_solver.h b/src/opt/opt_sls_solver.h new file mode 100644 index 000000000..007ade793 --- /dev/null +++ b/src/opt/opt_sls_solver.h @@ -0,0 +1,251 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + opt_sls_solver.h + +Abstract: + + Wraps a solver with SLS for improving a solution using an objective function. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-18 + +Notes: + + +--*/ +#ifndef _OPT_SLS_SOLVER_H_ +#define _OPT_SLS_SOLVER_H_ + +#include "solver_na2as.h" +#include "card2bv_tactic.h" +#include "nnf_tactic.h" +#include "pb_sls.h" +#include "bvsls_opt_engine.h" + + +namespace opt { + + class sls_solver : public solver_na2as { + ast_manager& m; + ref m_solver; + scoped_ptr m_bvsls; + scoped_ptr m_pbsls; + pb::card_pb_rewriter m_pb2bv; + vector m_weights; + expr_ref_vector m_soft; + model_ref m_model; + params_ref m_params; + symbol m_engine; + public: + sls_solver(ast_manager & m, solver* s, + expr_ref_vector const& soft, + vector const& weights, + params_ref & p): + solver_na2as(m), + m(m), + m_solver(s), + m_bvsls(0), + m_pbsls(0), + m_pb2bv(m), + m_weights(weights), + m_soft(soft) + { + updt_params(p); + } + virtual ~sls_solver() {} + + virtual void updt_params(params_ref & p) { + m_solver->updt_params(p); + m_params.copy(p); + opt_params _p(p); + m_engine = _p.sls_engine(); + } + virtual void collect_param_descrs(param_descrs & r) { + m_solver->collect_param_descrs(r); + } + virtual void collect_statistics(statistics & st) const { + m_solver->collect_statistics(st); + if (m_bvsls) m_bvsls->collect_statistics(st); + if (m_pbsls) m_pbsls->collect_statistics(st); + } + virtual void assert_expr(expr * t) { + m_solver->assert_expr(t); + } + virtual void get_unsat_core(ptr_vector & r) { + m_solver->get_unsat_core(r); + } + virtual void get_model(model_ref & m) { + m = m_model; + } + virtual proof * get_proof() { + return m_solver->get_proof(); + } + virtual std::string reason_unknown() const { + return m_solver->reason_unknown(); + } + virtual void get_labels(svector & r) { + m_solver->get_labels(r); + } + virtual void set_cancel(bool f) { + m_solver->set_cancel(f); + m_pb2bv.set_cancel(f); + #pragma omp critical (sls_solver) + { + if (m_bvsls) { + m_bvsls->set_cancel(f); + } + if (m_pbsls) { + m_pbsls->set_cancel(f); + } + } + } + virtual void set_progress_callback(progress_callback * callback) { + m_solver->set_progress_callback(callback); + } + virtual unsigned get_num_assertions() const { + return m_solver->get_num_assertions(); + } + virtual expr * get_assertion(unsigned idx) const { + return m_solver->get_assertion(idx); + } + virtual void display(std::ostream & out) const { + m_solver->display(out); + // if (m_bvsls) m_bvsls->display(out); + } + + void opt(model_ref& mdl) { + if (m_engine == symbol("pb")) { + pbsls_opt(mdl); + } + else { + bvsls_opt(mdl); + } + } + + static expr_ref soft2bv(expr_ref_vector const& soft, vector const& weights) { + ast_manager& m = soft.get_manager(); + pb::card_pb_rewriter pb2bv(m); + rational upper(1); + expr_ref objective(m); + for (unsigned i = 0; i < weights.size(); ++i) { + upper += weights[i]; + } + expr_ref zero(m), tmp(m); + bv_util bv(m); + expr_ref_vector es(m); + rational num = numerator(upper); + rational den = denominator(upper); + rational maxval = num*den; + unsigned bv_size = maxval.get_num_bits(); + zero = bv.mk_numeral(rational(0), bv_size); + for (unsigned i = 0; i < soft.size(); ++i) { + pb2bv(soft[i], tmp); + es.push_back(m.mk_ite(tmp, bv.mk_numeral(den*weights[i], bv_size), zero)); + } + if (es.empty()) { + objective = bv.mk_numeral(0, bv_size); + } + else { + objective = es[0].get(); + for (unsigned i = 1; i < es.size(); ++i) { + objective = bv.mk_bv_add(objective, es[i].get()); + } + } + return objective; + } + + protected: + typedef bvsls_opt_engine::optimization_result opt_result; + + virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) { + lbool r = m_solver->check_sat(num_assumptions, assumptions); + if (r == l_true) { + m_solver->get_model(m_model); + opt(m_model); + } + return r; + } + virtual void push_core() { + m_solver->push(); + } + virtual void pop_core(unsigned n) { + m_solver->pop(n); + } + + + private: + // convert soft constraints to bit-vector objective. + + void assertions2sls() { + expr_ref tmp(m); + goal_ref g(alloc(goal, m, true, false)); + for (unsigned i = 0; i < m_solver->get_num_assertions(); ++i) { + m_pb2bv(m_solver->get_assertion(i), tmp); + g->assert_expr(tmp); + } + tactic_ref simplify = mk_nnf_tactic(m); + proof_converter_ref pc; + expr_dependency_ref core(m); + goal_ref_buffer result; + model_converter_ref model_converter; + (*simplify)(g, result, model_converter, pc, core); + SASSERT(result.size() == 1); + goal* r = result[0]; + for (unsigned i = 0; i < r->size(); ++i) { + m_bvsls->assert_expr(r->form(i)); + } + } + + void pbsls_opt(model_ref& mdl) { + #pragma omp critical (sls_solver) + { + if (m_pbsls) { + m_pbsls->reset(); + } + else { + m_pbsls = alloc(smt::pb_sls, m); + } + } + m_pbsls->set_model(mdl); + m_pbsls->updt_params(m_params); + for (unsigned i = 0; i < m_solver->get_num_assertions(); ++i) { + m_pbsls->add(m_solver->get_assertion(i)); + } + for (unsigned i = 0; i < m_soft.size(); ++i) { + m_pbsls->add(m_soft[i].get(), m_weights[i]); + } + (*m_pbsls.get())(); + m_pbsls->get_model(m_model); + mdl = m_model.get(); + } + + void bvsls_opt(model_ref& mdl) { + #pragma omp critical (sls_solver) + { + m_bvsls = alloc(bvsls_opt_engine, m, m_params); + } + assertions2sls(); + expr_ref objective = soft2bv(m_soft, m_weights); + opt_result res(m); + res.is_sat = l_undef; + try { + res = m_bvsls->optimize(objective, mdl, true); + } + catch (...) { + + } + SASSERT(res.is_sat == l_true || res.is_sat == l_undef); + if (res.is_sat == l_true) { + m_bvsls->get_model(m_model); + mdl = m_model.get(); + } + } + + }; +} + +#endif diff --git a/src/opt/opt_solver.cpp b/src/opt/opt_solver.cpp new file mode 100644 index 000000000..2a12818c5 --- /dev/null +++ b/src/opt/opt_solver.cpp @@ -0,0 +1,378 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + opt_solver.cpp + +Abstract: + + Wraps smt::kernel as a solver for optimization + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-16 + +Notes: + + Based directly on smt_solver. + +--*/ +#include +#include "reg_decl_plugins.h" +#include "opt_solver.h" +#include "smt_context.h" +#include "theory_arith.h" +#include "theory_diff_logic.h" +#include "theory_dense_diff_logic.h" +#include "theory_pb.h" +#include "ast_pp.h" +#include "ast_smt_pp.h" +#include "pp_params.hpp" +#include "opt_params.hpp" +#include "model_smt2_pp.h" +#include "stopwatch.h" + +namespace opt { + + opt_solver::opt_solver(ast_manager & mgr, params_ref const & p, + filter_model_converter& fm): + solver_na2as(mgr), + m_params(p), + m_context(mgr, m_params), + m(mgr), + m_dump_benchmarks(false), + m_fm(fm), + m_objective_sorts(m), + m_first(true) { + m_params.updt_params(p); + m_params.m_relevancy_lvl = 0; + } + + unsigned opt_solver::m_dump_count = 0; + + opt_solver::~opt_solver() { + } + + void opt_solver::updt_params(params_ref & _p) { + opt_params p(_p); + m_dump_benchmarks = p.dump_benchmarks(); + m_params.updt_params(_p); + m_context.updt_params(_p); + } + + void opt_solver::collect_param_descrs(param_descrs & r) { + m_context.collect_param_descrs(r); + } + + void opt_solver::collect_statistics(statistics & st) const { + m_context.collect_statistics(st); + } + + void opt_solver::assert_expr(expr * t) { + m_context.assert_expr(t); + } + + void opt_solver::push_core() { + m_context.push(); + } + + void opt_solver::pop_core(unsigned n) { + m_context.pop(n); + } + + void opt_solver::set_logic(symbol const& logic) { + m_logic = logic; + m_context.set_logic(logic); + } + + smt::theory_opt& opt_solver::get_optimizer() { + smt::context& ctx = m_context.get_context(); + smt::theory_id arith_id = m_context.m().get_family_id("arith"); + smt::theory* arith_theory = ctx.get_theory(arith_id); + + if (!arith_theory) { + ctx.register_plugin(alloc(smt::theory_mi_arith, m, m_params)); + arith_theory = ctx.get_theory(arith_id); + SASSERT(arith_theory); + } + if (typeid(smt::theory_mi_arith) == typeid(*arith_theory)) { + return dynamic_cast(*arith_theory); + } + else if (typeid(smt::theory_i_arith) == typeid(*arith_theory)) { + return dynamic_cast(*arith_theory); + } + else if (typeid(smt::theory_inf_arith) == typeid(*arith_theory)) { + return dynamic_cast(*arith_theory); + } + else if (typeid(smt::theory_rdl&) == typeid(*arith_theory)) { + return dynamic_cast(*arith_theory); + } + else if (typeid(smt::theory_idl&) == typeid(*arith_theory)) { + return dynamic_cast(*arith_theory); + } + else if (typeid(smt::theory_dense_mi&) == typeid(*arith_theory)) { + return dynamic_cast(*arith_theory); + } + else if (typeid(smt::theory_dense_i&) == typeid(*arith_theory)) { + return dynamic_cast(*arith_theory); + } + else if (typeid(smt::theory_dense_smi&) == typeid(*arith_theory)) { + return dynamic_cast(*arith_theory); + } + else if (typeid(smt::theory_dense_si&) == typeid(*arith_theory)) { + return dynamic_cast(*arith_theory); + } + else { + UNREACHABLE(); + return dynamic_cast(*arith_theory); + } + } + + bool opt_solver::dump_benchmarks() { + return m_dump_benchmarks; + } + + lbool opt_solver::check_sat_core(unsigned num_assumptions, expr * const * assumptions) { + TRACE("opt_verbose", { + tout << "context size: " << m_context.size() << "\n"; + for (unsigned i = 0; i < m_context.size(); ++i) { + tout << mk_pp(m_context.get_formulas()[i], m_context.m()) << "\n"; + } + }); + stopwatch w; + if (dump_benchmarks()) { + w.start(); + std::stringstream file_name; + file_name << "opt_solver" << ++m_dump_count << ".smt2"; + std::ofstream buffer(file_name.str().c_str()); + to_smt2_benchmark(buffer, num_assumptions, assumptions, "opt_solver", ""); + buffer.close(); + IF_VERBOSE(1, verbose_stream() << "(created benchmark: " << file_name.str() << "..."; + verbose_stream().flush();); + } + lbool r; + if (m_first && num_assumptions == 0 && m_context.get_scope_level() == 0) { + r = m_context.setup_and_check(); + } + else { + r = m_context.check(num_assumptions, assumptions); + } + m_first = false; + if (dump_benchmarks()) { + w.stop(); + IF_VERBOSE(1, verbose_stream() << ".. " << r << " " << std::fixed << w.get_seconds() << ")\n";); + } + return r; + } + + void opt_solver::maximize_objectives(expr_ref_vector& blockers) { + expr_ref blocker(m); + for (unsigned i = 0; i < m_objective_vars.size(); ++i) { + maximize_objective(i, blocker); + blockers.push_back(blocker); + } + } + + + /** + \brief maximize the value of objective i in the current state. + Return a predicate that blocks the current maximal value. + + The result of 'maximize' is post-processed. + When maximization involves shared symbols the model produced + by local optimization does not necessarily satisfy combination + constraints (it may not be a real model). + In this case, the model is post-processed (update_model + causes an additional call to final_check to propagate theory equalities + when 'has_shared' is true). + + */ + void opt_solver::maximize_objective(unsigned i, expr_ref& blocker) { + smt::theory_var v = m_objective_vars[i]; + bool has_shared = false; + inf_eps val = get_optimizer().maximize(v, blocker, has_shared); + inf_eps val2; + m_valid_objectives[i] = true; + TRACE("opt", tout << (has_shared?"has shared":"non-shared") << "\n";); + if (m_context.get_context().update_model(has_shared)) { + if (has_shared) { + val2 = current_objective_value(i); + if (val2 != val) { + decrement_value(i, val); + } + } + } + else { + SASSERT(has_shared); + // model is not final. We set the current objective to + // close to the optimal (ignoring types). + decrement_value(i, val); + } + m_objective_values[i] = val; + + TRACE("opt", { model_ref mdl; tout << m_objective_values[i] << "\n"; + tout << blocker << "\n"; + get_model(mdl); model_smt2_pp(tout << "update model:\n", m, *mdl, 0); }); + } + + void opt_solver::decrement_value(unsigned i, inf_eps& val) { + if (arith_util(m).is_real(m_objective_sorts[i].get())) { + val -= inf_eps(inf_rational(rational(0),true)); + } + else { + val -= inf_eps(inf_rational(rational(1))); + } + m_valid_objectives[i] = false; + } + + + void opt_solver::get_unsat_core(ptr_vector & r) { + unsigned sz = m_context.get_unsat_core_size(); + for (unsigned i = 0; i < sz; i++) { + r.push_back(m_context.get_unsat_core_expr(i)); + } + } + + void opt_solver::get_model(model_ref & m) { + m_context.get_model(m); + } + + proof * opt_solver::get_proof() { + return m_context.get_proof(); + } + + std::string opt_solver::reason_unknown() const { + return m_context.last_failure_as_string(); + } + + void opt_solver::get_labels(svector & r) { + buffer tmp; + m_context.get_relevant_labels(0, tmp); + r.append(tmp.size(), tmp.c_ptr()); + } + + void opt_solver::set_cancel(bool f) { + m_context.set_cancel(f); + } + + void opt_solver::set_progress_callback(progress_callback * callback) { + m_callback = callback; + m_context.set_progress_callback(callback); + } + + unsigned opt_solver::get_num_assertions() const { + return m_context.size(); + } + + expr * opt_solver::get_assertion(unsigned idx) const { + SASSERT(idx < get_num_assertions()); + return m_context.get_formulas()[idx]; + } + + void opt_solver::display(std::ostream & out) const { + m_context.display(out); + } + + smt::theory_var opt_solver::add_objective(app* term) { + smt::theory_var v = get_optimizer().add_objective(term); + m_objective_vars.push_back(v); + m_objective_values.push_back(inf_eps(rational(-1), inf_rational())); + m_objective_sorts.push_back(m.get_sort(term)); + m_valid_objectives.push_back(true); + return v; + } + + vector const& opt_solver::get_objective_values() { + return m_objective_values; + } + + inf_eps const& opt_solver::saved_objective_value(unsigned i) { + return m_objective_values[i]; + } + + inf_eps opt_solver::current_objective_value(unsigned i) { + smt::theory_var v = m_objective_vars[i]; + return get_optimizer().value(v); + } + + + expr_ref opt_solver::mk_ge(unsigned var, inf_eps const& val) { + smt::theory_opt& opt = get_optimizer(); + smt::theory_var v = m_objective_vars[var]; + + if (typeid(smt::theory_inf_arith) == typeid(opt)) { + smt::theory_inf_arith& th = dynamic_cast(opt); + return th.mk_ge(m_fm, v, val); + } + + if (typeid(smt::theory_mi_arith) == typeid(opt)) { + smt::theory_mi_arith& th = dynamic_cast(opt); + SASSERT(val.is_finite()); + return th.mk_ge(m_fm, v, val.get_numeral()); + } + + if (typeid(smt::theory_i_arith) == typeid(opt)) { + SASSERT(val.is_finite()); + SASSERT(val.get_infinitesimal().is_zero()); + smt::theory_i_arith& th = dynamic_cast(opt); + return th.mk_ge(m_fm, v, val.get_rational()); + } + + if (typeid(smt::theory_idl) == typeid(opt)) { + smt::theory_idl& th = dynamic_cast(opt); + return th.mk_ge(m_fm, v, val.get_rational()); + } + + if (typeid(smt::theory_rdl) == typeid(opt) && + val.get_infinitesimal().is_zero()) { + smt::theory_rdl& th = dynamic_cast(opt); + return th.mk_ge(m_fm, v, val.get_rational()); + } + + // difference logic? + return expr_ref(m.mk_true(), m); + } + + void opt_solver::reset_objectives() { + m_objective_vars.reset(); + m_objective_values.reset(); + m_objective_sorts.reset(); + m_valid_objectives.reset(); + } + + opt_solver& opt_solver::to_opt(solver& s) { + if (typeid(opt_solver) != typeid(s)) { + throw default_exception("BUG: optimization context has not been initialized correctly"); + } + return dynamic_cast(s); + } + + + void opt_solver::to_smt2_benchmark( + std::ofstream & buffer, + unsigned num_assumptions, + expr * const * assumptions, + char const * name, + char const * logic, + char const * status, + char const * attributes) { + ast_smt_pp pp(m); + pp.set_benchmark_name(name); + pp.set_logic(logic); + pp.set_status(status); + pp.add_attributes(attributes); + pp_params params; + pp.set_simplify_implies(params.simplify_implies()); + + for (unsigned i = 0; i < num_assumptions; ++i) { + pp.add_assumption(assumptions[i]); + } + for (unsigned i = 0; i < get_num_assertions(); ++i) { + pp.add_assumption(get_assertion(i)); + } + pp.display_smt2(buffer, m.mk_true()); + } + + +} diff --git a/src/opt/opt_solver.h b/src/opt/opt_solver.h new file mode 100644 index 000000000..986136d7b --- /dev/null +++ b/src/opt/opt_solver.h @@ -0,0 +1,138 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + opt_solver.h + +Abstract: + + Wraps smt::kernel as a solver for optimization + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-16 + +Notes: + + Based directly on smt_solver. + +--*/ +#ifndef _OPT_SOLVER_H_ +#define _OPT_SOLVER_H_ + +#include"inf_rational.h" +#include"inf_eps_rational.h" +#include"ast.h" +#include"params.h" +#include"solver_na2as.h" +#include"smt_kernel.h" +#include"smt_params.h" +#include"smt_types.h" +#include"theory_opt.h" +#include"filter_model_converter.h" + +namespace opt { + + typedef inf_eps_rational inf_eps; + + // Adjust bound bound |-> m_offset + (m_negate?-1:1)*bound + class adjust_value { + rational m_offset; + bool m_negate; + public: + adjust_value(rational const& offset, bool neg): + m_offset(offset), + m_negate(neg) + {} + adjust_value(): m_offset(0), m_negate(false) {} + void set_offset(rational const& o) { m_offset = o; } + void set_negate(bool neg) { m_negate = neg; } + rational const& get_offset() const { return m_offset; } + bool get_negate() { return m_negate; } + inf_eps operator()(inf_eps const& r) const { + inf_eps result = r; + if (m_negate) result.neg(); + result += m_offset; + return result; + } + rational operator()(rational const& r) const { + rational result = r; + if (m_negate) result.neg(); + result += m_offset; + return result; + } + }; + + + class opt_solver : public solver_na2as { + private: + smt_params m_params; + smt::kernel m_context; + ast_manager& m; + filter_model_converter& m_fm; + progress_callback * m_callback; + symbol m_logic; + bool m_objective_enabled; + svector m_objective_vars; + vector m_objective_values; + sort_ref_vector m_objective_sorts; + svector m_valid_objectives; + bool m_dump_benchmarks; + static unsigned m_dump_count; + statistics m_stats; + bool m_first; + public: + opt_solver(ast_manager & m, params_ref const & p, filter_model_converter& fm); + virtual ~opt_solver(); + + virtual void updt_params(params_ref & p); + virtual void collect_param_descrs(param_descrs & r); + virtual void collect_statistics(statistics & st) const; + virtual void assert_expr(expr * t); + virtual void push_core(); + virtual void pop_core(unsigned n); + virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions); + virtual void get_unsat_core(ptr_vector & r); + virtual void get_model(model_ref & m); + virtual proof * get_proof(); + virtual std::string reason_unknown() const; + virtual void get_labels(svector & r); + virtual void set_cancel(bool f); + virtual void set_progress_callback(progress_callback * callback); + virtual unsigned get_num_assertions() const; + virtual expr * get_assertion(unsigned idx) const; + virtual void display(std::ostream & out) const; + void set_logic(symbol const& logic); + + smt::theory_var add_objective(app* term); + void reset_objectives(); + void maximize_objective(unsigned i, expr_ref& blocker); + void maximize_objectives(expr_ref_vector& blockers); + inf_eps const & saved_objective_value(unsigned obj_index); + inf_eps current_objective_value(unsigned obj_index); + bool objective_is_model_valid(unsigned obj_index) const { + return m_valid_objectives[obj_index]; + } + + vector const& get_objective_values(); + expr_ref mk_ge(unsigned obj_index, inf_eps const& val); + + static opt_solver& to_opt(solver& s); + bool dump_benchmarks(); + + smt::context& get_context() { return m_context.get_context(); } // used by weighted maxsat. + + smt::theory_opt& get_optimizer(); + + void to_smt2_benchmark(std::ofstream & buffer, + unsigned num_assumptions, expr * const * assumptions, + char const * name = "benchmarks", + char const * logic = "", char const * status = "unknown", char const * attributes = ""); + + private: + void decrement_value(unsigned i, inf_eps& val); + }; +} + +#endif diff --git a/src/opt/optsmt.cpp b/src/opt/optsmt.cpp new file mode 100644 index 000000000..1148e3411 --- /dev/null +++ b/src/opt/optsmt.cpp @@ -0,0 +1,431 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + optsmt.cpp + +Abstract: + + Objective optimization method. + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-16 + +Notes: + + Suppose we obtain solution t1 = k1, ..., tn = kn-epsilon + Assert: + t1 > k1 \/ t2 > k2 \/ ... \/ tn >= kn + If this solution is satisfiable, then for each t_i, maximize the + assignment and assert the new frontier. + Claim: we don't necessarily have to freeze assignments of + t_i when optimizing assignment for t_j + because the state will always satisfy the disjunction. + If one of the k_i is unbounded, then omit a disjunction for it. + + +--*/ + +#include +#include "optsmt.h" +#include "opt_solver.h" +#include "arith_decl_plugin.h" +#include "theory_arith.h" +#include "ast_pp.h" +#include "model_pp.h" +#include "th_rewriter.h" +#include "opt_params.hpp" + +namespace opt { + + + void optsmt::set_cancel(bool f) { + TRACE("opt", tout << "set cancel: " << f << "\n";); + m_cancel = f; + } + + void optsmt::set_max(vector& dst, vector const& src, expr_ref_vector& fmls) { + for (unsigned i = 0; i < src.size(); ++i) { + if (src[i] >= dst[i]) { + dst[i] = src[i]; + m_lower_fmls[i] = fmls[i].get(); + if (dst[i].is_pos() && !dst[i].is_finite()) { // review: likely done already. + m_lower_fmls[i] = m.mk_false(); + fmls[i] = m.mk_false(); + } + } + else if (src[i] < dst[i] && !m.is_true(m_lower_fmls[i].get())) { + fmls[i] = m_lower_fmls[i].get(); + } + } + } + + /* + Enumerate locally optimal assignments until fixedpoint. + */ + lbool optsmt::basic_opt() { + lbool is_sat = l_true; + + while (is_sat == l_true && !m_cancel) { + is_sat = m_s->check_sat(0, 0); + if (is_sat == l_true) { + update_lower(); + } + } + + if (m_cancel || is_sat == l_undef) { + return l_undef; + } + + // set the solution tight. + for (unsigned i = 0; i < m_lower.size(); ++i) { + m_upper[i] = m_lower[i]; + } + + return l_true; + } + + /* + Enumerate locally optimal assignments until fixedpoint. + */ + lbool optsmt::farkas_opt() { + smt::theory_opt& opt = m_s->get_optimizer(); + + if (typeid(smt::theory_inf_arith) != typeid(opt)) { + return l_undef; + } + + lbool is_sat = l_true; + + while (is_sat == l_true && !m_cancel) { + is_sat = update_upper(); + } + + if (m_cancel || is_sat == l_undef) { + return l_undef; + } + + // set the solution tight. + for (unsigned i = 0; i < m_lower.size(); ++i) { + m_upper[i] = m_lower[i]; + } + + return l_true; + } + + lbool optsmt::symba_opt() { + smt::theory_opt& opt = m_s->get_optimizer(); + + if (typeid(smt::theory_inf_arith) != typeid(opt)) { + return l_undef; + } + + + expr_ref_vector ors(m), disj(m); + expr_ref fml(m), bound(m.mk_true(), m); + for (unsigned i = 0; i < m_upper.size(); ++i) { + ors.push_back(m_s->mk_ge(i, m_upper[i])); + } + { + solver::scoped_push _push(*m_s); + fml = m.mk_or(ors.size(), ors.c_ptr()); + m_s->assert_expr(fml); + lbool is_sat = l_true; + while (!m_cancel) { + is_sat = m_s->check_sat(0,0); + if (is_sat == l_true) { + disj.reset(); + m_s->maximize_objectives(disj); + m_s->get_model(m_model); + for (unsigned i = 0; i < ors.size(); ++i) { + expr_ref tmp(m); + m_model->eval(ors[i].get(), tmp); + if (m.is_true(tmp)) { + m_lower[i] = m_upper[i]; + ors[i] = m.mk_false(); + disj[i] = m.mk_false(); + } + } + set_max(m_lower, m_s->get_objective_values(), disj); + fml = m.mk_or(ors.size(), ors.c_ptr()); + m_s->assert_expr(fml); + } + else if (is_sat == l_undef) { + return l_undef; + } + else { + break; + } + } + } + bound = m.mk_or(m_lower_fmls.size(), m_lower_fmls.c_ptr()); + m_s->assert_expr(bound); + + if (m_cancel) { + return l_undef; + } + return basic_opt(); + } + + void optsmt::update_lower(unsigned idx, inf_eps const& v) { + TRACE("opt", tout << "v" << idx << " >= " << v << "\n";); + m_lower_fmls[idx] = m_s->mk_ge(idx, v); + m_lower[idx] = v; + } + + void optsmt::update_upper(unsigned idx, inf_eps const& v) { + TRACE("opt", tout << "v" << idx << " <= " << v << "\n";); + m_upper[idx] = v; + } + + void optsmt::update_lower() { + expr_ref_vector disj(m); + m_s->get_model(m_model); + m_s->maximize_objectives(disj); + set_max(m_lower, m_s->get_objective_values(), disj); + TRACE("opt", + for (unsigned i = 0; i < m_lower.size(); ++i) { + tout << m_lower[i] << " "; + } + tout << "\n"; + model_pp(tout, *m_model); + ); + IF_VERBOSE(2, verbose_stream() << "(optsmt.lower "; + for (unsigned i = 0; i < m_lower.size(); ++i) { + verbose_stream() << m_lower[i] << " "; + } + verbose_stream() << ")\n";); + IF_VERBOSE(3, verbose_stream() << disj << "\n";); + IF_VERBOSE(3, model_pp(verbose_stream(), *m_model);); + + expr_ref constraint(m); + constraint = m.mk_or(disj.size(), disj.c_ptr()); + m_s->assert_expr(constraint); + } + + lbool optsmt::update_upper() { + smt::theory_opt& opt = m_s->get_optimizer(); + SASSERT(typeid(smt::theory_inf_arith) == typeid(opt)); + smt::theory_inf_arith& th = dynamic_cast(opt); + expr_ref bound(m); + expr_ref_vector bounds(m); + + solver::scoped_push _push(*m_s); + + // + // NB: we have to create all bound expressions before calling check_sat + // because the state after check_sat is not at base level. + // + + vector mid; + + for (unsigned i = 0; i < m_lower.size() && !m_cancel; ++i) { + if (m_lower[i] < m_upper[i]) { + mid.push_back((m_upper[i]+m_lower[i])/rational(2)); + bound = m_s->mk_ge(i, mid[i]); + bounds.push_back(bound); + } + else { + bounds.push_back(0); + mid.push_back(inf_eps()); + } + } + bool progress = false; + for (unsigned i = 0; i < m_lower.size() && !m_cancel; ++i) { + if (m_lower[i] <= mid[i] && mid[i] <= m_upper[i] && m_lower[i] < m_upper[i]) { + th.enable_record_conflict(bounds[i].get()); + lbool is_sat = m_s->check_sat(1, bounds.c_ptr() + i); + switch(is_sat) { + case l_true: + IF_VERBOSE(2, verbose_stream() << "(optsmt lower bound for v" << m_vars[i] << " := " << m_upper[i] << ")\n";); + m_lower[i] = mid[i]; + th.enable_record_conflict(0); + update_lower(); + break; + case l_false: + IF_VERBOSE(2, verbose_stream() << "(optsmt conflict: " << th.conflict_minimize() << ") \n";); + if (!th.conflict_minimize().is_finite()) { + // bounds is not in the core. The context is unsat. + m_upper[i] = m_lower[i]; + return l_false; + } + else { + m_upper[i] = std::min(m_upper[i], th.conflict_minimize()); + } + break; + default: + th.enable_record_conflict(0); + return l_undef; + } + th.enable_record_conflict(0); + progress = true; + } + } + if (m_cancel) { + return l_undef; + } + if (!progress) { + return l_false; + } + return l_true; + } + + void optsmt::setup(opt_solver& solver) { + m_s = &solver; + solver.reset_objectives(); + m_vars.reset(); + + // force base level + { + solver::scoped_push _push(solver); + } + + for (unsigned i = 0; i < m_objs.size(); ++i) { + smt::theory_var v = solver.add_objective(m_objs[i].get()); + if (v == smt::null_theory_var) { + std::ostringstream out; + out << "Objective function '" << mk_pp(m_objs[i].get(), m) << "' is not supported"; + throw default_exception(out.str()); + } + m_vars.push_back(v); + } + } + + lbool optsmt::lex(unsigned obj_index, bool is_maximize) { + TRACE("opt", tout << "optsmt:lex\n";); + solver::scoped_push _push(*m_s); + SASSERT(obj_index < m_vars.size()); + return basic_lex(obj_index, is_maximize); + } + + lbool optsmt::basic_lex(unsigned obj_index, bool is_maximize) { + lbool is_sat = l_true; + expr_ref block(m), tmp(m); + + for (unsigned i = 0; i < obj_index; ++i) { + commit_assignment(i); + } + while (is_sat == l_true && !m_cancel) { + is_sat = m_s->check_sat(0, 0); + if (is_sat != l_true) break; + + m_s->maximize_objective(obj_index, block); + m_s->get_model(m_model); + inf_eps obj = m_s->saved_objective_value(obj_index); + if (obj > m_lower[obj_index]) { + m_lower[obj_index] = obj; + IF_VERBOSE(1, + if (is_maximize) + verbose_stream() << "(optsmt lower bound: " << obj << ")\n"; + else + verbose_stream() << "(optsmt upper bound: " << (-obj) << ")\n"; + ); + for (unsigned i = obj_index+1; i < m_vars.size(); ++i) { + m_s->maximize_objective(i, tmp); + m_lower[i] = m_s->saved_objective_value(i); + } + } + m_s->assert_expr(block); + + // TBD: only works for simplex + // blocking formula should be extracted based + // on current state. + } + + if (m_cancel || is_sat == l_undef) { + TRACE("opt", tout << "undef: " << m_cancel << " " << is_sat << "\n";); + return l_undef; + } + + // set the solution tight. + m_upper[obj_index] = m_lower[obj_index]; + for (unsigned i = obj_index+1; i < m_lower.size(); ++i) { + m_lower[i] = inf_eps(rational(-1), inf_rational(0)); + } + return l_true; + } + + + /** + Takes solver with hard constraints added. + Returns an optimal assignment to objective functions. + */ + lbool optsmt::box() { + lbool is_sat = l_true; + if (m_vars.empty()) { + return is_sat; + } + // assertions added during search are temporary. + solver::scoped_push _push(*m_s); + if (m_optsmt_engine == symbol("farkas")) { + is_sat = farkas_opt(); + } + else if (m_optsmt_engine == symbol("symba")) { + is_sat = symba_opt(); + } + else { + is_sat = basic_opt(); + } + return is_sat; + } + + + inf_eps optsmt::get_lower(unsigned i) const { + if (i >= m_lower.size()) return inf_eps(); + return m_lower[i]; + } + + bool optsmt::objective_is_model_valid(unsigned index) const { + return m_s->objective_is_model_valid(index); + } + + inf_eps optsmt::get_upper(unsigned i) const { + if (i >= m_upper.size()) return inf_eps(); + return m_upper[i]; + } + + void optsmt::get_model(model_ref& mdl) { + mdl = m_model.get(); + } + + // force lower_bound(i) <= objective_value(i) + void optsmt::commit_assignment(unsigned i) { + inf_eps lo = m_lower[i]; + TRACE("opt", tout << "set lower bound of " << mk_pp(m_objs[i].get(), m) << " to: " << lo << "\n"; + tout << get_lower(i) << ":" << get_upper(i) << "\n";); + // Only assert bounds for bounded objectives + if (lo.is_finite()) { + m_s->assert_expr(m_s->mk_ge(i, lo)); + } + } + + unsigned optsmt::add(app* t) { + expr_ref t1(t, m), t2(m); + th_rewriter rw(m); + rw(t1, t2); + SASSERT(is_app(t2)); + m_objs.push_back(to_app(t2)); + m_lower.push_back(inf_eps(rational(-1),inf_rational(0))); + m_upper.push_back(inf_eps(rational(1), inf_rational(0))); + m_lower_fmls.push_back(m.mk_true()); + return m_objs.size()-1; + } + + void optsmt::updt_params(params_ref& p) { + opt_params _p(p); + m_optsmt_engine = _p.optsmt_engine(); + } + + void optsmt::reset() { + m_lower.reset(); + m_upper.reset(); + m_objs.reset(); + m_vars.reset(); + m_model.reset(); + m_lower_fmls.reset(); + m_s = 0; + } +} + diff --git a/src/opt/optsmt.h b/src/opt/optsmt.h new file mode 100644 index 000000000..8ec35c98e --- /dev/null +++ b/src/opt/optsmt.h @@ -0,0 +1,89 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + optsmt.h + +Abstract: + + Objective optimization method. + +Author: + + Anh-Dung Phan (t-anphan) 2013-10-16 + +Notes: + +--*/ +#ifndef _OPTSMT_H_ +#define _OPTSMT_H_ + +#include "opt_solver.h" + +namespace opt { + /** + Takes solver with hard constraints added. + Returns an optimal assignment to objective functions. + */ + + class optsmt { + ast_manager& m; + opt_solver* m_s; + volatile bool m_cancel; + vector m_lower; + vector m_upper; + app_ref_vector m_objs; + expr_ref_vector m_lower_fmls; + svector m_vars; + symbol m_optsmt_engine; + model_ref m_model; + public: + optsmt(ast_manager& m): + m(m), m_s(0), m_cancel(false), m_objs(m), m_lower_fmls(m) {} + + void setup(opt_solver& solver); + + lbool box(); + + lbool lex(unsigned obj_index, bool is_maximize); + + unsigned add(app* t); + + void set_cancel(bool f); + + void updt_params(params_ref& p); + + unsigned get_num_objectives() const { return m_objs.size(); } + void commit_assignment(unsigned index); + inf_eps get_lower(unsigned index) const; + inf_eps get_upper(unsigned index) const; + bool objective_is_model_valid(unsigned index) const; + void get_model(model_ref& mdl); + + void update_lower(unsigned idx, inf_eps const& r); + void update_upper(unsigned idx, inf_eps const& r); + + void reset(); + + private: + + lbool basic_opt(); + + lbool symba_opt(); + + lbool basic_lex(unsigned idx, bool is_maximize); + + lbool farkas_opt(); + + void set_max(vector& dst, vector const& src, expr_ref_vector& fmls); + + void update_lower(); + + lbool update_upper(); + + }; + +}; + +#endif diff --git a/src/opt/pb_sls.cpp b/src/opt/pb_sls.cpp new file mode 100644 index 000000000..05bdd5cf8 --- /dev/null +++ b/src/opt/pb_sls.cpp @@ -0,0 +1,741 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + pb_sls.cpp + +Abstract: + + SLS for PB optimization. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-03-18 + +Notes: + +--*/ +#include "pb_sls.h" +#include "smt_literal.h" +#include "ast_pp.h" +#include "th_rewriter.h" +#include "sat_sls.h" + +namespace smt { + struct pb_sls::imp { + + struct clause { + literal_vector m_lits; + scoped_mpz_vector m_weights; + scoped_mpz m_k; + scoped_mpz m_value; + bool m_eq; + clause(unsynch_mpz_manager& m): + m_weights(m), + m_k(m), + m_value(m), + m_eq(true) + {} + clause(clause const& cls): + m_lits(cls.m_lits), + m_weights(cls.m_weights.m()), + m_k(cls.m_k), + m_value(cls.m_value), + m_eq(cls.m_eq) { + for (unsigned i = 0; i < cls.m_weights.size(); ++i) { + m_weights.push_back(cls.m_weights[i]); + } + } + }; + + struct stats { + stats() { reset(); } + void reset() { memset(this, 0, sizeof(*this)); } + unsigned m_num_flips; + unsigned m_num_improvements; + }; + + ast_manager& m; + pb_util pb; + unsynch_mpz_manager mgr; + th_rewriter m_rewrite; + volatile bool m_cancel; + vector m_clauses; // clauses to be satisfied + expr_ref_vector m_orig_clauses; // for debugging + model_ref m_orig_model; // for debugging + vector m_soft; // soft constraints + vector m_weights; // weights of soft constraints + rational m_penalty; // current penalty of soft constraints + rational m_best_penalty; + vector m_hard_occ, m_soft_occ; // variable occurrence + svector m_assignment; // current assignment. + svector m_best_assignment; + expr_ref_vector m_trail; + obj_map m_decl2var; // map declarations to Boolean variables. + ptr_vector m_var2decl; // reverse map + sat::index_set m_hard_false; // list of hard clauses that are false. + sat::index_set m_soft_false; // list of soft clauses that are false. + unsigned m_max_flips; // maximal number of flips + unsigned m_non_greedy_percent; // percent of moves to do non-greedy style + random_gen m_rng; + scoped_mpz one; + stats m_stats; + + imp(ast_manager& m): + m(m), + pb(m), + m_rewrite(m), + m_cancel(false), + m_orig_clauses(m), + m_trail(m), + one(mgr) + { + reset(); + one = mpz(1); + } + + ~imp() { + } + + void reset() { + init_max_flips(); + m_non_greedy_percent = 30; + m_decl2var.reset(); + m_var2decl.reset(); + m_assignment.reset(); + m_hard_occ.reset(); + m_soft_occ.reset(); + m_clauses.reset(); + m_orig_clauses.reset(); + m_soft.reset(); + m_weights.reset(); + m_trail.reset(); + m_decl2var.insert(m.mk_true(), 0); + m_var2decl.push_back(m.mk_true()); + m_assignment.push_back(true); + m_hard_occ.push_back(unsigned_vector()); + m_soft_occ.push_back(unsigned_vector()); + } + + void init_max_flips() { + m_max_flips = 200; + } + + void add(expr* f) { + clause cls(mgr); + if (compile_clause(f, cls)) { + m_clauses.push_back(cls); + m_orig_clauses.push_back(f); + } + } + void add(expr* f, rational const& w) { + clause cls(mgr); + if (compile_clause(f, cls)) { + m_soft.push_back(cls); + m_weights.push_back(w); + } + } + + void set_model(model_ref & mdl) { + m_orig_model = mdl; + for (unsigned i = 0; i < m_var2decl.size(); ++i) { + expr_ref tmp(m); + VERIFY(mdl->eval(m_var2decl[i], tmp)); + m_assignment[i] = m.is_true(tmp); + } + } + + lbool operator()() { + init(); + IF_VERBOSE(1, verbose_stream() << "(pb.sls initial penalty: " << m_best_penalty << ")\n"; + verbose_stream() << "(pb.sls violated: " << m_hard_false.num_elems() + << " penalty: " << m_penalty << ")\n";); + svector assignment(m_assignment); + for (unsigned round = 0; round < 40; ++round) { + init_max_flips(); + while (m_max_flips > 0) { + --m_max_flips; + literal lit = flip(); + if (m_cancel) { + return l_undef; + } + IF_VERBOSE(3, verbose_stream() + << "(pb.sls violated: " << m_hard_false.num_elems() + << " penalty: " << m_penalty << " " << lit << ")\n";); + if (m_hard_false.empty() && m_best_penalty.is_zero()) { + break; + } + } + if (m_hard_false.empty() && m_best_penalty.is_zero()) { + break; + } + IF_VERBOSE(1, verbose_stream() << "(pb.sls best penalty " << m_best_penalty << ")\n";); + if (!m_best_assignment.empty()) { + assignment.reset(); + assignment.append(m_best_assignment); + round = 0; + } + m_assignment.reset(); + m_assignment.append(assignment); + m_best_assignment.reset(); + m_soft_false.reset(); + m_hard_false.reset(); + m_penalty.reset(); + for (unsigned i = 0; i < m_soft.size(); ++i) { + if (!eval(m_soft[i])) { + m_soft_false.insert(i); + m_penalty += m_weights[i]; + } + } + for (unsigned i = 0; i < m_clauses.size(); ++i) { + if (!eval(m_clauses[i])) { + m_hard_false.insert(i); + } + } + } + m_assignment.reset(); + m_assignment.append(assignment); + m_penalty = m_best_penalty; + return l_true; + } + + bool get_value(literal l) { + return l.sign() ^ m_assignment[l.var()]; + } + void set_cancel(bool f) { + m_cancel = f; + } + void get_model(model_ref& mdl) { + mdl = alloc(model, m); + for (unsigned i = 1; i < m_var2decl.size(); ++i) { + expr* d = m_var2decl[i]; + if (is_uninterp_const(d)) { + mdl->register_decl(to_app(d)->get_decl(), m_assignment[i] ? m.mk_true() : m.mk_false()); + } + } + } + + void collect_statistics(::statistics& st) const { + st.update("sls.num_flips", m_stats.m_num_flips); + st.update("sls.num_improvements", m_stats.m_num_improvements); + } + + void updt_params(params_ref& p) { + } + + bool soft_holds(unsigned index) { + return eval(m_soft[index]); + } + + void display(std::ostream& out, clause const& cls) { + scoped_mpz w(mgr); + for (unsigned i = 0; i < cls.m_lits.size(); ++i) { + w = cls.m_weights[i]; + out << w << "*" << cls.m_lits[i] << " "; + out << "(" << mk_pp(m_var2decl[cls.m_lits[i].var()], m) << ") "; + if (i + 1 < cls.m_lits.size()) { + out << "+ "; + } + } + out << "(" << cls.m_value << ") "; + if (cls.m_eq) { + out << "= "; + } + else { + out << ">= "; + } + out << cls.m_k << "\n"; + } + + void display(std::ostream& out) { + for (unsigned i = 0; i < m_clauses.size(); ++i) { + display(out, m_clauses[i]); + } + out << "soft:\n"; + for (unsigned i = 0; i < m_soft.size(); ++i) { + display(out << m_weights[i] << ": ", m_soft[i]); + } + for (unsigned i = 0; i < m_assignment.size(); ++i) { + out << literal(i) << ": " << mk_pp(m_var2decl[i], m) << " |-> " << (m_assignment[i]?"true":"false") << "\n"; + } + } + + bool eval(clause& cls) { + unsigned sz = cls.m_lits.size(); + cls.m_value.reset(); + for (unsigned i = 0; i < sz; ++i) { + if (get_value(cls.m_lits[i])) { + cls.m_value += cls.m_weights[i]; + } + } + if (cls.m_eq) { + return cls.m_value == cls.m_k; + } + else { + return cls.m_value >= cls.m_k; + } + } + + void init_occ(vector const& clauses, vector & occ) { + for (unsigned i = 0; i < clauses.size(); ++i) { + clause const& cls = clauses[i]; + for (unsigned j = 0; j < cls.m_lits.size(); ++j) { + literal lit = cls.m_lits[j]; + if (occ.size() <= static_cast(lit.var())) occ.resize(lit.var() + 1); + occ[lit.var()].push_back(i); + } + } + } + + void init() { + m_best_assignment.reset(); + m_best_penalty.reset(); + m_hard_false.reset(); + m_hard_occ.reset(); + m_soft_false.reset(); + m_soft_occ.reset(); + m_penalty.reset(); + for (unsigned i = 0; i <= m_var2decl.size(); ++i) { + m_soft_occ.push_back(unsigned_vector()); + m_hard_occ.push_back(unsigned_vector()); + } + + // initialize the occurs vectors. + init_occ(m_clauses, m_hard_occ); + init_occ(m_soft, m_soft_occ); + + // add clauses that are false. + for (unsigned i = 0; i < m_clauses.size(); ++i) { + if (!eval(m_clauses[i])) { + m_hard_false.insert(i); + expr_ref tmp(m); + VERIFY(m_orig_model->eval(m_orig_clauses[i].get(), tmp)); + IF_VERBOSE(0, + verbose_stream() << "original evaluation: " << tmp << "\n"; + verbose_stream() << mk_pp(m_orig_clauses[i].get(), m) << "\n"; + display(verbose_stream(), m_clauses[i]);); + } + } + for (unsigned i = 0; i < m_soft.size(); ++i) { + if (!eval(m_soft[i])) { + m_soft_false.insert(i); + m_penalty += m_weights[i]; + } + } + m_best_penalty = m_penalty; + TRACE("opt", display(tout);); + } + + literal flip() { + m_stats.m_num_flips++; + literal result; + if (m_hard_false.empty()) { + result = flip_soft(); + } + else { + result = flip_hard(); + } + if (m_hard_false.empty() && m_best_penalty > m_penalty) { + IF_VERBOSE(1, verbose_stream() << "(pb.sls improved bound " << m_penalty << ")\n";); + m_best_assignment.reset(); + m_best_assignment.append(m_assignment); + m_best_penalty = m_penalty; + m_stats.m_num_improvements++; + init_max_flips(); + } + if (!m_assignment[result.var()]) { + result.neg(); + } + return result; + } + + literal flip_hard() { + SASSERT(!m_hard_false.empty()); + literal lit; + clause const& cls = pick_hard_clause(); + // IF_VERBOSE(1, display(verbose_stream(), cls);); + int break_count; + int min_bc = INT_MAX; + unsigned min_bc_index = 0; + for (unsigned i = 0; i < cls.m_lits.size(); ++i) { + lit = cls.m_lits[i]; + break_count = flip(lit); + if (break_count < min_bc) { + min_bc = break_count; + min_bc_index = i; + } + else if (break_count == min_bc && m_rng(5) == 1) { + min_bc_index = i; + } + int new_break_count = flip(~lit); + if (-break_count != new_break_count) { + verbose_stream() << lit << "\n"; + IF_VERBOSE(0, display(verbose_stream(), cls);); + display(verbose_stream()); + exit(0); + } + // VERIFY(-break_count == flip(~lit)); + } + if (m_rng(100) <= m_non_greedy_percent) { + lit = cls.m_lits[m_rng(cls.m_lits.size())]; + } + else { + lit = cls.m_lits[min_bc_index]; + } + flip(lit); + return lit; + } + + literal flip_soft() { + literal lit; + clause const& cls = pick_soft_clause(); + int break_count; + int min_bc = INT_MAX; + unsigned min_bc_index = 0; + rational penalty = m_penalty; + rational min_penalty = penalty; + for (unsigned i = 0; i < cls.m_lits.size(); ++i) { + lit = cls.m_lits[i]; + break_count = flip(lit); + SASSERT(break_count >= 0); + if (break_count == 0 && penalty > m_penalty) { + return lit; + } + if ((break_count < min_bc) || + (break_count == min_bc && m_penalty < min_penalty)) { + min_bc = break_count; + min_bc_index = i; + min_penalty = m_penalty; + } + VERIFY(-break_count == flip(~lit)); + } + if (m_rng(100) <= m_non_greedy_percent) { + lit = cls.m_lits[m_rng(cls.m_lits.size())]; + } + else { + // just do a greedy move: + lit = cls.m_lits[min_bc_index]; + } + flip(lit); + return lit; + } + + // + // TODO: alternate version: loop over soft clauses and see if there is a flip that + // reduces the penalty while preserving the hard constraints. + // + + // crude selection strategy. + clause const& pick_hard_clause() { + SASSERT(!m_hard_false.empty()); + return m_clauses[m_hard_false.choose(m_rng)]; + } + + clause const& pick_soft_clause() { + SASSERT(!m_soft_false.empty()); + return m_soft[m_soft_false.choose(m_rng)]; + } + + int flip(literal l) { + m_assignment[l.var()] = !m_assignment[l.var()]; + int break_count = 0; + unsigned_vector const& occh = m_hard_occ[l.var()]; + scoped_mpz value(mgr); + for (unsigned i = 0; i < occh.size(); ++i) { + unsigned j = occh[i]; + clause& cls = m_clauses[j]; + value = cls.m_value; + if (eval(cls)) { + if (m_hard_false.contains(j)) { + break_count--; + m_hard_false.remove(j); + } + } + else { + if (!m_hard_false.contains(j)) { + break_count++; + m_hard_false.insert(j); + } + else if (value < m_clauses[j].m_value) { + } + } + } + unsigned_vector const& occs = m_soft_occ[l.var()]; + for (unsigned i = 0; i < occs.size(); ++i) { + unsigned j = occs[i]; + if (eval(m_soft[j])) { + if (m_soft_false.contains(j)) { + m_penalty -= m_weights[j]; + m_soft_false.remove(j); + } + } + else { + if (!m_soft_false.contains(j)) { + m_penalty += m_weights[j]; + m_soft_false.insert(j); + } + } + } + + TRACE("opt", tout << "flip: " << l << " num false: " << m_hard_false.num_elems() + << " penalty: " << m_penalty << " break count: " << break_count << "\n";); + return break_count; + } + + literal mk_aux_literal(expr* f) { + unsigned var; + expr_ref tmp(m); + if (!m_decl2var.find(f, var)) { + var = m_hard_occ.size(); + SASSERT(m_var2decl.size() == var); + SASSERT(m_soft_occ.size() == var); + m_hard_occ.push_back(unsigned_vector()); + m_soft_occ.push_back(unsigned_vector()); + VERIFY(m_orig_model->eval(f, tmp)); + m_assignment.push_back(m.is_true(tmp)); + m_decl2var.insert(f, var); + m_var2decl.push_back(f); + } + return literal(var); + } + void pad(scoped_mpz_vector& vec, unsigned sz, mpz& val) { + for (unsigned i = 0; i < sz; ++i) { + vec.push_back(val); + } + } + literal mk_literal(expr* f) { + if (m.is_not(f, f)) { + literal result = mk_literal(f); + if (result != null_literal) { + result.neg(); + } + return result; + } + if (is_uninterp_const(f)) + return mk_aux_literal(to_app(f)); + if (m.is_true(f)) + return true_literal; + if (m.is_false(f)) + return false_literal; + if (m.is_and(f)) { + literal_vector lits; + app* g = to_app(f); + for (unsigned i = 0; i < g->get_num_args(); ++i) { + lits.push_back(mk_literal(g->get_arg(i))); + } + literal result = mk_aux_literal(f); + for (unsigned i = 0; i < lits.size(); ++i) { + clause cls(mgr); + cls.m_lits.push_back(~result); + cls.m_weights.push_back(one); + cls.m_lits.push_back(lits[i]); + cls.m_weights.push_back(one); + cls.m_k = one; + cls.m_eq = false; + m_clauses.push_back(cls); + m_orig_clauses.push_back(f); + lits[i].neg(); + } + lits.push_back(result); + clause cls(mgr); + cls.m_lits.append(lits); + pad(cls.m_weights, lits.size(), one); + cls.m_k = one; + cls.m_eq = false; + m_clauses.push_back(cls); + m_orig_clauses.push_back(f); + return result; + } + if (m.is_or(f)) { + literal_vector lits; + app* g = to_app(f); + for (unsigned i = 0; i < g->get_num_args(); ++i) { + lits.push_back(mk_literal(g->get_arg(i))); + } + literal result = mk_aux_literal(f); + for (unsigned i = 0; i < lits.size(); ++i) { + clause cls(mgr); + cls.m_lits.push_back(result); + cls.m_weights.push_back(one); + cls.m_lits.push_back(~lits[i]); + cls.m_weights.push_back(one); + cls.m_k = one; + cls.m_eq = false; + m_clauses.push_back(cls); + m_orig_clauses.push_back(f); + } + lits.push_back(~result); + clause cls(mgr); + cls.m_lits.append(lits); + pad(cls.m_weights, lits.size(), one); + cls.m_k = one; + cls.m_eq = false; + m_clauses.push_back(cls); + m_orig_clauses.push_back(f); + return result; + } + expr* x, *y; + if ((m.is_eq(f, x, y) && m.is_bool(x)) || m.is_iff(f, x, y)) { + literal a = mk_literal(x); + literal b = mk_literal(y); + literal result = mk_aux_literal(f); + clause cls(mgr); + cls.m_lits.push_back(~result); + cls.m_lits.push_back(~a); + cls.m_lits.push_back(b); + pad(cls.m_weights, 3, one); + cls.m_k = one; + cls.m_eq = false; + m_clauses.push_back(cls); + m_orig_clauses.push_back(f); // actually, the clause that defines f + cls.m_lits[0] = ~result; + cls.m_lits[1] = a; + cls.m_lits[2] = ~b; + m_clauses.push_back(cls); + m_orig_clauses.push_back(f); + cls.m_lits[0] = result; + cls.m_lits[1] = a; + cls.m_lits[2] = b; + m_clauses.push_back(cls); + m_orig_clauses.push_back(f); + cls.m_lits[0] = result; + cls.m_lits[1] = ~a; + cls.m_lits[2] = ~b; + m_clauses.push_back(cls); + m_orig_clauses.push_back(f); + return result; + } + if (pb.is_ge(f)) { + + } + IF_VERBOSE(0, verbose_stream() << "not handled: " << mk_pp(f, m) << "\n";); + return mk_aux_literal(f); + } + + bool compile_clause(expr* _f, clause& cls) { + expr_ref tmp(m); + m_rewrite(_f, tmp); + if (!is_app(tmp)) return false; + app* f = to_app(tmp); + expr* f2; + unsigned sz = f->get_num_args(); + expr* const* args = f->get_args(); + literal lit; + rational coeff, k; + if (m.is_not(f, f2) && pb.is_ge(f2)) { + // ~(ax+by >= k) + // <=> + // ax + by < k + // <=> + // -ax - by >= -k + 1 + // <=> + // a(1-x) + b(1-y) >= -k + a + b + 1 + sz = to_app(f2)->get_num_args(); + args = to_app(f2)->get_args(); + k = pb.get_k(f2); + SASSERT(k.is_int()); + k.neg(); + k += rational::one(); + expr_ref_vector args(m); + vector coeffs; + for (unsigned i = 0; i < sz; ++i) { + args.push_back(m.mk_not(to_app(f2)->get_arg(i))); + coeffs.push_back(pb.get_coeff(f2, i)); + k += pb.get_coeff(f2, i); + } + tmp = pb.mk_ge(coeffs.size(), coeffs.c_ptr(), args.c_ptr(), k); + return compile_clause(tmp, cls); + } + else if (pb.is_ge(f) || pb.is_eq(f)) { + k = pb.get_k(f); + SASSERT(k.is_int()); + cls.m_k = k.to_mpq().numerator(); + for (unsigned i = 0; i < sz; ++i) { + coeff = pb.get_coeff(f, i); + SASSERT(coeff.is_int()); + lit = mk_literal(args[i]); + if (lit == null_literal) return false; + if (lit == false_literal) continue; + if (lit == true_literal) { + cls.m_k -= coeff.to_mpq().numerator(); + continue; + } + cls.m_lits.push_back(lit); + cls.m_weights.push_back(coeff.to_mpq().numerator()); + if (get_value(lit)) { + cls.m_value += coeff.to_mpq().numerator(); + } + } + cls.m_eq = pb.is_eq(f); + } + else if (m.is_or(f)) { + for (unsigned i = 0; i < sz; ++i) { + lit = mk_literal(args[i]); + if (lit == null_literal) return false; + if (lit == false_literal) continue; + if (lit == true_literal) return false; + cls.m_lits.push_back(lit); + cls.m_weights.push_back(mpz(1)); + if (get_value(lit)) { + cls.m_value += mpz(1); + } + } + cls.m_eq = false; + cls.m_k = mpz(1); + } + else if (m.is_true(f)) { + return false; + } + else { + lit = mk_literal(f); + if (lit == null_literal) return false; + SASSERT(lit != false_literal && lit != true_literal); + cls.m_lits.push_back(lit); + cls.m_weights.push_back(mpz(1)); + cls.m_eq = true; + cls.m_k = mpz(1); + } + return true; + } + + }; + + pb_sls::pb_sls(ast_manager& m) { + m_imp = alloc(imp, m); + } + pb_sls::~pb_sls() { + dealloc(m_imp); + } + void pb_sls::add(expr* f) { + m_imp->add(f); + } + void pb_sls::add(expr* f, rational const& w) { + m_imp->add(f, w); + } + void pb_sls::set_model(model_ref& mdl) { + m_imp->set_model(mdl); + } + lbool pb_sls::operator()() { + return (*m_imp)(); + } + void pb_sls::set_cancel(bool f) { + m_imp->set_cancel(f); + } + void pb_sls::collect_statistics(statistics& st) const { + m_imp->collect_statistics(st); + } + void pb_sls::get_model(model_ref& mdl) { + m_imp->get_model(mdl); + } + void pb_sls::reset() { + m_imp->reset(); + } + bool pb_sls::soft_holds(unsigned index) { + return m_imp->soft_holds(index); + } + void pb_sls::updt_params(params_ref& p) { + m_imp->updt_params(p); + } + +} diff --git a/src/opt/pb_sls.h b/src/opt/pb_sls.h new file mode 100644 index 000000000..d3993dc49 --- /dev/null +++ b/src/opt/pb_sls.h @@ -0,0 +1,51 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + pb_sls.h + +Abstract: + + SLS for PB optimization. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-03-18 + +Notes: + +--*/ +#ifndef _PB_SLS_H_ +#define _PB_SLS_H_ + +#include "pb_decl_plugin.h" +#include "model.h" +#include "lbool.h" +#include "params.h" +#include "statistics.h" + +namespace smt { + + class pb_sls { + struct imp; + imp* m_imp; + public: + pb_sls(ast_manager& m); + ~pb_sls(); + void add(expr* f); + void add(expr* f, rational const& w); + bool soft_holds(unsigned index); + void set_model(model_ref& mdl); + lbool operator()(); + void set_cancel(bool f); + void collect_statistics(::statistics& st) const; + void get_model(model_ref& mdl); + void updt_params(params_ref& p); + void reset(); + }; + + +}; + +#endif diff --git a/src/opt/wmax.cpp b/src/opt/wmax.cpp new file mode 100644 index 000000000..48d46a6c9 --- /dev/null +++ b/src/opt/wmax.cpp @@ -0,0 +1,83 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + wmax.cpp + +Abstract: + + Theory based MaxSAT. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-17 + +Notes: + +--*/ +#include "wmax.h" +#include "uint_set.h" +#include "ast_pp.h" +#include "model_smt2_pp.h" +#include "smt_theory.h" +#include "smt_context.h" +#include "theory_wmaxsat.h" +#include "opt_context.h" + +namespace opt { + // ---------------------------------------------------------- + // weighted max-sat using a custom theory solver for max-sat. + // NB. it is quite similar to pseudo-Boolean propagation. + + + class wmax : public maxsmt_solver_base { + public: + wmax(context& c, weights_t& ws, expr_ref_vector const& soft): + maxsmt_solver_base(c, ws, soft) {} + virtual ~wmax() {} + + lbool operator()() { + TRACE("opt", tout << "weighted maxsat\n";); + scoped_ensure_theory wth(*this); + lbool is_sat = l_true; + bool was_sat = false; + for (unsigned i = 0; i < m_soft.size(); ++i) { + wth().assert_weighted(m_soft[i], m_weights[i]); + } + while (l_true == is_sat) { + is_sat = s().check_sat(0,0); + if (m_cancel) { + is_sat = l_undef; + } + if (is_sat == l_true) { + if (wth().is_optimal()) { + m_upper = wth().get_min_cost(); + s().get_model(m_model); + } + expr_ref fml = wth().mk_block(); + s().assert_expr(fml); + was_sat = true; + } + trace_bounds("wmax"); + } + if (was_sat) { + wth().get_assignment(m_assignment); + } + if (is_sat == l_false && was_sat) { + is_sat = l_true; + } + m_upper = wth().get_min_cost(); + if (is_sat == l_true) { + m_lower = m_upper; + } + TRACE("opt", tout << "min cost: " << m_upper << "\n";); + return is_sat; + } + }; + + maxsmt_solver_base* mk_wmax(context& c, weights_t& ws, expr_ref_vector const& soft) { + return alloc(wmax, c, ws, soft); + } + +} diff --git a/src/opt/wmax.h b/src/opt/wmax.h new file mode 100644 index 000000000..bb1be1b4e --- /dev/null +++ b/src/opt/wmax.h @@ -0,0 +1,29 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + wmax.h + +Abstract: + + Theory Solver based MaxSAT. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-4-17 + +Notes: + +--*/ + +#ifndef _WMAX_H_ +#define _WMAX_H_ + +#include "maxsmt.h" + +namespace opt { + maxsmt_solver_base* mk_wmax(context& c, weights_t & ws, expr_ref_vector const& soft); + +} +#endif diff --git a/src/qe/qe.cpp b/src/qe/qe.cpp index d229d8735..7372fdc2c 100644 --- a/src/qe/qe.cpp +++ b/src/qe/qe.cpp @@ -1451,7 +1451,7 @@ namespace qe { if (assumption) m_solver.assert_expr(assumption); bool is_sat = false; lbool res = l_true; - while (true) { + while (res == l_true) { res = m_solver.check(); if (res == l_true) { is_sat = true; @@ -2277,17 +2277,14 @@ namespace qe { void expr_quant_elim::instantiate_expr(expr_ref_vector& bound, expr_ref& fml) { - ptr_vector sorts; - get_free_vars(fml, sorts); - if (!sorts.empty()) { + expr_free_vars fv; + fv(fml); + fv.set_default_sort(m.mk_bool_sort()); + if (!fv.empty()) { expr_ref tmp(m); - for (unsigned i = sorts.size(); i > 0;) { + for (unsigned i = fv.size(); i > 0;) { --i; - sort* s = sorts[i]; - if (!s) { - s = m.mk_bool_sort(); - } - bound.push_back(m.mk_fresh_const("bound", s)); + bound.push_back(m.mk_fresh_const("bound", fv[i])); } var_subst subst(m); subst(fml, bound.size(), bound.c_ptr(), tmp); @@ -2438,7 +2435,6 @@ namespace qe { cache_result(q, q, 0); return; } - ast_manager& m = m_manager; quantifier_ref new_q(m); expr * new_body = 0; @@ -2464,7 +2460,6 @@ namespace qe { } void expr_quant_elim_star1::reduce_with_assumption(expr* ctx, expr* fml, expr_ref& result) { - ast_manager& m = m_manager; proof_ref pr(m); m_assumption = ctx; (*this)(fml, result, pr); diff --git a/src/qe/qe_arith_plugin.cpp b/src/qe/qe_arith_plugin.cpp index 83c7b79d8..75cba61fe 100644 --- a/src/qe/qe_arith_plugin.cpp +++ b/src/qe/qe_arith_plugin.cpp @@ -2049,6 +2049,7 @@ public: // z < d expr* z_lt_d = m_util.m_arith.mk_le(z, m_util.m_arith.mk_numeral(d-rational(1), true)); m_ctx.add_constraint(false, z_lt_d); + TRACE("qe", tout << mk_pp(z_lt_d, m) << "\n";); // result <- result & z <= d - 1 SASSERT(!abs(d).is_one()); @@ -2062,9 +2063,11 @@ public: t1 = m_util.mk_sub(x, z); m_util.mk_divides(d, t1, new_atom); m_ctx.add_constraint(false, new_atom); + TRACE("qe", tout << mk_pp(new_atom, m) << "\n";); // (c | ax + t <-> c | az + t) for each divisor. mk_div_equivs(bounds, z, result); + TRACE("qe", tout << mk_pp(result, m) << "\n";); // update x_t to map x |-> dx + z x_t.set_term(z); diff --git a/src/qe/qe_lite.cpp b/src/qe/qe_lite.cpp index 130673527..41214acb3 100644 --- a/src/qe/qe_lite.cpp +++ b/src/qe/qe_lite.cpp @@ -238,67 +238,95 @@ namespace eq { } } - bool solve_arith_core(app * lhs, expr * rhs, expr * eq, ptr_vector& vs, expr_ref_vector& ts) { - SASSERT(a.is_add(lhs)); - bool is_int = a.is_int(lhs); - expr * a1, *v; - expr_ref def(m); - rational a_val; - unsigned num = lhs->get_num_args(); - unsigned i; - for (i = 0; i < num; i++) { - expr * arg = lhs->get_arg(i); - if (is_variable(arg)) { - a_val = rational(1); - v = arg; - break; - } - else if (a.is_mul(arg, a1, v) && - is_variable(v) && - a.is_numeral(a1, a_val) && - !a_val.is_zero() && - (!is_int || a_val.is_minus_one())) { - break; + bool is_invertible_const(bool is_int, expr* x, rational& a_val) { + expr* y; + if (a.is_uminus(x, y) && is_invertible_const(is_int, y, a_val)) { + a_val.neg(); + return true; + } + else if (a.is_numeral(x, a_val) && !a_val.is_zero()) { + if (!is_int || a_val.is_one() || a_val.is_minus_one()) { + return true; } } - if (i == num) - return false; - vs.push_back(to_var(v)); - expr_ref inv_a(m); - if (!a_val.is_one()) { - inv_a = a.mk_numeral(rational(1)/a_val, is_int); - rhs = a.mk_mul(inv_a, rhs); - } - - ptr_buffer other_args; - for (unsigned j = 0; j < num; j++) { - if (i != j) { - if (inv_a) - other_args.push_back(a.mk_mul(inv_a, lhs->get_arg(j))); - else - other_args.push_back(lhs->get_arg(j)); - } - } - switch (other_args.size()) { - case 0: - def = rhs; - break; - case 1: - def = a.mk_sub(rhs, other_args[0]); - break; - default: - def = a.mk_sub(rhs, a.mk_add(other_args.size(), other_args.c_ptr())); - break; - } - ts.push_back(def); - return true; + return false; } + bool is_invertible_mul(bool is_int, expr*& arg, rational& a_val) { + if (is_variable(arg)) { + a_val = rational(1); + return true; + } + expr* x, *y; + if (a.is_mul(arg, x, y)) { + if (is_variable(x) && is_invertible_const(is_int, y, a_val)) { + arg = x; + return true; + } + if (is_variable(y) && is_invertible_const(is_int, x, a_val)) { + arg = y; + return true; + } + } + return false; + } + + typedef std::pair signed_expr; + + expr_ref solve_arith(bool is_int, rational const& r, bool sign, svector const& exprs) { + expr_ref_vector result(m); + for (unsigned i = 0; i < exprs.size(); ++i) { + bool sign2 = exprs[i].first; + expr* e = exprs[i].second; + rational r2(r); + if (sign == sign2) { + r2.neg(); + } + if (!r2.is_one()) { + result.push_back(a.mk_mul(a.mk_numeral(r2, is_int), e)); + } + else { + result.push_back(e); + } + } + return expr_ref(a.mk_add(result.size(), result.c_ptr()), m); + } + + bool solve_arith(expr* lhs, expr* rhs, ptr_vector& vs, expr_ref_vector& ts) { + if (!a.is_int(lhs) && !a.is_real(rhs)) { + return false; + } + rational a_val; + bool is_int = a.is_int(lhs); + svector todo, done; + todo.push_back(std::make_pair(true, lhs)); + todo.push_back(std::make_pair(false, rhs)); + while (!todo.empty()) { + expr* e = todo.back().second; + bool sign = todo.back().first; + todo.pop_back(); + if (a.is_add(e)) { + for (unsigned i = 0; i < to_app(e)->get_num_args(); ++i) { + todo.push_back(std::make_pair(sign, to_app(e)->get_arg(i))); + } + } + else if (is_invertible_mul(is_int, e, a_val)) { + done.append(todo); + vs.push_back(to_var(e)); + a_val = rational(1)/a_val; + ts.push_back(solve_arith(is_int, a_val, sign, done)); + TRACE("qe_lite", tout << mk_pp(lhs, m) << " " << mk_pp(rhs, m) << " " << mk_pp(e, m) << " := " << mk_pp(ts.back(), m) << "\n";); + return true; + } + else { + done.push_back(std::make_pair(sign, e)); + } + } + return false; + } bool arith_solve(expr * lhs, expr * rhs, expr * eq, ptr_vector& vs, expr_ref_vector& ts) { - return - (a.is_add(lhs) && solve_arith_core(to_app(lhs), rhs, eq, vs, ts)) || - (a.is_add(rhs) && solve_arith_core(to_app(rhs), lhs, eq, vs, ts)); + return solve_arith(lhs, rhs, vs, ts); } bool trivial_solve(expr* lhs, expr* rhs, expr* eq, ptr_vector& vs, expr_ref_vector& ts) { diff --git a/src/sat/sat_bceq.cpp b/src/sat/sat_bceq.cpp new file mode 100644 index 000000000..7ad0ec837 --- /dev/null +++ b/src/sat/sat_bceq.cpp @@ -0,0 +1,495 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sat_bceq.cpp + +Abstract: + + Find equivalent literals based on blocked clause decomposition. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-09-27. + + +Revision History: + +--*/ +#include"sat_bceq.h" +#include"sat_solver.h" +#include"trace.h" +#include"bit_vector.h" +#include"map.h" +#include"sat_elim_eqs.h" + +namespace sat { + + bceq::bceq(solver & s): + m_solver(s) { + } + + void bceq::register_clause(clause* cls) { + m_clauses.setx(cls->id(), cls, 0); + } + + void bceq::unregister_clause(clause* cls) { + m_clauses.setx(cls->id(), 0, 0); + } + + void bceq::init() { + m_clauses.reset(); + m_bin_clauses.reset(); + m_L.reset(); + m_R.reset(); + m_L_blits.reset(); + m_R_blits.reset(); + clause * const* it = m_solver.begin_clauses(); + clause * const* end = m_solver.end_clauses(); + for (; it != end; ++it) { + clause* cls = *it; + if (!cls->was_removed()) { + m_use_list->insert(*cls); + register_clause(cls); + } + } + bin_clauses bc; + m_solver.collect_bin_clauses(bc, false); // exclude roots. + literal lits[2]; + for (unsigned i = 0; i < bc.size(); ++i) { + lits[0] = bc[i].first; + lits[1] = bc[i].second; + clause* cls = m_solver.m_cls_allocator.mk_clause(2, lits, false); + m_use_list->insert(*cls); + m_bin_clauses.push_back(cls); + register_clause(cls); + } + TRACE("sat", + for (unsigned i = 0; i < m_clauses.size(); ++i) { + clause const* cls = m_clauses[i]; + if (cls) tout << *cls << "\n"; + }); + } + + void bceq::pure_decompose() { + // while F != empty + // pick a clause and variable x in clause. + // get use list U1 of x and U2 of ~x + // assume |U1| >= |U2| + // add U1 to clause set. + for (unsigned i = 0; i < m_clauses.size(); ++i) { + clause* cls = m_clauses[i]; + if (cls) { + SASSERT(i == cls->id()); + pure_decompose((*cls)[0]); + SASSERT(!m_clauses[i]); + } + } + m_L.reverse(); + m_L_blits.reverse(); + } + + void bceq::pure_decompose(literal lit) { + clause_use_list& pos = m_use_list->get(lit); + clause_use_list& neg = m_use_list->get(~lit); + unsigned sz1 = m_L.size(); + unsigned sz2 = m_R.size(); + pure_decompose(pos, m_L); + pure_decompose(neg, m_R); + unsigned delta1 = m_L.size() - sz1; + unsigned delta2 = m_R.size() - sz2; + if (delta1 < delta2) { + m_L_blits.resize(sz1+delta2, ~lit); + m_R_blits.resize(sz2+delta1, lit); + for (unsigned i = 0; i < delta1; ++i) { + std::swap(m_L[sz1 + i], m_R[sz2 + i]); + } + for (unsigned i = delta1; i < delta2; ++i) { + m_L.push_back(m_R[sz2 + i]); + } + m_R.resize(sz2 + delta1); + std::swap(delta1, delta2); + } + else { + m_L_blits.resize(sz1+delta1, lit); + m_R_blits.resize(sz2+delta2, ~lit); + } + TRACE("bceq", tout << lit << " " << "pos: " << delta1 << " " << "neg: " << delta2 << "\n";); + } + + void bceq::pure_decompose(clause_use_list& uses, svector& clauses) { + clause_use_list::iterator it = uses.mk_iterator(); + while (!it.at_end()) { + clause& cls = it.curr(); + if (!cls.was_removed() && m_clauses[cls.id()]) { + clauses.push_back(&cls); + m_clauses[cls.id()] = 0; + } + it.next(); + } + } + + void bceq::post_decompose() { + m_marked.reset(); + m_marked.resize(2*m_solver.num_vars(), false); + use_list ul; + use_list* save = m_use_list; + m_use_list = &ul; + ul.init(m_solver.num_vars()); + for (unsigned i = 0; i < m_L.size(); ++i) { + ul.insert(*m_L[i]); + } +#define MOVE_R_TO_L \ + + // cheap pass: add clauses from R in order + // such that they are blocked with respect to + // predecessors. + m_removed.reset(); + for (unsigned i = 0; i < m_R.size(); ++i) { + literal lit = find_blocked(*m_R[i]); + if (lit != null_literal) { + m_L.push_back(m_R[i]); + m_L_blits.push_back(lit); + ul.insert(*m_R[i]); + m_R[i] = m_R.back(); + m_R_blits[i] = m_R_blits.back(); + m_R.pop_back(); + m_R_blits.pop_back(); + --i; + } + } + // expensive pass: add clauses from R as long + // as BCE produces the empty set of clauses. + for (unsigned i = 0; i < m_R.size(); ++i) { + if (bce(*m_R[i])) { + m_R[i] = m_R.back(); + m_R_blits[i] = m_R_blits.back(); + m_R.pop_back(); + m_R_blits.pop_back(); + --i; + } + } + m_use_list = save; + } + + bool bceq::bce(clause& cls) { + svector live_clauses; + use_list ul; + use_list* save = m_use_list; + m_use_list = &ul; + ul.init(m_solver.num_vars()); + for (unsigned i = 0; i < m_L.size(); ++i) { + ul.insert(*m_L[i]); + } + ul.insert(cls); + svector clauses(m_L), new_clauses; + literal_vector blits(m_L_blits), new_blits; + clauses.push_back(&cls); + blits.push_back(null_literal); + bool removed = false; + m_removed.reset(); + do { + removed = false; + for (unsigned i = 0; i < clauses.size(); ++i) { + clause& cls = *clauses[i]; + literal lit = find_blocked(cls); + if (lit != null_literal) { + m_removed.setx(cls.id(), true, false); + new_clauses.push_back(&cls); + new_blits.push_back(lit); + removed = true; + clauses[i] = clauses.back(); + blits[i] = blits.back(); + clauses.pop_back(); + blits.pop_back(); + --i; + } + } + } + while (removed); + if (clauses.empty()) { + m_L.reset(); + m_L_blits.reset(); + new_clauses.reverse(); + new_blits.reverse(); + m_L.append(new_clauses); + m_L_blits.append(new_blits); + } + if (!clauses.empty()) std::cout << "Number left after BCE: " << clauses.size() << "\n"; + return clauses.empty(); + } + + literal bceq::find_blocked(clause const& cls) { + TRACE("bceq", tout << cls << "\n";); + + unsigned sz = cls.size(); + for (unsigned i = 0; i < sz; ++i) { + m_marked[(~cls[i]).index()] = true; + } + literal result = null_literal; + for (unsigned i = 0; i < sz; ++i) { + literal lit = cls[i]; + if (is_blocked(lit)) { + TRACE("bceq", tout << "is blocked " << lit << " : " << cls << "\n";); + result = lit; + break; + } + } + for (unsigned i = 0; i < sz; ++i) { + m_marked[(~cls[i]).index()] = false; + } + return result; + } + + bool bceq::is_blocked(literal lit) const { + clause_use_list& uses = m_use_list->get(~lit); + clause_use_list::iterator it = uses.mk_iterator(); + while (!it.at_end()) { + clause const& cls = it.curr(); + unsigned sz = cls.size(); + bool is_axiom = m_removed.get(cls.id(), false); + for (unsigned i = 0; !is_axiom && i < sz; ++i) { + is_axiom = m_marked[cls[i].index()] && cls[i] != ~lit; + } + + TRACE("bceq", tout << "resolvent " << lit << " : " << cls << " " << (is_axiom?"axiom":"non-axiom") << "\n";); + if (!is_axiom) { + return false; + } + it.next(); + } + return true; + } + + + void bceq::init_rbits() { + m_rbits.reset(); + for (unsigned i = 0; i < m_solver.num_vars(); ++i) { + uint64 lo = m_rand() + (m_rand() << 16); + uint64 hi = m_rand() + (m_rand() << 16); + m_rbits.push_back(lo + (hi << 32ULL)); + } + } + + void bceq::init_reconstruction_stack() { + m_rstack.reset(); + m_bstack.reset(); + // decomposition already creates a blocked stack in the proper order. + m_rstack.append(m_L); + m_bstack.append(m_L_blits); + } + + uint64 bceq::eval_clause(clause const& cls) const { + uint64 b = 0; + unsigned sz = cls.size(); + for (unsigned i = 0; i < sz; ++i) { + literal lit = cls[i]; + uint64 val = m_rbits[lit.var()]; + if (lit.sign()) { + val = ~val; + } + b |= val; + } + return b; + } + + void bceq::sat_sweep() { + init_rbits(); + init_reconstruction_stack(); + for (unsigned i = 0; i < m_rstack.size(); ++i) { + clause const& cls = *m_rstack[i]; + literal block_lit = m_bstack[i]; + uint64 b = eval_clause(cls); + // v = 0, b = 0 -> v := 1 + // v = 0, b = 1 -> v := 0 + // v = 1, b = 0 -> v := 0 + // v = 1, b = 1 -> v := 1 + m_rbits[block_lit.var()] ^= ~b; + + } + DEBUG_CODE(verify_sweep();); + } + + void bceq::verify_sweep() { + for (unsigned i = 0; i < m_L.size(); ++i) { + uint64 b = eval_clause(*m_L[i]); + SASSERT((~b) == 0); + } + } + + struct u64_hash { unsigned operator()(uint64 u) const { return (unsigned)u; } }; + + struct u64_eq { bool operator()(uint64 u1, uint64 u2) const { return u1 == u2; } }; + + void bceq::extract_partition() { + unsigned num_vars = m_solver.num_vars(); + map table; + union_find<> union_find(m_union_find_ctx); + for (unsigned i = 0; i < num_vars; ++i) { + m_s->mk_var(true, true); + union_find.mk_var(); + } + for (unsigned i = 0; i < m_L.size(); ++i) { + m_s->mk_clause(m_L[i]->size(), m_L[i]->begin()); + } + for (unsigned i = 0; i < num_vars; ++i) { + uint64 val = m_rbits[i]; + unsigned index; + if (table.find(val, index)) { + union_find.merge(i, index); + } + else if (table.find(~val, index)) { + union_find.merge(i, index); + } + else { + table.insert(val, i); + } + } + TRACE("sat", union_find.display(tout);); + + // + // Preliminary version: + // A more appropriate is to walk each pair, + // and refine partition based on SAT results. + // + for (unsigned i = 0; i < num_vars; ++i) { + if (!union_find.is_root(i)) continue; + unsigned v = union_find.next(i); + unsigned last_v = UINT_MAX; + if (!m_solver.was_eliminated(i)) { + last_v = i; + } + while (v != i) { + if (!m_solver.was_eliminated(v)) { + if (last_v != UINT_MAX) { + if (check_equality(v, last_v)) { + // last_v was eliminated. + + } + else { + // TBD: refine partition. + } + } + last_v = v; + } + v = union_find.next(v); + } + } + } + + bool bceq::check_equality(unsigned v1, unsigned v2) { + TRACE("sat", tout << "check: " << v1 << " = " << v2 << "\n";); + uint64 val1 = m_rbits[v1]; + uint64 val2 = m_rbits[v2]; + literal l1 = literal(v1, false); + literal l2 = literal(v2, false); + if (val1 != val2) { + SASSERT(val1 == ~val2); + l2.neg(); + } + if (is_already_equiv(l1, l2)) { + TRACE("sat", tout << "Already equivalent: " << l1 << " " << l2 << "\n";); + return false; + } + + literal lits[2]; + lits[0] = l1; + lits[1] = ~l2; + lbool is_sat = m_s->check(2, lits); + if (is_sat == l_false) { + lits[0] = ~l1; + lits[1] = l2; + is_sat = m_s->check(2, lits); + } + if (is_sat == l_false) { + TRACE("sat", tout << "Found equivalent: " << l1 << " " << l2 << "\n";); + assert_equality(l1, l2); + } + else { + TRACE("sat", tout << "Not equivalent: " << l1 << " " << l2 << "\n";); + // TBD: if is_sat == l_true, then refine partition. + } + return is_sat == l_false; + } + + bool bceq::is_already_equiv(literal l1, literal l2) { + watch_list const& w1 = m_solver.get_wlist(l1); + bool found = false; + for (unsigned i = 0; !found && i < w1.size(); ++i) { + watched const& w = w1[i]; + found = w.is_binary_clause() && w.get_literal() == ~l2; + } + if (!found) return false; + found = false; + watch_list const& w2 = m_solver.get_wlist(~l1); + for (unsigned i = 0; !found && i < w2.size(); ++i) { + watched const& w = w2[i]; + found = w.is_binary_clause() && w.get_literal() == l2; + } + return found; + } + + void bceq::assert_equality(literal l1, literal l2) { + if (l2.sign()) { + l1.neg(); + l2.neg(); + } + literal_vector roots; + bool_var_vector vars; + for (unsigned i = 0; i < m_solver.num_vars(); ++i) { + roots.push_back(literal(i, false)); + } + roots[l2.var()] = l1; + vars.push_back(l2.var()); + elim_eqs elim(m_solver); + for (unsigned i = 0; i < vars.size(); ++i) { + std::cout << "var: " << vars[i] << " root: " << roots[vars[i]] << "\n"; + } + elim(roots, vars); + } + + void bceq::cleanup() { + m_solver.del_clauses(m_bin_clauses.begin(), m_bin_clauses.end()); + m_bin_clauses.reset(); + } + + + void bceq::operator()() { + if (!m_solver.m_config.m_bcd) return; + flet _disable_bcd(m_solver.m_config.m_bcd, false); + flet _disable_min(m_solver.m_config.m_minimize_core, false); + flet _disable_opt(m_solver.m_config.m_optimize_model, false); + flet _bound_maxc(m_solver.m_config.m_max_conflicts, 1500); + + use_list ul; + solver s(m_solver.m_params, 0); + s.m_config.m_bcd = false; + s.m_config.m_minimize_core = false; + s.m_config.m_optimize_model = false; + s.m_config.m_max_conflicts = 1500; + m_use_list = &ul; + m_s = &s; + ul.init(m_solver.num_vars()); + init(); + pure_decompose(); + post_decompose(); + std::cout << "Decomposed set " << m_L.size() << " rest: " << m_R.size() << "\n"; + + TRACE("sat", + tout << "Decomposed set " << m_L.size() << "\n"; + for (unsigned i = 0; i < m_L.size(); ++i) { + clause const* cls = m_L[i]; + if (cls) tout << *cls << "\n"; + } + tout << "remainder " << m_R.size() << "\n"; + for (unsigned i = 0; i < m_R.size(); ++i) { + clause const* cls = m_R[i]; + if (cls) tout << *cls << "\n"; + } + ); + sat_sweep(); + extract_partition(); + cleanup(); + } +}; diff --git a/src/sat/sat_bceq.h b/src/sat/sat_bceq.h new file mode 100644 index 000000000..0b05c45cd --- /dev/null +++ b/src/sat/sat_bceq.h @@ -0,0 +1,78 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sat_bceq.h + +Abstract: + + Find equivalent literals based on blocked clause decomposition. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-09-27. + +Revision History: + +--*/ +#ifndef _SAT_BCEQ_H_ +#define _SAT_BCEQ_H_ + +#include"sat_types.h" +#include "union_find.h" + + +namespace sat { + class solver; + class use_list; + class clause_use_list; + + class bceq { + typedef std::pair bin_clause; + typedef svector bin_clauses; + solver & m_solver; + use_list* m_use_list; + solver* m_s; + random_gen m_rand; + svector m_clauses; + svector m_L; + svector m_R; + literal_vector m_L_blits; + literal_vector m_R_blits; + svector m_bin_clauses; + svector m_rbits; + svector m_rstack; // stack of blocked clauses + literal_vector m_bstack; // stack of blocking literals + svector m_marked; + svector m_removed; // set of clauses removed (not considered in clause set during BCE) + union_find_default_ctx m_union_find_ctx; + + void init(); + void register_clause(clause* cls); + void unregister_clause(clause* cls); + void pure_decompose(); + void pure_decompose(literal lit); + void pure_decompose(clause_use_list& uses, svector& clauses); + void post_decompose(); + literal find_blocked(clause const& cls); + bool bce(clause& cls); + bool is_blocked(literal lit) const; + void init_rbits(); + void init_reconstruction_stack(); + void sat_sweep(); + void cleanup(); + uint64 eval_clause(clause const& cls) const; + void verify_sweep(); + void extract_partition(); + bool check_equality(unsigned v1, unsigned v2); + bool is_already_equiv(literal l1, literal l2); + void assert_equality(literal l1, literal l2); + public: + bceq(solver & s); + void operator()(); + }; + +}; + +#endif diff --git a/src/sat/sat_config.cpp b/src/sat/sat_config.cpp index fb81809b1..0c100aff2 100644 --- a/src/sat/sat_config.cpp +++ b/src/sat/sat_config.cpp @@ -107,6 +107,11 @@ namespace sat { m_gc_increment = p.gc_increment(); } m_minimize_lemmas = p.minimize_lemmas(); + m_minimize_core = p.minimize_core(); + m_minimize_core_partial = p.minimize_core_partial(); + m_optimize_model = p.optimize_model(); + m_soft_assumptions = p.soft_assumptions(); + m_bcd = p.bcd(); m_dyn_sub_res = p.dyn_sub_res(); } diff --git a/src/sat/sat_config.h b/src/sat/sat_config.h index 253786e11..29ef25f03 100644 --- a/src/sat/sat_config.h +++ b/src/sat/sat_config.h @@ -69,6 +69,12 @@ namespace sat { bool m_minimize_lemmas; bool m_dyn_sub_res; + bool m_minimize_core; + bool m_minimize_core_partial; + bool m_optimize_model; + bool m_soft_assumptions; + bool m_bcd; + symbol m_always_true; symbol m_always_false; diff --git a/src/sat/sat_justification.h b/src/sat/sat_justification.h index dd803feeb..b162662e8 100644 --- a/src/sat/sat_justification.h +++ b/src/sat/sat_justification.h @@ -52,6 +52,27 @@ namespace sat { bool is_ext_justification() const { return m_val2 == EXT_JUSTIFICATION; } ext_justification_idx get_ext_justification_idx() const { return m_val1; } }; + + inline std::ostream & operator<<(std::ostream & out, justification const & j) { + switch (j.get_kind()) { + case justification::NONE: + out << "none"; + break; + case justification::BINARY: + out << "binary " << j.get_literal(); + break; + case justification::TERNARY: + out << "ternary " << j.get_literal1() << " " << j.get_literal2(); + break; + case justification::CLAUSE: + out << "clause"; + break; + case justification::EXT_JUSTIFICATION: + out << "external"; + break; + } + return out; + } }; #endif diff --git a/src/sat/sat_mus.cpp b/src/sat/sat_mus.cpp new file mode 100644 index 000000000..65d776d84 --- /dev/null +++ b/src/sat/sat_mus.cpp @@ -0,0 +1,282 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sat_mus.cpp + +Abstract: + + Faster MUS extraction + +Author: + + Nikolaj Bjorner (nbjorner) 2014-20-7 + +Notes: + + +--*/ + +#include "sat_solver.h" +#include "sat_mus.h" +#include "sat_sls.h" + +namespace sat { + + mus::mus(solver& s):s(s), m_is_active(false) {} + + mus::~mus() {} + + void mus::reset() { + m_core.reset(); + m_mus.reset(); + m_model.reset(); + m_best_value = 0; + m_max_restarts = 10; + m_restart = s.m_stats.m_restart; + } + + void mus::set_core() { + m_mus.append(m_core); + s.m_core.reset(); + s.m_core.append(m_mus); + } + + void mus::update_model() { + double new_value = s.m_wsls.evaluate_model(s.m_model); + if (m_model.empty()) { + m_model.append(s.m_model); + m_best_value = new_value; + } + else if (m_best_value > new_value) { + m_model.reset(); + m_model.append(s.m_model); + m_best_value = new_value; + } + } + + lbool mus::operator()() { + flet _disable_min(s.m_config.m_minimize_core, false); + flet _disable_min_partial(s.m_config.m_minimize_core_partial, false); + flet _disable_opt(s.m_config.m_optimize_model, false); + flet _is_active(m_is_active, true); + IF_VERBOSE(2, verbose_stream() << "(sat.mus " << s.get_core() << ")\n";); + reset(); + return mus1(); + } + + lbool mus::mus1() { + bool minimize_partial = s.m_config.m_minimize_core_partial; + TRACE("sat", tout << "old core: " << s.get_core() << "\n";); + literal_vector& core = get_core(); + literal_vector& mus = m_mus; + if (core.size() > 64) { + return mus2(); + } + unsigned delta_time = 0; + unsigned core_miss = 0; + while (!core.empty()) { + IF_VERBOSE(2, verbose_stream() << "(opt.mus reducing core: " << core.size() << " new core: " << mus.size() << ")\n";); + TRACE("sat", + tout << "core: " << core << "\n"; + tout << "mus: " << mus << "\n";); + + if (s.m_cancel) { + set_core(); + return l_undef; + } + if (minimize_partial && 3*delta_time > core.size() && core.size() < mus.size()) { + break; + } + unsigned num_literals = core.size() + mus.size(); + if (num_literals <= 2) { + // IF_VERBOSE(0, verbose_stream() << "num literals: " << core << " " << mus << "\n";); + break; + } + + literal lit = core.back(); + core.pop_back(); + lbool is_sat; + { + scoped_append _sa(mus, core); + mus.push_back(~lit); + is_sat = s.check(mus.size(), mus.c_ptr()); + TRACE("sat", tout << "mus: " << mus << "\n";); + } + switch (is_sat) { + case l_undef: + core.push_back(lit); + set_core(); + return l_undef; + case l_true: { + SASSERT(value_at(lit, s.get_model()) == l_false); + mus.push_back(lit); + update_model(); + if (!core.empty()) { + // mr(); // TBD: measure + } + break; + } + case l_false: + literal_vector const& new_core = s.get_core(); + if (new_core.contains(~lit)) { + IF_VERBOSE(2, verbose_stream() << "miss core " << lit << "\n";); + ++core_miss; + } + else { + core_miss = 0; + TRACE("sat", tout << "new core: " << new_core << "\n";); + core.reset(); + for (unsigned i = 0; i < new_core.size(); ++i) { + literal lit = new_core[i]; + if (!mus.contains(lit)) { + core.push_back(lit); + } + } + } + break; + } + + unsigned new_num_literals = core.size() + mus.size(); + if (new_num_literals == num_literals) { + delta_time++; + } + else { + delta_time = 0; + } + } + TRACE("sat", tout << "new core: " << mus << "\n";); + set_core(); + IF_VERBOSE(2, verbose_stream() << "(sat.mus.new " << s.m_core << ")\n";); + return l_true; + } + + + // bisection search. + lbool mus::mus2() { + literal_set core(get_core()); + literal_set support; + lbool is_sat = qx(core, support, false); + s.m_core.reset(); + s.m_core.append(core.to_vector()); + IF_VERBOSE(2, verbose_stream() << "(sat.mus.new " << s.m_core << ")\n";); + return is_sat; + } + + lbool mus::qx(literal_set& assignment, literal_set& support, bool has_support) { + lbool is_sat = l_true; + if (s.m_stats.m_restart - m_restart > m_max_restarts) { + IF_VERBOSE(1, verbose_stream() << "restart budget exceeded\n";); + return l_true; + } + if (has_support) { + scoped_append _sa(m_mus, support.to_vector()); + is_sat = s.check(m_mus.size(), m_mus.c_ptr()); + switch (is_sat) { + case l_false: { + literal_set core(s.get_core()); + support &= core; + assignment.reset(); + return l_true; + } + case l_undef: + return l_undef; + case l_true: + update_model(); + break; + default: + break; + } + } + if (assignment.size() == 1) { + return l_true; + } + literal_set assign2; + split(assignment, assign2); + support |= assignment; + is_sat = qx(assign2, support, !assignment.empty()); + unsplit(support, assignment); + if (is_sat != l_true) return is_sat; + support |= assign2; + is_sat = qx(assignment, support, !assign2.empty()); + assignment |= assign2; + unsplit(support, assign2); + return is_sat; + } + + void mus::unsplit(literal_set& A, literal_set& B) { + literal_set A1, B1; + literal_set::iterator it = A.begin(), end = A.end(); + for (; it != end; ++it) { + if (B.contains(*it)) { + B1.insert(*it); + } + else { + A1.insert(*it); + } + } + A = A1; + B = B1; + } + + void mus::split(literal_set& lits1, literal_set& lits2) { + unsigned half = lits1.size()/2; + literal_set lits3; + literal_set::iterator it = lits1.begin(), end = lits1.end(); + for (unsigned i = 0; it != end; ++it, ++i) { + if (i < half) { + lits3.insert(*it); + } + else { + lits2.insert(*it); + } + } + lits1 = lits3; + } + + literal_vector& mus::get_core() { + m_core.reset(); + m_mus.reset(); + literal_vector& core = m_core; + core.append(s.get_core()); + for (unsigned i = 0; i < core.size(); ++i) { + if (s.m_user_scope_literals.contains(core[i])) { + m_mus.push_back(core[i]); + core[i] = core.back(); + core.pop_back(); + --i; + } + } + return core; + } + + void mus::verify_core(literal_vector const& core) { + lbool is_sat = s.check(core.size(), core.c_ptr()); + IF_VERBOSE(3, verbose_stream() << "core verification: " << is_sat << " " << core << "\n";); + } + + void mus::mr() { + sls sls(s); + literal_vector tabu; + tabu.append(m_mus); + tabu.append(m_core); + bool reuse_model = false; + for (unsigned i = m_mus.size(); i < tabu.size(); ++i) { + tabu[i] = ~tabu[i]; + lbool is_sat = sls(tabu.size(), tabu.c_ptr(), reuse_model); + tabu[i] = ~tabu[i]; + if (is_sat == l_true) { + m_mus.push_back(tabu[i]); + m_core.erase(tabu[i]); + IF_VERBOSE(2, verbose_stream() << "in core " << tabu[i] << "\n";); + reuse_model = true; + } + else { + IF_VERBOSE(2, verbose_stream() << "NOT in core " << tabu[i] << "\n";); + reuse_model = false; + } + } + } +} + diff --git a/src/sat/sat_mus.h b/src/sat/sat_mus.h new file mode 100644 index 000000000..944cceffb --- /dev/null +++ b/src/sat/sat_mus.h @@ -0,0 +1,71 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + mus.h + +Abstract: + + Faster MUS extraction based on Belov et.al. HYB (Algorithm 3, 4) + +Author: + + Nikolaj Bjorner (nbjorner) 2014-20-7 + +Notes: + +--*/ +#ifndef _SAT_MUS_H_ +#define _SAT_MUS_H_ + +namespace sat { + class mus { + literal_vector m_core; + literal_vector m_mus; + bool m_is_active; + model m_model; // model obtained during minimal unsat core + double m_best_value; + unsigned m_restart; + unsigned m_max_restarts; + + + solver& s; + public: + mus(solver& s); + ~mus(); + lbool operator()(); + bool is_active() const { return m_is_active; } + model const& get_model() const { return m_model; } + private: + lbool mus1(); + lbool mus2(); + lbool qx(literal_set& assignment, literal_set& support, bool has_support); + void mr(); + void reset(); + void set_core(); + void update_model(); + literal_vector & get_core(); + void verify_core(literal_vector const& lits); + void split(literal_set& src, literal_set& dst); + void intersect(literal_set& dst, literal_set const& src); + void unsplit(literal_set& A, literal_set& B); + class scoped_append { + unsigned m_size; + literal_vector& m_lits; + public: + scoped_append(literal_vector& lits, literal_vector const& other): + m_size(lits.size()), + m_lits(lits) { + m_lits.append(other); + } + ~scoped_append() { + m_lits.resize(m_size); + } + + }; + }; + +}; + +#endif diff --git a/src/sat/sat_params.pyg b/src/sat/sat_params.pyg index de0283897..ed4f4910a 100644 --- a/src/sat/sat_params.pyg +++ b/src/sat/sat_params.pyg @@ -18,4 +18,10 @@ def_module_params('sat', ('gc.small_lbd', UINT, 3, 'learned clauses with small LBD are never deleted (only used in dyn_psm)'), ('gc.k', UINT, 7, 'learned clauses that are inactive for k gc rounds are permanently deleted (only used in dyn_psm)'), ('minimize_lemmas', BOOL, True, 'minimize learned clauses'), - ('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'))) + ('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'), + ('minimize_core', BOOL, False, 'minimize computed core'), + ('minimize_core_partial', BOOL, False, 'apply partial (cheap) core minimization'), + ('optimize_model', BOOL, False, 'enable optimization of soft constraints'), + ('soft_assumptions', BOOL, False, 'disable assumptions that are forced during unit propagation'), + ('bcd', BOOL, False, 'enable blocked clause decomposition for equality extraction'), + ('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks'))) diff --git a/src/sat/sat_simplifier.cpp b/src/sat/sat_simplifier.cpp index 219b9f278..59447b53d 100644 --- a/src/sat/sat_simplifier.cpp +++ b/src/sat/sat_simplifier.cpp @@ -137,8 +137,10 @@ namespace sat { return; if (!m_subsumption && !m_elim_blocked_clauses && !m_resolution) return; + CASSERT("sat_solver", s.check_invariant()); TRACE("before_simplifier", s.display(tout);); + s.m_cleaner(true); m_last_sub_trail_sz = s.m_trail.size(); TRACE("after_cleanup", s.display(tout);); @@ -156,6 +158,7 @@ namespace sat { if (!learned && (m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls)) elim_blocked_clauses(); + if (!learned) m_num_calls++; @@ -179,23 +182,21 @@ namespace sat { bool vars_eliminated = m_num_elim_vars > old_num_elim_vars; - if (!m_need_cleanup) { + if (m_need_cleanup) { + TRACE("after_simplifier", tout << "cleanning watches...\n";); + cleanup_watches(); + cleanup_clauses(s.m_learned, true, vars_eliminated, learned_in_use_lists); + cleanup_clauses(s.m_clauses, false, vars_eliminated, true); + } + else { TRACE("after_simplifier", tout << "skipping cleanup...\n";); if (vars_eliminated) { // must remove learned clauses with eliminated variables cleanup_clauses(s.m_learned, true, true, learned_in_use_lists); } - CASSERT("sat_solver", s.check_invariant()); - TRACE("after_simplifier", s.display(tout); tout << "model_converter:\n"; s.m_mc.display(tout);); - free_memory(); - return; } - TRACE("after_simplifier", tout << "cleanning watches...\n";); - cleanup_watches(); - cleanup_clauses(s.m_learned, true, vars_eliminated, learned_in_use_lists); - cleanup_clauses(s.m_clauses, false, vars_eliminated, true); - TRACE("after_simplifier", s.display(tout); tout << "model_converter:\n"; s.m_mc.display(tout);); CASSERT("sat_solver", s.check_invariant()); + TRACE("after_simplifier", s.display(tout); tout << "model_converter:\n"; s.m_mc.display(tout);); free_memory(); } @@ -920,7 +921,6 @@ namespace sat { model_converter::entry * new_entry = 0; if (s.is_external(l.var()) || s.was_eliminated(l.var())) return; - { m_to_remove.reset(); @@ -1178,7 +1178,6 @@ namespace sat { continue; m_visited[l2.index()] = false; } - return res; } @@ -1426,6 +1425,7 @@ namespace sat { }; void simplifier::elim_vars() { + if (!m_elim_vars) return; elim_var_report rpt(*this); bool_var_vector vars; order_vars_for_elim(vars); @@ -1465,6 +1465,7 @@ namespace sat { m_res_cls_cutoff2 = p.resolution_cls_cutoff2(); m_subsumption = p.subsumption(); m_subsumption_limit = p.subsumption_limit(); + m_elim_vars = p.elim_vars(); } void simplifier::collect_param_descrs(param_descrs & r) { diff --git a/src/sat/sat_simplifier.h b/src/sat/sat_simplifier.h index cb6fa9557..521990ea0 100644 --- a/src/sat/sat_simplifier.h +++ b/src/sat/sat_simplifier.h @@ -82,6 +82,7 @@ namespace sat { bool m_subsumption; unsigned m_subsumption_limit; + bool m_elim_vars; // stats unsigned m_num_blocked_clauses; diff --git a/src/sat/sat_simplifier_params.pyg b/src/sat/sat_simplifier_params.pyg index 6165e7e62..ff2944987 100644 --- a/src/sat/sat_simplifier_params.pyg +++ b/src/sat/sat_simplifier_params.pyg @@ -15,5 +15,6 @@ def_module_params(module_name='sat', ('resolution.lit_cutoff_range3', UINT, 300, 'second cutoff (total number of literals) for Boolean variable elimination, for problems containing more than res_cls_cutoff2'), ('resolution.cls_cutoff1', UINT, 100000000, 'limit1 - total number of problems clauses for the second cutoff of Boolean variable elimination'), ('resolution.cls_cutoff2', UINT, 700000000, 'limit2 - total number of problems clauses for the second cutoff of Boolean variable elimination'), + ('elim_vars', BOOL, True, 'enable variable elimination during simplification'), ('subsumption', BOOL, True, 'eliminate subsumed clauses'), ('subsumption.limit', UINT, 100000000, 'approx. maximum number of literals visited during subsumption (and subsumption resolution)'))) diff --git a/src/sat/sat_sls.cpp b/src/sat/sat_sls.cpp new file mode 100644 index 000000000..bd0f8855a --- /dev/null +++ b/src/sat/sat_sls.cpp @@ -0,0 +1,685 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sat_sls.cpp + +Abstract: + + SLS for clauses in SAT solver + +Author: + + Nikolaj Bjorner (nbjorner) 2014-12-8 + +Notes: + +--*/ + +#include "sat_sls.h" +#include "sat_solver.h" + +namespace sat { + + bool index_set::contains(unsigned idx) const { + return + (idx < m_index.size()) && + (m_index[idx] < m_elems.size()) && + (m_elems[m_index[idx]] == idx); + } + + void index_set::insert(unsigned idx) { + m_index.reserve(idx+1); + if (!contains(idx)) { + m_index[idx] = m_elems.size(); + m_elems.push_back(idx); + } + } + + void index_set::remove(unsigned idx) { + if (!contains(idx)) return; + unsigned pos = m_index[idx]; + m_elems[pos] = m_elems.back(); + m_index[m_elems[pos]] = pos; + m_elems.pop_back(); + } + + unsigned index_set::choose(random_gen& rnd) const { + SASSERT(!empty()); + return m_elems[rnd(num_elems())]; + } + + sls::sls(solver& s): s(s), m_cancel(false) { + m_prob_choose_min_var = 43; + m_clause_generation = 0; + } + + sls::~sls() { + for (unsigned i = 0; i < m_bin_clauses.size(); ++i) { + m_alloc.del_clause(m_bin_clauses[i]); + } + } + + lbool sls::operator()(unsigned sz, literal const* tabu, bool reuse_model) { + init(sz, tabu, reuse_model); + unsigned i; + for (i = 0; !m_false.empty() && !m_cancel && i < m_max_tries; ++i) { + flip(); + } + IF_VERBOSE(2, verbose_stream() << "tries " << i << "\n";); + if (m_false.empty()) { + SASSERT(s.check_model(m_model)); + return l_true; + } + return l_undef; + } + + void sls::init(unsigned sz, literal const* tabu, bool reuse_model) { + bool same_generation = (m_clause_generation == s.m_stats.m_non_learned_generation); + if (!same_generation) { + init_clauses(); + init_use(); + IF_VERBOSE(0, verbose_stream() << s.m_stats.m_non_learned_generation << " " << m_clause_generation << "\n";); + } + if (!reuse_model) { + init_model(); + } + init_tabu(sz, tabu); + m_clause_generation = s.m_stats.m_non_learned_generation; + + m_max_tries = 10*(s.num_vars() + m_clauses.size()); + + } + + void sls::init_clauses() { + for (unsigned i = 0; i < m_bin_clauses.size(); ++i) { + m_alloc.del_clause(m_bin_clauses[i]); + } + m_bin_clauses.reset(); + m_clauses.reset(); + clause * const * it = s.begin_clauses(); + clause * const * end = s.end_clauses(); + for (; it != end; ++it) { + m_clauses.push_back(*it); + } + svector bincs; + s.collect_bin_clauses(bincs, false); + literal lits[2]; + for (unsigned i = 0; i < bincs.size(); ++i) { + lits[0] = bincs[i].first; + lits[1] = bincs[i].second; + clause* cl = m_alloc.mk_clause(2, lits, false); + m_clauses.push_back(cl); + m_bin_clauses.push_back(cl); + } + } + + void sls::init_model() { + m_num_true.reset(); + m_model.reset(); + m_model.append(s.get_model()); + unsigned sz = m_clauses.size(); + for (unsigned i = 0; i < sz; ++i) { + clause const& c = *m_clauses[i]; + unsigned n = 0; + unsigned csz = c.size(); + for (unsigned j = 0; j < csz; ++j) { + lbool val = value_at(c[j], m_model); + switch (val) { + case l_true: + ++n; + break; + case l_undef: + ++n; + m_model[c[j].var()] = c[j].sign()?l_false:l_true; + SASSERT(value_at(c[j], m_model) == l_true); + break; + default: + break; + } + } + m_num_true.push_back(n); + if (n == 0) { + m_false.insert(i); + } + } + } + + void sls::init_tabu(unsigned sz, literal const* tabu) { + // our main use is where m_model satisfies all the hard constraints. + // SASSERT(s.check_model(m_model)); + // SASSERT(m_false.empty()); + // ASSERT: m_num_true is correct count. + m_tabu.reset(); + m_tabu.resize(s.num_vars(), false); + for (unsigned i = 0; i < sz; ++i) { + literal lit = tabu[i]; + if (s.m_level[lit.var()] == 0) continue; + if (value_at(lit, m_model) == l_false) { + flip(lit); + } + m_tabu[lit.var()] = true; + } + for (unsigned i = 0; i < s.m_trail.size(); ++i) { + literal lit = s.m_trail[i]; + if (s.m_level[lit.var()] > 0) break; + if (value_at(lit, m_model) != l_true) { + flip(lit); + } + m_tabu[lit.var()] = true; + } + } + + void sls::init_use() { + m_use_list.reset(); + m_use_list.resize(s.num_vars()*2); + unsigned sz = m_clauses.size(); + for (unsigned i = 0; i < sz; ++i) { + clause const& c = *m_clauses[i]; + unsigned csz = c.size(); + for (unsigned j = 0; j < csz; ++j) { + m_use_list[c[j].index()].push_back(i); + } + } + DEBUG_CODE(check_use_list();); + } + + unsigned_vector const& sls::get_use(literal lit) { + SASSERT(lit.index() < m_use_list.size()); + return m_use_list[lit.index()]; + } + + unsigned sls::get_break_count(literal lit, unsigned min_break) { + SASSERT(value_at(lit, m_model) == l_false); + unsigned result = 0; + unsigned_vector const& uses = get_use(~lit); + unsigned sz = uses.size(); + for (unsigned i = 0; i < sz; ++i) { + if (m_num_true[uses[i]] == 1) { + ++result; + if (result > min_break) return result; + } + } + return result; + } + + bool sls::pick_flip(literal& lit) { + unsigned clause_idx = m_false.choose(m_rand); + clause const& c = *m_clauses[clause_idx]; + SASSERT(!c.satisfied_by(m_model)); + unsigned min_break = UINT_MAX; + unsigned sz = c.size(); + m_min_vars.reset(); + for (unsigned i = 0; i < sz; ++i) { + lit = c[i]; + if (m_tabu[lit.var()]) continue; + unsigned break_count = get_break_count(lit, min_break); + if (break_count < min_break) { + min_break = break_count; + m_min_vars.reset(); + m_min_vars.push_back(lit); + } + else if (break_count == min_break) { + m_min_vars.push_back(lit); + } + } + if (min_break == 0 || (!m_min_vars.empty() && m_rand(100) >= m_prob_choose_min_var)) { + lit = m_min_vars[m_rand(m_min_vars.size())]; + return true; + } + else if (min_break == UINT_MAX) { + return false; + } + else { + lit = c[m_rand(c.size())]; + return !m_tabu[lit.var()]; + } + } + + void sls::flip() { + literal lit; + if (pick_flip(lit)) { + flip(lit); + } + } + + void sls::flip(literal lit) { + //IF_VERBOSE(0, verbose_stream() << lit << " ";); + SASSERT(value_at(lit, m_model) == l_false); + SASSERT(!m_tabu[lit.var()]); + m_model[lit.var()] = lit.sign()?l_false:l_true; + SASSERT(value_at(lit, m_model) == l_true); + unsigned_vector const& use1 = get_use(lit); + unsigned sz = use1.size(); + for (unsigned i = 0; i < sz; ++i) { + unsigned cl = use1[i]; + m_num_true[cl]++; + SASSERT(m_num_true[cl] <= m_clauses[cl]->size()); + if (m_num_true[cl] == 1) m_false.remove(cl); + } + unsigned_vector const& use2 = get_use(~lit); + sz = use2.size(); + for (unsigned i = 0; i < sz; ++i) { + unsigned cl = use2[i]; + SASSERT(m_num_true[cl] > 0); + m_num_true[cl]--; + if (m_num_true[cl] == 0) m_false.insert(cl); + } + } + + void sls::check_invariant() { + for (unsigned i = 0; i < m_clauses.size(); ++i) { + clause const& c = *m_clauses[i]; + bool is_sat = c.satisfied_by(m_model); + SASSERT(is_sat != m_false.contains(i)); + SASSERT(is_sat == m_num_true[i] > 0); + } + } + + void sls::check_use_list() { + + for (unsigned i = 0; i < m_clauses.size(); ++i) { + clause const& c = *m_clauses[i]; + for (unsigned j = 0; j < c.size(); ++j) { + unsigned idx = c[j].index(); + SASSERT(m_use_list[idx].contains(i)); + } + } + + for (unsigned i = 0; i < m_use_list.size(); ++i) { + literal lit = to_literal(i); + for (unsigned j = 0; j < m_use_list[i].size(); ++j) { + clause const& c = *m_clauses[m_use_list[i][j]]; + bool found = false; + for (unsigned k = 0; !found && k < c.size(); ++k) { + found = c[k] == lit; + } + SASSERT(found); + } + } + } + + void sls::display(std::ostream& out) const { + out << "Model\n"; + for (bool_var v = 0; v < m_model.size(); ++v) { + out << v << ": " << m_model[v] << "\n"; + } + out << "Clauses\n"; + unsigned sz = m_false.num_elems(); + for (unsigned i = 0; i < sz; ++i) { + out << *m_clauses[m_false[i]] << "\n"; + } + for (unsigned i = 0; i < m_clauses.size(); ++i) { + if (m_false.contains(i)) continue; + clause const& c = *m_clauses[i]; + out << c << " " << m_num_true[i] << "\n"; + } + bool has_tabu = false; + for (unsigned i = 0; !has_tabu && i < m_tabu.size(); ++i) { + has_tabu = m_tabu[i]; + } + if (has_tabu) { + out << "Tabu: "; + for (unsigned i = 0; i < m_tabu.size(); ++i) { + if (m_tabu[i]) { + literal lit(i, false); + if (value_at(lit, m_model) == l_false) lit.neg(); + out << lit << " "; + } + } + out << "\n"; + } + } + + + wsls::wsls(solver& s): + sls(s) + { + m_smoothing_probability = 1; // 1/1000 + } + + wsls::~wsls() {} + + void wsls::set_soft(unsigned sz, literal const* lits, double const* weights) { + m_soft.reset(); + m_weights.reset(); + m_soft.append(sz, lits); + m_weights.append(sz, weights); + } + + void wsls::opt(unsigned sz, literal const* tabu, bool reuse_model) { + init(sz, tabu, reuse_model); + + // + // Initialize m_clause_weights, m_hscore, m_sscore. + // + m_best_value = m_false.empty()?evaluate_model(m_model):-1.0; + m_best_model.reset(); + m_clause_weights.reset(); + m_hscore.reset(); + m_sscore.reset(); + m_H.reset(); + m_S.reset(); + m_best_model.append(s.get_model()); + m_clause_weights.resize(m_clauses.size(), 1); + m_sscore.resize(s.num_vars(), 0.0); + m_hscore.resize(s.num_vars(), 0); + unsigned num_violated = 0; + for (unsigned i = 0; i < m_soft.size(); ++i) { + literal lit = m_soft[i]; + m_sscore[lit.var()] = m_weights[i]; + if (value_at(lit, m_model) == l_true) { + m_sscore[lit.var()] = -m_sscore[lit.var()]; + } + } + for (bool_var i = 0; i < s.num_vars(); ++i) { + m_hscore[i] = compute_hscore(i); + refresh_scores(i); + } + DEBUG_CODE(check_invariant();); + unsigned i = 0; + for (; !m_cancel && m_best_value > 0 && i < m_max_tries; ++i) { + wflip(); + if (m_false.empty()) { + double val = evaluate_model(m_model); + if (val < m_best_value || m_best_value < 0.0) { + m_best_value = val; + m_best_model.reset(); + m_best_model.append(m_model); + IF_VERBOSE(1, verbose_stream() << "new value: " << val << " @ " << i << "\n";); + if (i*2 > m_max_tries) { + m_max_tries *= 2; + } + } + } + } + TRACE("sat", display(tout);); + IF_VERBOSE(0, verbose_stream() << "tries " << i << "\n";); + } + + void wsls::wflip() { + literal lit; + if (pick_wflip(lit)) { + // IF_VERBOSE(0, verbose_stream() << lit << " ";); + wflip(lit); + } + } + + bool wsls::pick_wflip(literal & lit) { + unsigned idx; + if (!m_H.empty()) { + idx = m_H.choose(m_rand); + lit = literal(idx, false); + if (value_at(lit, m_model) == l_true) lit.neg(); + SASSERT(value_at(lit, m_model) == l_false); + TRACE("sat", tout << "flip H(" << m_H.num_elems() << ") " << lit << "\n";); + } + else if (!m_S.empty()) { + double score = 0.0; + m_min_vars.reset(); + for (unsigned i = 0; i < m_S.num_elems(); ++i) { + unsigned v = m_S[i]; + SASSERT(m_sscore[v] > 0.0); + if (m_sscore[v] > score) { + m_min_vars.reset(); + m_min_vars.push_back(literal(v, false)); + score = m_sscore[v]; + } + else if (m_sscore[v] == score) { + m_min_vars.push_back(literal(v, false)); + } + } + lit = m_min_vars[m_rand(m_min_vars.size())]; // pick with largest sscore. + SASSERT(value_at(lit, m_model) == l_false); + TRACE("sat", tout << "flip S(" << m_min_vars.size() << "," << score << ") " << lit << "\n";); + } + else { + update_hard_weights(); + if (!m_false.empty()) { + unsigned cls_idx = m_false.choose(m_rand); + clause const& c = *m_clauses[cls_idx]; + lit = c[m_rand(c.size())]; + TRACE("sat", tout << "flip hard(" << m_false.num_elems() << "," << c.size() << ") " << lit << "\n";); + } + else { + m_min_vars.reset(); + for (unsigned i = 0; i < m_soft.size(); ++i) { + lit = m_soft[i]; + if (value_at(lit, m_model) == l_false) { + m_min_vars.push_back(lit); + } + } + if (m_min_vars.empty()) { + SASSERT(m_best_value == 0.0); + UNREACHABLE(); // we should have exited the main loop before. + return false; + } + else { + lit = m_min_vars[m_rand(m_min_vars.size())]; + } + TRACE("sat", tout << "flip soft(" << m_min_vars.size() << ", " << m_sscore[lit.var()] << ") " << lit << "\n";); + + } + SASSERT(value_at(lit, m_model) == l_false); + } + return !m_tabu[lit.var()]; + } + + void wsls::wflip(literal lit) { + flip(lit); + unsigned v = lit.var(); + m_sscore[v] = -m_sscore[v]; + m_hscore[v] = compute_hscore(v); + refresh_scores(v); + recompute_hscores(lit); + } + + void wsls::update_hard_weights() { + unsigned csz = m_clauses.size(); + if (m_smoothing_probability >= m_rand(1000)) { + for (unsigned i = 0; i < csz; ++i) { + if (m_clause_weights[i] > 1 && !m_false.contains(i)) { + --m_clause_weights[i]; + if (m_num_true[i] == 1) { + clause const& c = *m_clauses[i]; + unsigned sz = c.size(); + for (unsigned j = 0; j < sz; ++j) { + if (value_at(c[j], m_model) == l_true) { + ++m_hscore[c[j].var()]; + refresh_scores(c[j].var()); + break; + } + } + } + } + } + } + else { + for (unsigned i = 0; i < csz; ++i) { + if (m_false.contains(i)) { + ++m_clause_weights[i]; + clause const& c = *m_clauses[i]; + unsigned sz = c.size(); + for (unsigned j = 0; j < sz; ++j) { + ++m_hscore[c[j].var()]; + refresh_scores(c[j].var()); + } + } + } + } + DEBUG_CODE(check_invariant();); + } + + double wsls::evaluate_model(model& mdl) { + SASSERT(m_false.empty()); + double result = 0.0; + for (unsigned i = 0; i < m_soft.size(); ++i) { + literal lit = m_soft[i]; + if (value_at(lit, mdl) != l_true) { + result += m_weights[i]; + } + } + return result; + } + + int wsls::compute_hscore(bool_var v) { + literal lit(v, false); + if (value_at(lit, m_model) == l_false) { + lit.neg(); + } + SASSERT(value_at(lit, m_model) == l_true); + int hs = 0; + unsigned_vector const& use1 = get_use(~lit); + unsigned sz = use1.size(); + for (unsigned i = 0; i < sz; ++i) { + unsigned cl = use1[i]; + if (m_num_true[cl] == 0) { + SASSERT(m_false.contains(cl)); + hs += m_clause_weights[cl]; + } + else { + SASSERT(!m_false.contains(cl)); + } + } + unsigned_vector const& use2 = get_use(lit); + sz = use2.size(); + for (unsigned i = 0; i < sz; ++i) { + unsigned cl = use2[i]; + if (m_num_true[cl] == 1) { + SASSERT(!m_false.contains(cl)); + hs -= m_clause_weights[cl]; + } + } + return hs; + } + + void wsls::recompute_hscores(literal lit) { + SASSERT(value_at(lit, m_model) == l_true); + bool_var v = lit.var(); + TRACE("sat", tout << v << " := " << m_hscore[v] << "\n";); + unsigned_vector const& use1 = get_use(lit); + unsigned sz = use1.size(); + for (unsigned i = 0; i < sz; ++i) { + unsigned cl = use1[i]; + TRACE("sat", tout << *m_clauses[cl] << " " << m_num_true[cl] << "\n";); + SASSERT(m_num_true[cl] > 0); + if (m_num_true[cl] == 1) { + // num_true 0 -> 1 + // other literals don't have upside any more. + // subtract one from all other literals + adjust_all_values(lit, cl, -static_cast(m_clause_weights[cl])); + } + else if (m_num_true[cl] == 2) { + // num_true 1 -> 2, previous critical literal is no longer critical + adjust_pivot_value(lit, cl, +m_clause_weights[cl]); + } + } + unsigned_vector const& use2 = get_use(~lit); + sz = use2.size(); + for (unsigned i = 0; i < sz; ++i) { + unsigned cl = use2[i]; + TRACE("sat", tout << *m_clauses[cl] << " " << m_num_true[cl] << "\n";); + if (m_num_true[cl] == 0) { + // num_true 1 -> 0 + // all variables became critical. + adjust_all_values(~lit, cl, +m_clause_weights[cl]); + } + else if (m_num_true[cl] == 1) { + adjust_pivot_value(~lit, cl, -static_cast(m_clause_weights[cl])); + } + // else n+1 -> n >= 2 + } + } + + void wsls::adjust_all_values(literal lit, unsigned cl, int delta) { + clause const& c = *m_clauses[cl]; + unsigned sz = c.size(); + TRACE("sat", tout << lit << " " << c << " delta: " << delta << " nt: " << m_num_true[cl] << "\n";); + for (unsigned i = 0; i < sz; ++i) { + literal lit2 = c[i]; + if (lit2 != lit) { + TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";); + m_hscore[lit2.var()] += delta; + TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";); + refresh_scores(lit2.var()); + } + } + } + + void wsls::adjust_pivot_value(literal lit, unsigned cl, int delta) { + clause const& c = *m_clauses[cl]; + unsigned csz = c.size(); + for (unsigned j = 0; j < csz; ++j) { + literal lit2 = c[j]; + if (lit2 != lit && value_at(lit2, m_model) == l_true) { + TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";); + m_hscore[lit2.var()] += delta; + TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";); + refresh_scores(lit2.var()); + break; + } + } + } + + void wsls::refresh_scores(bool_var v) { + if (m_hscore[v] > 0 && !m_tabu[v] && m_sscore[v] == 0) { + m_H.insert(v); + } + else { + m_H.remove(v); + } + if (m_sscore[v] > 0) { + if (m_hscore[v] == 0 && !m_tabu[v]) { + m_S.insert(v); + } + else { + m_S.remove(v); + } + } + else if (m_sscore[v] < 0) { + m_S.remove(v); + } + } + + void wsls::check_invariant() { + sls::check_invariant(); + // The hscore is the reward for flipping the truth value of variable v. + // hscore(v) = Sum weight(c) for num_true(c) = 0 and v in c + // - Sum weight(c) for num_true(c) = 1 and (v in c, M(v) or !v in c and !M(v)) + for (unsigned v = 0; v < s.num_vars(); ++v) { + int hs = compute_hscore(v); + CTRACE("sat", hs != m_hscore[v], display(tout << v << " - computed: " << hs << " - assigned: " << m_hscore[v] << "\n");); + SASSERT(m_hscore[v] == hs); + } + + // The score(v) is the reward on soft clauses for flipping v. + for (unsigned j = 0; j < m_soft.size(); ++j) { + unsigned v = m_soft[j].var(); + double ss = (l_true == value_at(m_soft[j], m_model))?(-m_weights[j]):m_weights[j]; + SASSERT(m_sscore[v] == ss); + } + + // m_H are values such that m_hscore > 0 and sscore = 0. + for (bool_var v = 0; v < m_hscore.size(); ++v) { + SASSERT((m_hscore[v] > 0 && !m_tabu[v] && m_sscore[v] == 0) == m_H.contains(v)); + } + + // m_S are values such that hscore = 0, sscore > 0 + for (bool_var v = 0; v < m_sscore.size(); ++v) { + SASSERT((m_hscore[v] == 0 && m_sscore[v] > 0 && !m_tabu[v]) == m_S.contains(v)); + } + } + + void wsls::display(std::ostream& out) const { + sls::display(out); + out << "Best model\n"; + for (bool_var v = 0; v < m_best_model.size(); ++v) { + out << v << ": " << m_best_model[v] << " h: " << m_hscore[v]; + if (m_sscore[v] != 0.0) out << " s: " << m_sscore[v]; + out << "\n"; + } + } + +}; + diff --git a/src/sat/sat_sls.h b/src/sat/sat_sls.h new file mode 100644 index 000000000..530d4be0c --- /dev/null +++ b/src/sat/sat_sls.h @@ -0,0 +1,118 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sat_sls.h + +Abstract: + + SLS for clauses in SAT solver + +Author: + + Nikolaj Bjorner (nbjorner) 2014-12-8 + +Notes: + +--*/ +#ifndef _SAT_SLS_H_ +#define _SAT_SLS_H_ + +#include "util.h" +#include "sat_simplifier.h" + +namespace sat { + + class index_set { + unsigned_vector m_elems; + unsigned_vector m_index; + public: + unsigned num_elems() const { return m_elems.size(); } + unsigned operator[](unsigned idx) const { return m_elems[idx]; } + void reset() { m_elems.reset(); m_index.reset(); } + bool empty() const { return m_elems.empty(); } + bool contains(unsigned idx) const; + void insert(unsigned idx); + void remove(unsigned idx); + unsigned choose(random_gen& rnd) const; + }; + + class sls { + protected: + solver& s; + random_gen m_rand; + unsigned m_max_tries; + unsigned m_prob_choose_min_var; // number between 0 and 99. + unsigned m_clause_generation; + ptr_vector m_clauses; // vector of all clauses. + index_set m_false; // clauses currently false + vector m_use_list; // use lists for literals + unsigned_vector m_num_true; // per clause, count of # true literals + svector m_min_vars; // literals with smallest break count + model m_model; // current model + clause_allocator m_alloc; // clause allocator + clause_vector m_bin_clauses; // binary clauses + svector m_tabu; // variables that cannot be swapped + volatile bool m_cancel; + public: + sls(solver& s); + virtual ~sls(); + lbool operator()(unsigned sz, literal const* tabu, bool reuse_model); + void set_cancel(bool f) { m_cancel = f; } + void set_max_tries(unsigned mx) { m_max_tries = mx; } + virtual void display(std::ostream& out) const; + protected: + void init(unsigned sz, literal const* tabu, bool reuse_model); + void init_tabu(unsigned sz, literal const* tabu); + void init_model(); + void init_use(); + void init_clauses(); + unsigned_vector const& get_use(literal lit); + void flip(literal lit); + virtual void check_invariant(); + void check_use_list(); + private: + bool pick_flip(literal& lit); + void flip(); + unsigned get_break_count(literal lit, unsigned min_break); + }; + + /** + \brief sls with weighted soft clauses. + */ + class wsls : public sls { + unsigned_vector m_clause_weights; + svector m_hscore; + svector m_sscore; + literal_vector m_soft; + svector m_weights; + double m_best_value; + model m_best_model; + index_set m_H, m_S; + unsigned m_smoothing_probability; + public: + wsls(solver& s); + virtual ~wsls(); + void set_soft(unsigned sz, literal const* lits, double const* weights); + bool has_soft() const { return !m_soft.empty(); } + void opt(unsigned sz, literal const* tabu, bool reuse_model); + model const& get_model() { return m_best_model; } + virtual void display(std::ostream& out) const; + double evaluate_model(model& mdl); + private: + void wflip(); + void wflip(literal lit); + void update_hard_weights(); + bool pick_wflip(literal & lit); + virtual void check_invariant(); + void refresh_scores(bool_var v); + int compute_hscore(bool_var v); + void recompute_hscores(literal lit); + void adjust_all_values(literal lit, unsigned cl, int delta); + void adjust_pivot_value(literal lit, unsigned cl, int delta); + }; + +}; + +#endif diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index f898130af..6a5148192 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -20,6 +20,7 @@ Revision History: #include"sat_integrity_checker.h" #include"luby.h" #include"trace.h" +#include"sat_bceq.h" // define to update glue during propagation #define UPDATE_GLUE @@ -39,6 +40,8 @@ namespace sat { m_scc(*this, p), m_asymm_branch(*this, p), m_probing(*this, p), + m_mus(*this), + m_wsls(*this), m_inconsistent(false), m_num_frozen(0), m_activity_inc(128), @@ -47,6 +50,10 @@ namespace sat { m_scope_lvl(0), m_params(p) { updt_params(p); + m_conflicts_since_gc = 0; + m_conflicts = 0; + m_next_simplify = 0; + m_num_checkpoints = 0; } solver::~solver() { @@ -58,6 +65,7 @@ namespace sat { for (clause * const * it = begin; it != end; ++it) { m_cls_allocator.del_clause(*it); } + ++m_stats.m_non_learned_generation; } void solver::copy(solver const & src) { @@ -140,7 +148,16 @@ namespace sat { for (unsigned i = 0; i < num_lits; i++) SASSERT(m_eliminated[lits[i].var()] == false); }); - mk_clause_core(num_lits, lits, false); + + if (m_user_scope_literals.empty()) { + mk_clause_core(num_lits, lits, false); + } + else { + m_aux_literals.reset(); + m_aux_literals.append(num_lits, lits); + m_aux_literals.append(m_user_scope_literals); + mk_clause_core(m_aux_literals.size(), m_aux_literals.c_ptr(), false); + } } void solver::mk_clause(literal l1, literal l2) { @@ -153,15 +170,22 @@ namespace sat { mk_clause(3, ls); } + void solver::del_clause(clause& c) { + if (!c.is_learned()) m_stats.m_non_learned_generation++; + m_cls_allocator.del_clause(&c); + m_stats.m_del_clause++; + } + clause * solver::mk_clause_core(unsigned num_lits, literal * lits, bool learned) { + TRACE("sat", tout << "mk_clause: " << mk_lits_pp(num_lits, lits) << "\n";); if (!learned) { - TRACE("sat_mk_clause", tout << "mk_clause: " << mk_lits_pp(num_lits, lits) << "\n";); bool keep = simplify_clause(num_lits, lits); TRACE("sat_mk_clause", tout << "mk_clause (after simp), keep: " << keep << "\n" << mk_lits_pp(num_lits, lits) << "\n";); if (!keep) { return 0; // clause is equivalent to true. } - } + ++m_stats.m_non_learned_generation; + } switch (num_lits) { case 0: @@ -507,6 +531,10 @@ namespace sat { return found_undef ? l_undef : l_false; } + void solver::initialize_soft(unsigned sz, literal const* lits, double const* weights) { + m_wsls.set_soft(sz, lits, weights); + } + // ----------------------- // // Propagation @@ -666,6 +694,7 @@ namespace sat { } wlist.set_end(it2); } + SASSERT(m_qhead == m_trail.size()); SASSERT(!m_inconsistent); return true; } @@ -682,7 +711,9 @@ namespace sat { // Search // // ----------------------- - lbool solver::check() { + lbool solver::check(unsigned num_lits, literal const* lits) { + pop_to_base_level(); + IF_VERBOSE(2, verbose_stream() << "(sat.sat-solver)\n";); SASSERT(scope_lvl() == 0); #ifdef CLONE_BEFORE_SOLVING if (m_mc.empty()) { @@ -695,22 +726,24 @@ namespace sat { init_search(); propagate(false); if (inconsistent()) return l_false; + init_assumptions(num_lits, lits); + propagate(false); + if (check_inconsistent()) return l_false; cleanup(); if (m_config.m_max_conflicts > 0 && m_config.m_burst_search > 0) { m_restart_threshold = m_config.m_burst_search; lbool r = bounded_search(); if (r != l_undef) return r; - pop(scope_lvl()); + pop_reinit(scope_lvl()); m_conflicts_since_restart = 0; m_restart_threshold = m_config.m_restart_initial; } - // iff3_finder(*this)(); + // iff3_finder(*this)(); simplify_problem(); - - if (inconsistent()) return l_false; - m_next_simplify = m_config.m_restart_initial * m_config.m_simplify_mult1; + if (check_inconsistent()) return l_false; + if (m_config.m_max_conflicts == 0) { IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "\"abort: max-conflicts = 0\"\n";); @@ -730,12 +763,8 @@ namespace sat { } restart(); - if (m_conflicts >= m_next_simplify) { - simplify_problem(); - m_next_simplify = static_cast(m_conflicts * m_config.m_simplify_mult2); - if (m_next_simplify > m_conflicts + m_config.m_simplify_max) - m_next_simplify = m_conflicts + m_config.m_simplify_max; - } + simplify_problem(); + if (check_inconsistent()) return l_false; gc(); } } @@ -800,7 +829,7 @@ namespace sat { SASSERT(phase != l_undef); literal next_lit(next, phase == l_false); assign(next_lit, justification()); - TRACE("sat_decide", tout << "next-case-split: " << next_lit << "\n";); + TRACE("sat_decide", tout << scope_lvl() << ": next-case-split: " << next_lit << "\n";); return true; } @@ -819,8 +848,10 @@ namespace sat { return l_undef; if (scope_lvl() == 0) { cleanup(); // cleaner may propagate frozen clauses - if (inconsistent()) + if (inconsistent()) { + TRACE("sat", tout << "conflict at level 0\n";); return l_false; + } gc(); } } @@ -847,26 +878,122 @@ namespace sat { } } + bool solver::check_inconsistent() { + if (inconsistent()) { + if (tracking_assumptions()) + resolve_conflict(); + return true; + } + else { + return false; + } + } + + void solver::init_assumptions(unsigned num_lits, literal const* lits) { + if (num_lits == 0 && m_user_scope_literals.empty()) { + return; + } + m_assumptions.reset(); + m_assumption_set.reset(); + push(); + + propagate(false); + if (inconsistent()) { + return; + } + + TRACE("sat", + for (unsigned i = 0; i < num_lits; ++i) + tout << lits[i] << " "; + tout << "\n"; + if (!m_user_scope_literals.empty()) { + tout << "user literals: " << m_user_scope_literals << "\n"; + } + m_mc.display(tout); + ); + + for (unsigned i = 0; !inconsistent() && i < m_user_scope_literals.size(); ++i) { + literal nlit = ~m_user_scope_literals[i]; + assign(nlit, justification()); + } + + for (unsigned i = 0; !inconsistent() && i < num_lits; ++i) { + literal lit = lits[i]; + SASSERT(is_external((lit).var())); + m_assumption_set.insert(lit); + + if (m_config.m_soft_assumptions) { + if (value(lit) == l_undef) { + m_assumptions.push_back(lit); + assign(lit, justification()); + } + propagate(false); + } + else { + m_assumptions.push_back(lit); + assign(lit, justification()); + // propagate(false); + } + } + } + + void solver::reinit_assumptions() { + if (tracking_assumptions() && scope_lvl() == 0) { + TRACE("sat", tout << m_assumptions << "\n";); + push(); + for (unsigned i = 0; !inconsistent() && i < m_user_scope_literals.size(); ++i) { + assign(~m_user_scope_literals[i], justification()); + } + for (unsigned i = 0; !inconsistent() && i < m_assumptions.size(); ++i) { + assign(m_assumptions[i], justification()); + } + } + } + + bool solver::tracking_assumptions() const { + return !m_assumptions.empty(); + } + + bool solver::is_assumption(literal l) const { + return tracking_assumptions() && m_assumption_set.contains(l); + } + void solver::init_search() { + m_model_is_current = false; m_phase_counter = 0; m_phase_cache_on = false; - m_conflicts = 0; m_conflicts_since_restart = 0; m_restart_threshold = m_config.m_restart_initial; m_luby_idx = 1; - m_conflicts_since_gc = 0; m_gc_threshold = m_config.m_gc_initial; m_min_d_tk = 1.0; - m_next_simplify = 0; m_stopwatch.reset(); m_stopwatch.start(); + m_core.reset(); TRACE("sat", display(tout);); + + if (m_config.m_bcd) { + bceq bc(*this); + bc(); + } } /** \brief Apply all simplifications. + */ void solver::simplify_problem() { + if (m_conflicts < m_next_simplify) { + return; + } + IF_VERBOSE(2, verbose_stream() << "(sat.simplify)\n";); + + // Disable simplification during MUS computation. + // if (m_mus.is_active()) return; + TRACE("sat", tout << "simplify\n";); + + pop(scope_lvl()); + SASSERT(scope_lvl() == 0); m_cleaner(); @@ -878,7 +1005,7 @@ namespace sat { m_simplifier(false); CASSERT("sat_simplify_bug", check_invariant()); CASSERT("sat_missed_prop", check_missed_propagation()); - + if (!m_learned.empty()) { m_simplifier(true); CASSERT("sat_missed_prop", check_missed_propagation()); @@ -900,6 +1027,19 @@ namespace sat { m_ext->clauses_modifed(); m_ext->simplify(); } + + TRACE("sat", display(tout << "consistent: " << (!inconsistent()) << "\n");); + + reinit_assumptions(); + + if (m_next_simplify == 0) { + m_next_simplify = m_config.m_restart_initial * m_config.m_simplify_mult1; + } + else { + m_next_simplify = static_cast(m_conflicts * m_config.m_simplify_mult2); + if (m_next_simplify > m_conflicts + m_config.m_simplify_max) + m_next_simplify = m_conflicts + m_config.m_simplify_max; + } } void solver::sort_watch_lits() { @@ -913,6 +1053,7 @@ namespace sat { void solver::mk_model() { m_model.reset(); + m_model_is_current = true; unsigned num = num_vars(); m_model.resize(num, l_undef); for (bool_var v = 0; v < num; v++) { @@ -920,13 +1061,19 @@ namespace sat { m_model[v] = value(v); } TRACE("sat_mc_bug", m_mc.display(tout);); + if (m_config.m_optimize_model) { + m_wsls.opt(0, 0, false); + m_model.reset(); + m_model.append(m_wsls.get_model()); + } m_mc(m_model); - TRACE("sat_model", for (bool_var v = 0; v < num; v++) tout << v << ": " << m_model[v] << "\n";); + TRACE("sat", for (bool_var v = 0; v < num; v++) tout << v << ": " << m_model[v] << "\n";); #ifndef _EXTERNAL_RELEASE IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "\"checking model\"\n";); if (!check_model(m_model)) throw solver_exception("check model failed"); + if (m_clone) { IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "\"checking model (on original set of clauses)\"\n";); if (!m_clone->check_model(m_model)) @@ -945,7 +1092,12 @@ namespace sat { for (; it != end; ++it) { clause const & c = *(*it); if (!c.satisfied_by(m)) { - TRACE("sat_model_bug", tout << "failed: " << c << "\n";); + TRACE("sat", tout << "failed: " << c << "\n"; + tout << "assumptions: " << m_assumptions << "\n"; + tout << "trail: " << m_trail << "\n"; + tout << "model: " << m << "\n"; + m_mc.display(tout); + ); ok = false; } } @@ -963,15 +1115,28 @@ namespace sat { continue; literal l2 = it2->get_literal(); if (value_at(l2, m) != l_true) { - TRACE("sat_model_bug", tout << "failed binary: " << l << " " << l2 << " learned: " << it2->is_learned() << "\n";); + TRACE("sat", tout << "failed binary: " << l << " " << l2 << " learned: " << it2->is_learned() << "\n"; + m_mc.display(tout);); ok = false; } } } } - if (!m_mc.check_model(m)) + for (unsigned i = 0; i < m_assumptions.size(); ++i) { + if (value_at(m_assumptions[i], m) != l_true) { + TRACE("sat", + tout << m_assumptions[i] << " does not model check\n"; + tout << "trail: " << m_trail << "\n"; + tout << "model: " << m << "\n"; + m_mc.display(tout); + ); + ok = false; + } + } + if (ok && !m_mc.check_model(m)) { ok = false; - CTRACE("sat_model_bug", !ok, tout << m << "\n";); + TRACE("sat", tout << "model: " << m << "\n"; m_mc.display(tout);); + } return ok; } @@ -982,7 +1147,7 @@ namespace sat { << " :restarts " << m_stats.m_restart << mk_stat(*this) << " :time " << std::fixed << std::setprecision(2) << m_stopwatch.get_current_seconds() << ")\n";); IF_VERBOSE(30, display_status(verbose_stream());); - pop(scope_lvl()); + pop_reinit(scope_lvl()); m_conflicts_since_restart = 0; switch (m_config.m_restart) { case RS_GEOMETRIC: @@ -1255,7 +1420,7 @@ namespace sat { break; } } - TRACE("sat_gc", tout << "after cleanup:\n" << mk_lits_pp(j, c.begin()) << "\n";); + TRACE("sat", tout << "after cleanup:\n" << mk_lits_pp(j, c.begin()) << "\n";); unsigned new_sz = j; switch (new_sz) { case 0: @@ -1313,7 +1478,6 @@ namespace sat { } bool solver::resolve_conflict_core() { - TRACE("sat_conflict", tout << "conflict detected\n";); m_stats.m_conflict++; m_conflicts++; @@ -1321,8 +1485,18 @@ namespace sat { m_conflicts_since_gc++; m_conflict_lvl = get_max_lvl(m_not_l, m_conflict); - if (m_conflict_lvl == 0) + TRACE("sat", tout << "conflict detected at level " << m_conflict_lvl << " for "; + if (m_not_l == literal()) tout << "null literal\n"; + else tout << m_not_l << "\n";); + + if (m_conflict_lvl <= 1 && tracking_assumptions()) { + resolve_conflict_for_unsat_core(); return false; + } + if (m_conflict_lvl == 0) { + return false; + } + m_lemma.reset(); forget_phase_of_vars(m_conflict_lvl); @@ -1426,7 +1600,7 @@ namespace sat { unsigned glue = num_diff_levels(m_lemma.size(), m_lemma.c_ptr()); - pop(m_scope_lvl - new_scope_lvl); + pop_reinit(m_scope_lvl - new_scope_lvl); TRACE("sat_conflict_detail", display(tout); tout << "assignment:\n"; display_assignment(tout);); clause * lemma = mk_clause_core(m_lemma.size(), m_lemma.c_ptr(), true); if (lemma) { @@ -1437,6 +1611,155 @@ namespace sat { return true; } + void solver::process_antecedent_for_unsat_core(literal antecedent) { + bool_var var = antecedent.var(); + unsigned var_lvl = lvl(var); + SASSERT(var < num_vars()); + TRACE("sat", tout << antecedent << " " << (is_marked(var)?"+":"-") << "\n";); + if (!is_marked(var)) { + mark(var); + m_unmark.push_back(var); + if (is_assumption(antecedent)) { + m_core.push_back(antecedent); + } + } + } + + void solver::process_consequent_for_unsat_core(literal consequent, justification const& js) { + TRACE("sat", tout << "processing consequent: "; + if (consequent == null_literal) tout << "null\n"; + else tout << consequent << "\n"; + display_justification(tout << "js kind: ", js); + tout << "\n";); + switch (js.get_kind()) { + case justification::NONE: + break; + case justification::BINARY: + SASSERT(consequent != null_literal); + process_antecedent_for_unsat_core(~(js.get_literal())); + break; + case justification::TERNARY: + SASSERT(consequent != null_literal); + process_antecedent_for_unsat_core(~(js.get_literal1())); + process_antecedent_for_unsat_core(~(js.get_literal2())); + break; + case justification::CLAUSE: { + clause & c = *(m_cls_allocator.get_clause(js.get_clause_offset())); + unsigned i = 0; + if (consequent != null_literal) { + SASSERT(c[0] == consequent || c[1] == consequent); + if (c[0] == consequent) { + i = 1; + } + else { + process_antecedent_for_unsat_core(~c[0]); + i = 2; + } + } + unsigned sz = c.size(); + for (; i < sz; i++) + process_antecedent_for_unsat_core(~c[i]); + break; + } + case justification::EXT_JUSTIFICATION: { + fill_ext_antecedents(consequent, js); + literal_vector::iterator it = m_ext_antecedents.begin(); + literal_vector::iterator end = m_ext_antecedents.end(); + for (; it != end; ++it) + process_antecedent_for_unsat_core(*it); + break; + } + default: + UNREACHABLE(); + break; + } + } + + void solver::resolve_conflict_for_unsat_core() { + TRACE("sat", display(tout); + unsigned level = 0; + for (unsigned i = 0; i < m_trail.size(); ++i) { + literal l = m_trail[i]; + if (level != m_level[l.var()]) { + level = m_level[l.var()]; + tout << level << ": "; + } + tout << l; + if (m_mark[l.var()]) { + tout << "*"; + } + tout << " "; + } + tout << "\n"; + ); + + m_core.reset(); + if (m_conflict_lvl == 0) { + return; + } + SASSERT(m_unmark.empty()); + DEBUG_CODE({ + for (unsigned i = 0; i < m_trail.size(); ++i) { + SASSERT(!is_marked(m_trail[i].var())); + }}); + + unsigned old_size = m_unmark.size(); + int idx = skip_literals_above_conflict_level(); + + if (m_not_l != null_literal) { + justification js = m_justification[m_not_l.var()]; + TRACE("sat", tout << "not_l: " << m_not_l << "\n"; + display_justification(tout, js); + tout << "\n";); + + process_antecedent_for_unsat_core(m_not_l); + if (is_assumption(~m_not_l)) { + m_core.push_back(~m_not_l); + } + else { + process_consequent_for_unsat_core(m_not_l, js); + } + } + + literal consequent = m_not_l; + justification js = m_conflict; + + + while (true) { + process_consequent_for_unsat_core(consequent, js); + while (idx >= 0) { + literal l = m_trail[idx]; + if (is_marked(l.var())) + break; + idx--; + } + + if (idx < 0) { + break; + } + consequent = m_trail[idx]; + if (lvl(consequent) < m_conflict_lvl) { + TRACE("sat", tout << consequent << " at level " << lvl(consequent) << "\n";); + break; + } + bool_var c_var = consequent.var(); + SASSERT(lvl(consequent) == m_conflict_lvl); + js = m_justification[c_var]; + idx--; + } + reset_unmark(old_size); + if (m_config.m_minimize_core || m_config.m_minimize_core_partial) { + // TBD: + // apply optional clause minimization by detecting subsumed literals. + // initial experiment suggests it has no effect. + m_mus(); // ignore return value on cancelation. + m_model.reset(); + m_model.append(m_mus.get_model()); + m_model_is_current = !m_model.empty(); + } + } + + unsigned solver::get_max_lvl(literal consequent, justification js) { if (!m_ext) return scope_lvl(); @@ -1525,6 +1848,7 @@ namespace sat { } } + /** \brief js is an external justification. Collect its antecedents and store at m_ext_antecedents. */ @@ -1712,7 +2036,8 @@ namespace sat { assigned at level 0. */ void solver::minimize_lemma() { - m_unmark.reset(); + SASSERT(m_unmark.empty()); + //m_unmark.reset(); updt_lemma_lvl_set(); unsigned sz = m_lemma.size(); @@ -1721,6 +2046,7 @@ namespace sat { for (; i < sz; i++) { literal l = m_lemma[i]; if (implied_by_marked(l)) { + TRACE("sat", tout << "drop: " << l << "\n";); m_unmark.push_back(l.var()); } else { @@ -1882,6 +2208,7 @@ namespace sat { // ----------------------- void solver::push() { SASSERT(!inconsistent()); + TRACE("sat_verbose", tout << "q:" << m_qhead << " trail: " << m_trail.size() << "\n";); SASSERT(m_qhead == m_trail.size()); m_scopes.push_back(scope()); scope & s = m_scopes.back(); @@ -1893,6 +2220,11 @@ namespace sat { m_ext->push(); } + void solver::pop_reinit(unsigned num_scopes) { + pop(num_scopes); + reinit_assumptions(); + } + void solver::pop(unsigned num_scopes) { if (num_scopes == 0) return; @@ -1957,6 +2289,74 @@ namespace sat { m_clauses_to_reinit.shrink(j); } + // + // All new clauses that are added to the solver + // are relative to the user-scope literals. + // + + void solver::user_push() { + literal lit; + if (m_user_scope_literal_pool.empty()) { + bool_var new_v = mk_var(true, false); + lit = literal(new_v, false); + } + else { + lit = m_user_scope_literal_pool.back(); + m_user_scope_literal_pool.pop_back(); + } + TRACE("sat", tout << "user_push: " << lit << "\n";); + m_user_scope_literals.push_back(lit); + } + + void solver::gc_lit(clause_vector &clauses, literal lit) { + unsigned j = 0; + for (unsigned i = 0; i < clauses.size(); ++i) { + clause & c = *(clauses[i]); + if (c.contains(lit)) { + dettach_clause(c); + del_clause(c); + } + else { + clauses[j] = &c; + ++j; + } + } + clauses.shrink(j); + } + + void solver::gc_bin(bool learned, literal nlit) { + m_user_bin_clauses.reset(); + collect_bin_clauses(m_user_bin_clauses, learned); + for (unsigned i = 0; i < m_user_bin_clauses.size(); ++i) { + literal l1 = m_user_bin_clauses[i].first; + literal l2 = m_user_bin_clauses[i].second; + if (nlit == l1 || nlit == l2) { + dettach_bin_clause(l1, l2, learned); + } + } + } + + void solver::user_pop(unsigned num_scopes) { + pop_to_base_level(); + while (num_scopes > 0) { + literal lit = m_user_scope_literals.back(); + m_user_scope_literal_pool.push_back(lit); + m_user_scope_literals.pop_back(); + gc_lit(m_learned, lit); + gc_lit(m_clauses, lit); + gc_bin(true, lit); + gc_bin(false, lit); + TRACE("sat", tout << "gc: " << lit << "\n"; display(tout);); + --num_scopes; + } + } + + void solver::pop_to_base_level() { + m_assumptions.reset(); + m_assumption_set.reset(); + pop(scope_lvl()); + } + // ----------------------- // // Misc @@ -1983,9 +2383,10 @@ namespace sat { void solver::set_cancel(bool f) { m_cancel = f; + m_wsls.set_cancel(f); } - void solver::collect_statistics(statistics & st) { + void solver::collect_statistics(statistics & st) const { m_stats.collect_statistics(st); m_cleaner.collect_statistics(st); m_simplifier.collect_statistics(st); @@ -2098,6 +2499,13 @@ namespace sat { out << ")\n"; } + void solver::display_justification(std::ostream & out, justification const& js) const { + out << js; + if (js.is_clause()) { + out << *(m_cls_allocator.get_clause(js.get_clause_offset())); + } + } + unsigned solver::num_clauses() const { unsigned num_cls = 0; num_cls += m_trail.size(); // units; @@ -2369,6 +2777,7 @@ namespace sat { m_del_clause = 0; m_minimized_lits = 0; m_dyn_sub_res = 0; + m_non_learned_generation = 0; } void mk_stat::display(std::ostream & out) const { diff --git a/src/sat/sat_solver.h b/src/sat/sat_solver.h index 2a64c9cd5..edc3a3509 100644 --- a/src/sat/sat_solver.h +++ b/src/sat/sat_solver.h @@ -32,6 +32,8 @@ Revision History: #include"sat_asymm_branch.h" #include"sat_iff3_finder.h" #include"sat_probing.h" +#include"sat_mus.h" +#include"sat_sls.h" #include"params.h" #include"statistics.h" #include"stopwatch.h" @@ -57,6 +59,7 @@ namespace sat { unsigned m_del_clause; unsigned m_minimized_lits; unsigned m_dyn_sub_res; + unsigned m_non_learned_generation; stats() { reset(); } void reset(); void collect_statistics(statistics & st) const; @@ -73,12 +76,15 @@ namespace sat { random_gen m_rand; clause_allocator m_cls_allocator; cleaner m_cleaner; - model m_model; + model m_model; model_converter m_mc; + bool m_model_is_current; simplifier m_simplifier; scc m_scc; asymm_branch m_asymm_branch; probing m_probing; + mus m_mus; // MUS for minimal core extraction + wsls m_wsls; // SLS facility for MaxSAT use bool m_inconsistent; // A conflict is usually a single justification. That is, a justification // for false. If m_not_l is not null_literal, then m_conflict is a @@ -118,6 +124,9 @@ namespace sat { stopwatch m_stopwatch; params_ref m_params; scoped_ptr m_clone; // for debugging purposes + literal_vector m_assumptions; // additional assumptions during check + literal_set m_assumption_set; // set of enabled assumptions + literal_vector m_core; // unsat core void del_clauses(clause * const * begin, clause * const * end); @@ -129,6 +138,10 @@ namespace sat { friend class asymm_branch; friend class probing; friend class iff3_finder; + friend class mus; + friend class sls; + friend class wsls; + friend class bceq; friend struct mk_stat; public: solver(params_ref const & p, extension * ext); @@ -143,7 +156,7 @@ namespace sat { static void collect_param_descrs(param_descrs & d); void set_cancel(bool f); - void collect_statistics(statistics & st); + void collect_statistics(statistics & st) const; void reset_statistics(); void display_status(std::ostream & out) const; @@ -166,7 +179,7 @@ namespace sat { void mk_clause(literal l1, literal l2, literal l3); protected: - void del_clause(clause & c) { m_cls_allocator.del_clause(&c); m_stats.m_del_clause++; } + void del_clause(clause & c); clause * mk_clause_core(unsigned num_lits, literal * lits, bool learned); void mk_bin_clause(literal l1, literal l2, bool learned); bool propagate_bin_clause(literal l1, literal l2); @@ -215,12 +228,17 @@ namespace sat { void assign_core(literal l, justification jst); void set_conflict(justification c, literal not_l); void set_conflict(justification c) { set_conflict(c, null_literal); } - lbool status(clause const & c) const; + lbool status(clause const & c) const; clause_offset get_offset(clause const & c) const { return m_cls_allocator.get_offset(&c); } void checkpoint() { if (m_cancel) throw solver_exception(Z3_CANCELED_MSG); + ++m_num_checkpoints; + if (m_num_checkpoints < 10) return; + m_num_checkpoints = 0; if (memory::get_allocation_size() > m_config.m_max_memory) throw solver_exception(Z3_MAX_MEMORY_MSG); } + typedef std::pair bin_clause; + void initialize_soft(unsigned sz, literal const* lits, double const* weights); protected: watch_list & get_wlist(literal l) { return m_watches[l.index()]; } watch_list const & get_wlist(literal l) const { return m_watches[l.index()]; } @@ -231,6 +249,8 @@ namespace sat { bool is_marked_lit(literal l) const { return m_lit_mark[l.index()] != 0; } void mark_lit(literal l) { SASSERT(!is_marked_lit(l)); m_lit_mark[l.index()] = true; } void unmark_lit(literal l) { SASSERT(is_marked_lit(l)); m_lit_mark[l.index()] = false; } + bool check_inconsistent(); + // ----------------------- // @@ -250,8 +270,10 @@ namespace sat { // // ----------------------- public: - lbool check(); + lbool check(unsigned num_lits = 0, literal const* lits = 0); model const & get_model() const { return m_model; } + bool model_is_current() const { return m_model_is_current; } + literal_vector const& get_core() const { return m_core; } model_converter const & get_model_converter() const { return m_mc; } protected: @@ -261,12 +283,17 @@ namespace sat { unsigned m_luby_idx; unsigned m_conflicts_since_gc; unsigned m_gc_threshold; + unsigned m_num_checkpoints; double m_min_d_tk; unsigned m_next_simplify; bool decide(); bool_var next_var(); lbool bounded_search(); void init_search(); + void init_assumptions(unsigned num_lits, literal const* lits); + void reinit_assumptions(); + bool tracking_assumptions() const; + bool is_assumption(literal l) const; void simplify_problem(); void mk_model(); bool check_model(model const & m) const; @@ -312,8 +339,11 @@ namespace sat { literal_vector m_ext_antecedents; bool resolve_conflict(); bool resolve_conflict_core(); + void resolve_conflict_for_unsat_core(); unsigned get_max_lvl(literal consequent, justification js); void process_antecedent(literal antecedent, unsigned & num_marks); + void process_antecedent_for_unsat_core(literal antecedent); + void process_consequent_for_unsat_core(literal consequent, justification const& js); void fill_ext_antecedents(literal consequent, justification js); unsigned skip_literals_above_conflict_level(); void forget_phase_of_vars(unsigned from_lvl); @@ -339,14 +369,23 @@ namespace sat { // Backtracking // // ----------------------- - public: void push(); void pop(unsigned num_scopes); + void pop_reinit(unsigned num_scopes); - protected: void unassign_vars(unsigned old_sz); void reinit_clauses(unsigned old_sz); + literal_vector m_user_scope_literals; + literal_vector m_user_scope_literal_pool; + literal_vector m_aux_literals; + svector m_user_bin_clauses; + void gc_lit(clause_vector& clauses, literal lit); + void gc_bin(bool learned, literal nlit); + public: + void user_push(); + void user_pop(unsigned num_scopes); + void pop_to_base_level(); // ----------------------- // // Simplification @@ -390,7 +429,6 @@ namespace sat { clause * const * end_clauses() const { return m_clauses.end(); } clause * const * begin_learned() const { return m_learned.begin(); } clause * const * end_learned() const { return m_learned.end(); } - typedef std::pair bin_clause; void collect_bin_clauses(svector & r, bool learned) const; // ----------------------- @@ -403,11 +441,12 @@ namespace sat { void display(std::ostream & out) const; void display_watches(std::ostream & out) const; void display_dimacs(std::ostream & out) const; + void display_assignment(std::ostream & out) const; + void display_justification(std::ostream & out, justification const& j) const; protected: void display_binary(std::ostream & out) const; void display_units(std::ostream & out) const; - void display_assignment(std::ostream & out) const; unsigned num_clauses() const; bool is_unit(clause const & c) const; bool is_empty(clause const & c) const; diff --git a/src/sat/sat_types.h b/src/sat/sat_types.h index db8de94a9..075c88fa1 100644 --- a/src/sat/sat_types.h +++ b/src/sat/sat_types.h @@ -160,6 +160,12 @@ namespace sat { m_in_set[v] = true; m_set.push_back(v); } + + uint_set& operator=(uint_set const& other) { + m_in_set = other.m_in_set; + m_set = other.m_set; + return *this; + } bool contains(unsigned v) const { return v < m_in_set.size() && m_in_set[v] != 0; @@ -177,10 +183,31 @@ namespace sat { m_in_set[v] = false; return v; } + unsigned size() const { return m_set.size(); } iterator begin() const { return m_set.begin(); } iterator end() const { return m_set.end(); } void reset() { m_set.reset(); m_in_set.reset(); } void cleanup() { m_set.finalize(); m_in_set.finalize(); } + uint_set& operator&=(uint_set const& other) { + unsigned j = 0; + for (unsigned i = 0; i < m_set.size(); ++i) { + if (other.contains(m_set[i])) { + m_set[j] = m_set[i]; + ++j; + } + else { + m_in_set[m_set[i]] = false; + } + } + m_set.resize(j); + return *this; + } + uint_set& operator|=(uint_set const& other) { + for (unsigned i = 0; i < other.m_set.size(); ++i) { + insert(other.m_set[i]); + } + return *this; + } }; typedef uint_set bool_var_set; @@ -188,11 +215,44 @@ namespace sat { class literal_set { uint_set m_set; public: + literal_set(literal_vector const& v) { + for (unsigned i = 0; i < v.size(); ++i) insert(v[i]); + } + literal_set() {} + literal_vector to_vector() const { + literal_vector result; + iterator it = begin(), e = end(); + for (; it != e; ++it) { + result.push_back(*it); + } + return result; + } void insert(literal l) { m_set.insert(l.index()); } bool contains(literal l) const { return m_set.contains(l.index()); } bool empty() const { return m_set.empty(); } + unsigned size() const { return m_set.size(); } void reset() { m_set.reset(); } void cleanup() { m_set.cleanup(); } + class iterator { + uint_set::iterator m_it; + public: + iterator(uint_set::iterator it):m_it(it) {} + literal operator*() const { return to_literal(*m_it); } + iterator& operator++() { ++m_it; return *this; } + iterator operator++(int) { iterator tmp = *this; ++m_it; return tmp; } + bool operator==(iterator const& it) const { return m_it == it.m_it; } + bool operator!=(iterator const& it) const { return m_it != it.m_it; } + }; + iterator begin() const { return iterator(m_set.begin()); } + iterator end() const { return iterator(m_set.end()); } + literal_set& operator&=(literal_set const& other) { + m_set &= other.m_set; + return *this; + } + literal_set& operator|=(literal_set const& other) { + m_set |= other.m_set; + return *this; + } }; struct mem_stat { diff --git a/src/sat/tactic/atom2bool_var.cpp b/src/sat/tactic/atom2bool_var.cpp index 935eeb28e..48ad85152 100644 --- a/src/sat/tactic/atom2bool_var.cpp +++ b/src/sat/tactic/atom2bool_var.cpp @@ -90,8 +90,22 @@ struct collect_boolean_interface_proc { template void operator()(T const & g) { unsigned sz = g.size(); - for (unsigned i = 0; i < sz; i++) + ptr_vector deps, all_deps; + for (unsigned i = 0; i < sz; i++) { + if (g.dep(i)) { + deps.reset(); + m.linearize(g.dep(i), deps); + all_deps.append(deps); + } + } + + for (unsigned i = 0; i < all_deps.size(); i++) { + quick_for_each_expr(proc, tvisited, all_deps[i]); + } + for (unsigned i = 0; i < sz; i++) { process(g.form(i)); + } + } void operator()(unsigned sz, expr * const * fs) { diff --git a/src/sat/tactic/goal2sat.cpp b/src/sat/tactic/goal2sat.cpp index 16184e2bc..7224de971 100644 --- a/src/sat/tactic/goal2sat.cpp +++ b/src/sat/tactic/goal2sat.cpp @@ -35,6 +35,8 @@ Notes: #include"for_each_expr.h" #include"model_v2_pp.h" #include"tactic.h" +#include"ast_pp.h" +#include struct goal2sat::imp { struct frame { @@ -52,15 +54,21 @@ struct goal2sat::imp { obj_hashtable m_interface_vars; sat::solver & m_solver; atom2bool_var & m_map; + dep2asm_map & m_dep2asm; sat::bool_var m_true; bool m_ite_extra; unsigned long long m_max_memory; volatile bool m_cancel; + expr_ref_vector m_trail; + bool m_default_external; - imp(ast_manager & _m, params_ref const & p, sat::solver & s, atom2bool_var & map): + imp(ast_manager & _m, params_ref const & p, sat::solver & s, atom2bool_var & map, dep2asm_map& dep2asm, bool default_external): m(_m), m_solver(s), - m_map(map) { + m_map(map), + m_dep2asm(dep2asm), + m_trail(m), + m_default_external(default_external) { updt_params(p); m_cancel = false; m_true = sat::null_bool_var; @@ -71,8 +79,9 @@ struct goal2sat::imp { m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX)); } - void throw_op_not_handled() { - throw tactic_exception("operator not supported, apply simplifier before invoking translator"); + void throw_op_not_handled(std::string const& s) { + std::string s0 = "operator " + s + " not supported, apply simplifier before invoking translator"; + throw tactic_exception(s0.c_str()); } void mk_clause(sat::literal l) { @@ -116,7 +125,7 @@ struct goal2sat::imp { l = sat::literal(mk_true(), !sign); } else { - bool ext = !is_uninterp_const(t) || m_interface_vars.contains(t); + bool ext = m_default_external || !is_uninterp_const(t) || m_interface_vars.contains(t); sat::bool_var v = m_solver.mk_var(ext); m_map.insert(t, v); l = sat::literal(v, sign); @@ -176,9 +185,12 @@ struct goal2sat::imp { case OP_AND: case OP_XOR: case OP_IMPLIES: - case OP_DISTINCT: + case OP_DISTINCT: { TRACE("goal2sat_not_handled", tout << mk_ismt2_pp(t, m) << "\n";); - throw_op_not_handled(); + std::ostringstream strm; + strm << mk_ismt2_pp(t, m); + throw_op_not_handled(strm.str()); + } default: convert_atom(t, root, sign); return true; @@ -360,15 +372,65 @@ struct goal2sat::imp { SASSERT(m_result_stack.empty()); } + void insert_dep(expr* dep0, expr* dep, bool sign) { + SASSERT(sign || dep0 == dep); // !sign || (not dep0) == dep. + SASSERT(!sign || m.is_not(dep0)); + expr_ref new_dep(m), fml(m); + if (is_uninterp_const(dep)) { + new_dep = dep; + } + else { + new_dep = m.mk_fresh_const("dep", m.mk_bool_sort()); + m_trail.push_back(new_dep); + m_interface_vars.insert(new_dep); + fml = m.mk_iff(new_dep, dep); + process(fml); + } + convert_atom(new_dep, false, false); + sat::literal lit = m_result_stack.back(); + m_dep2asm.insert(dep0, sign?~lit:lit); + m_result_stack.pop_back(); + } void operator()(goal const & g) { m_interface_vars.reset(); collect_boolean_interface(g, m_interface_vars); - unsigned size = g.size(); + expr_ref f(m), d_new(m); + ptr_vector deps; + expr_ref_vector fmls(m); for (unsigned idx = 0; idx < size; idx++) { - expr * f = g.form(idx); + f = g.form(idx); + // Add assumptions. + if (g.dep(idx)) { + deps.reset(); + fmls.reset(); + m.linearize(g.dep(idx), deps); + fmls.push_back(f); + for (unsigned i = 0; i < deps.size(); ++i) { + expr * d = deps[i]; + expr * d1 = d; + SASSERT(m.is_bool(d)); + bool sign = m.is_not(d, d1); + + insert_dep(d, d1, sign); + if (d == f) { + goto skip_dep; + } + if (sign) { + d_new = d1; + } + else { + d_new = m.mk_not(d); + } + fmls.push_back(d_new); + } + f = m.mk_or(fmls.size(), fmls.c_ptr()); + } + TRACE("sat", tout << mk_pp(f, m) << "\n";); process(f); + skip_dep: + ; } } @@ -439,8 +501,8 @@ struct goal2sat::scoped_set_imp { } }; -void goal2sat::operator()(goal const & g, params_ref const & p, sat::solver & t, atom2bool_var & m) { - imp proc(g.m(), p, t, m); +void goal2sat::operator()(goal const & g, params_ref const & p, sat::solver & t, atom2bool_var & m, dep2asm_map& dep2asm, bool default_external) { + imp proc(g.m(), p, t, m, dep2asm, default_external); scoped_set_imp set(this, &proc); proc(g); } diff --git a/src/sat/tactic/goal2sat.h b/src/sat/tactic/goal2sat.h index 7e38a1ca5..b4e9615a0 100644 --- a/src/sat/tactic/goal2sat.h +++ b/src/sat/tactic/goal2sat.h @@ -41,6 +41,8 @@ class goal2sat { public: goal2sat(); + typedef obj_map dep2asm_map; + static void collect_param_descrs(param_descrs & r); static bool has_unsupported_bool(goal const & s); @@ -55,7 +57,7 @@ public: \warning conversion throws a tactic_exception, if it is interrupted (by set_cancel), an unsupported operator is found, or memory consumption limit is reached (set with param :max-memory). */ - void operator()(goal const & g, params_ref const & p, sat::solver & t, atom2bool_var & m); + void operator()(goal const & g, params_ref const & p, sat::solver & t, atom2bool_var & m, dep2asm_map& dep2asm, bool default_external = false); void set_cancel(bool f); }; diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp index d48994861..e4d5e6df5 100644 --- a/src/sat/tactic/sat_tactic.cpp +++ b/src/sat/tactic/sat_tactic.cpp @@ -46,13 +46,15 @@ class sat_tactic : public tactic { expr_dependency_ref & core) { mc = 0; pc = 0; core = 0; fail_if_proof_generation("sat", g); - fail_if_unsat_core_generation("sat", g); bool produce_models = g->models_enabled(); + bool produce_core = g->unsat_core_enabled(); TRACE("before_sat_solver", g->display(tout);); g->elim_redundancies(); atom2bool_var map(m); - m_goal2sat(*g, m_params, m_solver, map); + obj_map dep2asm; + sat::literal_vector assumptions; + m_goal2sat(*g, m_params, m_solver, map, dep2asm); TRACE("sat_solver_unknown", tout << "interpreted_atoms: " << map.interpreted_atoms() << "\n"; atom2bool_var::iterator it = map.begin(); atom2bool_var::iterator end = map.end(); @@ -66,10 +68,21 @@ class sat_tactic : public tactic { CASSERT("sat_solver", m_solver.check_invariant()); IF_VERBOSE(TACTIC_VERBOSITY_LVL, m_solver.display_status(verbose_stream());); TRACE("sat_dimacs", m_solver.display_dimacs(tout);); - - lbool r = m_solver.check(); + dep2assumptions(dep2asm, assumptions); + lbool r = m_solver.check(assumptions.size(), assumptions.c_ptr()); if (r == l_false) { - g->assert_expr(m.mk_false(), 0, 0); + expr_dependency * lcore = 0; + if (produce_core) { + sat::literal_vector const& core = m_solver.get_core(); + u_map asm2dep; + mk_asm2dep(dep2asm, asm2dep); + for (unsigned i = 0; i < core.size(); ++i) { + sat::literal lit = core[i]; + expr* dep = asm2dep.find(lit.index()); + lcore = m.mk_join(lcore, m.mk_leaf(dep)); + } + } + g->assert_expr(m.mk_false(), 0, lcore); } else if (r == l_true && !map.interpreted_atoms()) { // register model @@ -103,7 +116,7 @@ class sat_tactic : public tactic { #if 0 IF_VERBOSE(TACTIC_VERBOSITY_LVL, verbose_stream() << "\"formula constains interpreted atoms, recovering formula from sat solver...\"\n";); #endif - m_solver.pop(m_solver.scope_lvl()); + m_solver.pop_to_base_level(); m_sat2goal(m_solver, map, m_params, *(g.get()), mc); } g->inc_depth(); @@ -115,6 +128,22 @@ class sat_tactic : public tactic { m_sat2goal.set_cancel(f); m_solver.set_cancel(f); } + + void dep2assumptions(obj_map& dep2asm, + sat::literal_vector& assumptions) { + obj_map::iterator it = dep2asm.begin(), end = dep2asm.end(); + for (; it != end; ++it) { + assumptions.push_back(it->m_value); + } + } + + void mk_asm2dep(obj_map& dep2asm, + u_map& lit2asm) { + obj_map::iterator it = dep2asm.begin(), end = dep2asm.end(); + for (; it != end; ++it) { + lit2asm.insert(it->m_value.index(), it->m_key); + } + } }; struct scoped_set_imp { diff --git a/src/shell/datalog_frontend.cpp b/src/shell/datalog_frontend.cpp index a487a99b4..e802112b2 100644 --- a/src/shell/datalog_frontend.cpp +++ b/src/shell/datalog_frontend.cpp @@ -77,7 +77,7 @@ static void display_statistics( out << "--------------\n"; out << "instructions \n"; - code.display(*ctx.get_rel_context(), out); + code.display(ex_ctx, out); out << "--------------\n"; out << "big relations \n"; @@ -190,7 +190,7 @@ unsigned read_datalog(char const * file) { datalog::compiler::compile(ctx, ctx.get_rules(), rules_code, termination_code); - TRACE("dl_compiler", rules_code.display(*ctx.get_rel_context(), tout);); + TRACE("dl_compiler", rules_code.display(ex_ctx, tout);); rules_code.make_annotations(ex_ctx); @@ -230,7 +230,7 @@ unsigned read_datalog(char const * file) { TRACE("dl_compiler", ctx.display(tout); - rules_code.display(*ctx.get_rel_context(), tout);); + rules_code.display(ex_ctx, tout);); if (ctx.output_tuples()) { ctx.get_rel_context()->display_output_facts(ctx.get_rules(), std::cout); diff --git a/src/shell/dimacs_frontend.cpp b/src/shell/dimacs_frontend.cpp index 0acd222dd..abaa2eace 100644 --- a/src/shell/dimacs_frontend.cpp +++ b/src/shell/dimacs_frontend.cpp @@ -22,6 +22,7 @@ Revision History: #include"timeout.h" #include"dimacs.h" #include"sat_solver.h" +#include"gparams.h" extern bool g_display_statistics; static sat::solver * g_solver = 0; @@ -63,11 +64,73 @@ static void display_model(sat::solver const & s) { std::cout << "\n"; } +static void display_core(sat::solver const& s, vector const& tracking_clauses) { + std::cout << "core\n"; + sat::literal_vector const& c = s.get_core(); + for (unsigned i = 0; i < c.size(); ++i) { + sat::literal_vector const& cls = tracking_clauses[c[i].var()]; + for (unsigned j = 0; j < cls.size(); ++j) { + std::cout << cls[j] << " "; + } + std::cout << "\n"; + } +} + +static void track_clause(sat::solver& dst, + sat::literal_vector& lits, + sat::literal_vector& assumptions, + vector& tracking_clauses) { + sat::literal lit = sat::literal(dst.mk_var(true, false), false); + tracking_clauses.set(lit.var(), lits); + lits.push_back(~lit); + dst.mk_clause(lits.size(), lits.c_ptr()); + assumptions.push_back(lit); +} + + +static void track_clauses(sat::solver const& src, + sat::solver& dst, + sat::literal_vector& assumptions, + vector& tracking_clauses) { + for (sat::bool_var v = 0; v < src.num_vars(); ++v) { + dst.mk_var(false, true); + } + sat::literal_vector lits; + sat::literal lit; + sat::clause * const * it = src.begin_clauses(); + sat::clause * const * end = src.end_clauses(); + svector bin_clauses; + src.collect_bin_clauses(bin_clauses, false); + tracking_clauses.reserve(2*src.num_vars() + static_cast(end - it) + bin_clauses.size()); + + for (sat::bool_var v = 1; v < src.num_vars(); ++v) { + if (src.value(v) != l_undef) { + bool sign = src.value(v) == l_false; + lits.reset(); + lits.push_back(sat::literal(v, sign)); + track_clause(dst, lits, assumptions, tracking_clauses); + } + } + for (; it != end; ++it) { + lits.reset(); + sat::clause& cls = *(*it); + lits.append(static_cast(cls.end()-cls.begin()), cls.begin()); + track_clause(dst, lits, assumptions, tracking_clauses); + } + for (unsigned i = 0; i < bin_clauses.size(); ++i) { + lits.reset(); + lits.push_back(bin_clauses[i].first); + lits.push_back(bin_clauses[i].second); + track_clause(dst, lits, assumptions, tracking_clauses); + } +} + + unsigned read_dimacs(char const * file_name) { g_start_time = clock(); register_on_timeout_proc(on_timeout); signal(SIGINT, on_ctrl_c); - params_ref p; + params_ref p = gparams::get_module("sat"); p.set_bool("produce_models", true); sat::solver solver(p, 0); g_solver = &solver; @@ -85,17 +148,31 @@ unsigned read_dimacs(char const * file_name) { } IF_VERBOSE(20, solver.display_status(verbose_stream());); - lbool r = solver.check(); + lbool r; + vector tracking_clauses; + sat::solver solver2(p, 0); + if (p.get_bool("dimacs.core", false)) { + g_solver = &solver2; + sat::literal_vector assumptions; + track_clauses(solver, solver2, assumptions, tracking_clauses); + r = g_solver->check(assumptions.size(), assumptions.c_ptr()); + } + else { + r = g_solver->check(); + } switch (r) { case l_true: std::cout << "sat\n"; - display_model(solver); + display_model(*g_solver); break; case l_undef: std::cout << "unknown\n"; break; case l_false: std::cout << "unsat\n"; + if (p.get_bool("dimacs.core", false)) { + display_core(*g_solver, tracking_clauses); + } break; } if (g_display_statistics) diff --git a/src/shell/dimacs_frontend.h b/src/shell/dimacs_frontend.h index 9521c8256..5448d1af0 100644 --- a/src/shell/dimacs_frontend.h +++ b/src/shell/dimacs_frontend.h @@ -21,5 +21,5 @@ Revision History: unsigned read_dimacs(char const * benchmark_file); -#endif /* _DATALOG_FRONTEND_H_ */ +#endif /* _DIMACS_FRONTEND_H_ */ diff --git a/src/shell/main.cpp b/src/shell/main.cpp index 0eb612f35..9d7857766 100644 --- a/src/shell/main.cpp +++ b/src/shell/main.cpp @@ -29,13 +29,14 @@ Revision History: #include"version.h" #include"dimacs_frontend.h" #include"datalog_frontend.h" +#include"opt_frontend.h" #include"timeout.h" #include"z3_exception.h" #include"error_codes.h" #include"gparams.h" #include"env_params.h" -typedef enum { IN_UNSPECIFIED, IN_SMTLIB, IN_SMTLIB_2, IN_DATALOG, IN_DIMACS, IN_Z3_LOG } input_kind; +typedef enum { IN_UNSPECIFIED, IN_SMTLIB, IN_SMTLIB_2, IN_DATALOG, IN_DIMACS, IN_WCNF, IN_OPB, IN_Z3_LOG } input_kind; std::string g_aux_input_file; char const * g_input_file = 0; @@ -168,6 +169,12 @@ void parse_cmd_line_args(int argc, char ** argv) { else if (strcmp(opt_name, "dimacs") == 0) { g_input_kind = IN_DIMACS; } + else if (strcmp(opt_name, "wcnf") == 0) { + g_input_kind = IN_WCNF; + } + else if (strcmp(opt_name, "bpo") == 0) { + g_input_kind = IN_OPB; + } else if (strcmp(opt_name, "log") == 0) { g_input_kind = IN_Z3_LOG; } @@ -297,7 +304,7 @@ int main(int argc, char ** argv) { } if (g_input_kind == IN_UNSPECIFIED) { - g_input_kind = IN_SMTLIB; + g_input_kind = IN_SMTLIB_2; char const * ext = get_extension(g_input_file); if (ext) { if (strcmp(ext, "datalog") == 0 || strcmp(ext, "dl") == 0) { @@ -306,6 +313,12 @@ int main(int argc, char ** argv) { else if (strcmp(ext, "dimacs") == 0 || strcmp(ext, "cnf") == 0) { g_input_kind = IN_DIMACS; } + else if (strcmp(ext, "wcnf") == 0) { + g_input_kind = IN_WCNF; + } + else if (strcmp(ext, "opb") == 0) { + g_input_kind = IN_OPB; + } else if (strcmp(ext, "log") == 0) { g_input_kind = IN_Z3_LOG; } @@ -328,6 +341,12 @@ int main(int argc, char ** argv) { case IN_DIMACS: return_value = read_dimacs(g_input_file); break; + case IN_WCNF: + return_value = parse_opt(g_input_file, true); + break; + case IN_OPB: + return_value = parse_opt(g_input_file, false); + break; case IN_DATALOG: read_datalog(g_input_file); break; diff --git a/src/shell/opt_frontend.cpp b/src/shell/opt_frontend.cpp new file mode 100644 index 000000000..616fc1962 --- /dev/null +++ b/src/shell/opt_frontend.cpp @@ -0,0 +1,356 @@ +#include +#include +#include +#include"opt_context.h" +#include"ast_util.h" +#include"arith_decl_plugin.h" +#include"gparams.h" +#include"timeout.h" +#include"reg_decl_plugins.h" + +extern bool g_display_statistics; +static bool g_first_interrupt = true; +static opt::context* g_opt = 0; +static double g_start_time = 0; +static unsigned_vector g_handles; + +class stream_buffer { + std::istream & m_stream; + int m_val; + unsigned m_line; +public: + stream_buffer(std::istream & s): + m_stream(s), + m_line(0) { + m_val = m_stream.get(); + } + int operator *() const { return m_val;} + void operator ++() { m_val = m_stream.get(); } + int ch() const { return m_val; } + void next() { m_val = m_stream.get(); } + bool eof() const { return ch() == EOF; } + unsigned line() const { return m_line; } + void skip_whitespace() { + while ((ch() >= 9 && ch() <= 13) || ch() == 32) { + if (ch() == 10) ++m_line; + next(); + } + } + void skip_line() { + while(true) { + if (eof()) { + return; + } + if (ch() == '\n') { + ++m_line; + next(); + return; + } + next(); + } + } + + bool parse_token(char const* token) { + skip_whitespace(); + char const* t = token; + while (ch() == *t) { + next(); + ++t; + } + return 0 == *t; + } + + int parse_int() { + int val = 0; + bool neg = false; + skip_whitespace(); + + if (ch() == '-') { + neg = true; + next(); + } + else if (ch() == '+') { + next(); + } + if (ch() < '0' || ch() > '9') { + std::cerr << "(error line " << line() << " \"unexpected char: " << ((char)ch()) << "\" )\n"; + exit(3); + } + while (ch() >= '0' && ch() <= '9') { + val = val*10 + (ch() - '0'); + next(); + } + return neg ? -val : val; + } +}; + +class wcnf { + opt::context& opt; + ast_manager& m; + stream_buffer& in; + + app_ref read_clause(unsigned& weight) { + int parsed_lit; + int var; + parsed_lit = in.parse_int(); + weight = static_cast(parsed_lit); + app_ref result(m), p(m); + expr_ref_vector ors(m); + while (true) { + parsed_lit = in.parse_int(); + if (parsed_lit == 0) + break; + var = abs(parsed_lit); + p = m.mk_const(symbol(var), m.mk_bool_sort()); + if (parsed_lit < 0) p = m.mk_not(p); + ors.push_back(p); + } + result = to_app(mk_or(m, ors.size(), ors.c_ptr())); + return result; + } + + void parse_spec(int& num_vars, int& num_clauses, int& max_weight) { + in.parse_token("wcnf"); + num_vars = in.parse_int(); + num_clauses = in.parse_int(); + max_weight = in.parse_int(); + } + +public: + + wcnf(opt::context& opt, stream_buffer& in): opt(opt), m(opt.get_manager()), in(in) { + opt.set_clausal(true); + } + + void parse() { + int num_vars = 0, num_clauses = 0, max_weight = 0; + while (true) { + in.skip_whitespace(); + if (in.eof()) { + break; + } + else if (*in == 'c') { + in.skip_line(); + } + else if (*in == 'p') { + ++in; + parse_spec(num_vars, num_clauses, max_weight); + } + else { + unsigned weight = 0; + app_ref cls = read_clause(weight); + if (weight == max_weight) { + opt.add_hard_constraint(cls); + } + else { + unsigned id = opt.add_soft_constraint(cls, rational(weight), symbol::null); + if (g_handles.empty()) { + g_handles.push_back(id); + } + } + } + } + } +}; + + +class opb { + opt::context& opt; + ast_manager& m; + stream_buffer& in; + arith_util arith; + + app_ref parse_id() { + bool negated = in.parse_token("~"); + if (!in.parse_token("x")) { + std::cerr << "(error line " << in.line() << " \"unexpected char: " << ((char)in.ch()) << "\")\n"; + exit(3); + } + app_ref p(m); + int id = in.parse_int(); + p = m.mk_const(symbol(id), m.mk_bool_sort()); + if (negated) p = m.mk_not(p); + in.skip_whitespace(); + return p; + } + + app_ref parse_ids() { + app_ref result = parse_id(); + while (*in == '~' || *in == 'x') { + result = m.mk_and(result, parse_id()); + } + return result; + } + + rational parse_coeff_r() { + in.skip_whitespace(); + svector num; + bool pos = true; + if (*in == '-') pos = false, ++in; + if (*in == '+') ++in; + if (!pos) num.push_back('-'); + in.skip_whitespace(); + while ('0' <= *in && *in <='9') num.push_back(*in), ++in; + num.push_back(0); + return rational(num.c_ptr()); + } + + app_ref parse_coeff() { + return app_ref(arith.mk_numeral(parse_coeff_r(), true), m); + } + + app_ref parse_term() { + app_ref c = parse_coeff(); + app_ref e = parse_ids(); + return app_ref(m.mk_ite(e, c, arith.mk_numeral(rational(0), true)), m); + } + + void parse_objective() { + app_ref t = parse_term(); + while (!in.parse_token(";") && !in.eof()) { + t = arith.mk_add(t, parse_term()); + } + g_handles.push_back(opt.add_objective(t, false)); + } + + void parse_constraint() { + app_ref t = parse_term(); + while (!in.eof()) { + if (in.parse_token(">=")) { + t = arith.mk_ge(t, parse_coeff()); + in.parse_token(";"); + break; + } + if (in.parse_token("=")) { + t = m.mk_eq(t, parse_coeff()); + in.parse_token(";"); + break; + } + t = arith.mk_add(t, parse_term()); + } + opt.add_hard_constraint(t); + } +public: + opb(opt::context& opt, stream_buffer& in): + opt(opt), m(opt.get_manager()), + in(in), arith(m) {} + + void parse() { + while (true) { + in.skip_whitespace(); + if (in.eof()) { + break; + } + else if (*in == '*') { + in.skip_line(); + } + else if (in.parse_token("min:")) { + parse_objective(); + } + else { + parse_constraint(); + } + } + } +}; + + + +static void display_statistics() { + if (g_display_statistics && g_opt) { + ::statistics stats; + g_opt->collect_statistics(stats); + stats.display(std::cout); + double end_time = static_cast(clock()); + std::cout << "time: " << (end_time - g_start_time)/CLOCKS_PER_SEC << " secs\n"; + for (unsigned i = 0; i < g_handles.size(); ++i) { + expr_ref lo = g_opt->get_lower(g_handles[i]); + expr_ref hi = g_opt->get_upper(g_handles[i]); + if (lo == hi) { + std::cout << " " << lo << "\n"; + } + else { + std::cout << " [" << lo << ":" << hi << "]\n"; + } + } + } +} + +static void on_ctrl_c(int) { + if (g_opt && g_first_interrupt) { + g_opt->set_cancel(true); + g_first_interrupt = false; + } + else { + signal (SIGINT, SIG_DFL); + #pragma omp critical (g_display_stats) + { + display_statistics(); + } + raise(SIGINT); + } +} + +static void on_timeout() { + #pragma omp critical (g_display_stats) + { + display_statistics(); + exit(0); + } +} + +static unsigned parse_opt(std::istream& in, bool is_wcnf) { + ast_manager m; + reg_decl_plugins(m); + opt::context opt(m); + g_opt = &opt; + params_ref p = gparams::get_module("opt"); + opt.updt_params(p); + stream_buffer _in(in); + if (is_wcnf) { + wcnf wcnf(opt, _in); + wcnf.parse(); + } + else { + opb opb(opt, _in); + opb.parse(); + } + try { + lbool r = opt.optimize(); + switch (r) { + case l_true: std::cout << "sat\n"; break; + case l_false: std::cout << "unsat\n"; break; + case l_undef: std::cout << "unknown\n"; break; + } + } + catch (z3_exception & ex) { + std::cerr << ex.msg() << "\n"; + } + #pragma omp critical (g_display_stats) + { + display_statistics(); + register_on_timeout_proc(0); + g_opt = 0; + } + return 0; +} + +unsigned parse_opt(char const* file_name, bool is_wcnf) { + g_first_interrupt = true; + g_start_time = static_cast(clock()); + register_on_timeout_proc(on_timeout); + signal(SIGINT, on_ctrl_c); + unsigned result = 0; + if (file_name) { + std::ifstream in(file_name); + if (in.bad() || in.fail()) { + std::cerr << "(error \"failed to open file '" << file_name << "'\")" << std::endl; + exit(ERR_OPEN_FILE); + } + return parse_opt(in, is_wcnf); + } + else { + return parse_opt(std::cin, is_wcnf); + } +} + diff --git a/src/shell/opt_frontend.h b/src/shell/opt_frontend.h new file mode 100644 index 000000000..df6070378 --- /dev/null +++ b/src/shell/opt_frontend.h @@ -0,0 +1,20 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + opt_frontend.h + +Author: + + Nikolaj Bjorner (nbjorner) 2014-10-10. + +--*/ +#ifndef _OPT_FRONTEND_H_ +#define _OPT_FRONTEND_H_ + +unsigned parse_opt(char const* file_name, bool is_wcnf); + +#endif /* _OPT_FRONTEND_H_ */ + + diff --git a/src/shell/smtlib_frontend.cpp b/src/shell/smtlib_frontend.cpp index 3197f8cff..eb3b3587d 100644 --- a/src/shell/smtlib_frontend.cpp +++ b/src/shell/smtlib_frontend.cpp @@ -26,6 +26,7 @@ Revision History: #include"smt2parser.h" #include"dl_cmds.h" #include"dbg_cmds.h" +#include"opt_cmds.h" #include"polynomial_cmds.h" #include"subpaving_cmds.h" #include"smt_strategic_solver.h" @@ -112,6 +113,7 @@ unsigned read_smtlib2_commands(char const * file_name) { install_dbg_cmds(ctx); install_polynomial_cmds(ctx); install_subpaving_cmds(ctx); + install_opt_cmds(ctx); g_cmd_context = &ctx; signal(SIGINT, on_ctrl_c); diff --git a/src/smt/diff_logic.h b/src/smt/diff_logic.h index 2717e4a92..0685bb90c 100644 --- a/src/smt/diff_logic.h +++ b/src/smt/diff_logic.h @@ -25,6 +25,7 @@ Revision History: #include"trace.h" #include"warning.h" #include"uint_set.h" +#include typedef int dl_var; @@ -281,6 +282,8 @@ public: unsigned get_num_edges() const { return m_edges.size(); } + unsigned get_num_nodes() const { return m_out_edges.size(); } + dl_var get_source(edge_id id) const { return m_edges[id].get_source(); } dl_var get_target(edge_id id) const { return m_edges[id].get_target(); } @@ -931,6 +934,120 @@ public: return found; } + // Return true if there is an edge source --> target (also counting disabled edges). + // If there is such edge, return its edge_id in parameter id. + bool get_edge_id(dl_var source, dl_var target, edge_id & id) const { + edge_id_vector const & edges = m_out_edges[source]; + typename edge_id_vector::const_iterator it = edges.begin(); + typename edge_id_vector::const_iterator end = edges.end(); + for (; it != end; ++it) { + id = *it; + edge const & e = m_edges[id]; + if (e.get_target() == target) { + return true; + } + } + return false; + } + + edges const & get_all_edges() const { + return m_edges; + } + + void get_neighbours_undirected(dl_var current, svector & neighbours) { + neighbours.reset(); + edge_id_vector & out_edges = m_out_edges[current]; + typename edge_id_vector::iterator it = out_edges.begin(), end = out_edges.end(); + for (; it != end; ++it) { + edge_id e_id = *it; + edge & e = m_edges[e_id]; + SASSERT(e.get_source() == current); + dl_var neighbour = e.get_target(); + neighbours.push_back(neighbour); + } + edge_id_vector & in_edges = m_in_edges[current]; + typename edge_id_vector::iterator it2 = in_edges.begin(), end2 = in_edges.end(); + for (; it2 != end2; ++it2) { + edge_id e_id = *it2; + edge & e = m_edges[e_id]; + SASSERT(e.get_target() == current); + dl_var neighbour = e.get_source(); + neighbours.push_back(neighbour); + } + } + + void dfs_undirected(dl_var start, svector & threads) { + threads.reset(); + threads.resize(get_num_nodes()); + uint_set discovered, explored; + svector nodes; + discovered.insert(start); + nodes.push_back(start); + dl_var prev = start; + while(!nodes.empty()) { + dl_var current = nodes.back(); + SASSERT(discovered.contains(current) && !explored.contains(current)); + svector neighbours; + get_neighbours_undirected(current, neighbours); + SASSERT(!neighbours.empty()); + bool found = false; + for (unsigned i = 0; i < neighbours.size(); ++i) { + dl_var next = neighbours[i]; + DEBUG_CODE( + edge_id id; + SASSERT(get_edge_id(current, next, id) || get_edge_id(next, current, id));); + if (!discovered.contains(next) && !explored.contains(next)) { + TRACE("diff_logic", tout << "thread[" << prev << "] --> " << next << std::endl;); + threads[prev] = next; + prev = next; + discovered.insert(next); + nodes.push_back(next); + found = true; + break; + } + } + SASSERT(!nodes.empty()); + if (!found) { + explored.insert(current); + nodes.pop_back(); + } + } + threads[prev] = start; + } + + void bfs_undirected(dl_var start, svector & parents, svector & depths) { + parents.reset(); + parents.resize(get_num_nodes()); + parents[start] = -1; + depths.reset(); + depths.resize(get_num_nodes()); + uint_set visited; + std::deque nodes; + visited.insert(start); + nodes.push_front(start); + while(!nodes.empty()) { + dl_var current = nodes.back(); + nodes.pop_back(); + SASSERT(visited.contains(current)); + svector neighbours; + get_neighbours_undirected(current, neighbours); + SASSERT(!neighbours.empty()); + for (unsigned i = 0; i < neighbours.size(); ++i) { + dl_var next = neighbours[i]; + DEBUG_CODE( + edge_id id; + SASSERT(get_edge_id(current, next, id) || get_edge_id(next, current, id));); + if (!visited.contains(next)) { + TRACE("diff_logic", tout << "parents[" << next << "] --> " << current << std::endl;); + parents[next] = current; + depths[next] = depths[current] + 1; + visited.insert(next); + nodes.push_front(next); + } + } + } + } + template void enumerate_edges(dl_var source, dl_var target, Functor& f) { edge_id_vector & edges = m_out_edges[source]; @@ -1076,6 +1193,10 @@ public: return m_assignment[v]; } + void set_assignment(dl_var v, numeral const & n) { + m_assignment[v] = n; + } + unsigned get_timestamp() const { return m_timestamp; } diff --git a/src/smt/elim_term_ite.cpp b/src/smt/elim_term_ite.cpp index 2e1671f43..74b804c21 100644 --- a/src/smt/elim_term_ite.cpp +++ b/src/smt/elim_term_ite.cpp @@ -33,16 +33,16 @@ void elim_term_ite::operator()(expr * n, proof * pr2; get_cached(n, r2, pr2); r = r2; - switch (m_manager.proof_mode()) { + switch (m.proof_mode()) { case PGM_DISABLED: - pr = m_manager.mk_undef_proof(); + pr = m.mk_undef_proof(); break; case PGM_COARSE: remove_duplicates(m_coarse_proofs); - pr = n == r2 ? m_manager.mk_oeq_reflexivity(n) : m_manager.mk_apply_defs(n, r, m_coarse_proofs.size(), m_coarse_proofs.c_ptr()); + pr = n == r2 ? m.mk_oeq_reflexivity(n) : m.mk_apply_defs(n, r, m_coarse_proofs.size(), m_coarse_proofs.c_ptr()); break; case PGM_FINE: - pr = pr2 == 0 ? m_manager.mk_oeq_reflexivity(n) : pr2; + pr = pr2 == 0 ? m.mk_oeq_reflexivity(n) : pr2; break; } m_coarse_proofs.reset(); @@ -107,36 +107,36 @@ void elim_term_ite::reduce1_app(app * n) { m_args.reset(); func_decl * decl = n->get_decl(); - proof_ref p1(m_manager); + proof_ref p1(m); get_args(n, m_args, p1); - if (!m_manager.fine_grain_proofs()) + if (!m.fine_grain_proofs()) p1 = 0; - expr_ref r(m_manager); - r = m_manager.mk_app(decl, m_args.size(), m_args.c_ptr()); - if (m_manager.is_term_ite(r)) { - expr_ref new_def(m_manager); - proof_ref new_def_pr(m_manager); - app_ref new_r(m_manager); - proof_ref new_pr(m_manager); + expr_ref r(m); + r = m.mk_app(decl, m_args.size(), m_args.c_ptr()); + if (m.is_term_ite(r)) { + expr_ref new_def(m); + proof_ref new_def_pr(m); + app_ref new_r(m); + proof_ref new_pr(m); if (m_defined_names.mk_name(r, new_def, new_def_pr, new_r, new_pr)) { - CTRACE("elim_term_ite_bug", new_def.get() == 0, tout << mk_ismt2_pp(r, m_manager) << "\n";); + CTRACE("elim_term_ite_bug", new_def.get() == 0, tout << mk_ismt2_pp(r, m) << "\n";); SASSERT(new_def.get() != 0); m_new_defs->push_back(new_def); - if (m_manager.fine_grain_proofs()) { + if (m.fine_grain_proofs()) { m_new_def_proofs->push_back(new_def_pr); - new_pr = m_manager.mk_transitivity(p1, new_pr); + new_pr = m.mk_transitivity(p1, new_pr); } else { // [Leo] This looks fishy... why do we add 0 into m_coarse_proofs when fine_grain_proofs are disabled? new_pr = 0; - if (m_manager.proofs_enabled()) + if (m.proofs_enabled()) m_coarse_proofs.push_back(new_pr); } } else { SASSERT(new_def.get() == 0); - if (!m_manager.fine_grain_proofs()) + if (!m.fine_grain_proofs()) new_pr = 0; } cache_result(n, new_r, new_pr); @@ -151,8 +151,8 @@ void elim_term_ite::reduce1_quantifier(quantifier * q) { proof * new_body_pr; get_cached(q->get_expr(), new_body, new_body_pr); - quantifier * new_q = m_manager.update_quantifier(q, new_body); - proof * p = q == new_q ? 0 : m_manager.mk_oeq_quant_intro(q, new_q, new_body_pr); + quantifier * new_q = m.update_quantifier(q, new_body); + proof * p = q == new_q ? 0 : m.mk_oeq_quant_intro(q, new_q, new_body_pr); cache_result(q, new_q, p); } diff --git a/src/smt/old_interval.cpp b/src/smt/old_interval.cpp index ffc3331be..616b74ed6 100644 --- a/src/smt/old_interval.cpp +++ b/src/smt/old_interval.cpp @@ -72,7 +72,11 @@ ext_numeral & ext_numeral::operator-=(ext_numeral const & other) { } ext_numeral & ext_numeral::operator*=(ext_numeral const & other) { - if (is_zero() || other.is_zero()) { + if (is_zero()) { + m_kind = FINITE; + return *this; + } + if (other.is_zero()) { m_kind = FINITE; m_value.reset(); return *this; @@ -295,6 +299,8 @@ interval & interval::operator*=(interval const & other) { } if (other.is_zero()) { *this = other; + m_lower_dep = m_manager.mk_join(m_lower_dep, m_upper_dep); + m_upper_dep = m_lower_dep; return *this; } diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp index 18619c8ec..a8d2bc52f 100644 --- a/src/smt/params/smt_params.cpp +++ b/src/smt/params/smt_params.cpp @@ -49,6 +49,7 @@ void smt_params::updt_params(params_ref const & p) { qi_params::updt_params(p); theory_arith_params::updt_params(p); theory_bv_params::updt_params(p); + theory_pb_params::updt_params(p); // theory_array_params::updt_params(p); updt_local_params(p); } diff --git a/src/smt/params/smt_params.h b/src/smt/params/smt_params.h index 256c5a646..9646c4549 100644 --- a/src/smt/params/smt_params.h +++ b/src/smt/params/smt_params.h @@ -25,6 +25,7 @@ Revision History: #include"theory_arith_params.h" #include"theory_array_params.h" #include"theory_bv_params.h" +#include"theory_pb_params.h" #include"theory_datatype_params.h" #include"preprocessor_params.h" #include"context_params.h" @@ -73,7 +74,8 @@ struct smt_params : public preprocessor_params, public qi_params, public theory_arith_params, public theory_array_params, - public theory_bv_params, + public theory_bv_params, + public theory_pb_params, public theory_datatype_params { bool m_display_proof; bool m_display_dot_proof; diff --git a/src/smt/params/smt_params_helper.pyg b/src/smt/params/smt_params_helper.pyg index 869b8cdc4..a0d7e7823 100644 --- a/src/smt/params/smt_params_helper.pyg +++ b/src/smt/params/smt_params_helper.pyg @@ -44,6 +44,11 @@ def_module_params(module_name='smt', ('arith.branch_cut_ratio', UINT, 2, 'branch/cut ratio for linear integer arithmetic'), ('arith.int_eq_branch', BOOL, False, 'branching using derived integer equations'), ('arith.ignore_int', BOOL, False, 'treat integer variables as real'), + ('arith.dump_lemmas', BOOL, False, 'dump arithmetic theory lemmas to files'), + ('pb.conflict_frequency', UINT, 1000, 'conflict frequency for Pseudo-Boolean theory'), + ('pb.learn_complements', BOOL, True, 'learn complement literals for Pseudo-Boolean theory'), + ('pb.enable_compilation', BOOL, True, 'enable compilation into sorting circuits for Pseudo-Boolean'), + ('pb.enable_simplex', BOOL, False, 'enable simplex to check rational feasibility'), ('array.weak', BOOL, False, 'weak array theory'), ('array.extensional', BOOL, True, 'extensional array theory') )) diff --git a/src/smt/params/theory_arith_params.cpp b/src/smt/params/theory_arith_params.cpp index 7287cac2f..fef7ca2a0 100644 --- a/src/smt/params/theory_arith_params.cpp +++ b/src/smt/params/theory_arith_params.cpp @@ -34,6 +34,7 @@ void theory_arith_params::updt_params(params_ref const & _p) { m_arith_int_eq_branching = p.arith_int_eq_branch(); m_arith_ignore_int = p.arith_ignore_int(); m_arith_bound_prop = static_cast(p.arith_propagation_mode()); + m_arith_dump_lemmas = p.arith_dump_lemmas(); } diff --git a/src/smt/params/theory_arith_params.h b/src/smt/params/theory_arith_params.h index 911c75d36..4394f46d3 100644 --- a/src/smt/params/theory_arith_params.h +++ b/src/smt/params/theory_arith_params.h @@ -27,7 +27,8 @@ enum arith_solver_id { AS_DIFF_LOGIC, AS_ARITH, AS_DENSE_DIFF_LOGIC, - AS_UTVPI + AS_UTVPI, + AS_OPTINF }; enum bound_prop_mode { diff --git a/src/smt/params/theory_pb_params.cpp b/src/smt/params/theory_pb_params.cpp new file mode 100644 index 000000000..6d980fe5d --- /dev/null +++ b/src/smt/params/theory_pb_params.cpp @@ -0,0 +1,28 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + theory_pb_params.cpp + +Abstract: + + + +Author: + + Nikolaj Bjorner (nbjorner) 2014-01-01 + +Revision History: + +--*/ +#include"theory_pb_params.h" +#include"smt_params_helper.hpp" + +void theory_pb_params::updt_params(params_ref const & _p) { + smt_params_helper p(_p); + m_pb_conflict_frequency = p.pb_conflict_frequency(); + m_pb_learn_complements = p.pb_learn_complements(); + m_pb_enable_compilation = p.pb_enable_compilation(); + m_pb_enable_simplex = p.pb_enable_simplex(); +} diff --git a/src/smt/params/theory_pb_params.h b/src/smt/params/theory_pb_params.h new file mode 100644 index 000000000..0432ac633 --- /dev/null +++ b/src/smt/params/theory_pb_params.h @@ -0,0 +1,41 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + theory_pb_params.h + +Abstract: + + + +Author: + + Nikolaj Bjorner (nbjorner) 2014-01-01 + +Revision History: + +--*/ +#ifndef _THEORY_PB_PARAMS_H_ +#define _THEORY_PB_PARAMS_H_ + +#include"params.h" + + +struct theory_pb_params { + unsigned m_pb_conflict_frequency; + bool m_pb_learn_complements; + bool m_pb_enable_compilation; + bool m_pb_enable_simplex; + theory_pb_params(params_ref const & p = params_ref()): + m_pb_conflict_frequency(1000), + m_pb_learn_complements(true), + m_pb_enable_compilation(true), + m_pb_enable_simplex(false) + {} + + void updt_params(params_ref const & p); +}; + +#endif /* _THEORY_PB_PARAMS_H_ */ + diff --git a/src/smt/smt_b_justification.h b/src/smt/smt_b_justification.h index 4798af4b0..5a82e36e8 100644 --- a/src/smt/smt_b_justification.h +++ b/src/smt/smt_b_justification.h @@ -54,7 +54,7 @@ namespace smt { m_data(BOXTAGINT(void*, l.index(), BIN_CLAUSE)) { } - explicit b_justification(justification * js): + explicit b_justification(justification * js): m_data(TAG(void*, js, JUSTIFICATION)) { SASSERT(js); } diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index f3f2d4948..adb17f6e2 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -199,6 +199,9 @@ namespace smt { bool context::bcp() { SASSERT(!inconsistent()); while (m_qhead < m_assigned_literals.size()) { + if (m_cancel_flag) { + return true; + } literal l = m_assigned_literals[m_qhead]; SASSERT(get_assignment(l) == l_true); m_qhead++; @@ -225,9 +228,6 @@ namespace smt { case l_true: break; } - if (m_cancel_flag) { - return true; - } } } @@ -1334,6 +1334,7 @@ namespace smt { TRACE("propagate_bool_var_enode_bug", tout << "var: " << v << " #" << bool_var2expr(v)->get_id() << "\n";); SASSERT(v < static_cast(m_b_internalized_stack.size())); enode * n = bool_var2enode(v); + CTRACE("mk_bool_var", !n, tout << "No enode for " << v << "\n";); bool sign = val == l_false; if (n->merge_tf()) add_eq(n, sign ? m_false_enode : m_true_enode, eq_justification(literal(v, sign))); @@ -2853,7 +2854,7 @@ namespace smt { void context::init_assumptions(unsigned num_assumptions, expr * const * assumptions) { reset_assumptions(); - m_bool_var2assumption.reset(); + m_literal2assumption.reset(); m_unsat_core.reset(); if (num_assumptions > 0) { // We must give a chance to the theories to propagate before we create a new scope... @@ -2869,16 +2870,16 @@ namespace smt { proof * pr = m_manager.mk_asserted(curr_assumption); internalize_assertion(curr_assumption, pr, 0); literal l = get_literal(curr_assumption); - m_bool_var2assumption.insert(l.var(), curr_assumption); + m_literal2assumption.insert(l.index(), curr_assumption); // mark_as_relevant(l); <<< not needed // internalize_assertion marked l as relevant. SASSERT(is_relevant(l)); - TRACE("assumptions", tout << mk_pp(curr_assumption, m_manager) << "\n";); + TRACE("assumptions", tout << l << ":" << mk_pp(curr_assumption, m_manager) << "\n";); if (m_manager.proofs_enabled()) assign(l, mk_justification(justification_proof_wrapper(*this, pr))); else assign(l, b_justification::mk_axiom()); - m_assumptions.push_back(l.var()); + m_assumptions.push_back(l); get_bdata(l.var()).m_assumption = true; } } @@ -2888,10 +2889,10 @@ namespace smt { } void context::reset_assumptions() { - bool_var_vector::iterator it = m_assumptions.begin(); - bool_var_vector::iterator end = m_assumptions.end(); + literal_vector::iterator it = m_assumptions.begin(); + literal_vector::iterator end = m_assumptions.end(); for (; it != end; ++it) - get_bdata(*it).m_assumption = false; + get_bdata(it->var()).m_assumption = false; m_assumptions.reset(); } @@ -2908,10 +2909,9 @@ namespace smt { literal l = *it; TRACE("unsat_core_bug", tout << "answer literal: " << l << "\n";); SASSERT(get_bdata(l.var()).m_assumption); - SASSERT(m_bool_var2assumption.contains(l.var())); - expr * a = 0; - m_bool_var2assumption.find(l.var(), a); - SASSERT(a); + if (!m_literal2assumption.contains(l.index())) l.neg(); + SASSERT(m_literal2assumption.contains(l.index())); + expr * a = m_literal2assumption[l.index()]; if (!already_found_assumptions.contains(a)) { already_found_assumptions.insert(a); m_unsat_core.push_back(a); @@ -2952,7 +2952,7 @@ namespace smt { \brief Execute some finalization code after performing the search. */ void context::check_finalize(lbool r) { - TRACE("after_search", display(tout);); + TRACE("after_search", display(tout << "result: " << r << "\n");); display_profile(verbose_stream()); } @@ -3239,7 +3239,7 @@ namespace smt { for (; it != end; ++it) (*it)->restart_eh(); TRACE("mbqi_bug_detail", tout << "before instantiating quantifiers...\n";); - m_qmanager->restart_eh(); + m_qmanager->restart_eh(); } if (m_fparams.m_simplify_clauses) simplify_clauses(); @@ -3939,6 +3939,20 @@ namespace smt { return th->get_value(n, value); } + bool context::update_model(bool refinalize) { + final_check_status fcs = FC_DONE; + if (refinalize) { + fcs = final_check(); + } + TRACE("opt", tout << (refinalize?"refinalize":"no-op") << " " << fcs << "\n";); + if (fcs == FC_DONE) { + mk_proto_model(l_true); + m_model = m_proto_model->mk_model(); + } + + return fcs == FC_DONE; + } + void context::mk_proto_model(lbool r) { TRACE("get_model", display(tout); diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index 24a4c0f45..62bfacb38 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -206,9 +206,9 @@ namespace smt { // Unsat core extraction // // ----------------------------------- - typedef u_map bool_var2assumption; - bool_var_vector m_assumptions; - bool_var2assumption m_bool_var2assumption; // maps an expression associated with a literal to the original assumption + typedef u_map literal2assumption; + literal_vector m_assumptions; + literal2assumption m_literal2assumption; // maps an expression associated with a literal to the original assumption expr_ref_vector m_unsat_core; // ----------------------------------- @@ -337,6 +337,10 @@ namespace smt { return get_assignment(literal(v)); } + literal_vector const & assigned_literals() const { + return m_assigned_literals; + } + lbool get_assignment(expr * n) const; // Similar to get_assignment, but returns l_undef if n is not internalized. @@ -1391,6 +1395,8 @@ namespace smt { void get_model(model_ref & m) const; + bool update_model(bool refinalize); + void get_proto_model(proto_model_ref & m) const; unsigned get_num_asserted_formulas() const { return m_asserted_formulas.get_num_formulas(); } diff --git a/src/smt/smt_context_pp.cpp b/src/smt/smt_context_pp.cpp index 9ce684440..305e84518 100644 --- a/src/smt/smt_context_pp.cpp +++ b/src/smt/smt_context_pp.cpp @@ -427,7 +427,7 @@ namespace smt { } expr_ref n(m_manager); literal2expr(~consequent, n); - pp.display(out, n); + pp.display_smt2(out, n); } static unsigned g_lemma_id = 0; @@ -437,9 +437,9 @@ namespace smt { void context::display_lemma_as_smt_problem(unsigned num_antecedents, literal const * antecedents, literal consequent, const char * logic) const { char buffer[BUFFER_SZ]; #ifdef _WINDOWS - sprintf_s(buffer, BUFFER_SZ, "lemma_%d.smt", g_lemma_id); + sprintf_s(buffer, BUFFER_SZ, "lemma_%d.smt2", g_lemma_id); #else - sprintf(buffer, "lemma_%d.smt", g_lemma_id); + sprintf(buffer, "lemma_%d.smt2", g_lemma_id); #endif std::ofstream out(buffer); display_lemma_as_smt_problem(out, num_antecedents, antecedents, consequent, logic); @@ -468,7 +468,7 @@ namespace smt { } expr_ref n(m_manager); literal2expr(~consequent, n); - pp.display(out, n); + pp.display_smt2(out, n); } void context::display_lemma_as_smt_problem(unsigned num_antecedents, literal const * antecedents, @@ -476,9 +476,9 @@ namespace smt { literal consequent, const char * logic) const { char buffer[BUFFER_SZ]; #ifdef _WINDOWS - sprintf_s(buffer, BUFFER_SZ, "lemma_%d.smt", g_lemma_id); + sprintf_s(buffer, BUFFER_SZ, "lemma_%d.smt2", g_lemma_id); #else - sprintf(buffer, "lemma_%d.smt", g_lemma_id); + sprintf(buffer, "lemma_%d.smt2", g_lemma_id); #endif std::ofstream out(buffer); display_lemma_as_smt_problem(out, num_antecedents, antecedents, num_eq_antecedents, eq_antecedents, consequent, logic); diff --git a/src/smt/smt_farkas_util.cpp b/src/smt/smt_farkas_util.cpp new file mode 100644 index 000000000..c1a303299 --- /dev/null +++ b/src/smt/smt_farkas_util.cpp @@ -0,0 +1,356 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + smt_farkas_util.cpp + +Abstract: + + Utility for combining inequalities using coefficients obtained from Farkas lemmas. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-2. + +Revision History: + + NB. This utility is specialized to proofs generated by the arithmetic solvers. + +--*/ + +#include "smt_farkas_util.h" +#include "ast_pp.h" +#include "th_rewriter.h" +#include "bool_rewriter.h" + + +namespace smt { + + farkas_util::farkas_util(ast_manager& m): + m(m), + a(m), + m_ineqs(m), + m_split_literals(false), + m_time(0) { + } + + void farkas_util::mk_coerce(expr*& e1, expr*& e2) { + if (a.is_int(e1) && a.is_real(e2)) { + e1 = a.mk_to_real(e1); + } + else if (a.is_int(e2) && a.is_real(e1)) { + e2 = a.mk_to_real(e2); + } + } + + // TBD: arith_decl_util now supports coercion, so this should be deprecated. + app* farkas_util::mk_add(expr* e1, expr* e2) { + mk_coerce(e1, e2); + return a.mk_add(e1, e2); + } + + app* farkas_util::mk_mul(expr* e1, expr* e2) { + mk_coerce(e1, e2); + return a.mk_mul(e1, e2); + } + + app* farkas_util::mk_le(expr* e1, expr* e2) { + mk_coerce(e1, e2); + return a.mk_le(e1, e2); + } + + app* farkas_util::mk_ge(expr* e1, expr* e2) { + mk_coerce(e1, e2); + return a.mk_gt(e1, e2); + } + + app* farkas_util::mk_gt(expr* e1, expr* e2) { + mk_coerce(e1, e2); + return a.mk_gt(e1, e2); + } + + app* farkas_util::mk_lt(expr* e1, expr* e2) { + mk_coerce(e1, e2); + return a.mk_lt(e1, e2); + } + + void farkas_util::mul(rational const& c, expr* e, expr_ref& res) { + expr_ref tmp(m); + if (c.is_one()) { + tmp = e; + } + else { + tmp = mk_mul(a.mk_numeral(c, c.is_int() && a.is_int(e)), e); + } + res = mk_add(res, tmp); + } + + bool farkas_util::is_int_sort(app* c) { + SASSERT(m.is_eq(c) || a.is_le(c) || a.is_lt(c) || a.is_gt(c) || a.is_ge(c)); + SASSERT(a.is_int(c->get_arg(0)) || a.is_real(c->get_arg(0))); + return a.is_int(c->get_arg(0)); + } + + bool farkas_util::is_int_sort() { + SASSERT(!m_ineqs.empty()); + return is_int_sort(m_ineqs[0].get()); + } + + void farkas_util::normalize_coeffs() { + rational l(1); + for (unsigned i = 0; i < m_coeffs.size(); ++i) { + l = lcm(l, denominator(m_coeffs[i])); + } + if (!l.is_one()) { + for (unsigned i = 0; i < m_coeffs.size(); ++i) { + m_coeffs[i] *= l; + } + } + m_normalize_factor = l; + } + + app* farkas_util::mk_one() { + return a.mk_numeral(rational(1), true); + } + + app* farkas_util::fix_sign(bool is_pos, app* c) { + expr* x, *y; + SASSERT(m.is_eq(c) || a.is_le(c) || a.is_lt(c) || a.is_gt(c) || a.is_ge(c)); + bool is_int = is_int_sort(c); + if (is_int && is_pos && (a.is_lt(c, x, y) || a.is_gt(c, y, x))) { + return mk_le(mk_add(x, mk_one()), y); + } + if (is_int && !is_pos && (a.is_le(c, x, y) || a.is_ge(c, y, x))) { + // !(x <= y) <=> x > y <=> x >= y + 1 + return mk_ge(x, mk_add(y, mk_one())); + } + if (is_pos) { + return c; + } + if (a.is_le(c, x, y)) return mk_gt(x, y); + if (a.is_lt(c, x, y)) return mk_ge(x, y); + if (a.is_ge(c, x, y)) return mk_lt(x, y); + if (a.is_gt(c, x, y)) return mk_le(x, y); + UNREACHABLE(); + return c; + } + + void farkas_util::partition_ineqs() { + m_reps.reset(); + m_his.reset(); + ++m_time; + for (unsigned i = 0; i < m_ineqs.size(); ++i) { + m_reps.push_back(process_term(m_ineqs[i].get())); + } + unsigned head = 0; + while (head < m_ineqs.size()) { + unsigned r = find(m_reps[head]); + unsigned tail = head; + for (unsigned i = head+1; i < m_ineqs.size(); ++i) { + if (find(m_reps[i]) == r) { + ++tail; + if (tail != i) { + SASSERT(tail < i); + std::swap(m_reps[tail], m_reps[i]); + app_ref tmp(m); + tmp = m_ineqs[i].get(); + m_ineqs[i] = m_ineqs[tail].get(); + m_ineqs[tail] = tmp; + std::swap(m_coeffs[tail], m_coeffs[i]); + } + } + } + head = tail + 1; + m_his.push_back(head); + } + } + + unsigned farkas_util::find(unsigned idx) { + if (m_ts.size() <= idx) { + m_roots.resize(idx+1); + m_size.resize(idx+1); + m_ts.resize(idx+1); + m_roots[idx] = idx; + m_ts[idx] = m_time; + m_size[idx] = 1; + return idx; + } + if (m_ts[idx] != m_time) { + m_size[idx] = 1; + m_ts[idx] = m_time; + m_roots[idx] = idx; + return idx; + } + while (true) { + if (m_roots[idx] == idx) { + return idx; + } + idx = m_roots[idx]; + } + } + + void farkas_util::merge(unsigned i, unsigned j) { + i = find(i); + j = find(j); + if (i == j) { + return; + } + if (m_size[i] > m_size[j]) { + std::swap(i, j); + } + m_roots[i] = j; + m_size[j] += m_size[i]; + } + unsigned farkas_util::process_term(expr* e) { + unsigned r = e->get_id(); + ptr_vector todo; + ast_mark mark; + todo.push_back(e); + while (!todo.empty()) { + e = todo.back(); + todo.pop_back(); + if (mark.is_marked(e)) { + continue; + } + mark.mark(e, true); + if (is_uninterp(e)) { + merge(r, e->get_id()); + } + if (is_app(e)) { + app* a = to_app(e); + for (unsigned i = 0; i < a->get_num_args(); ++i) { + todo.push_back(a->get_arg(i)); + } + } + } + return r; + } + expr_ref farkas_util::extract_consequence(unsigned lo, unsigned hi) { + bool is_int = is_int_sort(); + app_ref zero(a.mk_numeral(rational::zero(), is_int), m); + expr_ref res(m); + res = zero; + bool is_strict = false; + bool is_eq = true; + expr* x, *y; + for (unsigned i = lo; i < hi; ++i) { + app* c = m_ineqs[i].get(); + if (m.is_eq(c, x, y)) { + mul(m_coeffs[i], x, res); + mul(-m_coeffs[i], y, res); + } + if (a.is_lt(c, x, y) || a.is_gt(c, y, x)) { + mul(m_coeffs[i], x, res); + mul(-m_coeffs[i], y, res); + is_strict = true; + is_eq = false; + } + if (a.is_le(c, x, y) || a.is_ge(c, y, x)) { + mul(m_coeffs[i], x, res); + mul(-m_coeffs[i], y, res); + is_eq = false; + } + } + + zero = a.mk_numeral(rational::zero(), a.is_int(res)); + if (is_eq) { + res = m.mk_eq(res, zero); + } + else if (is_strict) { + res = mk_lt(res, zero); + } + else { + res = mk_le(res, zero); + } + res = m.mk_not(res); + th_rewriter rw(m); + params_ref params; + params.set_bool("gcd_rounding", true); + rw.updt_params(params); + proof_ref pr(m); + expr_ref result(m); + rw(res, result, pr); + fix_dl(result); + return result; + } + + void farkas_util::fix_dl(expr_ref& r) { + expr* e; + if (m.is_not(r, e)) { + r = e; + fix_dl(r); + r = m.mk_not(r); + return; + } + expr* e1, *e2, *e3, *e4; + if ((m.is_eq(r, e1, e2) || a.is_lt(r, e1, e2) || a.is_gt(r, e1, e2) || + a.is_le(r, e1, e2) || a.is_ge(r, e1, e2))) { + if (a.is_add(e1, e3, e4) && a.is_mul(e3)) { + r = m.mk_app(to_app(r)->get_decl(), a.mk_add(e4,e3), e2); + } + } + } + + void farkas_util::reset() { + m_ineqs.reset(); + m_coeffs.reset(); + } + + void farkas_util::add(rational const & coef, app * c) { + bool is_pos = true; + expr* e; + while (m.is_not(c, e)) { + is_pos = !is_pos; + c = to_app(e); + } + + if (!coef.is_zero() && !m.is_true(c)) { + m_coeffs.push_back(coef); + m_ineqs.push_back(fix_sign(is_pos, c)); + } + } + + expr_ref farkas_util::get() { + m_normalize_factor = rational::one(); + expr_ref res(m); + if (m_coeffs.empty()) { + res = m.mk_false(); + return res; + } + bool is_int = is_int_sort(); + if (is_int) { + normalize_coeffs(); + } + + if (m_split_literals) { + // partition equalities into variable disjoint sets. + // take the conjunction of these instead of the + // linear combination. + partition_ineqs(); + expr_ref_vector lits(m); + unsigned lo = 0; + for (unsigned i = 0; i < m_his.size(); ++i) { + unsigned hi = m_his[i]; + lits.push_back(extract_consequence(lo, hi)); + lo = hi; + } + bool_rewriter(m).mk_or(lits.size(), lits.c_ptr(), res); + IF_VERBOSE(2, { if (lits.size() > 1) { verbose_stream() << "combined lemma: " << mk_pp(res, m) << "\n"; } }); + } + else { + res = extract_consequence(0, m_coeffs.size()); + } + + TRACE("arith", + for (unsigned i = 0; i < m_coeffs.size(); ++i) { + tout << m_coeffs[i] << " * (" << mk_pp(m_ineqs[i].get(), m) << ") "; + } + tout << "\n"; + tout << res << "\n"; + ); + + return res; + } +} + diff --git a/src/smt/smt_farkas_util.h b/src/smt/smt_farkas_util.h new file mode 100644 index 000000000..0152ee289 --- /dev/null +++ b/src/smt/smt_farkas_util.h @@ -0,0 +1,96 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + smt_farkas_util.h + +Abstract: + + Utility for combining inequalities using coefficients obtained from Farkas lemmas. + +Author: + + Nikolaj Bjorner (nbjorne) 2013-11-2. + +Revision History: + + NB. This utility is specialized to proofs generated by the arithmetic solvers. + +--*/ + +#ifndef __FARKAS_UTIL_H_ +#define __FARKAS_UTIL_H_ + +#include "arith_decl_plugin.h" + +namespace smt { + + class farkas_util { + ast_manager& m; + arith_util a; + app_ref_vector m_ineqs; + vector m_coeffs; + rational m_normalize_factor; + // utilities for separating coefficients + bool m_split_literals; + unsigned m_time; + unsigned_vector m_roots, m_size, m_his, m_reps, m_ts; + + void mk_coerce(expr*& e1, expr*& e2); + app* mk_add(expr* e1, expr* e2); + app* mk_mul(expr* e1, expr* e2); + app* mk_le(expr* e1, expr* e2); + app* mk_ge(expr* e1, expr* e2); + app* mk_gt(expr* e1, expr* e2); + app* mk_lt(expr* e1, expr* e2); + void mul(rational const& c, expr* e, expr_ref& res); + bool is_int_sort(app* c); + bool is_int_sort(); + void normalize_coeffs(); + app* mk_one(); + app* fix_sign(bool is_pos, app* c); + void partition_ineqs(); + unsigned find(unsigned idx); + void merge(unsigned i, unsigned j); + unsigned process_term(expr* e); + expr_ref extract_consequence(unsigned lo, unsigned hi); + void fix_dl(expr_ref& r); + + public: + farkas_util(ast_manager& m); + + /** + \brief Reset state + */ + void reset(); + + /** + \brief add a multiple of constraint c to the current state + */ + void add(rational const & coef, app * c); + + /** + \brief Extract the complement of premises multiplied by Farkas coefficients. + */ + expr_ref get(); + + /** + \brief Coefficients are normalized for integer problems. + Retrieve multiplicant for normalization. + */ + rational const& get_normalize_factor() const { return m_normalize_factor; } + + /** + \brief extract one or multiple consequences based on literal partition. + Multiple consequences are strongst modulo a partition of variables. + Consequence generation under literal partitioning maintains difference logic constraints. + That is, if the original constraints are difference logic, then the consequent + produced by literal partitioning is also difference logic. + */ + void set_split_literals(bool f) { m_split_literals = f; } + + }; +} + +#endif diff --git a/src/smt/smt_internalizer.cpp b/src/smt/smt_internalizer.cpp index 42e761b61..74f2e09fa 100644 --- a/src/smt/smt_internalizer.cpp +++ b/src/smt/smt_internalizer.cpp @@ -814,6 +814,7 @@ namespace smt { */ bool_var context::mk_bool_var(expr * n) { SASSERT(!b_internalized(n)); + //SASSERT(!m_manager.is_not(n)); unsigned id = n->get_id(); bool_var v = m_b_internalized_stack.size(); #ifndef _EXTERNAL_RELEASE @@ -828,7 +829,7 @@ namespace smt { } #endif TRACE("mk_bool_var", tout << "creating boolean variable: " << v << " for:\n" << mk_pp(n, m_manager) << "\n";); - TRACE("mk_var_bug", tout << "mk_bool: " << v << "\n";); + TRACE("mk_var_bug", tout << "mk_bool: " << v << "\n";); set_bool_var(id, v); m_bdata.reserve(v+1); m_activity.reserve(v+1); diff --git a/src/smt/smt_justification.h b/src/smt/smt_justification.h index 4f402daf2..ba306ba73 100644 --- a/src/smt/smt_justification.h +++ b/src/smt/smt_justification.h @@ -225,6 +225,7 @@ namespace smt { virtual proof * mk_proof(conflict_resolution & cr) = 0; virtual char const * get_name() const { return "simple"; } + }; class simple_theory_justification : public simple_justification { @@ -274,6 +275,7 @@ namespace smt { virtual char const * get_name() const { return "theory-propagation"; } + }; class theory_conflict_justification : public simple_theory_justification { diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index 51b83d61c..5eac22853 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -30,6 +30,7 @@ Revision History: #include"theory_dummy.h" #include"theory_dl.h" #include"theory_seq_empty.h" +#include"theory_pb.h" namespace smt { @@ -300,7 +301,7 @@ namespace smt { } void setup::setup_QF_IDL() { - TRACE("setup", tout << "setup_QF_IDL(st)\n";); + TRACE("setup", tout << "setup_QF_IDL()\n";); m_params.m_relevancy_lvl = 0; m_params.m_arith_expand_eqs = true; m_params.m_arith_reflect = false; @@ -354,6 +355,10 @@ namespace smt { m_context.register_plugin(alloc(smt::theory_dense_si, m_manager, m_params)); else m_context.register_plugin(alloc(smt::theory_dense_i, m_manager, m_params)); + + } + else if (!m_params.m_arith_auto_config_simplex && !is_dense(st)) { + m_context.register_plugin(alloc(smt::theory_idl, m_manager, m_params)); } else { // if (st.m_arith_k_sum < rational(INT_MAX / 8)) { @@ -373,6 +378,7 @@ namespace smt { m_params.m_arith_reflect = false; m_params.m_nnf_cnf = false; m_params.m_arith_eq_bounds = true; + m_params.m_arith_expand_eqs = true; m_params.m_phase_selection = PS_ALWAYS_FALSE; m_params.m_restart_strategy = RS_GEOMETRIC; m_params.m_restart_factor = 1.5; @@ -405,6 +411,15 @@ namespace smt { return; } } +#if 0 + switch (m_params.m_arith_mode) { + case AS_DIFF_LOGIC: + case AS_DENSE_DIFF_LOGIC: + case AS_UTVPI: + setup_arith(); + return; + } +#endif m_params.m_arith_eq_bounds = true; m_params.m_phase_selection = PS_ALWAYS_FALSE; m_params.m_restart_strategy = RS_GEOMETRIC; @@ -414,7 +429,7 @@ namespace smt { m_context.register_plugin(alloc(smt::theory_mi_arith, m_manager, m_params)); } // else if (st.m_arith_k_sum < rational(INT_MAX / 8)) - // m_context.register_plugin(alloc(smt::theory_si_arith, m_manager, m_params)); + // m_context.register_plugin(alloc(smt::theory_dense_si, m_manager, m_params)); else m_context.register_plugin(alloc(smt::theory_i_arith, m_manager, m_params)); } @@ -688,7 +703,12 @@ namespace smt { } void setup::setup_mi_arith() { - m_context.register_plugin(alloc(smt::theory_mi_arith, m_manager, m_params)); + if (m_params.m_arith_mode == AS_OPTINF) { + m_context.register_plugin(alloc(smt::theory_inf_arith, m_manager, m_params)); + } + else { + m_context.register_plugin(alloc(smt::theory_mi_arith, m_manager, m_params)); + } } void setup::setup_arith() { @@ -697,6 +717,7 @@ namespace smt { m_context.register_plugin(alloc(smt::theory_dummy, m_manager.mk_family_id("arith"), "no arithmetic")); break; case AS_DIFF_LOGIC: + m_params.m_arith_expand_eqs = true; if (m_params.m_arith_fixnum) { if (m_params.m_arith_int_only) m_context.register_plugin(alloc(smt::theory_fidl, m_manager, m_params)); @@ -711,6 +732,7 @@ namespace smt { } break; case AS_DENSE_DIFF_LOGIC: + m_params.m_arith_expand_eqs = true; if (m_params.m_arith_fixnum) { if (m_params.m_arith_int_only) m_context.register_plugin(alloc(smt::theory_dense_si, m_manager, m_params)); @@ -725,11 +747,15 @@ namespace smt { } break; case AS_UTVPI: + m_params.m_arith_expand_eqs = true; if (m_params.m_arith_int_only) m_context.register_plugin(alloc(smt::theory_iutvpi, m_manager)); else m_context.register_plugin(alloc(smt::theory_rutvpi, m_manager)); break; + case AS_OPTINF: + m_context.register_plugin(alloc(smt::theory_inf_arith, m_manager, m_params)); + break; default: if (m_params.m_arith_int_only) m_context.register_plugin(alloc(smt::theory_i_arith, m_manager, m_params)); @@ -780,6 +806,10 @@ namespace smt { m_context.register_plugin(alloc(theory_seq_empty, m_manager)); } + void setup::setup_card() { + m_context.register_plugin(alloc(theory_pb, m_manager, m_params)); + } + void setup::setup_unknown() { setup_arith(); setup_arrays(); @@ -787,6 +817,7 @@ namespace smt { setup_datatypes(); setup_dl(); setup_seq(); + setup_card(); } void setup::setup_unknown(static_features & st) { diff --git a/src/smt/smt_setup.h b/src/smt/smt_setup.h index e0188537e..da07ad9ea 100644 --- a/src/smt/smt_setup.h +++ b/src/smt/smt_setup.h @@ -42,7 +42,7 @@ namespace smt { class setup { context & m_context; ast_manager & m_manager; - smt_params & m_params; + smt_params & m_params; symbol m_logic; bool m_already_configured; void setup_auto_config(); @@ -92,7 +92,7 @@ namespace smt { void setup_arith(); void setup_dl(); void setup_seq(); - void setup_instgen(); + void setup_card(); void setup_i_arith(); void setup_mi_arith(); public: diff --git a/src/smt/spanning_tree.h b/src/smt/spanning_tree.h new file mode 100644 index 000000000..5bd5b9fb0 --- /dev/null +++ b/src/smt/spanning_tree.h @@ -0,0 +1,82 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + spanning_tree.h + +Abstract: + + Represent spanning trees with needed operations for Network Simplex + +Author: + + Anh-Dung Phan (t-anphan) 2013-11-06 + +Notes: + +--*/ +#ifndef _SPANNING_TREE_H_ +#define _SPANNING_TREE_H_ + +#include "diff_logic.h" +#include "spanning_tree_base.h" + +namespace smt { + + template + class thread_spanning_tree : public spanning_tree_base, protected Ext { + protected: + typedef dl_edge edge; + typedef dl_graph graph; + typedef typename Ext::numeral numeral; + typedef typename Ext::fin_numeral fin_numeral; + + // Store the parent of a node i in the spanning tree + svector m_pred; + // Store the number of edge on the path from node i to the root + svector m_depth; + svector m_thread; // Store the pointer from node i to the next node in depth-first search order + + svector m_tree; // i |-> edge between (i, m_pred[i]) + + node_id m_root_t2; + + graph & m_graph; + + void swap_order(node_id q, node_id v); + node_id find_rev_thread(node_id n) const; + void fix_depth(node_id start, node_id after_end); + node_id get_final(int start); + bool is_preorder_traversal(node_id start, node_id end); + node_id get_common_ancestor(node_id u, node_id v); + bool is_forward_edge(edge_id e_id) const; + bool is_ancestor_of(node_id ancestor, node_id child); + + public: + thread_spanning_tree(graph & g); + + virtual void initialize(svector const & tree); + void get_descendants(node_id start, svector & descendants); + + virtual void update(edge_id enter_id, edge_id leave_id); + void get_path(node_id start, node_id end, svector & path, svector & against); + bool in_subtree_t2(node_id child); + + bool check_well_formed(); + }; + + template + class basic_spanning_tree : public thread_spanning_tree { + private: + graph * m_tree_graph; + + public: + basic_spanning_tree(graph & g); + void initialize(svector const & tree); + void update(edge_id enter_id, edge_id leave_id); + }; + +} + +#endif diff --git a/src/smt/spanning_tree_base.h b/src/smt/spanning_tree_base.h new file mode 100644 index 000000000..3d3ee7b3a --- /dev/null +++ b/src/smt/spanning_tree_base.h @@ -0,0 +1,53 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + spanning_tree_base.h + +Abstract: + + Represent spanning trees with needed operations for Network Simplex + +Author: + + Anh-Dung Phan (t-anphan) 2013-11-06 + +Notes: + +--*/ + +#ifndef _SPANNING_TREE_BASE_H_ +#define _SPANNING_TREE_BASE_H_ + +#include "util.h" +#include "vector.h" + +namespace smt { + template + inline std::string pp_vector(std::string const & label, TV v) { + std::ostringstream oss; + oss << label << " "; + for (unsigned i = 0; i < v.size(); ++i) { + oss << v[i] << " "; + } + oss << std::endl; + return oss.str(); + } + + class spanning_tree_base { + public: + typedef int node_id; + typedef int edge_id; + virtual void initialize(svector const & tree) = 0; + virtual void get_descendants(node_id start, svector & descendants) = 0; + + virtual void update(edge_id enter_id, edge_id leave_id) = 0; + virtual void get_path(node_id start, node_id end, svector & path, svector & against) = 0; + virtual bool in_subtree_t2(node_id child) = 0; + + virtual bool check_well_formed() = 0; + }; +} + +#endif diff --git a/src/smt/spanning_tree_def.h b/src/smt/spanning_tree_def.h new file mode 100644 index 000000000..5dbcd2b8b --- /dev/null +++ b/src/smt/spanning_tree_def.h @@ -0,0 +1,489 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + spanning_tree_def.h + +Abstract: + + +Author: + + Anh-Dung Phan (t-anphan) 2013-11-06 + +Notes: + +--*/ + +#ifndef _SPANNING_TREE_DEF_H_ +#define _SPANNING_TREE_DEF_H_ + +#include "spanning_tree.h" + +namespace smt { + + template + thread_spanning_tree::thread_spanning_tree(graph & g) : + m_graph(g) { + } + + template + void thread_spanning_tree::initialize(svector const & tree) { + m_tree = tree; + + unsigned num_nodes = m_graph.get_num_nodes(); + m_pred.resize(num_nodes); + m_depth.resize(num_nodes); + m_thread.resize(num_nodes); + + node_id root = num_nodes - 1; + m_pred[root] = -1; + m_depth[root] = 0; + m_thread[root] = 0; + + // Create artificial edges from/to root node to/from other nodes and initialize the spanning tree + for (int i = 0; i < root; ++i) { + m_pred[i] = root; + m_depth[i] = 1; + m_thread[i] = i + 1; + } + + TRACE("network_flow", { + tout << pp_vector("Predecessors", m_pred) << pp_vector("Threads", m_thread); + tout << pp_vector("Depths", m_depth) << pp_vector("Tree", m_tree); + }); + } + + template + typename thread_spanning_tree::node_id thread_spanning_tree::get_common_ancestor(node_id u, node_id v) { + while (u != v) { + if (m_depth[u] > m_depth[v]) + u = m_pred[u]; + else + v = m_pred[v]; + } + return u; + } + + template + void thread_spanning_tree::get_path(node_id start, node_id end, svector & path, svector & against) { + node_id join = get_common_ancestor(start, end); + path.reset(); + while (start != join) { + edge_id e_id = m_tree[start]; + path.push_back(e_id); + against.push_back(is_forward_edge(e_id)); + start = m_pred[start]; + } + while (end != join) { + edge_id e_id = m_tree[end]; + path.push_back(e_id); + against.push_back(!is_forward_edge(e_id)); + end = m_pred[end]; + } + } + + template + bool thread_spanning_tree::is_forward_edge(edge_id e_id) const { + node_id start = m_graph.get_source(e_id); + node_id end = m_graph.get_target(e_id); + SASSERT(m_pred[start] == end || m_pred[end] == start); + return m_pred[start] == end; + } + + template + void thread_spanning_tree::get_descendants(node_id start, svector & descendants) { + descendants.reset(); + descendants.push_back(start); + node_id u = m_thread[start]; + while (m_depth[u] > m_depth[start]) { + descendants.push_back(u); + u = m_thread[u]; + } + + } + + template + bool thread_spanning_tree::in_subtree_t2(node_id child) { + if (m_depth[child] < m_depth[m_root_t2]) { + return false; + } + return is_ancestor_of(m_root_t2, child); + } + + template + bool thread_spanning_tree::is_ancestor_of(node_id ancestor, node_id child) { + for (node_id n = child; n != -1; n = m_pred[n]) { + if (n == ancestor) { + return true; + } + } + return false; + } + + /** + \brief add entering_edge, remove leaving_edge from spanning tree. + + Old tree: New tree: + root root + / \ / \ + x y x y + / \ / \ / \ / \ + u s u s + | / / + v w v w + / \ \ / \ \ + z p z p + \ \ / + q q + */ + template + void thread_spanning_tree::update(edge_id enter_id, edge_id leave_id) { + node_id p = m_graph.get_source(enter_id); + node_id q = m_graph.get_target(enter_id); + node_id u = m_graph.get_source(leave_id); + node_id v = m_graph.get_target(leave_id); + + if (m_pred[u] == v) { + std::swap(u, v); + } + + SASSERT(m_pred[v] == u); + + if (is_ancestor_of(v, p)) { + std::swap(p, q); + } + + SASSERT(is_ancestor_of(v, q)); + + TRACE("network_flow", { + tout << "update_spanning_tree: (" << p << ", " << q << ") enters, ("; + tout << u << ", " << v << ") leaves\n"; + }); + + // Old threads: alpha -> v -*-> f(v) -> beta | p -*-> f(p) -> gamma + // New threads: alpha -> beta | p -*-> f(p) -> v -*-> f(v) -> gamma + + node_id f_p = get_final(p); + node_id f_v = get_final(v); + node_id alpha = find_rev_thread(v); + node_id beta = m_thread[f_v]; + node_id gamma = m_thread[f_p]; + + if (v != gamma) { + m_thread[alpha] = beta; + m_thread[f_p] = v; + m_thread[f_v] = gamma; + } + + node_id old_pred = m_pred[q]; + // Update stem nodes from q to v + if (q != v) { + for (node_id n = q; n != v; ) { + SASSERT(old_pred != u); // the last processed node_id is v + SASSERT(-1 != m_pred[old_pred]); + int next_old_pred = m_pred[old_pred]; + swap_order(n, old_pred); + m_tree[old_pred] = m_tree[n]; + n = old_pred; + old_pred = next_old_pred; + } + } + + m_pred[q] = p; + m_tree[q] = enter_id; + m_root_t2 = q; + + node_id after_final_q = (v == gamma) ? beta : gamma; + fix_depth(q, after_final_q); + + SASSERT(!in_subtree_t2(p)); + SASSERT(in_subtree_t2(q)); + SASSERT(!in_subtree_t2(u)); + SASSERT(in_subtree_t2(v)); + + TRACE("network_flow", { + tout << pp_vector("Predecessors", m_pred) << pp_vector("Threads", m_thread); + tout << pp_vector("Depths", m_depth) << pp_vector("Tree", m_tree); + }); + } + + /** + swap v and q in tree. + - fixup m_thread + - fixup m_pred + + Case 1: final(q) == final(v) + ------- + Old thread: prev -> v -*-> alpha -> q -*-> final(q) -> next + New thread: prev -> q -*-> final(q) -> v -*-> alpha -> next + + Case 2: final(q) != final(v) + ------- + Old thread: prev -> v -*-> alpha -> q -*-> final(q) -> beta -*-> final(v) -> next + New thread: prev -> q -*-> final(q) -> v -*-> alpha -> beta -*-> final(v) -> next + + */ + template + void thread_spanning_tree::swap_order(node_id q, node_id v) { + SASSERT(q != v); + SASSERT(m_pred[q] == v); + SASSERT(is_preorder_traversal(v, get_final(v))); + node_id prev = find_rev_thread(v); + node_id f_q = get_final(q); + node_id f_v = get_final(v); + node_id next = m_thread[f_v]; + node_id alpha = find_rev_thread(q); + + if (f_q == f_v) { + SASSERT(f_q != v && alpha != next); + m_thread[f_q] = v; + m_thread[alpha] = next; + f_q = alpha; + } + else { + node_id beta = m_thread[f_q]; + SASSERT(f_q != v && alpha != beta); + m_thread[f_q] = v; + m_thread[alpha] = beta; + f_q = f_v; + } + SASSERT(prev != q); + m_thread[prev] = q; + m_pred[v] = q; + // Notes: f_q has to be used since m_depth hasn't been updated yet. + SASSERT(is_preorder_traversal(q, f_q)); + } + + /** + \brief Check invariants of main data-structures. + + Spanning tree of m_graph + root is represented using: + + svector m_states; edge_id |-> edge_state + svector m_pred; node_id |-> node + svector m_depth; node_id |-> int + svector m_thread; node_id |-> node + + Tree is determined by m_pred: + - m_pred[root] == -1 + - m_pred[n] = m != n for each node_id n, acyclic until reaching root. + - m_depth[m_pred[n]] + 1 == m_depth[n] for each n != root + + m_thread is a linked list traversing all nodes. + Furthermore, the nodes linked in m_thread follows a + depth-first traversal order. + + */ + template + bool thread_spanning_tree::check_well_formed() { + node_id root = m_pred.size()-1; + + // Check that m_thread traverses each node. + // This gets checked using union-find as well. + svector found(m_thread.size(), false); + found[root] = true; + for (node_id x = m_thread[root]; x != root; x = m_thread[x]) { + SASSERT(x != m_thread[x]); + found[x] = true; + } + for (unsigned i = 0; i < found.size(); ++i) { + SASSERT(found[i]); + } + + // m_pred is acyclic, and points to root. + SASSERT(m_pred[root] == -1); + SASSERT(m_depth[root] == 0); + for (node_id i = 0; i < root; ++i) { + SASSERT(m_depth[m_pred[i]] < m_depth[i]); + } + + // m_depth[x] denotes distance from x to the root node + for (node_id x = m_thread[root]; x != root; x = m_thread[x]) { + SASSERT(m_depth[x] > 0); + SASSERT(m_depth[x] == m_depth[m_pred[x]] + 1); + } + + // m_thread forms a spanning tree over [0..root] + // Union-find structure + svector roots(m_pred.size(), -1); + + for (node_id x = m_thread[root]; x != root; x = m_thread[x]) { + node_id y = m_pred[x]; + // We are now going to check the edge between x and y + SASSERT(find(roots, x) != find(roots, y)); + merge(roots, x, y); + } + + // All nodes belong to the same spanning tree + for (unsigned i = 0; i < roots.size(); ++i) { + SASSERT(roots[i] + roots.size() == 0 || roots[i] >= 0); + } + + for (unsigned i = 0; i < m_tree.size(); ++i) { + node_id src = m_graph.get_source(m_tree[i]); + node_id tgt = m_graph.get_target(m_tree[i]); + SASSERT(m_pred[src] == tgt || m_pred[tgt] == src); + } + + return true; + } + + static unsigned find(svector& roots, unsigned x) { + unsigned old_x = x; + while (roots[x] >= 0) { + x = roots[x]; + } + SASSERT(roots[x] < 0); + if (old_x != x) { + roots[old_x] = x; + } + return x; + } + + static void merge(svector& roots, unsigned x, unsigned y) { + x = find(roots, x); + y = find(roots, y); + SASSERT(roots[x] < 0 && roots[y] < 0); + if (x == y) { + return; + } + if (roots[x] > roots[y]) { + std::swap(x, y); + } + SASSERT(roots[x] <= roots[y]); + roots[x] += roots[y]; + roots[y] = x; + } + + /** + \brief find node_id that points to 'n' in m_thread + */ + template + typename thread_spanning_tree::node_id thread_spanning_tree::find_rev_thread(node_id n) const { + node_id ancestor = m_pred[n]; + SASSERT(ancestor != -1); + while (m_thread[ancestor] != n) { + ancestor = m_thread[ancestor]; + } + return ancestor; + } + + template + void thread_spanning_tree::fix_depth(node_id start, node_id after_end) { + while (start != after_end) { + SASSERT(m_pred[start] != -1); + m_depth[start] = m_depth[m_pred[start]]+1; + start = m_thread[start]; + } + } + + template + typename thread_spanning_tree::node_id thread_spanning_tree::get_final(int start) { + int n = start; + while (m_depth[m_thread[n]] > m_depth[start]) { + n = m_thread[n]; + } + return n; + } + + template + bool thread_spanning_tree::is_preorder_traversal(node_id start, node_id end) { + // get children of start + uint_set children; + children.insert(start); + node_id root = m_pred.size()-1; + for (int i = 0; i < root; ++i) { + for (int j = 0; j < root; ++j) { + if (children.contains(m_pred[j])) { + children.insert(j); + } + } + } + // visit children using m_thread + children.remove(start); + do { + start = m_thread[start]; + SASSERT(children.contains(start)); + children.remove(start); + } + while (start != end); + SASSERT(children.empty()); + return true; + } + + // Basic spanning tree + template + basic_spanning_tree::basic_spanning_tree(graph & g) : thread_spanning_tree(g) { + } + + template + void basic_spanning_tree::initialize(svector const & tree) { + m_tree_graph = alloc(graph); + m_tree = tree; + unsigned num_nodes = m_graph.get_num_nodes(); + for (unsigned i = 0; i < num_nodes; ++i) { + m_tree_graph->init_var(i); + } + + vector const & es = m_graph.get_all_edges(); + svector::const_iterator it = m_tree.begin(), end = m_tree.end(); + for(; it != end; ++it) { + edge const & e = es[*it]; + m_tree_graph->add_edge(e.get_source(), e.get_target(), e.get_weight(), explanation()); + } + + node_id root = num_nodes - 1; + m_tree_graph->bfs_undirected(root, m_pred, m_depth); + m_tree_graph->dfs_undirected(root, m_thread); + } + + template + void basic_spanning_tree::update(edge_id enter_id, edge_id leave_id) { + if (m_tree_graph) dealloc(m_tree_graph); + m_tree_graph = alloc(graph); + unsigned num_nodes = m_graph.get_num_nodes(); + for (unsigned i = 0; i < num_nodes; ++i) { + m_tree_graph->init_var(i); + } + + vector const & es = m_graph.get_all_edges(); + svector::const_iterator it = m_tree.begin(), end = m_tree.end(); + for(; it != end; ++it) { + edge const & e = es[*it]; + if (leave_id != *it) { + m_tree_graph->add_edge(e.get_source(), e.get_target(), e.get_weight(), explanation()); + } + } + edge const & e = es[enter_id]; + m_tree_graph->add_edge(e.get_source(), e.get_target(), e.get_weight(), explanation()); + + node_id root = num_nodes - 1; + m_tree_graph->bfs_undirected(root, m_pred, m_depth); + m_tree_graph->dfs_undirected(root, m_thread); + + vector const & tree_edges = m_tree_graph->get_all_edges(); + for (unsigned i = 0; i < tree_edges.size(); ++i) { + edge const & e = tree_edges[i]; + dl_var src = e.get_source(); + dl_var tgt = e.get_target(); + edge_id id; + VERIFY(m_graph.get_edge_id(src, tgt, id)); + SASSERT(tgt == m_pred[src] || src == m_pred[tgt]); + if (tgt == m_pred[src]) { + m_tree[src] = id; + } + else { + m_tree[tgt] = id; + } + } + + node_id p = m_graph.get_source(enter_id); + node_id q = m_graph.get_target(enter_id); + m_root_t2 = p == m_pred[q] ? q : p; + } + +} + +#endif diff --git a/src/smt/theory_arith.cpp b/src/smt/theory_arith.cpp index 0bb356b95..9a7d08151 100644 --- a/src/smt/theory_arith.cpp +++ b/src/smt/theory_arith.cpp @@ -25,5 +25,6 @@ namespace smt { template class theory_arith; // template class theory_arith; // template class theory_arith; - + + template class smt::theory_arith; }; diff --git a/src/smt/theory_arith.h b/src/smt/theory_arith.h index d1af762bb..a81be26f6 100644 --- a/src/smt/theory_arith.h +++ b/src/smt/theory_arith.h @@ -36,6 +36,8 @@ Revision History: #include"grobner.h" #include"arith_simplifier_plugin.h" #include"arith_eq_solver.h" +#include"theory_opt.h" +#include"uint_set.h" namespace smt { @@ -80,7 +82,7 @@ namespace smt { */ template - class theory_arith : public theory, private Ext { + class theory_arith : public theory, public theory_opt, private Ext { public: typedef typename Ext::numeral numeral; typedef typename Ext::inf_numeral inf_numeral; @@ -90,6 +92,7 @@ namespace smt { static const int dead_row_id = -1; protected: bool proofs_enabled() const { return get_manager().proofs_enabled(); } + bool coeffs_enabled() const { return proofs_enabled() || m_bound_watch != null_bool_var; } struct linear_monomial { numeral m_coeff; @@ -262,6 +265,7 @@ namespace smt { inf_numeral const & get_value() const { return m_value; } virtual bool has_justification() const { return false; } virtual void push_justification(antecedents& antecedents, numeral const& coeff, bool proofs_enabled) {} + virtual void display(theory_arith const& th, std::ostream& out) const; }; @@ -273,14 +277,14 @@ namespace smt { class atom : public bound { protected: bool_var m_bvar; - numeral m_k; + inf_numeral m_k; unsigned m_atom_kind:2; // atom kind unsigned m_is_true:1; // cache: true if the atom was assigned to true. public: - atom(bool_var bv, theory_var v, numeral const & k, atom_kind kind); + atom(bool_var bv, theory_var v, inf_numeral const & k, atom_kind kind); atom_kind get_atom_kind() const { return static_cast(m_atom_kind); } virtual ~atom() {} - numeral const & get_k() const { return m_k; } + inline inf_numeral const & get_k() const { return m_k; } bool_var get_bool_var() const { return m_bvar; } bool is_true() const { return m_is_true; } void assign_eh(bool is_true, inf_numeral const & epsilon); @@ -288,6 +292,7 @@ namespace smt { virtual void push_justification(antecedents& a, numeral const& coeff, bool proofs_enabled) { a.push_lit(literal(get_bool_var(), !m_is_true), coeff, proofs_enabled); } + virtual void display(theory_arith const& th, std::ostream& out) const; }; class eq_bound : public bound { @@ -306,6 +311,7 @@ namespace smt { SASSERT(m_lhs->get_root() == m_rhs->get_root()); a.push_eq(enode_pair(m_lhs, m_rhs), coeff, proofs_enabled); } + virtual void display(theory_arith const& th, std::ostream& out) const; }; class derived_bound : public bound { @@ -320,6 +326,7 @@ namespace smt { virtual void push_justification(antecedents& a, numeral const& coeff, bool proofs_enabled); virtual void push_lit(literal l, numeral const&) { m_lits.push_back(l); } virtual void push_eq(enode_pair const& p, numeral const&) { m_eqs.push_back(p); } + virtual void display(theory_arith const& th, std::ostream& out) const; }; class justified_derived_bound : public derived_bound { @@ -433,6 +440,7 @@ namespace smt { bool m_eager_gcd; // true if gcd should be applied at every add_row unsigned m_final_check_idx; + // backtracking svector m_bound_trail; svector m_unassigned_atoms_trail; @@ -869,13 +877,29 @@ namespace smt { row m_tmp_row; void add_tmp_row(row & r1, numeral const & coeff, row const & r2); - theory_var pick_var_to_leave(theory_var x_j, bool inc, numeral & a_ij, inf_numeral & gain); + theory_var pick_var_to_leave(bool has_int, theory_var x_j, bool inc, numeral & a_ij, inf_numeral & gain, bool& skiped_row); + bool is_safe_to_leave(theory_var x, bool inc, bool& has_int, bool& is_shared); + bool move_to_bound(theory_var x_i, bool inc); template void add_tmp_row_entry(row & r, numeral const & coeff, theory_var v); - bool max_min(row & r, bool max); - bool max_min(theory_var v, bool max); + enum max_min_t { UNBOUNDED, AT_BOUND, OPTIMIZED, BEST_EFFORT}; + max_min_t max_min(theory_var v, bool max, bool& has_shared); + max_min_t max_min_orig(row & r, bool max, bool& has_shared); bool max_min(svector const & vars); + max_min_t max_min_new(row& r, bool max, bool& has_shared); + bool unbounded_gain(inf_numeral const & max_gain) const; + bool safe_gain(inf_numeral const& min_gain, inf_numeral const & max_gain) const; + void normalize_gain(numeral const& divisor, inf_numeral & max_gain) const; + void init_gains(theory_var x, bool inc, inf_numeral& min_gain, inf_numeral& max_gain); + bool update_gains(bool inc, theory_var x_i, numeral const& a_ij, + inf_numeral& min_gain, inf_numeral& max_gain); + bool move_to_bound_new(theory_var x_i, bool inc, unsigned& best_efforts, bool& has_shared); + bool pick_var_to_leave( + theory_var x_j, bool inc, numeral & a_ij, + inf_numeral& min_gain, inf_numeral& max_gain, + bool& shared, theory_var& x_i); + // ----------------------------------- // // Non linear @@ -1004,6 +1028,27 @@ namespace smt { virtual bool get_value(enode * n, expr_ref & r); + // ----------------------------------- + // + // Optimization + // + // ----------------------------------- + virtual inf_eps_rational maximize(theory_var v, expr_ref& blocker, bool& has_shared); + virtual inf_eps_rational value(theory_var v); + virtual theory_var add_objective(app* term); + virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val); + void enable_record_conflict(expr* bound); + void record_conflict(unsigned num_lits, literal const * lits, + unsigned num_eqs, enode_pair const * eqs, + unsigned num_params, parameter* params); + inf_eps_rational conflict_minimize(); + private: + virtual expr_ref mk_gt(theory_var v); + + bool_var m_bound_watch; + inf_eps_rational m_upper_bound; + bool get_theory_vars(expr * n, uint_set & vars); + public: // ----------------------------------- // // Pretty Printing @@ -1034,6 +1079,8 @@ namespace smt { void display_bounds_in_smtlib() const; void display_nl_monomials(std::ostream & out) const; void display_coeff_exprs(std::ostream & out, sbuffer const & p) const; + void display_interval(std::ostream& out, interval const& i); + void display_deps(std::ostream& out, v_dependency* dep); protected: // ----------------------------------- @@ -1049,9 +1096,11 @@ namespace smt { bool wf_rows() const; bool wf_column(theory_var v) const; bool wf_columns() const; + bool valid_assignment() const; bool valid_row_assignment() const; bool valid_row_assignment(row const & r) const; bool satisfy_bounds() const; + bool satisfy_integrality() const; #endif }; @@ -1071,6 +1120,7 @@ namespace smt { static inf_numeral mk_inf_numeral(numeral const & n, numeral const & r) { return inf_numeral(n, r); } + static bool is_infinite(inf_numeral const& ) { return false; } mi_ext() : m_int_epsilon(rational(1)), m_real_epsilon(rational(0), true) {} }; @@ -1087,6 +1137,8 @@ namespace smt { UNREACHABLE(); return inf_numeral(n); } + static bool is_infinite(inf_numeral const& ) { return false; } + i_ext() : m_int_epsilon(1), m_real_epsilon(1) {} }; @@ -1103,6 +1155,8 @@ namespace smt { UNREACHABLE(); return inf_numeral(n); } + static bool is_infinite(inf_numeral const& ) { return false; } + si_ext(): m_int_epsilon(s_integer(1)), m_real_epsilon(s_integer(1)) {} }; @@ -1123,13 +1177,41 @@ namespace smt { static inf_numeral mk_inf_numeral(numeral const& n, numeral const& i) { return inf_numeral(n, i); } + static bool is_infinite(inf_numeral const& ) { return false; } + smi_ext() : m_int_epsilon(s_integer(1)), m_real_epsilon(s_integer(0), true) {} }; + + class inf_ext { + public: + typedef rational numeral; + typedef inf_eps_rational inf_numeral; + inf_numeral m_int_epsilon; + inf_numeral m_real_epsilon; + numeral fractional_part(inf_numeral const& n) { + SASSERT(n.is_rational()); + return n.get_rational() - floor(n); + } + static numeral fractional_part(numeral const & n) { + return n - floor(n); + } + static inf_numeral mk_inf_numeral(numeral const & n, numeral const & r) { + return inf_numeral(inf_rational(n, r)); + } + static bool is_infinite(inf_numeral const& n) { + return !n.get_infinity().is_zero(); + } + + inf_ext() : m_int_epsilon(inf_rational(rational(1))), m_real_epsilon(inf_rational(rational(0), true)) {} + }; + typedef theory_arith theory_mi_arith; typedef theory_arith theory_i_arith; + typedef smt::theory_arith theory_inf_arith; // typedef theory_arith theory_si_arith; // typedef theory_arith theory_smi_arith; + }; diff --git a/src/smt/theory_arith_aux.h b/src/smt/theory_arith_aux.h index 21b892e57..b4ebd9622 100644 --- a/src/smt/theory_arith_aux.h +++ b/src/smt/theory_arith_aux.h @@ -19,7 +19,11 @@ Revision History: #ifndef _THEORY_ARITH_AUX_H_ #define _THEORY_ARITH_AUX_H_ +#include"inf_eps_rational.h" #include"theory_arith.h" +#include"smt_farkas_util.h" +#include"th_rewriter.h" +#include"filter_model_converter.h" namespace smt { @@ -359,6 +363,19 @@ namespace smt { return m_params.c_ptr(); } + // ----------------------------------- + // + // Bounds + // + // ----------------------------------- + + + template + void theory_arith::bound::display(theory_arith const& th, std::ostream& out) const { + out << "v" << get_var() << " " << get_bound_kind() << " " << get_value(); + } + + // ----------------------------------- // // Atoms @@ -366,7 +383,7 @@ namespace smt { // ----------------------------------- template - theory_arith::atom::atom(bool_var bv, theory_var v, numeral const & k, atom_kind kind): + theory_arith::atom::atom(bool_var bv, theory_var v, inf_numeral const & k, atom_kind kind): bound(v, inf_numeral::zero(), B_LOWER, true), m_bvar(bv), m_k(k), @@ -397,6 +414,27 @@ namespace smt { } } + template + void theory_arith::atom::display(theory_arith const& th, std::ostream& out) const { + literal l(get_bool_var(), !m_is_true); + out << "v" << bound::get_var() << " " << bound::get_bound_kind() << " " << get_k() << " "; + out << l << ":"; + th.get_context().display_detailed_literal(out, l); + } + + // ----------------------------------- + // + // eq_bound + // + // ----------------------------------- + + template + void theory_arith::eq_bound::display(theory_arith const& th, std::ostream& out) const { + ast_manager& m = th.get_manager(); + out << "#" << m_lhs->get_owner_id() << " " << mk_pp(m_lhs->get_owner(), m) << " = " + << "#" << m_rhs->get_owner_id() << " " << mk_pp(m_rhs->get_owner(), m); + } + // ----------------------------------- // // Auxiliary methods @@ -475,11 +513,11 @@ namespace smt { bool theory_arith::all_coeff_int(row const & r) const { typename vector::const_iterator it = r.begin_entries(); typename vector::const_iterator end = r.end_entries(); - for (; it != end; ++it) { - if (!it->is_dead() && !it->m_coeff.is_int()) + for (; it != end; ++it) { + if (!it->is_dead() && !it->m_coeff.is_int()) { TRACE("gomory_cut", display_row(tout, r, true);); return false; - + } } return true; } @@ -707,6 +745,24 @@ namespace smt { } } + template + void theory_arith::derived_bound::display(theory_arith const& th, std::ostream& out) const { + out << "v" << bound::get_var() << " " << bound::get_bound_kind() << " " << bound::get_value(); + + ast_manager& m = th.get_manager(); + for (unsigned i = 0; i < m_eqs.size(); ++i) { + enode* a = m_eqs[i].first; + enode* b = m_eqs[i].second; + out << " "; + out << "#" << a->get_owner_id() << " " << mk_pp(a->get_owner(), m) << " = " + << "#" << b->get_owner_id() << " " << mk_pp(b->get_owner(), m); + } + for (unsigned i = 0; i < m_lits.size(); ++i) { + literal l = m_lits[i]; + out << " " << l << ":"; th.get_context().display_detailed_literal(out, l); + } + } + template void theory_arith::justified_derived_bound::push_justification(antecedents& a, numeral const& coeff, bool proofs_enabled) { @@ -901,6 +957,38 @@ namespace smt { r1.reset_var_pos(m_var_pos); } + template + bool theory_arith::is_safe_to_leave(theory_var x, bool inc, bool& has_int, bool& shared) { + + context& ctx = get_context(); + shared |= ctx.is_shared(get_enode(x)); + column & c = m_columns[x]; + typename svector::iterator it = c.begin_entries(); + typename svector::iterator end = c.end_entries(); + has_int = false; + bool unbounded = (inc && !upper(x)) || (!inc && !lower(x)); + bool was_unsafe = false; + for (; it != end; ++it) { + if (it->is_dead()) continue; + row const & r = m_rows[it->m_row_id]; + theory_var s = r.get_base_var(); + numeral const & coeff = r[it->m_row_idx].m_coeff; + if (s != null_theory_var && is_int(s)) has_int = true; + bool is_unsafe = (s != null_theory_var && is_int(s) && !coeff.is_int()); + shared |= (s != null_theory_var && ctx.is_shared(get_enode(s))); + was_unsafe |= is_unsafe; + bool inc_s = coeff.is_neg() ? inc : !inc; + unbounded &= !get_bound(s, inc_s); + TRACE("opt", tout << "is v" << x << " safe to leave for v" << s + << "? " << (is_unsafe?"no":"yes") << " " << (has_int?"int":"real") << " " << (unbounded?"unbounded":"bounded") << "\n"; + display_row(tout, r, true);); + if (was_unsafe && !unbounded) return false; + } + + return !was_unsafe || unbounded; + } + + /** \brief Select tightest variable x_i to pivot with x_j. The goal is to select a x_i such that the value of x_j is increased @@ -912,10 +1000,22 @@ namespace smt { If no x_i imposes a restriction on x_j, then return null_theory_var. That is, x_j is free to move to its upper bound (lower bound). + + Get the equations for x_j: + + x_i1 = coeff_1 * x_j + rest_1 + ... + x_in = coeff_n * x_j + rest_n + + gain_k := (upper_bound(x_ik) - value(x_ik))/coeff_k + */ + template - theory_var theory_arith::pick_var_to_leave(theory_var x_j, bool inc, numeral & a_ij, inf_numeral & gain) { - TRACE("maximize", tout << "selecting variable to replace v" << x_j << ", inc: " << inc << "\n";); + theory_var theory_arith::pick_var_to_leave( + bool has_int, theory_var x_j, bool inc, + numeral & a_ij, inf_numeral & gain, bool& skipped_row) { + TRACE("opt", tout << "selecting variable to replace v" << x_j << ", inc: " << inc << "\n";); theory_var x_i = null_theory_var; inf_numeral curr_gain; column & c = m_columns[x_j]; @@ -936,44 +1036,351 @@ namespace smt { if (curr_gain.is_neg()) curr_gain.neg(); if (x_i == null_theory_var || (curr_gain < gain) || (gain.is_zero() && curr_gain.is_zero() && s < x_i)) { + if (is_int(s) && !curr_gain.is_int()) { + skipped_row = true; + continue; + } + if (is_int(x_j) && !curr_gain.is_int()) { + skipped_row = true; + continue; + } + if (!curr_gain.is_int() && has_int) { + skipped_row = true; + continue; + } x_i = s; a_ij = coeff; gain = curr_gain; + TRACE("opt", + tout << "x_i: v" << x_i << ", gain: " << gain << "\n"; + tout << "value(s): (" << get_value(s) << " - " << b->get_value() << ")/" << coeff << "\n"; + display_row(tout, r, true); + ); } } } - TRACE("maximize", tout << "x_j: v" << x_i << ", gain: " << gain << "\n";); + TRACE("opt", tout << "x_i: v" << x_i << ", gain: " << gain << "\n";); } } - TRACE("maximize", tout << "x_i v" << x_i << "\n";); + TRACE("opt", tout << "x_i v" << x_i << "\n";); return x_i; } + template + bool theory_arith::get_theory_vars(expr * n, uint_set & vars) { + rational r; + expr* x, *y; + if (m_util.is_numeral(n, r)) { + return true; + } + else if (m_util.is_add(n)) { + for (unsigned i = 0; i < to_app(n)->get_num_args(); ++i) { + if (!get_theory_vars(to_app(n)->get_arg(i), vars)) { + return false; + } + } + } + else if (m_util.is_to_real(n, x) || m_util.is_to_int(n, x)) { + return get_theory_vars(x, vars); + } + else if (m_util.is_mul(n, x, y) && m_util.is_numeral(x, r)) { + return get_theory_vars(y, vars); + } + else if (m_util.is_mul(n, y, x) && m_util.is_numeral(x, r)) { + return get_theory_vars(y, vars); + } + else if (!is_app(n)) { + return false; + } + else if (to_app(n)->get_family_id() == m_util.get_family_id()) { + return false; + } + else { + context & ctx = get_context(); + SASSERT(ctx.e_internalized(n)); + enode * e = ctx.get_enode(n); + if (is_attached_to_var(e)) { + vars.insert(e->get_th_var(get_id())); + } + return true; + } + return true; + } + + // + // add_objective(expr* term) internalizes the arithmetic term and creates + // a row for it if it is not already internalized. + // Then return the variable corresponding to the term. + // + + template + theory_var theory_arith::add_objective(app* term) { + theory_var v = internalize_term_core(term); + TRACE("opt", tout << mk_pp(term, get_manager()) << " |-> v" << v << "\n";); + SASSERT(!is_quasi_base(v)); + if (!is_linear(get_manager(), term)) { + v = null_theory_var; + } + return v; + } + + template + inf_eps_rational theory_arith::value(theory_var v) { + return inf_eps_rational(get_value(v)); + } + + template + inf_eps_rational theory_arith::maximize(theory_var v, expr_ref& blocker, bool& has_shared) { + TRACE("bound_bug", display_var(tout, v); display(tout);); + has_shared = false; + max_min_t r = max_min(v, true, has_shared); + if (r == UNBOUNDED) { + has_shared = false; + blocker = get_manager().mk_false(); + return inf_eps_rational::infinity(); + } + else { + blocker = mk_gt(v); + return inf_eps_rational(get_value(v)); + } + + } + + /** + \brief: Create an atom that enforces the inequality v > val + The arithmetical expression encoding the inequality suffices + for the theory of aritmetic. + */ + template + expr_ref theory_arith::mk_gt(theory_var v) { + ast_manager& m = get_manager(); + inf_numeral const& val = get_value(v); + expr* obj = get_enode(v)->get_owner(); + expr_ref e(m); + rational r = val.get_rational(); + if (m_util.is_int(m.get_sort(obj))) { + if (r.is_int()) { + r += rational::one(); + } + else { + r = ceil(r); + } + e = m_util.mk_numeral(r, m.get_sort(obj)); + e = m_util.mk_ge(obj, e); + } + else { + // obj is over the reals. + e = m_util.mk_numeral(r, m.get_sort(obj)); + + if (val.get_infinitesimal().is_neg()) { + e = m_util.mk_ge(obj, e); + } + else { + e = m_util.mk_gt(obj, e); + } + } + return e; + } + + /** + \brief create atom that enforces: val <= v + The atom that enforces the inequality is created directly + as opposed to using arithmetical terms. + This allows to handle inequalities with non-standard numbers. + */ + template + expr_ref theory_arith::mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val) { + ast_manager& m = get_manager(); + context& ctx = get_context(); + std::ostringstream strm; + strm << val << " <= " << mk_pp(get_enode(v)->get_owner(), get_manager()); + app* b = m.mk_const(symbol(strm.str().c_str()), m.mk_bool_sort()); + if (!ctx.b_internalized(b)) { + fm.insert(b->get_decl()); + bool_var bv = ctx.mk_bool_var(b); + ctx.set_var_theory(bv, get_id()); + // ctx.set_enode_flag(bv, true); + atom* a = alloc(atom, bv, v, val, A_LOWER); + m_unassigned_atoms[v]++; + m_var_occs[v].push_back(a); + m_atoms.push_back(a); + insert_bv2a(bv, a); + TRACE("arith", tout << mk_pp(b, m) << "\n"; + display_atom(tout, a, false);); + } + return expr_ref(b, m); + } + + + /** + \brief enable watching bound atom. + */ + template + void theory_arith::enable_record_conflict(expr* bound) { + m_params.m_arith_bound_prop = BP_NONE; + SASSERT(propagation_mode() == BP_NONE); // bound propagtion rules are not (yet) handled. + if (bound) { + context& ctx = get_context(); + m_bound_watch = ctx.get_bool_var(bound); + } + else { + m_bound_watch = null_bool_var; + } + m_upper_bound = -inf_eps_rational::infinity(); + } + + /** + \brief + pos < 0 + == + r(Ax <= b) + q(v <= val) + == + val' <= q*v & q*v <= q*val + + q*v - val' >= 0 + + => + (q*v - val' - q*v)/q >= -v + == + val/q <= v + */ + + template + void theory_arith::record_conflict( + unsigned num_lits, literal const * lits, + unsigned num_eqs, enode_pair const * eqs, + unsigned num_params, parameter* params) { + ast_manager& m = get_manager(); + context& ctx = get_context(); + expr_ref tmp(m), vq(m); + expr* x, *y, *e; + if (null_bool_var == m_bound_watch) { + return; + } + unsigned idx = num_lits; + for (unsigned i = 0; i < num_lits; ++i) { + if (m_bound_watch == lits[i].var()) { + //SASSERT(!lits[i].sign()); + idx = i; + break; + } + } + if (idx == num_lits) { + return; + } + for (unsigned i = 0; i < num_lits; ++i) { + ctx.literal2expr(lits[i], tmp); + } + for (unsigned i = 0; i < num_eqs; ++i) { + enode_pair const& p = eqs[i]; + x = p.first->get_owner(); + y = p.second->get_owner(); + tmp = m.mk_eq(x,y); + } + + SASSERT(num_params == 1 + num_lits + num_eqs); + SASSERT(params[0].is_symbol()); + SASSERT(params[0].get_symbol() == symbol("farkas")); // for now, just handle this rule. + farkas_util farkas(m); + rational q; + for (unsigned i = 0; i < num_lits; ++i) { + parameter const& pa = params[i+1]; + SASSERT(pa.is_rational()); + if (idx == i) { + q = abs(pa.get_rational()); + continue; + } + ctx.literal2expr(lits[i], tmp); + farkas.add(abs(pa.get_rational()), to_app(tmp)); + } + for (unsigned i = 0; i < num_eqs; ++i) { + enode_pair const& p = eqs[i]; + x = p.first->get_owner(); + y = p.second->get_owner(); + tmp = m.mk_eq(x,y); + parameter const& pa = params[1 + num_lits + i]; + SASSERT(pa.is_rational()); + farkas.add(abs(pa.get_rational()), to_app(tmp)); + } + tmp = farkas.get(); + // IF_VERBOSE(1, verbose_stream() << "Farkas result: " << tmp << "\n";); + atom* a = get_bv2a(m_bound_watch); + SASSERT(a); + expr_ref_vector terms(m); + vector mults; + bool strict = false; + if (m_util.is_le(tmp, x, y) || m_util.is_ge(tmp, y, x)) { + } + else if (m.is_not(tmp, e) && (m_util.is_le(e, y, x) || m_util.is_ge(e, x, y))) { + strict = true; + } + else if (m.is_eq(tmp, x, y)) { + } + else { + UNREACHABLE(); + } + e = var2expr(a->get_var()); + q *= farkas.get_normalize_factor(); + SASSERT(!m_util.is_int(e) || q.is_int()); // TBD: not fully handled. + if (q.is_one()) { + vq = e; + } + else { + vq = m_util.mk_mul(m_util.mk_numeral(q, q.is_int()), e); + } + vq = m_util.mk_add(m_util.mk_sub(x, y), vq); + if (!q.is_one()) { + vq = m_util.mk_div(vq, m_util.mk_numeral(q, q.is_int())); + } + th_rewriter rw(m); + rw(vq, tmp); + VERIFY(m_util.is_numeral(tmp, q)); + if (m_upper_bound < q) { + m_upper_bound = q; + if (strict) { + m_upper_bound -= get_epsilon(a->get_var()); + } + IF_VERBOSE(1, verbose_stream() << "new upper bound: " << m_upper_bound << "\n";); + } + } + + /** + \brief find the minimal upper bound on the variable that was last enabled + for conflict recording. + */ + template + inf_eps_rational theory_arith::conflict_minimize() { + return m_upper_bound; + } + + /** \brief Maximize (Minimize) the given temporary row. Return true if succeeded. */ template - bool theory_arith::max_min(row & r, bool max) { - TRACE("max_min", tout << "max_min...\n";); + typename theory_arith::max_min_t theory_arith::max_min_orig(row & r, bool max, bool& has_shared) { m_stats.m_max_min++; + bool skipped_row = false; + has_shared = false; + + SASSERT(valid_assignment()); - SASSERT(valid_row_assignment()); - SASSERT(satisfy_bounds()); theory_var x_i = null_theory_var; theory_var x_j = null_theory_var; bool inc = false; numeral a_ij, curr_a_ij, coeff, curr_coeff; - inf_numeral curr_gain, gain; + inf_numeral gain, curr_gain; #ifdef _TRACE unsigned i = 0; #endif + max_min_t result; while (true) { x_j = null_theory_var; x_i = null_theory_var; gain.reset(); - TRACE("maximize", tout << "i: " << i << ", max: " << max << "\n"; display_row(tout, r, true); tout << "state:\n"; display(tout); i++;); + TRACE("opt", tout << "i: " << i << ", max: " << max << "\n"; display_row(tout, r, true); tout << "state:\n"; display(tout); i++;); typename vector::const_iterator it = r.begin_entries(); typename vector::const_iterator end = r.end_entries(); for (; it != end; ++it) { @@ -982,10 +1389,16 @@ namespace smt { SASSERT(is_non_base(curr_x_j)); curr_coeff = it->m_coeff; bool curr_inc = curr_coeff.is_pos() ? max : !max; + bool has_int = false; if ((curr_inc && at_upper(curr_x_j)) || (!curr_inc && at_lower(curr_x_j))) continue; // variable cannot be used for max/min. - theory_var curr_x_i = pick_var_to_leave(curr_x_j, curr_inc, curr_a_ij, curr_gain); + if (!is_safe_to_leave(curr_x_j, curr_inc, has_int, has_shared)) { + skipped_row = true; + continue; + } + theory_var curr_x_i = pick_var_to_leave(has_int, curr_x_j, curr_inc, curr_a_ij, curr_gain, skipped_row); if (curr_x_i == null_theory_var) { + TRACE("opt", tout << "unbounded\n";); // we can increase/decrease curr_x_j as much as we want. x_i = null_theory_var; // unbounded x_j = curr_x_j; @@ -1011,69 +1424,549 @@ namespace smt { } } } - TRACE("maximize", tout << "after traversing row:\nx_i: v" << x_i << ", x_j: v" << x_j << ", gain: " << gain << "\n";); + TRACE("opt", tout << "after traversing row:\nx_i: v" << x_i << ", x_j: v" << x_j << ", gain: " << gain << "\n"; + tout << "skipped row: " << (skipped_row?"yes":"no") << "\n"; + display(tout);); if (x_j == null_theory_var) { - TRACE("maximize", tout << "row is " << (max ? "maximized" : "minimized") << "\n";); - SASSERT(valid_row_assignment()); - SASSERT(satisfy_bounds()); - return true; + TRACE("opt", tout << "row is " << (max ? "maximized" : "minimized") << "\n";); + SASSERT(valid_assignment()); + result = skipped_row?BEST_EFFORT:OPTIMIZED; + break; } if (x_i == null_theory_var) { // can increase/decrease x_j as much as we want. - if (inc && upper(x_j)) { + if (inc && upper(x_j) && !skipped_row) { update_value(x_j, upper_bound(x_j) - get_value(x_j)); - TRACE("maximize", tout << "moved v" << x_j << " to upper bound\n";); - SASSERT(valid_row_assignment()); - SASSERT(satisfy_bounds()); + TRACE("opt", tout << "moved v" << x_j << " to upper bound\n";); + SASSERT(valid_assignment()); continue; } - if (!inc && lower(x_j)) { + if (!inc && lower(x_j) && !skipped_row) { update_value(x_j, lower_bound(x_j) - get_value(x_j)); - TRACE("maximize", tout << "moved v" << x_j << " to lower bound\n";); - SASSERT(valid_row_assignment()); - SASSERT(satisfy_bounds()); + TRACE("opt", tout << "moved v" << x_j << " to lower bound\n";); + SASSERT(valid_assignment()); continue; } - return false; // unbounded. + result = skipped_row?BEST_EFFORT:UNBOUNDED; + break; } - if (!is_fixed(x_j) && is_bounded(x_j) && (upper_bound(x_j) - lower_bound(x_j) <= gain)) { + if (!is_fixed(x_j) && is_bounded(x_j) && !skipped_row && (upper_bound(x_j) - lower_bound(x_j) <= gain)) { // can increase/decrease x_j up to upper/lower bound. if (inc) { update_value(x_j, upper_bound(x_j) - get_value(x_j)); - TRACE("maximize", tout << "moved v" << x_j << " to upper bound\n";); + TRACE("opt", tout << "moved v" << x_j << " to upper bound\n";); } else { update_value(x_j, lower_bound(x_j) - get_value(x_j)); - TRACE("maximize", tout << "moved v" << x_j << " to lower bound\n";); + TRACE("opt", tout << "moved v" << x_j << " to lower bound\n";); } - SASSERT(valid_row_assignment()); - SASSERT(satisfy_bounds()); + SASSERT(valid_assignment()); continue; } - TRACE("maximize", tout << "max: " << max << ", x_i: v" << x_i << ", x_j: v" << x_j << ", a_ij: " << a_ij << ", coeff: " << coeff << "\n";); + TRACE("opt", tout << "max: " << max << ", x_i: v" << x_i << ", x_j: v" << x_j << ", a_ij: " << a_ij << ", coeff: " << coeff << "\n"; + if (upper(x_i)) tout << "upper x_i: " << upper_bound(x_i) << " "; + if (lower(x_i)) tout << "lower x_i: " << lower_bound(x_i) << " "; + tout << "value x_i: " << get_value(x_i) << "\n"; + if (upper(x_j)) tout << "upper x_j: " << upper_bound(x_j) << " "; + if (lower(x_j)) tout << "lower x_j: " << lower_bound(x_j) << " "; + tout << "value x_j: " << get_value(x_j) << "\n"; + ); + pivot(x_i, x_j, a_ij, false); + + + SASSERT(is_non_base(x_i)); + SASSERT(is_base(x_j)); + bool move_xi_to_lower; if (inc) move_xi_to_lower = a_ij.is_pos(); else move_xi_to_lower = a_ij.is_neg(); - pivot(x_i, x_j, a_ij, false); - SASSERT(is_non_base(x_i)); - SASSERT(is_base(x_j)); - if (move_xi_to_lower) - update_value(x_i, lower_bound(x_i) - get_value(x_i)); - else - update_value(x_i, upper_bound(x_i) - get_value(x_i)); + if (!move_to_bound(x_i, move_xi_to_lower)) { + result = BEST_EFFORT; + break; + } + row & r2 = m_rows[get_var_row(x_j)]; coeff.neg(); add_tmp_row(r, coeff, r2); SASSERT(r.get_idx_of(x_j) == -1); - SASSERT(valid_row_assignment()); - SASSERT(satisfy_bounds()); + SASSERT(valid_assignment()); } + TRACE("opt", display(tout);); + return result; + } + + + /** + \brief Select tightest variable x_i to pivot with x_j. The goal + is to select a x_i such that the value of x_j is increased + (decreased) if inc = true (inc = false), and the tableau + remains feasible. Store the gain in x_j of the pivoting + operation in 'gain'. Note the gain can be too much. That is, + it may make x_i infeasible. In this case, instead of pivoting + we move x_j to its upper bound (lower bound) when inc = true (inc = false). + + If no x_i imposes a restriction on x_j, then return null_theory_var. + That is, x_j is free to move to its upper bound (lower bound). + + Get the equations for x_j: + + x_i1 = coeff_1 * x_j + rest_1 + ... + x_in = coeff_n * x_j + rest_n + + gain_k := (upper_bound(x_ik) - value(x_ik))/coeff_k + + */ + + + template + bool theory_arith::pick_var_to_leave( + theory_var x_j, // non-base variable to increment/decrement + bool inc, + numeral & a_ij, // coefficient of x_i + inf_numeral& min_gain, // minimal required gain on x_j (integral value on integers) + inf_numeral& max_gain, // maximal possible gain on x_j + bool& has_shared, // determine if pivot involves shared variable + theory_var& x_i) { // base variable to pivot with x_j + + x_i = null_theory_var; + context& ctx = get_context(); + column & c = m_columns[x_j]; + typename svector::iterator it = c.begin_entries(); + typename svector::iterator end = c.end_entries(); + init_gains(x_j, inc, min_gain, max_gain); + has_shared |= ctx.is_shared(get_enode(x_j)); + for (; it != end; ++it) { + if (it->is_dead()) continue; + row const & r = m_rows[it->m_row_id]; + theory_var s = r.get_base_var(); + numeral const & coeff_ij = r[it->m_row_idx].m_coeff; + if (update_gains(inc, s, coeff_ij, min_gain, max_gain) || + (x_i == null_theory_var && !unbounded_gain(max_gain))) { + x_i = s; + a_ij = coeff_ij; + } + has_shared |= ctx.is_shared(get_enode(s)); + } + bool empty_column = (c.begin_entries() == end); + TRACE("opt", + tout << (safe_gain(min_gain, max_gain)?"safe":"unsafe") << "\n"; + tout << "min gain: " << min_gain; + tout << " max gain: " << max_gain << "\n"; + tout << "v" << x_i << " "; + tout << (has_shared?"shared":"not shared") << "\n";); + + SASSERT(!safe_gain(min_gain, max_gain) || + empty_column || + (unbounded_gain(max_gain) == (x_i == null_theory_var))); + + return !empty_column && safe_gain(min_gain, max_gain); + } + + template + bool theory_arith::unbounded_gain(inf_numeral const & max_gain) const { + return max_gain.is_minus_one(); + } + + /* + A gain is 'safe' with respect to the tableau if: + - the selected variable is unbounded and every base variable where it occurs is unbounded + in the direction of the gain. max_gain == -1 is used to indicate unbounded variables. + - the selected variable is a rational (min_gain == -1, max_gain >= 0). + - + */ + template + bool theory_arith::safe_gain(inf_numeral const& min_gain, inf_numeral const & max_gain) const { + return + unbounded_gain(max_gain) || + min_gain <= max_gain; + } + + /** + \brief ensure that maximal gain is divisible by divisor. + */ + template + void theory_arith::normalize_gain(numeral const& divisor, inf_numeral & max_gain) const { + SASSERT(divisor.is_int()); + SASSERT(divisor.is_pos()); + if (!divisor.is_one() && !max_gain.is_minus_one()) { + max_gain = floor(max_gain/divisor)*divisor; + } + } + + /** + \brief initialize gains for x_j based on the bounds for x_j. + */ + template + void theory_arith::init_gains( + theory_var x, // non-base variable to increment/decrement + bool inc, + inf_numeral& min_gain, // min value to increment, -1 if rational + inf_numeral& max_gain) { // max value to decrement, -1 if unbounded + min_gain = -inf_numeral::one(); + max_gain = -inf_numeral::one(); + if (inc && upper(x)) { + max_gain = upper_bound(x) - get_value(x); + } + else if (!inc && lower(x)) { + max_gain = get_value(x) - lower_bound(x); + } + if (is_int(x)) { + min_gain = inf_numeral::one(); + } + SASSERT(max_gain.is_minus_one() || !max_gain.is_neg()); + SASSERT(min_gain.is_minus_one() || min_gain.is_one()); + SASSERT(!is_int(x) || max_gain.is_int()); + SASSERT(is_int(x) == min_gain.is_one()); + TRACE("opt", + tout << "v" << x << " " + << "min gain: " << min_gain << " " + << "max gain: " << max_gain << "\n";); + + } + + template + bool theory_arith::update_gains( + bool inc, // increment/decrement x_j + theory_var x_i, // potential base variable to pivot + numeral const& a_ij, // coefficient of x_j in row where x_i is base. + inf_numeral& min_gain, // min value to increment, -1 if rational + inf_numeral& max_gain) { // max value to decrement, -1 if unbounded + + // x_i = row + a_ij*x_j + // a_ij > 0, inc -> decrement x_i + // a_ij < 0, !inc -> decrement x_i + // a_ij denominator + + if (!safe_gain(min_gain, max_gain)) return false; + + inf_numeral max_inc = inf_numeral::minus_one(); + bool decrement_x_i = (inc && a_ij.is_pos()) || (!inc && a_ij.is_neg()); + if (decrement_x_i && lower(x_i)) { + max_inc = abs((get_value(x_i) - lower_bound(x_i))/a_ij); + } + else if (!decrement_x_i && upper(x_i)) { + max_inc = abs((upper_bound(x_i) - get_value(x_i))/a_ij); + } + numeral den_aij(1); + bool is_tighter = false; + if (is_int(x_i)) den_aij = denominator(a_ij); + SASSERT(den_aij.is_pos() && den_aij.is_int()); + + if (is_int(x_i) && !den_aij.is_one()) { + SASSERT(min_gain.is_pos()); + min_gain = inf_numeral(lcm(min_gain.get_rational(), den_aij)); + normalize_gain(min_gain.get_rational(), max_gain); + } + + if (!max_inc.is_minus_one()) { + if (is_int(x_i)) { + max_inc = floor(max_inc); + normalize_gain(min_gain.get_rational(), max_inc); + } + if (unbounded_gain(max_gain)) { + max_gain = max_inc; + is_tighter = true; + } + else if (max_gain > max_inc) { + max_gain = max_inc; + is_tighter = true; + } + } + TRACE("opt", + tout << "v" << x_i << " a_ij " << a_ij << " " + << "min gain: " << min_gain << " " + << "max gain: " << max_gain << " tighter: " + << (is_tighter?"true":"false") << "\n";); + SASSERT(max_gain.is_minus_one() || !max_gain.is_neg()); + SASSERT(min_gain.is_minus_one() || !min_gain.is_neg()); + SASSERT(!is_int(x_i) || min_gain.is_pos()); + SASSERT(!is_int(x_i) || min_gain.is_int()); + SASSERT(!is_int(x_i) || max_gain.is_int()); + return is_tighter; + } + + /** + \brief Maximize (Minimize) the given temporary row. + Return true if succeeded. + */ + template + typename theory_arith::max_min_t theory_arith::max_min_new( + row & r, + bool max, + bool& has_shared) { + m_stats.m_max_min++; + unsigned best_efforts = 0; + bool inc = false; + + SASSERT(valid_assignment()); + + numeral a_ij, curr_a_ij, coeff, curr_coeff; + inf_numeral min_gain, max_gain, curr_min_gain, curr_max_gain; +#ifdef _TRACE + unsigned round = 0; +#endif + max_min_t result = OPTIMIZED; + has_shared = false; + unsigned max_efforts = 10 + (get_context().get_random_value() % 20); + while (best_efforts < max_efforts) { + theory_var x_j = null_theory_var; + theory_var x_i = null_theory_var; + max_gain.reset(); + min_gain.reset(); + TRACE("opt", tout << "round: " << (round++) << ", max: " << max << "\n"; display_row(tout, r, true); tout << "state:\n"; display(tout);); + typename vector::const_iterator it = r.begin_entries(); + typename vector::const_iterator end = r.end_entries(); + for (; it != end; ++it) { + if (it->is_dead()) continue; + theory_var curr_x_j = it->m_var; + theory_var curr_x_i = null_theory_var; + SASSERT(is_non_base(curr_x_j)); + curr_coeff = it->m_coeff; + bool curr_inc = curr_coeff.is_pos() ? max : !max; + if ((curr_inc && at_upper(curr_x_j)) || (!curr_inc && at_lower(curr_x_j))) { + // variable cannot be used for max/min. + continue; + } + if (!pick_var_to_leave(curr_x_j, curr_inc, curr_a_ij, + curr_min_gain, curr_max_gain, + has_shared, curr_x_i)) { + best_efforts++; + } + else { + SASSERT(safe_gain(curr_min_gain, curr_max_gain)); + } + if (curr_x_i == null_theory_var) { + TRACE("opt", tout << "unbounded\n";); + // we can increase/decrease curr_x_j as much as we want. + x_i = null_theory_var; // unbounded + x_j = curr_x_j; + inc = curr_inc; + min_gain = curr_min_gain; + max_gain = curr_max_gain; + break; + } + else if (curr_max_gain > max_gain) { + x_i = curr_x_i; + x_j = curr_x_j; + a_ij = curr_a_ij; + coeff = curr_coeff; + max_gain = curr_max_gain; + min_gain = curr_min_gain; + inc = curr_inc; + } + else if (curr_max_gain.is_zero() && (x_i == null_theory_var || curr_x_i < x_i)) { + x_i = curr_x_i; + x_j = curr_x_j; + a_ij = curr_a_ij; + coeff = curr_coeff; + max_gain = curr_max_gain; + min_gain = curr_min_gain; + inc = curr_inc; + // continue + } + } + + TRACE("opt", tout << "after traversing row:\nx_i: v" << x_i << ", x_j: v" << x_j << ", gain: " << max_gain << "\n"; + tout << "best efforts: " << best_efforts << "\n"; + display(tout);); + + if (x_j == null_theory_var) { + TRACE("opt", tout << "row is " << (max ? "maximized" : "minimized") << "\n";); + SASSERT(valid_assignment()); + result = OPTIMIZED; + break; + } + + if (min_gain.is_pos() && !min_gain.is_one()) { + ++best_efforts; + } + if (x_i == null_theory_var) { + // can increase/decrease x_j as much as we want. + + if (inc && upper(x_j)) { + SASSERT(!unbounded_gain(max_gain)); + update_value(x_j, max_gain); + TRACE("opt", tout << "moved v" << x_j << " to upper bound\n";); + SASSERT(valid_assignment()); + continue; + } + if (!inc && lower(x_j)) { + SASSERT(!unbounded_gain(max_gain)); + max_gain.neg(); + update_value(x_j, max_gain); + TRACE("opt", tout << "moved v" << x_j << " to lower bound\n";); + SASSERT(valid_assignment()); + continue; + } + SASSERT(unbounded_gain(max_gain)); + best_efforts = 0; + result = UNBOUNDED; + break; + } + + if (!is_fixed(x_j) && is_bounded(x_j) && + (upper_bound(x_j) - lower_bound(x_j) == max_gain)) { + // can increase/decrease x_j up to upper/lower bound. + if (inc) { + TRACE("opt", tout << "moved v" << x_j << " to upper bound\n";); + } + else { + max_gain.neg(); + TRACE("opt", tout << "moved v" << x_j << " to lower bound\n";); + } + update_value(x_j, max_gain); + SASSERT(valid_assignment()); + continue; + } + + TRACE("opt", tout << "max: " << max << ", x_i: v" << x_i << ", x_j: v" << x_j << ", a_ij: " << a_ij << ", coeff: " << coeff << "\n"; + if (upper(x_i)) tout << "upper x_i: " << upper_bound(x_i) << " "; + if (lower(x_i)) tout << "lower x_i: " << lower_bound(x_i) << " "; + tout << "value x_i: " << get_value(x_i) << "\n"; + if (upper(x_j)) tout << "upper x_j: " << upper_bound(x_j) << " "; + if (lower(x_j)) tout << "lower x_j: " << lower_bound(x_j) << " "; + tout << "value x_j: " << get_value(x_j) << "\n"; + ); + pivot(x_i, x_j, a_ij, false); + + SASSERT(is_non_base(x_i)); + SASSERT(is_base(x_j)); + + bool inc_xi = inc?a_ij.is_neg():a_ij.is_pos(); + if (!move_to_bound_new(x_i, inc_xi, best_efforts, has_shared)) { + // break; + } + + row & r2 = m_rows[get_var_row(x_j)]; + coeff.neg(); + add_tmp_row(r, coeff, r2); + SASSERT(r.get_idx_of(x_j) == -1); + SASSERT(valid_assignment()); + } + TRACE("opt", display(tout);); + return (best_efforts>0)?BEST_EFFORT:result; + } + + /** + Move the variable x_i maximally towards its bound as long as + bounds of other variables are not violated. + Returns false if an integer bound was truncated and no + progress was made. + */ + + template + bool theory_arith::move_to_bound_new( + theory_var x_i, // variable to move + bool inc, // increment variable or decrement + unsigned& best_efforts, // is bound move a best effort? + bool& has_shared) { // does move include shared variables? + inf_numeral min_gain, max_gain; + init_gains(x_i, inc, min_gain, max_gain); + column & c = m_columns[x_i]; + typename svector::iterator it = c.begin_entries(); + typename svector::iterator end = c.end_entries(); + for (; it != end; ++it) { + if (it->is_dead()) continue; + row const & r = m_rows[it->m_row_id]; + theory_var s = r.get_base_var(); + numeral const & coeff = r[it->m_row_idx].m_coeff; + update_gains(inc, s, coeff, min_gain, max_gain); + has_shared |= get_context().is_shared(get_enode(s)); + } + bool result = false; + if (safe_gain(min_gain, max_gain)) { + TRACE("opt", tout << "Safe delta: " << max_gain << "\n";); + SASSERT(!unbounded_gain(max_gain)); + if (!inc) { + max_gain.neg(); + } + update_value(x_i, max_gain); + if (!min_gain.is_pos() || min_gain.is_one()) { + ++best_efforts; + } + result = !max_gain.is_zero(); + } + if (!result) { + ++best_efforts; + } + return result; + } + + /** + Move the variable x_i maximally towards its bound as long as + bounds of other variables are not violated. + Returns false if an integer bound was truncated and no + progress was made. + */ + + template + bool theory_arith::move_to_bound(theory_var x_i, bool move_to_lower) { + inf_numeral delta, delta_abs; + numeral lc(1); + + if (move_to_lower) { + delta = lower_bound(x_i) - get_value(x_i); + SASSERT(!delta.is_pos()); + } + else { + delta = upper_bound(x_i) - get_value(x_i); + SASSERT(!delta.is_neg()); + } + + TRACE("opt", tout << "Original delta: " << delta << "\n";); + + delta_abs = abs(delta); + // + // Decrease absolute value of delta according to bounds on rows where x_i is used. + // + column & c = m_columns[x_i]; + typename svector::iterator it = c.begin_entries(); + typename svector::iterator end = c.end_entries(); + for (; it != end && delta_abs.is_pos(); ++it) { + if (it->is_dead()) continue; + row & r = m_rows[it->m_row_id]; + theory_var s = r.get_base_var(); + if (s != null_theory_var && !is_quasi_base(s)) { + numeral const & coeff = r[it->m_row_idx].m_coeff; + SASSERT(!coeff.is_zero()); + bool inc_s = coeff.is_pos() ? move_to_lower : !move_to_lower; // NSB: review this.. + bound * b = get_bound(s, inc_s); + if (b) { + inf_numeral delta2 = abs((get_value(s) - b->get_value())/coeff); + if (delta2 < delta_abs) { + delta_abs = delta2; + } + } + if (is_int(x_i)) { + lc = lcm(lc, denominator(abs(coeff))); + } + } + } + + bool truncated = false; + if (is_int(x_i)) { + inf_numeral tmp = delta_abs/lc; + truncated = !tmp.is_int(); + delta_abs = lc*floor(tmp); + } + + if (move_to_lower) { + delta = -delta_abs; + } + else { + delta = delta_abs; + } + + TRACE("opt", tout << "Safe delta: " << delta << "\n";); + update_value(x_i, delta); + return !truncated || !delta.is_zero(); } /** @@ -1096,13 +1989,15 @@ namespace smt { \brief Maximize/Minimize the given variable. The bounds of v are update if procedure succeeds. */ template - bool theory_arith::max_min(theory_var v, bool max) { - TRACE("maximize", tout << (max ? "maximizing" : "minimizing") << " v" << v << "...\n";); - SASSERT(valid_row_assignment()); - SASSERT(satisfy_bounds()); + typename theory_arith::max_min_t theory_arith::max_min(theory_var v, bool max, bool& has_shared) { + expr* e = get_enode(v)->get_owner(); + + SASSERT(valid_assignment()); SASSERT(!is_quasi_base(v)); - if ((max && at_upper(v)) || (!max && at_lower(v))) - return false; // nothing to be done... + if ((max && at_upper(v)) || (!max && at_lower(v))) { + TRACE("opt", tout << "At bound: " << mk_pp(e, get_manager()) << "...\n";); + return AT_BOUND; // nothing to be done... + } m_tmp_row.reset(); if (is_non_base(v)) { add_tmp_row_entry(m_tmp_row, numeral(1), v); @@ -1116,14 +2011,20 @@ namespace smt { add_tmp_row_entry(m_tmp_row, it->m_coeff, it->m_var); } } - if (max_min(m_tmp_row, max)) { - TRACE("maximize", tout << "v" << v << " " << (max ? "max" : "min") << " value is: " << get_value(v) << "\n"; + max_min_t r = max_min_new(m_tmp_row, max, has_shared); + if (r == OPTIMIZED) { + TRACE("opt", tout << mk_pp(e, get_manager()) << " " << (max ? "max" : "min") << " value is: " << get_value(v) << "\n"; display_row(tout, m_tmp_row, true); display_row_info(tout, m_tmp_row);); - mk_bound_from_row(v, get_value(v), max ? B_UPPER : B_LOWER, m_tmp_row); - return true; + mk_bound_from_row(v, get_value(v), max ? B_UPPER : B_LOWER, m_tmp_row); } - return false; + else if (r == UNBOUNDED) { + TRACE("opt", tout << "unbounded: " << mk_pp(e, get_manager()) << "...\n";); + } + else { + TRACE("opt", tout << "not optimized: " << mk_pp(e, get_manager()) << "...\n";); + } + return r; } /** @@ -1133,18 +2034,19 @@ namespace smt { template bool theory_arith::max_min(svector const & vars) { bool succ = false; + bool has_shared = false; svector::const_iterator it = vars.begin(); svector::const_iterator end = vars.end(); for (; it != end; ++it) { - if (max_min(*it, true)) + if (max_min(*it, true, has_shared) == OPTIMIZED && !has_shared) succ = true; - if (max_min(*it, false)) + if (max_min(*it, false, has_shared) == OPTIMIZED && !has_shared) succ = true; } if (succ) { // process new bounds bool r = propagate_core(); - TRACE("maximize", tout << "after max/min round:\n"; display(tout);); + TRACE("opt", tout << "after max/min round:\n"; display(tout);); return r; } return true; @@ -1250,8 +2152,7 @@ namespace smt { bool theory_arith::try_to_imply_eq(theory_var v1, theory_var v2) { SASSERT(v1 != v2); SASSERT(get_value(v1) == get_value(v2)); - SASSERT(valid_row_assignment()); - SASSERT(satisfy_bounds()); + SASSERT(valid_assignment()); if (is_quasi_base(v1) || is_quasi_base(v2)) return false; m_tmp_row.reset(); @@ -1312,9 +2213,9 @@ namespace smt { m_tmp_lit_set.reset(); m_tmp_eq_set.reset(); - if (max_min(m_tmp_row, true) && + if ((OPTIMIZED == max_min(m_tmp_row, true)) && is_zero_row(m_tmp_row, true, m_tmp_acc_lits, m_tmp_acc_eqs, m_tmp_lit_set, m_tmp_eq_set) && - max_min(m_tmp_row, false) && + (OPTIMIZED == max_min(m_tmp_row, false)) && is_zero_row(m_tmp_row, false, m_tmp_acc_lits, m_tmp_acc_eqs, m_tmp_lit_set, m_tmp_eq_set)) { // v1 == v2 TRACE("imply_eq", tout << "found new implied equality:\n"; diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index 66d232227..264eb0f10 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -821,7 +821,7 @@ namespace smt { m_new_atoms.push_back(a1); return; } - numeral const & k1(a1->get_k()); + inf_numeral const & k1(a1->get_k()); atom_kind kind1 = a1->get_atom_kind(); TRACE("mk_bound_axioms", tout << "making bound axioms for v" << v << " " << kind1 << " " << k1 << "\n";); typename atoms::iterator it = occs.begin(); @@ -831,7 +831,7 @@ namespace smt { typename atoms::iterator hi_inf = end, hi_sup = end; for (; it != end; ++it) { atom * a2 = *it; - numeral const & k2(a2->get_k()); + inf_numeral const & k2(a2->get_k()); atom_kind kind2 = a2->get_atom_kind(); SASSERT(k1 != k2 || kind1 != kind2); if (kind2 == A_LOWER) { @@ -864,12 +864,13 @@ namespace smt { theory_var v = a1->get_var(); literal l1(a1->get_bool_var()); literal l2(a2->get_bool_var()); - numeral const & k1(a1->get_k()); - numeral const & k2(a2->get_k()); + inf_numeral const & k1(a1->get_k()); + inf_numeral const & k2(a2->get_k()); atom_kind kind1 = a1->get_atom_kind(); atom_kind kind2 = a2->get_atom_kind(); bool v_is_int = is_int(v); SASSERT(v == a2->get_var()); + if (k1 == k2 && kind1 == kind2) return; SASSERT(k1 != k2 || kind1 != kind2); parameter coeffs[3] = { parameter(symbol("farkas")), parameter(rational(1)), parameter(rational(1)) }; @@ -890,7 +891,7 @@ namespace smt { else { // k1 > hi_inf, k1 <= x => ~(x <= hi_inf) mk_clause(~l1, ~l2, 3, coeffs); - if (v_is_int && k1 == k2 + numeral(1)) { + if (v_is_int && k1 == k2 + inf_numeral(1)) { // k1 <= x or x <= k1-1 mk_clause(l1, l2, 3, coeffs); } @@ -904,7 +905,7 @@ namespace smt { else { // k1 < k2, k2 <= x => ~(x <= k1) mk_clause(~l1, ~l2, 3, coeffs); - if (v_is_int && k1 == k2 - numeral(1)) { + if (v_is_int && k1 == k2 - inf_numeral(1)) { // x <= k1 or k1+l <= x mk_clause(l1, l2, 3, coeffs); } @@ -1000,14 +1001,14 @@ namespace smt { typename atoms::iterator it, typename atoms::iterator end, bool& found_compatible) { - numeral const & k1(a1->get_k()); + inf_numeral const & k1(a1->get_k()); typename atoms::iterator result = end; found_compatible = false; for (; it != end; ++it) { atom * a2 = *it; if (a1 == a2) continue; if (a2->get_atom_kind() != kind) continue; - numeral const & k2(a2->get_k()); + inf_numeral const & k2(a2->get_k()); found_compatible = true; if (k2 <= k1) { result = it; @@ -1027,13 +1028,13 @@ namespace smt { typename atoms::iterator it, typename atoms::iterator end, bool& found_compatible) { - numeral const & k1(a1->get_k()); + inf_numeral const & k1(a1->get_k()); found_compatible = false; for (; it != end; ++it) { atom * a2 = *it; if (a1 == a2) continue; if (a2->get_atom_kind() != kind) continue; - numeral const & k2(a2->get_k()); + inf_numeral const & k2(a2->get_k()); found_compatible = true; if (k1 < k2) { return it; @@ -1081,7 +1082,7 @@ namespace smt { ctx.set_var_theory(bv, get_id()); rational _k; VERIFY(m_util.is_numeral(rhs, _k)); - numeral k(_k); + inf_numeral k(_k); atom * a = alloc(atom, bv, v, k, kind); mk_bound_axioms(a); m_unassigned_atoms[v]++; @@ -1269,7 +1270,9 @@ namespace smt { result = FC_GIVEUP; break; case FC_CONTINUE: - TRACE("final_check_arith", tout << "continue arith...\n";); + TRACE("final_check_arith", + tout << "continue arith..." + << (get_context().inconsistent()?"inconsistent\n":"\n");); return FC_CONTINUE; } } @@ -1519,7 +1522,8 @@ namespace smt { m_assume_eq_head(0), m_nl_rounds(0), m_nl_gb_exhausted(false), - m_nl_new_exprs(m) { + m_nl_new_exprs(m), + m_bound_watch(null_bool_var) { } template @@ -2184,7 +2188,7 @@ namespace smt { tout << "is_below_lower: " << below_lower(x_i) << ", is_above_upper: " << above_upper(x_i) << "\n";); antecedents& ante = get_antecedents(); explain_bound(r, idx, !is_below, delta, ante); - b->push_justification(ante, numeral(1), proofs_enabled()); + b->push_justification(ante, numeral(1), coeffs_enabled()); set_conflict(ante.lits().size(), ante.lits().c_ptr(), @@ -2327,11 +2331,12 @@ namespace smt { void theory_arith::sign_bound_conflict(bound * b1, bound * b2) { SASSERT(b1->get_var() == b2->get_var()); antecedents& ante = get_antecedents(); - b1->push_justification(ante, numeral(1), proofs_enabled()); - b2->push_justification(ante, numeral(1), proofs_enabled()); + b1->push_justification(ante, numeral(1), coeffs_enabled()); + b2->push_justification(ante, numeral(1), coeffs_enabled()); set_conflict(ante.lits().size(), ante.lits().c_ptr(), ante.eqs().size(), ante.eqs().c_ptr(), ante, is_int(b1->get_var()), "farkas"); - TRACE("arith_conflict", tout << "bound conflict\n";); + TRACE("arith_conflict", tout << "bound conflict v" << b1->get_var() << "\n"; + tout << "bounds: " << b1 << " " << b2 << "\n";); } // ----------------------------------- @@ -2587,7 +2592,7 @@ namespace smt { if (!b->has_justification()) continue; if (!relax_bounds() || delta.is_zero()) { - b->push_justification(ante, it->m_coeff, proofs_enabled()); + b->push_justification(ante, it->m_coeff, coeffs_enabled()); continue; } numeral coeff = it->m_coeff; @@ -2649,7 +2654,7 @@ namespace smt { SASSERT(!is_b_lower || k_2 <= k_1); SASSERT(is_b_lower || k_2 >= k_1); if (new_atom == 0) { - b->push_justification(ante, coeff, proofs_enabled()); + b->push_justification(ante, coeff, coeffs_enabled()); continue; } SASSERT(!is_b_lower || k_2 < k_1); @@ -2663,7 +2668,7 @@ namespace smt { delta -= coeff*(k_2 - k_1); } TRACE("propagate_bounds", tout << "delta (after replace): " << delta << "\n";); - new_atom->push_justification(ante, coeff, proofs_enabled()); + new_atom->push_justification(ante, coeff, coeffs_enabled()); SASSERT(delta >= inf_numeral::zero()); } } @@ -2682,7 +2687,7 @@ namespace smt { bool_var bv = a->get_bool_var(); literal l(bv); if (get_context().get_assignment(bv) == l_undef) { - numeral const & k2 = a->get_k(); + inf_numeral const & k2 = a->get_k(); delta.reset(); if (a->get_atom_kind() == A_LOWER) { // v >= k k >= k2 |- v >= k2 @@ -2863,13 +2868,13 @@ namespace smt { for (unsigned i = 0; i < num_literals; i++) { ctx.display_detailed_literal(tout, lits[i]); tout << " "; - if (proofs_enabled()) { + if (coeffs_enabled()) { tout << "bound: " << bounds.lit_coeffs()[i] << "\n"; } } for (unsigned i = 0; i < num_eqs; i++) { tout << "#" << eqs[i].first->get_owner_id() << "=#" << eqs[i].second->get_owner_id() << " "; - if (proofs_enabled()) { + if (coeffs_enabled()) { tout << "bound: " << bounds.eq_coeffs()[i] << "\n"; } } @@ -2877,6 +2882,7 @@ namespace smt { tout << bounds.params(proof_rule)[i] << "\n"; } tout << "\n";); + record_conflict(num_literals, lits, num_eqs, eqs, bounds.num_params(), bounds.params(proof_rule)); ctx.set_conflict( ctx.mk_justification( ext_theory_conflict_justification(get_id(), r, num_literals, lits, num_eqs, eqs, @@ -2893,8 +2899,8 @@ namespace smt { typename vector::const_iterator end = r.end_entries(); for (; it != end; ++it) { if (!it->is_dead() && is_fixed(it->m_var)) { - lower(it->m_var)->push_justification(antecedents, it->m_coeff, proofs_enabled()); - upper(it->m_var)->push_justification(antecedents, it->m_coeff, proofs_enabled()); + lower(it->m_var)->push_justification(antecedents, it->m_coeff, coeffs_enabled()); + upper(it->m_var)->push_justification(antecedents, it->m_coeff, coeffs_enabled()); } } } @@ -2997,6 +3003,9 @@ namespace smt { if (!get_context().is_shared(get_enode(v))) continue; inf_numeral const & val = get_value(v); + if (Ext::is_infinite(val)) { + continue; + } rational value = val.get_rational().to_rational() + m_epsilon.to_rational() * val.get_infinitesimal().to_rational(); theory_var v2; if (mapping.find(value, v2)) { @@ -3220,11 +3229,13 @@ namespace smt { case QUASI_BASE: SASSERT(m_columns[v].size() == 1); del_row(get_var_row(v)); + TRACE("arith_make_feasible", tout << "del row v" << v << "\n";); break; case BASE: SASSERT(lazy_pivoting_lvl() != 0 || m_columns[v].size() == 1); if (lazy_pivoting_lvl() > 0) eliminate(v, false); + TRACE("arith_make_feasible", tout << "del row v" << v << "\n";); del_row(get_var_row(v)); break; case NON_BASE: { @@ -3236,6 +3247,10 @@ namespace smt { pivot(r.get_base_var(), v, r[entry->m_row_idx].m_coeff, false); SASSERT(is_base(v)); del_row(get_var_row(v)); + TRACE("arith_make_feasible", tout << "del row v" << v << "\n";); + } + else { + TRACE("arith_make_feasible", tout << "no row v" << v << "\n";); } break; } } diff --git a/src/smt/theory_arith_int.h b/src/smt/theory_arith_int.h index 0a70e2645..b600dd3c0 100644 --- a/src/smt/theory_arith_int.h +++ b/src/smt/theory_arith_int.h @@ -33,11 +33,15 @@ namespace smt { // Integrality // // ----------------------------------- + /** \brief Move non base variables to one of its bounds. If the variable does not have bounds, it is integer, but it is not assigned to an integer value, then the variable is set to an integer value. + In mixed integer/real problems moving a real variable to a bound could cause an integer value to + have an infinitesimal. Such an assignment would disable mk_gomory_cut, and Z3 would loop. + */ template void theory_arith::move_non_base_vars_to_bounds() { @@ -413,10 +417,10 @@ namespace smt { for (; it != end; ++it) { // All non base variables must be at their bounds and assigned to rationals (that is, infinitesimals are not allowed). if (!it->is_dead() && it->m_var != b && (!at_bound(it->m_var) || !get_value(it->m_var).is_rational())) { - TRACE("gomory_cut", tout << "row is gomory cut target:\n"; + TRACE("gomory_cut", tout << "row is not gomory cut target:\n"; display_var(tout, it->m_var); tout << "at_bound: " << at_bound(it->m_var) << "\n"; - tout << "infinitesimal: " << get_value(it->m_var).is_rational() << "\n";); + tout << "infinitesimal: " << !get_value(it->m_var).is_rational() << "\n";); return false; } } @@ -473,7 +477,8 @@ namespace smt { */ template bool theory_arith::mk_gomory_cut(row const & r) { - SASSERT(!all_coeff_int(r)); + // The following assertion is wrong. It may be violated in mixed-integer problems. + // SASSERT(!all_coeff_int(r)); theory_var x_i = r.get_base_var(); SASSERT(is_int(x_i)); @@ -525,7 +530,7 @@ namespace smt { } // k += new_a_ij * lower_bound(x_j).get_rational(); k.addmul(new_a_ij, lower_bound(x_j).get_rational()); - lower(x_j)->push_justification(ante, numeral::zero(), proofs_enabled()); + lower(x_j)->push_justification(ante, numeral::zero(), coeffs_enabled()); } else { SASSERT(at_upper(x_j)); @@ -541,7 +546,7 @@ namespace smt { } // k += new_a_ij * upper_bound(x_j).get_rational(); k.addmul(new_a_ij, upper_bound(x_j).get_rational()); - upper(x_j)->push_justification(ante, numeral::zero(), proofs_enabled()); + upper(x_j)->push_justification(ante, numeral::zero(), coeffs_enabled()); } pol.push_back(row_entry(new_a_ij, x_j)); } @@ -566,7 +571,7 @@ namespace smt { } // k += new_a_ij * lower_bound(x_j).get_rational(); k.addmul(new_a_ij, lower_bound(x_j).get_rational()); - lower(x_j)->push_justification(ante, numeral::zero(), proofs_enabled()); + lower(x_j)->push_justification(ante, numeral::zero(), coeffs_enabled()); } else { SASSERT(at_upper(x_j)); @@ -579,7 +584,7 @@ namespace smt { new_a_ij.neg(); // the upper terms are inverted // k += new_a_ij * upper_bound(x_j).get_rational(); k.addmul(new_a_ij, upper_bound(x_j).get_rational()); - upper(x_j)->push_justification(ante, numeral::zero(), proofs_enabled()); + upper(x_j)->push_justification(ante, numeral::zero(), coeffs_enabled()); } TRACE("gomory_cut_detail", tout << "new_a_ij: " << new_a_ij << "\n";); pol.push_back(row_entry(new_a_ij, x_j)); @@ -772,8 +777,8 @@ namespace smt { // u += ncoeff * lower_bound(v).get_rational(); u.addmul(ncoeff, lower_bound(v).get_rational()); } - lower(v)->push_justification(ante, numeral::zero(), proofs_enabled()); - upper(v)->push_justification(ante, numeral::zero(), proofs_enabled()); + lower(v)->push_justification(ante, numeral::zero(), coeffs_enabled()); + upper(v)->push_justification(ante, numeral::zero(), coeffs_enabled()); } else if (gcds.is_zero()) { gcds = abs_ncoeff; @@ -1379,6 +1384,7 @@ namespace smt { m_branch_cut_counter++; // TODO: add giveup code if (m_branch_cut_counter % m_params.m_arith_branch_cut_ratio == 0) { + TRACE("opt", display(tout);); move_non_base_vars_to_bounds(); if (!make_feasible()) { TRACE("arith_int", tout << "failed to move variables to bounds.\n";); @@ -1390,7 +1396,9 @@ namespace smt { TRACE("arith_int", tout << "v" << int_var << " does not have an integer assignment: " << get_value(int_var) << "\n";); SASSERT(is_base(int_var)); row const & r = m_rows[get_var_row(int_var)]; - mk_gomory_cut(r); + if (!mk_gomory_cut(r)) { + // silent failure + } return FC_CONTINUE; } } @@ -1400,7 +1408,7 @@ namespace smt { } theory_var int_var = find_infeasible_int_base_var(); if (int_var != null_theory_var) { - TRACE("arith_int", tout << "v" << int_var << " does not have and integer assignment: " << get_value(int_var) << "\n";); + TRACE("arith_int", tout << "v" << int_var << " does not have an integer assignment: " << get_value(int_var) << "\n";); // apply branching branch_infeasible_int_var(int_var); return FC_CONTINUE; diff --git a/src/smt/theory_arith_inv.h b/src/smt/theory_arith_inv.h index 80bb9307f..007c8025f 100644 --- a/src/smt/theory_arith_inv.h +++ b/src/smt/theory_arith_inv.h @@ -199,6 +199,27 @@ namespace smt { } return true; } + + template + bool theory_arith::satisfy_integrality() const { + int num = get_num_vars(); + for (theory_var v = 0; v < num; v++) { + if (is_int(v) && !get_value(v).is_int()) { + TRACE("bound_bug", display_var(tout, v); display(tout);); + return false; + } + } + return true; + } + + template + bool theory_arith::valid_assignment() const { + return + valid_row_assignment() && + satisfy_bounds() && + satisfy_integrality(); + } + #endif }; diff --git a/src/smt/theory_arith_nl.h b/src/smt/theory_arith_nl.h index 6a7017a29..8ff122c1e 100644 --- a/src/smt/theory_arith_nl.h +++ b/src/smt/theory_arith_nl.h @@ -333,12 +333,15 @@ namespace smt { void theory_arith::mul_bound_of(expr * var, unsigned power, interval & target) { theory_var v = expr2var(var); interval i = mk_interval_for(v); - TRACE("non_linear", tout << "bound: " << i << "\n" << mk_pp(var, get_manager()) << "\n"; + + TRACE("non_linear", + display_interval(tout << "bound: ",i); tout << i << "\n"; + tout << mk_pp(var, get_manager()) << "\n"; tout << "power " << power << ": " << expt(i, power) << "\n"; - tout << "target before: " << target << "\n";); + display_interval(tout << "target before: ", target); tout << "\n";); i.expt(power); target *= i; - TRACE("non_linear", tout << "target after: " << target << "\n";); + TRACE("non_linear", display_interval(tout << "target after: ", target); tout << "\n";); } /** @@ -427,12 +430,12 @@ namespace smt { template void theory_arith::mk_derived_nl_bound(theory_var v, inf_numeral const & coeff, bound_kind k, v_dependency * dep) { inf_numeral coeff_norm = normalize_bound(v, coeff, k); - TRACE("buggy_bound", tout << "v" << v << " " << coeff << " " << coeff_norm << " " << k << "\n";); derived_bound * new_bound = alloc(derived_bound, v, coeff_norm, k); m_bounds_to_delete.push_back(new_bound); m_asserted_bounds.push_back(new_bound); // copy justification to new bound dependency2new_bound(dep, *new_bound); + TRACE("buggy_bound", new_bound->display(*this, tout); tout << "\n";); } /** @@ -449,7 +452,8 @@ namespace smt { new_lower += get_epsilon(v); bound * old_lower = lower(v); if (old_lower == 0 || new_lower > old_lower->get_value()) { - TRACE("non_linear", tout << "NEW lower bound for v" << v << " " << new_lower << "\n";); + TRACE("non_linear", tout << "NEW lower bound for v" << v << " " << new_lower << "\n"; + display_interval(tout, i); tout << "\n";); mk_derived_nl_bound(v, new_lower, B_LOWER, i.get_lower_dependencies()); r = true; } @@ -460,7 +464,8 @@ namespace smt { new_upper -= get_epsilon(v); bound * old_upper = upper(v); if (old_upper == 0 || new_upper < old_upper->get_value()) { - TRACE("non_linear", tout << "NEW upper bound for v" << v << " " << new_upper << "\n";); + TRACE("non_linear", tout << "NEW upper bound for v" << v << " " << new_upper << "\n"; + display_interval(tout, i); tout << "\n";); mk_derived_nl_bound(v, new_upper, B_UPPER, i.get_upper_dependencies()); r = true; } @@ -897,31 +902,54 @@ namespace smt { m_tmp_lit_set.reset(); m_tmp_eq_set.reset(); - bool found_zero = false; SASSERT(is_pure_monomial(m)); - for (unsigned i = 0; i < to_app(m)->get_num_args(); i++) { - expr * arg = to_app(m)->get_arg(i); - if (!found_zero) { - theory_var _var = expr2var(arg); - if (is_fixed(_var)) { - bound * l = lower(_var); - bound * u = upper(_var); - if (l->get_value().is_zero()) { - /* if zero was found, then it is the explanation */ - SASSERT(k.is_zero()); - found_zero = true; - m_tmp_lit_set.reset(); - m_tmp_eq_set.reset(); - new_lower->m_lits.reset(); - new_lower->m_eqs.reset(); - } - accumulate_justification(*l, *new_lower, numeral::zero(), m_tmp_lit_set, m_tmp_eq_set); - accumulate_justification(*u, *new_lower, numeral::zero(), m_tmp_lit_set, m_tmp_eq_set); - } - } - } + bool found_zero = false; + for (unsigned i = 0; !found_zero && i < to_app(m)->get_num_args(); i++) { + expr * arg = to_app(m)->get_arg(i); + theory_var _var = expr2var(arg); + if (is_fixed(_var)) { + bound * l = lower(_var); + bound * u = upper(_var); + if (l->get_value().is_zero()) { + /* if zero was found, then it is the explanation */ + SASSERT(k.is_zero()); + found_zero = true; + m_tmp_lit_set.reset(); + m_tmp_eq_set.reset(); + new_lower->m_lits.reset(); + new_lower->m_eqs.reset(); + } + accumulate_justification(*l, *new_lower, numeral::zero(), m_tmp_lit_set, m_tmp_eq_set); + + TRACE("non_linear", + for (unsigned j = 0; j < new_lower->m_lits.size(); ++j) { + ctx.display_detailed_literal(tout, new_lower->m_lits[j]); + tout << " "; + } + tout << "\n";); + + accumulate_justification(*u, *new_lower, numeral::zero(), m_tmp_lit_set, m_tmp_eq_set); + + TRACE("non_linear", + for (unsigned j = 0; j < new_lower->m_lits.size(); ++j) { + ctx.display_detailed_literal(tout, new_lower->m_lits[j]); + tout << " "; + } + tout << "\n";); + + } + } new_upper->m_lits.append(new_lower->m_lits); new_upper->m_eqs.append(new_lower->m_eqs); + + TRACE("non_linear", + tout << "lower: " << new_lower << " upper: " << new_upper << "\n"; + for (unsigned j = 0; j < new_upper->m_lits.size(); ++j) { + ctx.display_detailed_literal(tout, new_upper->m_lits[j]); + tout << " "; + } + tout << "\n";); + return true; } @@ -1887,6 +1915,10 @@ namespace smt { derived_bound b(null_theory_var, inf_numeral(0), B_LOWER); dependency2new_bound(d, b); set_conflict(b.m_lits.size(), b.m_lits.c_ptr(), b.m_eqs.size(), b.m_eqs.c_ptr(), ante, is_lia, "arith_nl"); + TRACE("non_linear", + for (unsigned i = 0; i < b.m_lits.size(); ++i) { + tout << b.m_lits[i] << " "; + }); } /** diff --git a/src/smt/theory_arith_pp.h b/src/smt/theory_arith_pp.h index 274cd5499..f954f082c 100644 --- a/src/smt/theory_arith_pp.h +++ b/src/smt/theory_arith_pp.h @@ -395,9 +395,30 @@ namespace smt { template void theory_arith::display_bound(std::ostream & out, bound * b, unsigned indent) const { for (unsigned i = 0; i < indent; i++) out << " "; - theory_var v = b->get_var(); - enode * e = get_enode(v); - out << "v" << v << " #" << e->get_owner_id() << " " << (b->get_bound_kind() == B_LOWER ? ">=" : "<=") << " " << b->get_value() << "\n"; + b->display(*this, out); + out << "\n"; + } + + template + void theory_arith::display_deps(std::ostream & out, v_dependency* dep) { + ptr_vector bounds; + m_dep_manager.linearize(dep, bounds); + m_tmp_lit_set.reset(); + m_tmp_eq_set.reset(); + ptr_vector::const_iterator it = bounds.begin(); + ptr_vector::const_iterator end = bounds.end(); + for (; it != end; ++it) { + bound * b = static_cast(*it); + out << " "; + b->display(*this, out); + } + } + + template + void theory_arith::display_interval(std::ostream & out, interval const& i) { + i.display(out); + display_deps(out << " lo:", i.get_lower_dependencies()); + display_deps(out << " hi:", i.get_upper_dependencies()); } template @@ -428,7 +449,7 @@ namespace smt { template void theory_arith::display_atom(std::ostream & out, atom * a, bool show_sign) const { theory_var v = a->get_var(); - numeral const & k = a->get_k(); + inf_numeral const & k = a->get_k(); enode * e = get_enode(v); if (show_sign) { if (!a->is_true()) diff --git a/src/smt/theory_array_base.cpp b/src/smt/theory_array_base.cpp index b2c17b4e0..b33e6b4e6 100644 --- a/src/smt/theory_array_base.cpp +++ b/src/smt/theory_array_base.cpp @@ -362,7 +362,6 @@ namespace smt { (store A i v) <--- v is used as an value */ bool theory_array_base::is_shared(theory_var v) const { - context & ctx = get_context(); enode * n = get_enode(v); enode * r = n->get_root(); bool is_array = false; diff --git a/src/smt/theory_array_full.h b/src/smt/theory_array_full.h index 5a80b7fae..7c066f765 100644 --- a/src/smt/theory_array_full.h +++ b/src/smt/theory_array_full.h @@ -19,8 +19,9 @@ Revision History: #ifndef _THEORY_ARRAY_FULL_H_ #define _THEORY_ARRAY_FULL_H_ -#include"theory_array.h" +#include "theory_array.h" #include "simplifier.h" +#include "ast_trail.h" namespace smt { diff --git a/src/smt/theory_datatype.cpp b/src/smt/theory_datatype.cpp index 8c6543eff..b5cdbcfe2 100644 --- a/src/smt/theory_datatype.cpp +++ b/src/smt/theory_datatype.cpp @@ -61,6 +61,13 @@ namespace smt { if (antecedent == null_literal) { ctx.assign_eq(lhs, ctx.get_enode(rhs), eq_justification::mk_axiom()); } + else if (ctx.get_assignment(antecedent) != l_true) { + literal l(mk_eq(lhs->get_owner(), rhs, true)); + ctx.mark_as_relevant(l); + ctx.mark_as_relevant(antecedent); + literal lits[2] = {l, ~antecedent}; + ctx.mk_th_axiom(get_id(), 2, lits); + } else { SASSERT(ctx.get_assignment(antecedent) == l_true); region & r = ctx.get_region(); @@ -143,6 +150,48 @@ namespace smt { ctx.set_conflict(ctx.mk_justification(ext_theory_conflict_justification(get_id(), reg, 1, &l, 1, &p))); } + /** + \brief Given a field update n := { r with field := v } for constructor C, assert the axioms: + (=> (is-C r) (= (acc_j n) (acc_j r))) for acc_j != field + (=> (is-C r) (= (field n) v)) for acc_j != field + (=> (not (is-C r)) (= n r)) + */ + void theory_datatype::assert_update_field_axioms(enode * n) { + m_stats.m_assert_update_field++; + SASSERT(is_update_field(n)); + context & ctx = get_context(); + ast_manager & m = get_manager(); + app* own = n->get_owner(); + expr* arg1 = own->get_arg(0); + expr* arg2 = own->get_arg(1); + func_decl * upd = n->get_decl(); + func_decl * acc = to_func_decl(upd->get_parameter(0).get_ast()); + func_decl * con = m_util.get_accessor_constructor(acc); + func_decl * rec = m_util.get_constructor_recognizer(con); + ptr_vector const * accessors = m_util.get_constructor_accessors(con); + ptr_vector::const_iterator it = accessors->begin(); + ptr_vector::const_iterator end = accessors->end(); + app_ref rec_app(m.mk_app(rec, arg1), m); + ctx.internalize(rec_app, false); + literal is_con(ctx.get_bool_var(rec_app)); + for (; it != end; ++it) { + enode* arg; + func_decl * acc1 = *it; + if (acc1 == acc) { + arg = n->get_arg(1); + } + else { + app* acc_app = m.mk_app(acc1, arg1); + ctx.internalize(acc_app, false); + arg = ctx.get_enode(acc_app); + } + app * acc_own = m.mk_app(acc1, own); + assert_eq_axiom(arg, acc_own, is_con); + } + // update_field is identity if 'n' is not created by a matching constructor. + assert_eq_axiom(n, arg1, ~is_con); + } + theory_var theory_datatype::mk_var(enode * n) { theory_var r = theory::mk_var(n); theory_var r2 = m_find.mk_var(); @@ -150,15 +199,17 @@ namespace smt { SASSERT(r == static_cast(m_var_data.size())); m_var_data.push_back(alloc(var_data)); var_data * d = m_var_data[r]; + context & ctx = get_context(); + ctx.attach_th_var(n, this, r); if (is_constructor(n)) { d->m_constructor = n; - get_context().attach_th_var(n, this, r); assert_accessor_axioms(n); } + else if (is_update_field(n)) { + assert_update_field_axioms(n); + } else { ast_manager & m = get_manager(); - context & ctx = get_context(); - ctx.attach_th_var(n, this, r); sort * s = m.get_sort(n->get_owner()); if (m_util.get_datatype_num_constructors(s) == 1) { func_decl * c = m_util.get_datatype_constructors(s)->get(0); @@ -192,7 +243,7 @@ namespace smt { ctx.set_var_theory(bv, get_id()); ctx.set_enode_flag(bv, true); } - if (is_constructor(term)) { + if (is_constructor(term) || is_update_field(term)) { SASSERT(!is_attached_to_var(e)); // *** We must create a theory variable for each argument that has sort datatype *** // @@ -478,6 +529,7 @@ namespace smt { st.update("datatype splits", m_stats.m_splits); st.update("datatype constructor ax", m_stats.m_assert_cnstr); st.update("datatype accessor ax", m_stats.m_assert_accessor); + st.update("datatype update ax", m_stats.m_assert_update_field); } void theory_datatype::display_var(std::ostream & out, theory_var v) const { diff --git a/src/smt/theory_datatype.h b/src/smt/theory_datatype.h index cf2f933ad..5ebfc220f 100644 --- a/src/smt/theory_datatype.h +++ b/src/smt/theory_datatype.h @@ -41,7 +41,7 @@ namespace smt { struct stats { unsigned m_occurs_check, m_splits; - unsigned m_assert_cnstr, m_assert_accessor; + unsigned m_assert_cnstr, m_assert_accessor, m_assert_update_field; void reset() { memset(this, 0, sizeof(stats)); } stats() { reset(); } }; @@ -58,14 +58,17 @@ namespace smt { bool is_constructor(app * f) const { return m_util.is_constructor(f); } bool is_recognizer(app * f) const { return m_util.is_recognizer(f); } bool is_accessor(app * f) const { return m_util.is_accessor(f); } - + bool is_update_field(app * f) const { return m_util.is_update_field(f); } + bool is_constructor(enode * n) const { return is_constructor(n->get_owner()); } bool is_recognizer(enode * n) const { return is_recognizer(n->get_owner()); } bool is_accessor(enode * n) const { return is_accessor(n->get_owner()); } + bool is_update_field(enode * n) const { return m_util.is_update_field(n->get_owner()); } void assert_eq_axiom(enode * lhs, expr * rhs, literal antecedent); void assert_is_constructor_axiom(enode * n, func_decl * c, literal antecedent); void assert_accessor_axioms(enode * n); + void assert_update_field_axioms(enode * n); void add_recognizer(theory_var v, enode * recognizer); void propagate_recognizer(theory_var v, enode * r); void sign_recognizer_conflict(enode * c, enode * r); diff --git a/src/smt/theory_dense_diff_logic.h b/src/smt/theory_dense_diff_logic.h index 355e38c0c..04e257889 100644 --- a/src/smt/theory_dense_diff_logic.h +++ b/src/smt/theory_dense_diff_logic.h @@ -25,6 +25,8 @@ TODO: eager equality propagation #include"theory_arith_params.h" #include"arith_decl_plugin.h" #include"arith_eq_adapter.h" +#include"theory_opt.h" + namespace smt { @@ -41,7 +43,7 @@ namespace smt { }; template - class theory_dense_diff_logic : public theory, private Ext { + class theory_dense_diff_logic : public theory, public theory_opt, private Ext { public: theory_dense_diff_logic_statistics m_stats; @@ -127,6 +129,12 @@ namespace smt { svector m_scopes; bool m_non_diff_logic_exprs; + // For optimization purpose + typedef vector > objective_term; + vector m_objectives; + vector m_objective_consts; + vector m_objective_assignments; + struct f_target { theory_var m_target; numeral m_new_distance; @@ -189,6 +197,8 @@ namespace smt { void del_atoms(unsigned old_size); void del_vars(unsigned old_num_vars); void init_model(); + bool internalize_objective(expr * n, rational const& m, rational& r, objective_term & objective); + expr_ref mk_ineq(theory_var v, inf_rational const& val, bool is_strict); #ifdef Z3DEBUG bool check_vector_sizes() const; bool check_matrix() const; @@ -229,6 +239,8 @@ namespace smt { virtual void flush_eh(); virtual void reset_eh(); + bool dump_lemmas() const { return m_params.m_arith_dump_lemmas; } + virtual bool validate_eq_in_model(theory_var v1, theory_var v2, bool is_true) const; virtual void display(std::ostream & out) const; @@ -249,6 +261,18 @@ namespace smt { virtual void init_model(model_generator & m); virtual model_value_proc * mk_value(enode * n, model_generator & mg); + // ----------------------------------- + // + // Optimization + // + // ----------------------------------- + + virtual inf_eps_rational maximize(theory_var v, expr_ref& blocker, bool& has_shared); + virtual inf_eps_rational value(theory_var v); + virtual theory_var add_objective(app* term); + virtual expr_ref mk_gt(theory_var v, inf_rational const& val); + virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_rational const& val); + // ----------------------------------- // // Main diff --git a/src/smt/theory_dense_diff_logic_def.h b/src/smt/theory_dense_diff_logic_def.h index 21f1262ac..89e23cd3f 100644 --- a/src/smt/theory_dense_diff_logic_def.h +++ b/src/smt/theory_dense_diff_logic_def.h @@ -23,6 +23,8 @@ Revision History: #include"theory_dense_diff_logic.h" #include"ast_pp.h" #include"smt_model_generator.h" +#include"simplex.h" +#include"simplex_def.h" namespace smt { @@ -120,6 +122,7 @@ namespace smt { if (!m_non_diff_logic_exprs) { TRACE("non_diff_logic", tout << "found non diff logic expression:\n" << mk_pp(n, get_manager()) << "\n";); get_context().push_trail(value_trail(m_non_diff_logic_exprs)); + IF_VERBOSE(0, verbose_stream() << "(smt.diff_logic: non-diff logic expression " << mk_pp(n, get_manager()) << ")\n";); m_non_diff_logic_exprs = true; } } @@ -587,6 +590,11 @@ namespace smt { context & ctx = get_context(); region & r = ctx.get_region(); ctx.set_conflict(ctx.mk_justification(theory_conflict_justification(get_id(), r, antecedents.size(), antecedents.c_ptr()))); + + if (dump_lemmas()) { + ctx.display_lemma_as_smt_problem(antecedents.size(), antecedents.c_ptr(), false_literal, ""); + } + return; } @@ -818,6 +826,273 @@ namespace smt { return alloc(expr_wrapper_proc, m_factory->mk_value(num, is_int(v))); } + // TBD: code is common to both sparse and dense difference logic solvers. + template + bool theory_dense_diff_logic::internalize_objective(expr * n, rational const& m, rational& q, objective_term & objective) { + + // Compile term into objective_term format + rational r; + expr* x, *y; + if (m_autil.is_numeral(n, r)) { + q += r; + } + else if (m_autil.is_add(n)) { + for (unsigned i = 0; i < to_app(n)->get_num_args(); ++i) { + if (!internalize_objective(to_app(n)->get_arg(i), m, q, objective)) { + return false; + } + } + } + else if (m_autil.is_mul(n, x, y) && m_autil.is_numeral(x, r)) { + return internalize_objective(y, m*r, q, objective); + } + else if (m_autil.is_mul(n, y, x) && m_autil.is_numeral(x, r)) { + return internalize_objective(y, m*r, q, objective); + } + else if (!is_app(n)) { + return false; + } + else if (to_app(n)->get_family_id() == m_autil.get_family_id()) { + return false; + } + else { + context& ctx = get_context(); + enode * e = 0; + theory_var v = 0; + if (ctx.e_internalized(n)) { + e = ctx.get_enode(to_app(n)); + } + else { + e = ctx.mk_enode(to_app(n), false, false, true); + } + v = e->get_th_var(get_id()); + if (v == null_theory_var) { + v = mk_var(e); + } + + objective.push_back(std::make_pair(v, m)); + } + return true; + } + + template + inf_eps_rational theory_dense_diff_logic::value(theory_var v) { + objective_term const& objective = m_objectives[v]; + inf_eps r = inf_eps(m_objective_consts[v]); + for (unsigned i = 0; i < objective.size(); ++i) { + numeral n = m_assignment[v]; + rational r1 = n.get_rational().to_rational(); + rational r2 = n.get_infinitesimal().to_rational(); + r += objective[i].second * inf_eps(rational(0), inf_rational(r1, r2)); + } + return r; + } + + template + inf_eps_rational theory_dense_diff_logic::maximize(theory_var v, expr_ref& blocker, bool& has_shared) { + typedef simplex::simplex Simplex; + Simplex S; + ast_manager& m = get_manager(); + objective_term const& objective = m_objectives[v]; + has_shared = false; + + IF_VERBOSE(1, + for (unsigned i = 0; i < objective.size(); ++i) { + verbose_stream() << objective[i].second + << " * v" << objective[i].first << " "; + } + verbose_stream() << " + " << m_objective_consts[v] << "\n";); + + unsigned num_nodes = get_num_vars(); + unsigned num_edges = m_edges.size(); + S.ensure_var(num_nodes + num_edges + m_objectives.size()); + for (unsigned i = 0; i < num_nodes; ++i) { + numeral const& a = m_assignment[i]; + rational fin = a.get_rational().to_rational(); + rational inf = a.get_infinitesimal().to_rational(); + mpq_inf q(fin.to_mpq(), inf.to_mpq()); + S.set_value(i, q); + } + for (unsigned i = 0; i < num_nodes; ++i) { + enode * n = get_enode(i); + if (m_autil.is_zero(n->get_owner())) { + S.set_lower(v, mpq_inf(mpq(0), mpq(0))); + S.set_upper(v, mpq_inf(mpq(0), mpq(0))); + break; + } + } + svector vars; + unsynch_mpq_manager mgr; + scoped_mpq_vector coeffs(mgr); + coeffs.push_back(mpq(1)); + coeffs.push_back(mpq(-1)); + coeffs.push_back(mpq(-1)); + vars.resize(3); + for (unsigned i = 0; i < num_edges; ++i) { + edge const& e = m_edges[i]; + if (e.m_source == null_theory_var || e.m_target == null_theory_var) { + continue; + } + unsigned base_var = num_nodes + i; + vars[0] = e.m_target; + vars[1] = e.m_source; + vars[2] = base_var; + S.add_row(base_var, 3, vars.c_ptr(), coeffs.c_ptr()); + // t - s <= w + // t - s - b = 0, b >= w + numeral const& w = e.m_offset; + rational fin = w.get_rational().to_rational(); + rational inf = w.get_infinitesimal().to_rational(); + mpq_inf q(fin.to_mpq(),inf.to_mpq()); + S.set_upper(base_var, q); + } + unsigned w = num_nodes + num_edges + v; + + // add objective function as row. + coeffs.reset(); + vars.reset(); + for (unsigned i = 0; i < objective.size(); ++i) { + coeffs.push_back(objective[i].second.to_mpq()); + vars.push_back(objective[i].first); + } + coeffs.push_back(mpq(1)); + vars.push_back(w); + Simplex::row row = S.add_row(w, vars.size(), vars.c_ptr(), coeffs.c_ptr()); + + TRACE("opt", S.display(tout); display(tout);); + + // optimize + lbool is_sat = S.make_feasible(); + if (is_sat == l_undef) { + blocker = m.mk_false(); + return inf_eps::infinity(); + } + TRACE("opt", S.display(tout); ); + SASSERT(is_sat != l_false); + lbool is_fin = S.minimize(w); + + switch (is_fin) { + case l_true: { + simplex::mpq_ext::eps_numeral const& val = S.get_value(w); + inf_rational r(-rational(val.first), -rational(val.second)); + TRACE("opt", tout << r << " " << "\n"; + S.display_row(tout, row, true);); + Simplex::row_iterator it = S.row_begin(row), end = S.row_end(row); + expr_ref_vector& core = m_objective_assignments[v]; + expr_ref tmp(m); + core.reset(); + for (; it != end; ++it) { + unsigned v = it->m_var; + if (num_nodes <= v && v < num_nodes + num_edges) { + unsigned edge_id = v - num_nodes; + literal lit = m_edges[edge_id].m_justification; + get_context().literal2expr(lit, tmp); + core.push_back(tmp); + } + } + for (unsigned i = 0; i < num_nodes; ++i) { + mpq_inf const& val = S.get_value(i); + rational q(val.first), eps(val.second); + numeral a(q); + m_assignment[i] = a; + // TBD: if epsilon is != 0, then adjust a by some small fraction. + } + blocker = mk_gt(v, r); + IF_VERBOSE(10, verbose_stream() << blocker << "\n";); + return inf_eps(rational(0), r); + } + default: + TRACE("opt", tout << "unbounded\n"; ); + blocker = m.mk_false(); + return inf_eps::infinity(); + } + } + + template + theory_var theory_dense_diff_logic::add_objective(app* term) { + objective_term objective; + theory_var result = m_objectives.size(); + rational q(1), r(0); + expr_ref_vector vr(get_manager()); + if (!is_linear(get_manager(), term)) { + result = null_theory_var; + } + else if (internalize_objective(term, q, r, objective)) { + m_objectives.push_back(objective); + m_objective_consts.push_back(r); + m_objective_assignments.push_back(vr); + } + else { + result = null_theory_var; + } + return result; + } + + template + expr_ref theory_dense_diff_logic::mk_gt(theory_var v, inf_rational const& val) { + return mk_ineq(v, val, true); + } + + template + expr_ref theory_dense_diff_logic::mk_ge( + filter_model_converter& fm, theory_var v, inf_rational const& val) { + return mk_ineq(v, val, false); + } + + template + expr_ref theory_dense_diff_logic::mk_ineq(theory_var v, inf_rational const& val, bool is_strict) { + ast_manager& m = get_manager(); + objective_term const& t = m_objectives[v]; + expr_ref e(m), f(m), f2(m); + if (t.size() == 1 && t[0].second.is_one()) { + f = get_enode(t[0].first)->get_owner(); + } + else if (t.size() == 1 && t[0].second.is_minus_one()) { + f = m_autil.mk_uminus(get_enode(t[0].first)->get_owner()); + } + else if (t.size() == 2 && t[0].second.is_one() && t[1].second.is_minus_one()) { + f = get_enode(t[0].first)->get_owner(); + f2 = get_enode(t[1].first)->get_owner(); + f = m_autil.mk_sub(f, f2); + } + else if (t.size() == 2 && t[1].second.is_one() && t[0].second.is_minus_one()) { + f = get_enode(t[1].first)->get_owner(); + f2 = get_enode(t[0].first)->get_owner(); + f = m_autil.mk_sub(f, f2); + } + else { + // + expr_ref_vector const& core = m_objective_assignments[v]; + f = m.mk_and(core.size(), core.c_ptr()); + if (is_strict) { + f = m.mk_not(f); + } + TRACE("arith", tout << "block: " << f << "\n";); + return f; + } + + e = m_autil.mk_numeral(val.get_rational(), m.get_sort(f)); + + if (val.get_infinitesimal().is_neg()) { + if (is_strict) { + f = m_autil.mk_ge(f, e); + } + else { + expr_ref_vector const& core = m_objective_assignments[v]; + f = m.mk_and(core.size(), core.c_ptr()); + } + } + else { + if (is_strict) { + f = m_autil.mk_gt(f, e); + } + else { + f = m_autil.mk_ge(f, e); + } + } + return f; + } + }; #endif /* _THEORY_DENSE_DIFF_LOGIC_DEF_H_ */ diff --git a/src/smt/theory_diff_logic.cpp b/src/smt/theory_diff_logic.cpp index a68b7782b..f1f00833b 100644 --- a/src/smt/theory_diff_logic.cpp +++ b/src/smt/theory_diff_logic.cpp @@ -21,6 +21,7 @@ Revision History: #include"rational.h" #include"theory_diff_logic_def.h" +#include"sparse_matrix_def.h" namespace smt { @@ -29,4 +30,10 @@ template class theory_diff_logic; template class theory_diff_logic; template class theory_diff_logic; + +}; + +namespace simplex { +template class simplex; +template class sparse_matrix; }; diff --git a/src/smt/theory_diff_logic.h b/src/smt/theory_diff_logic.h index 7302ccfd4..8b5bb2b86 100644 --- a/src/smt/theory_diff_logic.h +++ b/src/smt/theory_diff_logic.h @@ -37,7 +37,9 @@ Revision History: #include"smt_model_generator.h" #include"numeral_factory.h" #include"smt_clause.h" - +#include"theory_opt.h" +#include"simplex.h" +#include"simplex_def.h" // The DL theory can represent term such as n + k, where n is an enode and k is a numeral. namespace smt { @@ -59,9 +61,11 @@ namespace smt { }; template - class theory_diff_logic : public theory, private Ext { + class theory_diff_logic : public theory, public theory_opt, private Ext { typedef typename Ext::numeral numeral; + typedef simplex::simplex Simplex; + typedef inf_eps_rational inf_eps; class atom { bool_var m_bvar; @@ -158,18 +162,21 @@ namespace smt { unsigned m_asserted_atoms_lim; unsigned m_asserted_qhead_old; }; + typedef dl_graph Graph; smt_params & m_params; arith_util m_util; arith_eq_adapter m_arith_eq_adapter; theory_diff_logic_statistics m_stats; - dl_graph m_graph; - theory_var m_zero_int; // cache the variable representing the zero variable. - theory_var m_zero_real; // cache the variable representing the zero variable. + Graph m_graph; + theory_var m_zero; // cache the variable representing the zero variable. int_vector m_scc_id; // Cheap equality propagation eq_prop_info_set m_eq_prop_info_set; // set of existing equality prop infos ptr_vector m_eq_prop_infos; + app_ref_vector m_terms; + svector m_signs; + ptr_vector m_atoms; ptr_vector m_asserted_atoms; // set of asserted atoms unsigned m_asserted_qhead; @@ -184,7 +191,16 @@ namespace smt { arith_factory * m_factory; rational m_delta; - nc_functor m_nc_functor; + nc_functor m_nc_functor; + + // For optimization purpose + typedef vector > objective_term; + vector m_objectives; + vector m_objective_consts; + vector m_objective_assignments; + vector m_objective_rows; + Simplex m_S; + unsigned m_num_simplex_edges; // Set a conflict due to a negative cycle. void set_neg_cycle_conflict(); @@ -210,8 +226,8 @@ namespace smt { m_params(params), m_util(m), m_arith_eq_adapter(*this, params, m_util), - m_zero_int(null_theory_var), - m_zero_real(null_theory_var), + m_zero(null_theory_var), + m_terms(m), m_asserted_qhead(0), m_num_core_conflicts(0), m_num_propagation_calls(0), @@ -219,7 +235,8 @@ namespace smt { m_is_lia(true), m_non_diff_logic_exprs(false), m_factory(0), - m_nc_functor(*this) { + m_nc_functor(*this), + m_num_simplex_edges(0) { } virtual ~theory_diff_logic() { @@ -296,12 +313,33 @@ namespace smt { virtual void collect_statistics(::statistics & st) const; - private: + + // ----------------------------------- + // + // Optimization + // + // ----------------------------------- + + virtual inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared); + virtual inf_eps value(theory_var v); + virtual theory_var add_objective(app* term); + virtual expr_ref mk_gt(theory_var v, inf_rational const& val); + virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_rational const& val); + + bool internalize_objective(expr * n, rational const& m, rational& r, objective_term & objective); + + private: + + expr_ref mk_ineq(theory_var v, inf_rational const& val, bool is_strict); virtual void new_eq_eh(theory_var v1, theory_var v2, justification& j); virtual void new_diseq_eh(theory_var v1, theory_var v2, justification& j); + bool decompose_linear(app_ref_vector& args, svector& signs); + + bool is_sign(expr* n, bool& sign); + bool is_negative(app* n, app*& m); void del_atoms(unsigned old_size); @@ -336,18 +374,26 @@ namespace smt { void get_implied_bound_antecedents(edge_id bridge_edge, edge_id subsumed_edge, conflict_resolution & cr); - theory_var get_zero(sort* s) const { return m_util.is_int(s)?m_zero_int:m_zero_real; } - - theory_var get_zero(expr* e) const { return get_zero(get_manager().get_sort(e)); } + theory_var get_zero() const { return m_zero; } void inc_conflicts(); + // Optimization: + // convert variables, edges and objectives to simplex. + unsigned node2simplex(unsigned v); + unsigned edge2simplex(unsigned e); + unsigned obj2simplex(unsigned v); + unsigned num_simplex_vars(); + bool is_simplex_edge(unsigned e); + unsigned simplex2edge(unsigned e); + void update_simplex(Simplex& S); }; struct idl_ext { // TODO: It doesn't need to be a rational, but a bignum integer. static const bool m_int_theory = true; typedef rational numeral; + typedef rational fin_numeral; numeral m_epsilon; idl_ext() : m_epsilon(1) {} }; @@ -356,6 +402,7 @@ namespace smt { // TODO: It doesn't need to be a rational, but a bignum integer. static const bool m_int_theory = true; typedef s_integer numeral; + typedef s_integer fin_numeral; numeral m_epsilon; sidl_ext() : m_epsilon(1) {} }; @@ -363,18 +410,19 @@ namespace smt { struct rdl_ext { static const bool m_int_theory = false; typedef inf_int_rational numeral; - numeral m_epsilon; + typedef rational fin_numeral; + numeral m_epsilon; rdl_ext() : m_epsilon(rational(), true) {} }; struct srdl_ext { static const bool m_int_theory = false; typedef inf_s_integer numeral; + typedef s_integer fin_numeral; numeral m_epsilon; srdl_ext() : m_epsilon(s_integer(0),true) {} }; - typedef theory_diff_logic theory_idl; typedef theory_diff_logic theory_fidl; typedef theory_diff_logic theory_rdl; diff --git a/src/smt/theory_diff_logic_def.h b/src/smt/theory_diff_logic_def.h index a2e1ece40..6c43c8d11 100644 --- a/src/smt/theory_diff_logic_def.h +++ b/src/smt/theory_diff_logic_def.h @@ -28,6 +28,8 @@ Revision History: #include"ast_pp.h" #include"warning.h" #include"smt_model_generator.h" +#include"model_implicant.h" + using namespace smt; @@ -69,12 +71,7 @@ void theory_diff_logic::init(context * ctx) { zero = m_util.mk_numeral(rational(0), true); e = ctx->mk_enode(zero, false, false, true); SASSERT(!is_attached_to_var(e)); - m_zero_int = mk_var(e); - - zero = m_util.mk_numeral(rational(0), false); - e = ctx->mk_enode(zero, false, false, true); - SASSERT(!is_attached_to_var(e)); - m_zero_real = mk_var(e); + m_zero = mk_var(e); } @@ -82,8 +79,10 @@ template bool theory_diff_logic::internalize_term(app * term) { bool result = null_theory_var != mk_term(term); CTRACE("arith", !result, tout << "Did not internalize " << mk_pp(term, get_manager()) << "\n";); - TRACE("non_diff_logic", tout << "Terms may not be internalized\n";); - found_non_diff_logic_expr(term); + if (!result) { + TRACE("non_diff_logic", tout << "Terms may not be internalized\n";); + found_non_diff_logic_expr(term); + } return result; } @@ -159,6 +158,7 @@ template void theory_diff_logic::found_non_diff_logic_expr(expr * n) { if (!m_non_diff_logic_exprs) { TRACE("non_diff_logic", tout << "found non diff logic expression:\n" << mk_pp(n, get_manager()) << "\n";); + IF_VERBOSE(0, verbose_stream() << "(smt.diff_logic: non-diff logic expression " << mk_pp(n, get_manager()) << ")\n";); get_context().push_trail(value_trail(m_non_diff_logic_exprs)); m_non_diff_logic_exprs = true; } @@ -177,7 +177,6 @@ bool theory_diff_logic::internalize_atom(app * n, bool gate_ctx) { bool is_ge = m_util.is_ge(n); bool_var bv; rational kr; - app * x, *y, *z; theory_var source, target; // target - source <= k app * lhs = to_app(n->get_arg(0)); app * rhs = to_app(n->get_arg(1)); @@ -191,25 +190,26 @@ bool theory_diff_logic::internalize_atom(app * n, bool gate_ctx) { } numeral k(kr); - bool is_add = m_util.is_add(lhs) && lhs->get_num_args() == 2; - - if (is_add) { - x = to_app(lhs->get_arg(0)); - y = to_app(lhs->get_arg(1)); + m_terms.reset(); + m_signs.reset(); + m_terms.push_back(lhs); + m_signs.push_back(true); + if (!decompose_linear(m_terms, m_signs)) { + found_non_diff_logic_expr(n); + return false; } - - if (is_add && is_negative(x, z)) { - target = mk_var(y); - source = mk_var(z); - } - else if (is_add && is_negative(y, z)) { - target = mk_var(x); - source = mk_var(z); + if (m_terms.size() == 2 && m_signs[0] != m_signs[1]) { + target = mk_var(m_terms[0].get()); + source = mk_var(m_terms[1].get()); + if (!m_signs[0]) { + std::swap(target, source); + } } else { target = mk_var(lhs); - source = get_zero(lhs); + source = get_zero(); } + if (is_ge) { std::swap(target, source); k.neg(); @@ -273,6 +273,8 @@ bool theory_diff_logic::internalize_atom(app * n, bool gate_ctx) { template void theory_diff_logic::internalize_eq_eh(app * atom, bool_var v) { context & ctx = get_context(); + ast_manager& m = get_manager(); + TRACE("arith", tout << mk_pp(atom, m) << "\n";); app * lhs = to_app(atom->get_arg(0)); app * rhs = to_app(atom->get_arg(1)); app * s; @@ -339,7 +341,13 @@ void theory_diff_logic::pop_scope_eh(unsigned num_scopes) { m_asserted_atoms.shrink(s.m_asserted_atoms_lim); m_asserted_qhead = s.m_asserted_qhead_old; m_scopes.shrink(new_lvl); + unsigned num_edges = m_graph.get_num_edges(); m_graph.pop(num_scopes); + if (num_edges != m_graph.get_num_edges() && m_num_simplex_edges > 0) { + m_S.reset(); + m_num_simplex_edges = 0; + m_objective_rows.reset(); + } theory::pop_scope_eh(num_scopes); } @@ -353,7 +361,7 @@ final_check_status theory_diff_logic::final_check_eh() { TRACE("arith_final", display(tout); ); // either will already be zero (as we don't do mixed constraints). - m_graph.set_to_zero(m_zero_int, m_zero_real); + m_graph.set_to_zero(m_zero); SASSERT(is_consistent()); if (m_non_diff_logic_exprs) { return FC_GIVEUP; @@ -378,6 +386,70 @@ void theory_diff_logic::del_atoms(unsigned old_size) { } +template +bool theory_diff_logic::decompose_linear(app_ref_vector& terms, svector& signs) { + for (unsigned i = 0; i < terms.size(); ++i) { + app* n = terms[i].get(); + if (m_util.is_add(n)) { + expr* arg = n->get_arg(0); + if (!is_app(arg)) return false; + terms[i] = to_app(arg); + for (unsigned j = 1; j < n->get_num_args(); ++j) { + arg = n->get_arg(j); + if (!is_app(arg)) return false; + terms.push_back(to_app(arg)); + signs.push_back(signs[i]); + } + --i; + continue; + } + expr* x, *y; + bool sign; + if (m_util.is_mul(n, x, y)) { + if (is_sign(x, sign) && is_app(y)) { + terms[i] = to_app(y); + signs[i] = (signs[i] == sign); + --i; + } + else if (is_sign(y, sign) && is_app(x)) { + terms[i] = to_app(x); + signs[i] = (signs[i] == sign); + --i; + } + continue; + } + if (m_util.is_uminus(n, x) && is_app(x)) { + terms[i] = to_app(x); + signs[i] = !signs[i]; + --i; + continue; + } + } + return true; +} + +template +bool theory_diff_logic::is_sign(expr* n, bool& sign) { + rational r; + expr* x; + if (m_util.is_numeral(n, r)) { + if (r.is_one()) { + sign = true; + return true; + } + if (r.is_minus_one()) { + sign = false; + return true; + } + } + else if (m_util.is_uminus(n, x)) { + if (is_sign(x, sign)) { + sign = !sign; + return true; + } + } + return false; +} template bool theory_diff_logic::is_negative(app* n, app*& m) { @@ -474,7 +546,7 @@ void theory_diff_logic::propagate_core() { template bool theory_diff_logic::propagate_atom(atom* a) { context& ctx = get_context(); - TRACE("arith", a->display(*this, tout); ); + TRACE("arith", a->display(*this, tout); tout << "\n";); if (ctx.inconsistent()) { return false; } @@ -650,6 +722,7 @@ theory_var theory_diff_logic::mk_term(app* n) { app* a, *offset; theory_var source, target; enode* e; + context& ctx = get_context(); TRACE("arith", tout << mk_pp(n, get_manager()) << "\n";); @@ -660,6 +733,13 @@ theory_var theory_diff_logic::mk_term(app* n) { else if (is_offset(n, a, offset, r)) { // n = a + k source = mk_var(a); + for (unsigned i = 0; i < n->get_num_args(); ++i) { + expr* arg = n->get_arg(i); + std::cout << "internalize: " << mk_pp(arg, get_manager()) << " " << ctx.e_internalized(arg) << "\n"; + if (!ctx.e_internalized(arg)) { + ctx.internalize(arg, false); + } + } e = get_context().mk_enode(n, false, false, true); target = mk_var(e); numeral k(r); @@ -698,7 +778,7 @@ theory_var theory_diff_logic::mk_num(app* n, rational const& r) { enode* e = 0; context& ctx = get_context(); if (r.is_zero()) { - v = get_zero(n); + v = get_zero(); } else if (ctx.e_internalized(n)) { e = ctx.get_enode(n); @@ -706,7 +786,8 @@ theory_var theory_diff_logic::mk_num(app* n, rational const& r) { SASSERT(v != null_theory_var); } else { - theory_var zero = get_zero(n); + theory_var zero = get_zero(); + SASSERT(n->get_num_args() == 0); e = ctx.mk_enode(n, false, false, true); v = mk_var(e); // internalizer is marking enodes as interpreted whenever the associated ast is a value and a constant. @@ -763,8 +844,7 @@ void theory_diff_logic::reset_eh() { dealloc(m_atoms[i]); } m_graph .reset(); - m_zero_int = null_theory_var; - m_zero_real = null_theory_var; + m_zero = null_theory_var; m_atoms .reset(); m_asserted_atoms .reset(); m_stats .reset(); @@ -775,6 +855,9 @@ void theory_diff_logic::reset_eh() { m_agility = 0.5; m_is_lia = true; m_non_diff_logic_exprs = false; + m_objectives .reset(); + m_objective_consts.reset(); + m_objective_assignments.reset(); theory::reset_eh(); } @@ -993,5 +1076,313 @@ void theory_diff_logic::get_implied_bound_antecedents(edge_id bridge_edge, m_graph.explain_subsumed_lazy(bridge_edge, subsumed_edge, f); } +template +unsigned theory_diff_logic::node2simplex(unsigned v) { + return m_objectives.size() + 2*v + 1; +} +template +unsigned theory_diff_logic::edge2simplex(unsigned e) { + return m_objectives.size() + 2*e; +} +template +unsigned theory_diff_logic::obj2simplex(unsigned e) { + return e; +} + +template +unsigned theory_diff_logic::num_simplex_vars() { + return m_objectives.size() + std::max(2*m_graph.get_num_edges(),2*m_graph.get_num_nodes()+1); +} + +template +bool theory_diff_logic::is_simplex_edge(unsigned e) { + if (e < m_objectives.size()) return false; + e -= m_objectives.size(); + return (0 == (e & 0x1)); +} + +template +unsigned theory_diff_logic::simplex2edge(unsigned e) { + SASSERT(is_simplex_edge(e)); + return (e - m_objectives.size())/2; +} + +template +void theory_diff_logic::update_simplex(Simplex& S) { + unsigned num_nodes = m_graph.get_num_nodes(); + vector > const& es = m_graph.get_all_edges(); + S.ensure_var(num_simplex_vars()); + for (unsigned i = 0; i < num_nodes; ++i) { + numeral const& a = m_graph.get_assignment(i); + rational fin = a.get_rational().to_rational(); + rational inf = a.get_infinitesimal().to_rational(); + mpq_inf q(fin.to_mpq(), inf.to_mpq()); + S.set_value(node2simplex(i), q); + } + S.set_lower(node2simplex(get_zero()), mpq_inf(mpq(0), mpq(0))); + S.set_upper(node2simplex(get_zero()), mpq_inf(mpq(0), mpq(0))); + svector vars; + unsynch_mpq_manager mgr; + scoped_mpq_vector coeffs(mgr); + coeffs.push_back(mpq(1)); + coeffs.push_back(mpq(-1)); + coeffs.push_back(mpq(-1)); + vars.resize(3); + for (unsigned i = m_num_simplex_edges; i < es.size(); ++i) { + // t - s <= w + // => + // t - s - b = 0, b >= w + dl_edge const& e = es[i]; + unsigned base_var = edge2simplex(i); + vars[0] = node2simplex(e.get_target()); + vars[1] = node2simplex(e.get_source()); + vars[2] = base_var; + S.add_row(base_var, 3, vars.c_ptr(), coeffs.c_ptr()); + } + m_num_simplex_edges = es.size(); + for (unsigned i = 0; i < es.size(); ++i) { + dl_edge const& e = es[i]; + unsigned base_var = edge2simplex(i); + if (e.is_enabled()) { + numeral const& w = e.get_weight(); + rational fin = w.get_rational().to_rational(); + rational inf = w.get_infinitesimal().to_rational(); + mpq_inf q(fin.to_mpq(),inf.to_mpq()); + S.set_upper(base_var, q); + } + else { + S.unset_upper(base_var); + } + } + for (unsigned v = m_objective_rows.size(); v < m_objectives.size(); ++v) { + unsigned w = obj2simplex(v); + objective_term const& objective = m_objectives[v]; + + // add objective function as row. + coeffs.reset(); + vars.reset(); + for (unsigned i = 0; i < objective.size(); ++i) { + coeffs.push_back(objective[i].second.to_mpq()); + vars.push_back(node2simplex(objective[i].first)); + } + coeffs.push_back(mpq(1)); + vars.push_back(w); + Simplex::row row = S.add_row(w, vars.size(), vars.c_ptr(), coeffs.c_ptr()); + m_objective_rows.push_back(row); + } +} + +template +typename theory_diff_logic::inf_eps theory_diff_logic::value(theory_var v) { + objective_term const& objective = m_objectives[v]; + inf_eps r = inf_eps(m_objective_consts[v]); + for (unsigned i = 0; i < objective.size(); ++i) { + numeral n = m_graph.get_assignment(v); + rational r1 = n.get_rational().to_rational(); + rational r2 = n.get_infinitesimal().to_rational(); + r += objective[i].second * inf_eps(rational(0), inf_rational(r1, r2)); + } + return r; +} + +template +typename theory_diff_logic::inf_eps +theory_diff_logic::maximize(theory_var v, expr_ref& blocker, bool& has_shared) { + + has_shared = false; + Simplex& S = m_S; + ast_manager& m = get_manager(); + + update_simplex(S); + objective_term const& objective = m_objectives[v]; + + TRACE("arith", + for (unsigned i = 0; i < objective.size(); ++i) { + tout << "Coefficient " << objective[i].second + << " of theory_var " << objective[i].first << "\n"; + } + tout << "Free coefficient " << m_objective_consts[v] << "\n"; + ); + + TRACE("opt", S.display(tout); display(tout);); + + // optimize + lbool is_sat = S.make_feasible(); + if (is_sat == l_undef) { + blocker = m.mk_false(); + return inf_eps::infinity(); + } + TRACE("opt", S.display(tout); ); + SASSERT(is_sat != l_false); + unsigned w = obj2simplex(v); + lbool is_fin = S.minimize(w); + switch (is_fin) { + case l_true: { + simplex::mpq_ext::eps_numeral const& val = S.get_value(w); + inf_rational r(-rational(val.first), -rational(val.second)); + Simplex::row row = m_objective_rows[v]; + TRACE("opt", tout << r << " " << "\n"; + S.display_row(tout, row, true);); + Simplex::row_iterator it = S.row_begin(row), end = S.row_end(row); + expr_ref_vector& core = m_objective_assignments[v]; + expr_ref tmp(m); + core.reset(); + for (; it != end; ++it) { + unsigned v = it->m_var; + if (is_simplex_edge(v)) { + unsigned edge_id = simplex2edge(v); + literal lit = m_graph.get_explanation(edge_id); + get_context().literal2expr(lit, tmp); + core.push_back(tmp); + } + } + compute_delta(); + for (unsigned i = 0; i < m_graph.get_num_nodes(); ++i) { + unsigned w = node2simplex(i); + simplex::mpq_ext::eps_numeral const& val = S.get_value(w); + rational r = rational(val.first) + m_delta*rational(val.second); + m_graph.set_assignment(i, numeral(r)); + } + blocker = mk_gt(v, r); + return inf_eps(rational(0), r + m_objective_consts[v]); + } + default: + TRACE("opt", tout << "unbounded\n"; ); + blocker = m.mk_false(); + return inf_eps::infinity(); + } +} + +template +theory_var theory_diff_logic::add_objective(app* term) { + objective_term objective; + theory_var result = m_objectives.size(); + rational q(1), r(0); + expr_ref_vector vr(get_manager()); + if (!is_linear(get_manager(), term)) { + result = null_theory_var; + } + else if (internalize_objective(term, q, r, objective)) { + m_objectives.push_back(objective); + m_objective_consts.push_back(r); + m_objective_assignments.push_back(vr); + } + else { + result = null_theory_var; + } + return result; +} + +template +expr_ref theory_diff_logic::mk_ineq(theory_var v, inf_rational const& val, bool is_strict) { + ast_manager& m = get_manager(); + objective_term const& t = m_objectives[v]; + expr_ref e(m), f(m), f2(m); + if (t.size() == 1 && t[0].second.is_one()) { + f = get_enode(t[0].first)->get_owner(); + } + else if (t.size() == 1 && t[0].second.is_minus_one()) { + f = m_util.mk_uminus(get_enode(t[0].first)->get_owner()); + } + else if (t.size() == 2 && t[0].second.is_one() && t[1].second.is_minus_one()) { + f = get_enode(t[0].first)->get_owner(); + f2 = get_enode(t[1].first)->get_owner(); + f = m_util.mk_sub(f, f2); + } + else if (t.size() == 2 && t[1].second.is_one() && t[0].second.is_minus_one()) { + f = get_enode(t[1].first)->get_owner(); + f2 = get_enode(t[0].first)->get_owner(); + f = m_util.mk_sub(f, f2); + } + else { + // + expr_ref_vector const& core = m_objective_assignments[v]; + f = m.mk_and(core.size(), core.c_ptr()); + if (is_strict) { + f = m.mk_not(f); + } + TRACE("arith", tout << "block: " << f << "\n";); + return f; + } + + inf_rational new_val = val; // - inf_rational(m_objective_consts[v]); + e = m_util.mk_numeral(new_val.get_rational(), m.get_sort(f)); + + if (new_val.get_infinitesimal().is_neg()) { + if (is_strict) { + f = m_util.mk_ge(f, e); + } + else { + expr_ref_vector const& core = m_objective_assignments[v]; + f = m.mk_and(core.size(), core.c_ptr()); + } + } + else { + if (is_strict) { + f = m_util.mk_gt(f, e); + } + else { + f = m_util.mk_ge(f, e); + } + } + return f; +} + +template +expr_ref theory_diff_logic::mk_gt(theory_var v, inf_rational const& val) { + return mk_ineq(v, val, true); +} + +template +expr_ref theory_diff_logic::mk_ge(filter_model_converter& fm, theory_var v, inf_rational const& val) { + return mk_ineq(v, val, false); +} + +#if 0 + context & ctx = get_context(); + model_ref mdl; + ctx.get_model(mdl); + ptr_vector formulas(ctx.get_num_asserted_formulas(), ctx.get_asserted_formulas()); + ast_manager& m = get_manager(); + model_implicant impl_extractor(m); + expr_ref_vector implicants = impl_extractor.minimize_literals(formulas, mdl); + return m.mk_and(o, m.mk_not(m.mk_and(implicants.size(), implicants.c_ptr()))); +#endif + +template +bool theory_diff_logic::internalize_objective(expr * n, rational const& m, rational& q, objective_term & objective) { + + // Compile term into objective_term format + rational r; + expr* x, *y; + if (m_util.is_numeral(n, r)) { + q += r; + } + else if (m_util.is_add(n)) { + for (unsigned i = 0; i < to_app(n)->get_num_args(); ++i) { + if (!internalize_objective(to_app(n)->get_arg(i), m, q, objective)) { + return false; + } + } + } + else if (m_util.is_mul(n, x, y) && m_util.is_numeral(x, r)) { + return internalize_objective(y, m*r, q, objective); + } + else if (m_util.is_mul(n, y, x) && m_util.is_numeral(x, r)) { + return internalize_objective(y, m*r, q, objective); + } + else if (!is_app(n)) { + return false; + } + else if (to_app(n)->get_family_id() == m_util.get_family_id()) { + return false; + } + else { + theory_var v = mk_var(to_app(n)); + objective.push_back(std::make_pair(v, m)); + } + return true; +} + #endif /* _THEORY_DIFF_LOGIC_DEF_H_ */ diff --git a/src/smt/theory_opt.cpp b/src/smt/theory_opt.cpp new file mode 100644 index 000000000..279863885 --- /dev/null +++ b/src/smt/theory_opt.cpp @@ -0,0 +1,84 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + theory_opt.cpp + +Abstract: + + Interface utilities used by optimization providing + theory solvers. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-10-18 + +Notes: + +--*/ + +#include "arith_decl_plugin.h" +#include "smt_types.h" +#include "smt_theory.h" +#include "theory_opt.h" + +namespace smt { + bool theory_opt::is_linear(ast_manager& m, expr* term) { + arith_util a(m); + ptr_vector todo; + ast_mark mark; + todo.push_back(term); + expr* t1, *t2; + while (!todo.empty()) { + term = todo.back(); + todo.pop_back(); + if (mark.is_marked(term)) { + continue; + } + mark.mark(term, true); + if (!is_app(term)) { + return false; + } + app* t = to_app(term); + if (t->get_family_id() != a.get_family_id()) { + // done + } + else if (a.is_add(t) || a.is_to_real(t) || a.is_to_int(t) || + a.is_uminus(t) || a.is_numeral(t) || a.is_sub(t)) { + todo.append(t->get_num_args(), t->get_args()); + } + else if (a.is_mul(t, t1, t2)) { + if (is_numeral(a, t1)) { + todo.push_back(t2); + } + else if (is_numeral(a, t2)) { + todo.push_back(t1); + } + else { + return false; + } + } + else { + return false; + } + } + return true; + } + + + bool theory_opt::is_numeral(arith_util& a, expr* term) { + while (true) { + if (a.is_uminus(term) || a.is_to_real(term) || a.is_to_int(term)) { + term = to_app(term)->get_arg(0); + } + else if (a.is_numeral(term)) { + return true; + } + else { + return false; + } + } + } + +}; diff --git a/src/smt/theory_opt.h b/src/smt/theory_opt.h new file mode 100644 index 000000000..61acfc381 --- /dev/null +++ b/src/smt/theory_opt.h @@ -0,0 +1,42 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + theory_opt.h + +Abstract: + + Interface utilities used by optimization providing + theory solvers. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-10-18 + +Notes: + +--*/ + +#include "inf_rational.h" +#include "inf_eps_rational.h" +#include "arith_decl_plugin.h" + +#ifndef _THEORY_OPT_H_ +#define _THEORY_OPT_H_ + +class filter_model_converter; +namespace smt { + class theory_opt { + public: + typedef inf_eps_rational inf_eps; + virtual inf_eps value(theory_var) = 0; + virtual inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared) = 0; + virtual theory_var add_objective(app* term) = 0; + virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_eps const& val) { UNREACHABLE(); return expr_ref(*((ast_manager*)0)); } + bool is_linear(ast_manager& m, expr* term); + bool is_numeral(arith_util& a, expr* term); + }; +} + +#endif diff --git a/src/smt/theory_pb.cpp b/src/smt/theory_pb.cpp new file mode 100644 index 000000000..1eff86db4 --- /dev/null +++ b/src/smt/theory_pb.cpp @@ -0,0 +1,2090 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + theory_pb.cpp + +Abstract: + + Pseudo-Boolean theory plugin. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-05 + +Notes: + + +--*/ + +#include +#include "theory_pb.h" +#include "smt_context.h" +#include "ast_pp.h" +#include "sorting_network.h" +#include "uint_set.h" +#include "smt_model_generator.h" +#include "pb_rewriter_def.h" +#include "sparse_matrix_def.h" +#include "simplex_def.h" + + +namespace smt { + + class pb_lit_rewriter_util { + public: + typedef std::pair arg_t; + typedef vector args_t; + typedef rational numeral; + + literal negate(literal l) { + return ~l; + } + + void display(std::ostream& out, literal l) { + out << l; + } + + bool is_negated(literal l) const { + return l.sign(); + } + + bool is_true(literal l) const { + return l == true_literal; + } + + bool is_false(literal l) const { + return l == false_literal; + } + + struct compare { + bool operator()(arg_t const& a, arg_t const& b) { + return a.first < b.first; + } + }; + }; + + const unsigned theory_pb::null_index = UINT_MAX; + + + unsigned theory_pb::arg_t::get_hash() const { + return get_composite_hash(*this, size()); + } + + bool theory_pb::arg_t::operator==(arg_t const& other) const { + if (size() != other.size()) return false; + for (unsigned i = 0; i < size(); ++i) { + if (lit(i) != other.lit(i)) return false; + if (coeff(i) != other.coeff(i)) return false; + } + return true; + } + + void theory_pb::arg_t::remove_negations() { + for (unsigned i = 0; i < size(); ++i) { + if (lit(i).sign()) { + (*this)[i].first.neg(); + (*this)[i].second.neg(); + m_k += coeff(i); + } + } + } + + void theory_pb::arg_t::negate() { + numeral sum(0); + for (unsigned i = 0; i < size(); ++i) { + (*this)[i].first.neg(); + sum += coeff(i); + } + m_k = sum - m_k + numeral::one(); + VERIFY(l_undef == normalize(false)); + } + + lbool theory_pb::arg_t::normalize(bool is_eq) { + pb_lit_rewriter_util pbu; + pb_rewriter_util util(pbu); + return util.normalize(*this, m_k, is_eq); + } + + void theory_pb::arg_t::prune(bool is_eq) { + pb_lit_rewriter_util pbu; + pb_rewriter_util util(pbu); + util.prune(*this, m_k, is_eq); + } + + std::ostream& theory_pb::arg_t::display(context& ctx, std::ostream& out, bool values) const { + for (unsigned i = 0; i < size(); ++i) { + literal l(lit(i)); + if (!coeff(i).is_one()) { + out << coeff(i) << "*"; + } + out << l; + if (values) { + out << "@(" << ctx.get_assignment(l); + if (ctx.get_assignment(l) != l_undef) { + out << ":" << ctx.get_assign_level(l); + } + out << ")"; + } + if (i + 1 < size()) { + out << " + "; + } + } + out << " ~ " << k() << "\n"; + return out; + } + + app_ref theory_pb::arg_t::to_expr(bool is_eq, context& ctx, ast_manager& m) { + expr_ref tmp(m); + app_ref result(m); + svector coeffs; + expr_ref_vector args(m); + for (unsigned i = 0; i < size(); ++i) { + ctx.literal2expr(lit(i), tmp); + args.push_back(tmp); + coeffs.push_back(coeff(i)); + } + pb_util pb(m); + if (is_eq) { + result = pb.mk_eq(coeffs.size(), coeffs.c_ptr(), args.c_ptr(), k()); + } + else { + result = pb.mk_ge(coeffs.size(), coeffs.c_ptr(), args.c_ptr(), k()); + } + return result; + } + + void theory_pb::ineq::reset() { + m_max_watch.reset(); + m_watch_sz = 0; + m_watch_sum.reset(); + m_num_propagations = 0; + m_compilation_threshold = UINT_MAX; + m_compiled = l_false; + m_args[0].reset(); + m_args[0].m_k.reset(); + m_args[1].reset(); + m_args[1].m_k.reset(); + m_nfixed = 0; + m_max_sum.reset(); + m_min_sum.reset(); + } + + + void theory_pb::ineq::unique() { + pb_lit_rewriter_util pbu; + pb_rewriter_util util(pbu); + util.unique(m_args[0], m_args[0].m_k, m_is_eq); + } + + void theory_pb::ineq::post_prune() { + if (!m_args[0].empty() && is_ge()) { + m_args[0].negate(); + m_args[0].negate(); + m_args[1].reset(); + m_args[1].m_k = m_args[0].m_k; + m_args[1].append(m_args[0]); + m_args[1].negate(); + + SASSERT(m_args[0].size() == m_args[1].size()); + SASSERT(m_args[0].well_formed()); + SASSERT(m_args[1].well_formed()); + } + } + + void theory_pb::ineq::negate() { + SASSERT(!m_is_eq); + m_lit.neg(); + } + + void theory_pb::ineq::prune() { + m_args[0].prune(m_is_eq); + } + + lbool theory_pb::ineq::normalize() { + return m_args[0].normalize(m_is_eq); + } + + app_ref theory_pb::ineq::to_expr(context& ctx, ast_manager& m) { + return args().to_expr(m_is_eq, ctx, m); + } + + bool theory_pb::arg_t::well_formed() const { + SASSERT(k().is_pos()); + uint_set vars; + numeral sum = numeral::zero(); + for (unsigned i = 0; i < size(); ++i) { + SASSERT(coeff(i) <= k()); + SASSERT(numeral::one() <= coeff(i)); + SASSERT(lit(i) != true_literal); + SASSERT(lit(i) != false_literal); + SASSERT(lit(i) != null_literal); + SASSERT(!vars.contains(lit(i).var())); + vars.insert(lit(i).var()); + sum += coeff(i); + } + SASSERT(sum >= k()); + return true; + } + + theory_pb::theory_pb(ast_manager& m, theory_pb_params& p): + theory(m.mk_family_id("pb")), + m_params(p), + m_util(m), + m_max_compiled_coeff(rational(8)) + { + m_learn_complements = p.m_pb_learn_complements; + m_conflict_frequency = p.m_pb_conflict_frequency; + m_enable_compilation = p.m_pb_enable_compilation; + m_enable_simplex = p.m_pb_enable_simplex; + } + + theory_pb::~theory_pb() { + reset_eh(); + } + + theory * theory_pb::mk_fresh(context * new_ctx) { + return alloc(theory_pb, new_ctx->get_manager(), m_params); + } + + class theory_pb::remove_var : public trail { + theory_pb& pb; + unsigned v; + public: + remove_var(theory_pb& pb, unsigned v): pb(pb), v(v) {} + virtual void undo(context& ctx) { + pb.m_vars.remove(v); + pb.m_simplex.unset_lower(v); + pb.m_simplex.unset_upper(v); + } + }; + + class theory_pb::undo_bound : public trail { + theory_pb& pb; + unsigned m_v; + bool m_is_lower; + scoped_eps_numeral m_last_bound; + bool m_last_bound_valid; + literal m_last_explain; + + public: + undo_bound(theory_pb& pb, unsigned v, + bool is_lower, + scoped_eps_numeral& last_bound, + bool last_bound_valid, + literal last_explain): + pb(pb), + m_v(v), + m_is_lower(is_lower), + m_last_bound(last_bound), + m_last_bound_valid(last_bound_valid), + m_last_explain(last_explain) {} + + virtual void undo(context& ctx) { + if (m_is_lower) { + if (m_last_bound_valid) { + pb.m_simplex.set_lower(m_v, m_last_bound); + } + else { + pb.m_simplex.unset_lower(m_v); + } + pb.set_explain(pb.m_explain_lower, m_v, m_last_explain); + } + else { + if (m_last_bound_valid) { + pb.m_simplex.set_upper(m_v, m_last_bound); + } + else { + pb.m_simplex.unset_upper(m_v); + } + pb.set_explain(pb.m_explain_upper, m_v, m_last_explain); + } + m_last_bound.reset(); + } + }; + + literal theory_pb::set_explain(literal_vector& explains, unsigned var, literal expl) { + if (var >= explains.size()) { + explains.resize(var+1, null_literal); + } + literal last_explain = explains[var]; + explains[var] = expl; + return last_explain; + } + + bool theory_pb::update_bound(bool_var v, literal explain, bool is_lower, mpq_inf const& bound) { + if (is_lower) { + if (m_simplex.above_lower(v, bound)) { + scoped_eps_numeral last_bound(m_mpq_inf_mgr); + if (m_simplex.upper_valid(v)) { + m_simplex.get_upper(v, last_bound); + if (m_mpq_inf_mgr.gt(bound, last_bound)) { + literal lit = m_explain_upper.get(v, null_literal); + get_context().mk_clause(~lit, ~explain, justify(~lit, ~explain)); + return false; + } + } + bool last_bound_valid = m_simplex.lower_valid(v); + if (last_bound_valid) { + m_simplex.get_lower(v, last_bound); + } + m_simplex.set_lower(v, bound); + literal last_explain = set_explain(m_explain_lower, v, explain); + get_context().push_trail(undo_bound(*this, v, true, last_bound, last_bound_valid, last_explain)); + } + } + else { + if (m_simplex.below_upper(v, bound)) { + scoped_eps_numeral last_bound(m_mpq_inf_mgr); + if (m_simplex.lower_valid(v)) { + m_simplex.get_lower(v, last_bound); + if (m_mpq_inf_mgr.gt(last_bound, bound)) { + literal lit = m_explain_lower.get(v, null_literal); + get_context().mk_clause(~lit, ~explain, justify(~lit, ~explain)); + return false; + } + } + bool last_bound_valid = m_simplex.upper_valid(v); + if (last_bound_valid) { + m_simplex.get_upper(v, last_bound); + } + m_simplex.set_upper(v, bound); + literal last_explain = set_explain(m_explain_upper, v, explain); + get_context().push_trail(undo_bound(*this, v, false, last_bound, last_bound_valid, last_explain)); + } + } + return true; + }; + + bool theory_pb::check_feasible() { + context& ctx = get_context(); + lbool is_sat = m_simplex.make_feasible(); + if (l_false != is_sat) { + return true; + } + + row r = m_simplex.get_infeasible_row(); + // m_simplex.display_row(std::cout, r, true); + mpz const& coeff = m_simplex.get_base_coeff(r); + bool_var base_var = m_simplex.get_base_var(r); + SASSERT(m_simplex.below_lower(base_var) || m_simplex.above_upper(base_var)); + bool cant_increase = m_simplex.below_lower(base_var)?m_mpz_mgr.is_pos(coeff):m_mpz_mgr.is_neg(coeff); + + literal_vector explains; + row_iterator it = m_simplex.row_begin(r), end = m_simplex.row_end(r); + for (; it != end; ++it) { + bool_var v = it->m_var; + if (v == base_var) { + if (m_simplex.below_lower(base_var)) { + explains.push_back(m_explain_lower.get(v, null_literal)); + } + else { + explains.push_back(m_explain_upper.get(v, null_literal)); + } + } + else if (cant_increase == m_mpz_mgr.is_pos(it->m_coeff)) { + explains.push_back(m_explain_lower.get(v, null_literal)); + } + else { + explains.push_back(m_explain_upper.get(v, null_literal)); + } + } + + literal_vector lits; + for (unsigned i = 0; i < explains.size(); ++i) { + literal lit(explains[i]); + if (lit != null_literal) { + lits.push_back(~lit); + } + } + + m_stats.m_num_conflicts++; + justification* js = 0; + if (proofs_enabled()) { + js = alloc(theory_lemma_justification, get_id(), ctx, lits.size(), lits.c_ptr()); + } + ctx.mk_clause(lits.size(), lits.c_ptr(), js, CLS_AUX_LEMMA, 0); + + return false; + } + + bool theory_pb::internalize_atom(app * atom, bool gate_ctx) { + SASSERT(m_util.is_at_most_k(atom) || m_util.is_le(atom) || + m_util.is_ge(atom) || m_util.is_at_least_k(atom) || + m_util.is_eq(atom)); + + context& ctx = get_context(); + if (ctx.b_internalized(atom)) { + return false; + } + + SASSERT(!ctx.b_internalized(atom)); + m_stats.m_num_predicates++; + + unsigned num_args = atom->get_num_args(); + bool_var abv = ctx.mk_bool_var(atom); + ctx.set_var_theory(abv, get_id()); + + ineq* c = alloc(ineq, m_mpz_mgr, literal(abv), m_util.is_eq(atom)); + c->m_args[0].m_k = m_util.get_k(atom); + numeral& k = c->m_args[0].m_k; + arg_t& args = c->m_args[0]; + + // extract literals and coefficients. + for (unsigned i = 0; i < num_args; ++i) { + expr* arg = atom->get_arg(i); + literal l = compile_arg(arg); + numeral c = m_util.get_coeff(atom, i); + args.push_back(std::make_pair(l, c)); + } + if (m_util.is_at_most_k(atom) || m_util.is_le(atom)) { + // turn W <= k into -W >= -k + for (unsigned i = 0; i < args.size(); ++i) { + args[i].second = -args[i].second; + } + k = -k; + } + else { + SASSERT(m_util.is_at_least_k(atom) || m_util.is_ge(atom) || m_util.is_eq(atom)); + } + TRACE("pb", display(tout, *c);); + //app_ref fml1(m), fml2(m); + //fml1 = c->to_expr(ctx, m); + c->unique(); + lbool is_true = c->normalize(); + c->prune(); + c->post_prune(); + //fml2 = c->to_expr(ctx, m); + //expr_ref validate_pb = pb_rewriter(m).mk_validate_rewrite(fml1, fml2); + //pb_rewriter(m).dump_pb_rewrite(validate_pb); + + literal lit(abv); + + + TRACE("pb", display(tout, *c); tout << " := " << lit << "\n";); + switch(is_true) { + case l_false: + lit = ~lit; + // fall-through + case l_true: + ctx.mk_th_axiom(get_id(), 1, &lit); + dealloc(c); + return true; + case l_undef: + break; + } + + if (c->k().is_one() && c->is_ge() && !m_enable_simplex) { + literal_vector& lits = get_lits(); + lits.push_back(~lit); + for (unsigned i = 0; i < c->size(); ++i) { + lits.push_back(c->lit(i)); + SASSERT(c->coeff(i).is_one()); + ctx.mk_th_axiom(get_id(), lit, ~c->lit(i)); + } + ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr()); + return true; + } + + // maximal coefficient: + scoped_mpz& max_watch = c->m_max_watch; + max_watch.reset(); + for (unsigned i = 0; i < args.size(); ++i) { + mpz const& num = args[i].second.to_mpq().numerator(); + if (m_mpz_mgr.lt(max_watch, num)) { + max_watch = num; + } + } + + // pre-compile threshold for cardinality + bool enable_compile = m_enable_compilation && c->is_ge() && !c->k().is_one(); + for (unsigned i = 0; enable_compile && i < args.size(); ++i) { + enable_compile = (args[i].second <= m_max_compiled_coeff); + } + if (enable_compile) { + unsigned log = 1, n = 1; + while (n <= args.size()) { + ++log; + n *= 2; + } + unsigned th = args.size()*log; // 10* + c->m_compilation_threshold = th; + IF_VERBOSE(2, verbose_stream() << "(smt.pb setting compilation threhshold to " << th << ")\n";); + TRACE("pb", tout << "compilation threshold: " << th << "\n";); + } + else { + c->m_compilation_threshold = UINT_MAX; + } + init_watch_var(*c); + m_ineqs.insert(abv, c); + m_ineqs_trail.push_back(abv); + + if (m_enable_simplex) { + // + // TBD: using abv as slack identity doesn't quite + // work if psuedo-Booleans are used + // in a nested way. So assume + // + + arg_t rep(c->args()); + rep.remove_negations(); // normalize representative + numeral k = rep.k(); + theory_var slack; + bool_var abv2; + TRACE("pb", display(tout << abv <<"\n", rep);); + if (m_ineq_rep.find(rep, abv2)) { + slack = abv2; + TRACE("pb", + tout << "Old row: " << abv << " |-> " << slack << " "; + tout << m_ineq_row_info.find(abv2).m_bound << " vs. " << k << "\n"; + display(tout, rep);); + } + else { + m_ineq_rep.insert(rep, abv); + svector vars; + scoped_mpz_vector coeffs(m_mpz_mgr); + for (unsigned i = 0; i < rep.size(); ++i) { + unsigned v = rep.lit(i).var(); + m_simplex.ensure_var(v); + vars.push_back(v); + if (!m_vars.contains(v)) { + mpq_inf zero(mpq(0),mpq(0)), one(mpq(1),mpq(0)); + switch(ctx.get_assignment(rep.lit(i))) { + case l_true: + VERIFY(update_bound(v, literal(v), true, one)); + m_simplex.set_lower(v, one); + break; + case l_false: + VERIFY(update_bound(v, ~literal(v), false, zero)); + m_simplex.set_upper(v, zero); + break; + default: + m_simplex.set_lower(v, zero); + m_simplex.set_upper(v, one); + break; + } + m_vars.insert(v); + ctx.push_trail(remove_var(*this, v)); + } + coeffs.push_back(rep.coeff(i).to_mpq().numerator()); + } + slack = abv; + m_simplex.ensure_var(slack); + vars.push_back(slack); + coeffs.push_back(mpz(-1)); + m_simplex.add_row(slack, vars.size(), vars.c_ptr(), coeffs.c_ptr()); + TRACE("pb", tout << "New row: " << abv << " " << k << "\n"; display(tout, rep);); + } + m_ineq_row_info.insert(abv, row_info(slack, k, rep)); + } + + TRACE("pb", display(tout, *c);); + + return true; + } + + literal theory_pb::compile_arg(expr* arg) { + context& ctx = get_context(); + ast_manager& m = get_manager(); + + bool_var bv; + bool has_bv = false; + bool negate = m.is_not(arg, arg); + SASSERT(!m.is_not(arg)); + if (!ctx.b_internalized(arg)) { + ctx.internalize(arg, false); + } + if (ctx.b_internalized(arg)) { + bv = ctx.get_bool_var(arg); + if (is_uninterp(arg) && null_theory_var == ctx.get_var_theory(bv)) { + ctx.set_var_theory(bv, get_id()); + } + has_bv = (ctx.get_var_theory(bv) == get_id()); + } + else if (m.is_true(arg)) { + bv = true_bool_var; + has_bv = true; + } + else if (m.is_false(arg)) { + bv = true_bool_var; + has_bv = true; + negate = !negate; + } + + // assumes relevancy level = 2 or 0. + // TBD: should should have been like an uninterpreted + // function internalize, where enodes for each argument + // is available. + if (!has_bv) { + expr_ref tmp(m), fml(m); + tmp = m.mk_fresh_const("pb_proxy",m.mk_bool_sort()); + fml = m.mk_iff(tmp, arg); + TRACE("pb", tout << "create proxy " << fml << "\n";); + ctx.internalize(fml, false); + SASSERT(ctx.b_internalized(tmp)); + bv = ctx.get_bool_var(tmp); + SASSERT(null_theory_var == ctx.get_var_theory(bv)); + ctx.set_var_theory(bv, get_id()); + literal lit(ctx.get_bool_var(fml)); + ctx.mk_th_axiom(get_id(), 1, &lit); + ctx.mark_as_relevant(tmp.get()); + } + return negate?~literal(bv):literal(bv); + } + + void theory_pb::del_watch(watch_list& watch, unsigned index, ineq& c, unsigned ineq_index) { + SASSERT(c.is_ge()); + if (index < watch.size()) { + std::swap(watch[index], watch[watch.size()-1]); + } + watch.pop_back(); + + SASSERT(ineq_index < c.watch_size()); + scoped_mpz coeff(m_mpz_mgr); + coeff = c.ncoeff(ineq_index); + if (ineq_index + 1 < c.watch_size()) { + std::swap(c.args()[ineq_index], c.args()[c.watch_size()-1]); + } + --c.m_watch_sz; + c.m_watch_sum -= coeff; + if (coeff == c.max_watch()) { + coeff = c.ncoeff(0); + for (unsigned i = 1; coeff != c.max_watch() && i < c.watch_size(); ++i) { + if (coeff < c.ncoeff(i)) coeff = c.ncoeff(i); + } + c.set_max_watch(coeff); + } + + // current index of unwatched literal is c.watch_size(). + } + + void theory_pb::add_watch(ineq& c, unsigned i) { + SASSERT(c.is_ge()); + literal lit = c.lit(i); + scoped_mpz coeff(m_mpz_mgr); + coeff = c.ncoeff(i); + c.m_watch_sum += coeff; + SASSERT(i >= c.watch_size()); + + if (i > c.watch_size()) { + std::swap(c.args()[i], c.args()[c.watch_size()]); + } + ++c.m_watch_sz; + if (coeff > c.max_watch()) { + c.set_max_watch(coeff); + } + watch_literal(lit, &c); + } + + void theory_pb::watch_literal(literal lit, ineq* c) { + ptr_vector* ineqs; + if (!m_lwatch.find(lit.index(), ineqs)) { + ineqs = alloc(ptr_vector); + m_lwatch.insert(lit.index(), ineqs); + } + ineqs->push_back(c); + } + + void theory_pb::watch_var(bool_var v, ineq* c) { + ptr_vector* ineqs; + if (!m_vwatch.find(v, ineqs)) { + ineqs = alloc(ptr_vector); + m_vwatch.insert(v, ineqs); + } + ineqs->push_back(c); + } + + void theory_pb::unwatch_var(bool_var v, ineq* c) { + ptr_vector* ineqs = 0; + if (m_vwatch.find(v, ineqs)) { + remove(*ineqs, c); + } + } + + void theory_pb::unwatch_literal(literal w, ineq* c) { + ptr_vector* ineqs = 0; + if (m_lwatch.find(w.index(), ineqs)) { + remove(*ineqs, c); + } + } + + void theory_pb::remove(ptr_vector& ineqs, ineq* c) { + for (unsigned j = 0; j < ineqs.size(); ++j) { + if (ineqs[j] == c) { + std::swap(ineqs[j], ineqs[ineqs.size()-1]); + ineqs.pop_back(); + break; + } + } + } + + void theory_pb::collect_statistics(::statistics& st) const { + st.update("pb conflicts", m_stats.m_num_conflicts); + st.update("pb propagations", m_stats.m_num_propagations); + st.update("pb predicates", m_stats.m_num_predicates); + st.update("pb compilations", m_stats.m_num_compiles); + st.update("pb compiled clauses", m_stats.m_num_compiled_clauses); + st.update("pb compiled vars", m_stats.m_num_compiled_vars); + m_simplex.collect_statistics(st); + } + + void theory_pb::reset_eh() { + + // m_watch; + u_map*>::iterator it = m_lwatch.begin(), end = m_lwatch.end(); + for (; it != end; ++it) { + dealloc(it->m_value); + } + it = m_vwatch.begin(), end = m_vwatch.end(); + for (; it != end; ++it) { + dealloc(it->m_value); + } + u_map::iterator itc = m_ineqs.begin(), endc = m_ineqs.end(); + for (; itc != endc; ++itc) { + dealloc(itc->m_value); + } + m_lwatch.reset(); + m_vwatch.reset(); + m_ineqs.reset(); + m_ineqs_trail.reset(); + m_ineqs_lim.reset(); + m_stats.reset(); + m_to_compile.reset(); + } + + void theory_pb::new_eq_eh(theory_var v1, theory_var v2) { + UNREACHABLE(); + } + + final_check_status theory_pb::final_check_eh() { + TRACE("pb", display(tout);); + DEBUG_CODE(validate_final_check();); + return FC_DONE; + } + + void theory_pb::assign_eh(bool_var v, bool is_true) { + ptr_vector* ineqs = 0; + literal nlit(v, is_true); + TRACE("pb", tout << "assign: " << ~nlit << "\n";); + if (m_lwatch.find(nlit.index(), ineqs)) { + if (m_enable_simplex) { + mpq_inf num(mpq(is_true?1:0),mpq(0)); + if (!update_bound(v, ~nlit, is_true, num)) { + return; + } + + if (!check_feasible()) { + return; + } + } + + for (unsigned i = 0; i < ineqs->size(); ++i) { + ineq* c = (*ineqs)[i]; + SASSERT(c->is_ge()); + if (assign_watch_ge(v, is_true, *ineqs, i)) { + // i was removed from watch list. + --i; + } + } + } + if (m_vwatch.find(v, ineqs)) { + for (unsigned i = 0; i < ineqs->size(); ++i) { + ineq* c = (*ineqs)[i]; + assign_watch(v, is_true, *c); + } + } + ineq* c = 0; + if (m_ineqs.find(v, c)) { + if (m_enable_simplex) { + row_info const& info = m_ineq_row_info.find(v); + scoped_eps_numeral coeff(m_mpq_inf_mgr); + coeff = std::make_pair(info.m_bound.to_mpq(), mpq(0)); + unsigned slack = info.m_slack; + if (is_true) { + update_bound(slack, literal(v), true, coeff); + if (c->is_eq()) { + update_bound(slack, literal(v), false, coeff); + } + } + else if (c->is_ge()) { + m_mpq_inf_mgr.sub(coeff, std::make_pair(mpq(1),mpq(0)), coeff); + update_bound(slack, ~literal(v), false, coeff); + } + + if (!check_feasible()) { + return; + } + } + if (c->is_ge()) { + assign_ineq(*c, is_true); + } + else { + assign_eq(*c, is_true); + } + } + } + + literal_vector& theory_pb::get_all_literals(ineq& c, bool negate) { + context& ctx = get_context(); + literal_vector& lits = get_lits(); + for (unsigned i = 0; i < c.size(); ++i) { + literal l = c.lit(i); + switch(ctx.get_assignment(l)) { + case l_true: + lits.push_back(negate?(~l):l); + break; + case l_false: + lits.push_back(negate?l:(~l)); + break; + default: + break; + } + } + return lits; + + } + + literal_vector& theory_pb::get_helpful_literals(ineq& c, bool negate) { + scoped_mpz sum(m_mpz_mgr); + mpz const& k = c.mpz_k(); + context& ctx = get_context(); + literal_vector& lits = get_lits(); + for (unsigned i = 0; sum < k && i < c.size(); ++i) { + literal l = c.lit(i); + if (ctx.get_assignment(l) == l_true) { + sum += c.ncoeff(i); + if (negate) l = ~l; + lits.push_back(l); + } + } + SASSERT(sum >= k); + return lits; + } + + literal_vector& theory_pb::get_unhelpful_literals(ineq& c, bool negate) { + context& ctx = get_context(); + literal_vector& lits = get_lits(); + for (unsigned i = 0; i < c.size(); ++i) { + literal l = c.lit(i); + if (ctx.get_assignment(l) == l_false) { + if (negate) l = ~l; + lits.push_back(l); + } + } + return lits; + } + + class theory_pb::rewatch_vars : public trail { + theory_pb& pb; + ineq& c; + public: + rewatch_vars(theory_pb& p, ineq& c): pb(p), c(c) {} + virtual void undo(context& ctx) { + for (unsigned i = 0; i < c.size(); ++i) { + pb.watch_var(c.lit(i).var(), &c); + } + } + }; + + class theory_pb::negate_ineq : public trail { + ineq& c; + public: + negate_ineq(ineq& c): c(c) {} + virtual void undo(context& ctx) { + c.negate(); + } + }; + + /** + \brief propagate assignment to inequality. + This is a basic, non-optimized implementation based + on the assumption that inequalities are mostly units + and/or relatively few compared to number of argumets. + */ + void theory_pb::assign_ineq(ineq& c, bool is_true) { + context& ctx = get_context(); + ctx.push_trail(value_trail(c.m_max_sum)); + ctx.push_trail(value_trail(c.m_min_sum)); + ctx.push_trail(value_trail(c.m_nfixed)); + ctx.push_trail(rewatch_vars(*this, c)); + + clear_watch(c); + SASSERT(c.is_ge()); + unsigned sz = c.size(); + if (c.lit().sign() == is_true) { + c.negate(); + ctx.push_trail(negate_ineq(c)); + } + + scoped_mpz maxsum(m_mpz_mgr), mininc(m_mpz_mgr); + for (unsigned i = 0; i < sz; ++i) { + lbool asgn = ctx.get_assignment(c.lit(i)); + if (asgn != l_false) { + maxsum += c.ncoeff(i); + } + if (asgn == l_undef && (mininc.is_zero() || mininc > c.ncoeff(i))) { + mininc = c.ncoeff(i); + } + } + + TRACE("pb", + tout << "assign: " << c.lit() << "\n"; + display(tout, c); ); + + if (maxsum < c.mpz_k()) { + literal_vector& lits = get_unhelpful_literals(c, false); + lits.push_back(~c.lit()); + add_clause(c, lits); + } + else { + init_watch_literal(c); + SASSERT(c.m_watch_sum >= c.mpz_k()); + DEBUG_CODE(validate_watch(c);); + } + + // perform unit propagation + if (maxsum >= c.mpz_k() && maxsum - mininc < c.mpz_k()) { + literal_vector& lits = get_unhelpful_literals(c, true); + lits.push_back(c.lit()); + for (unsigned i = 0; i < sz; ++i) { + if (ctx.get_assignment(c.lit(i)) == l_undef) { + DEBUG_CODE(validate_assign(c, lits, c.lit(i));); + add_assign(c, lits, c.lit(i)); + } + } + } + } + + /** + \brief propagate assignment to equality. + */ + void theory_pb::assign_eq(ineq& c, bool is_true) { + SASSERT(c.is_eq()); + + } + + /** + Propagation rules: + + nfixed = N & minsum = k -> T + nfixed = N & minsum != k -> F + + minsum > k or maxsum < k -> F + minsum = k & = -> fix 0 variables + nfixed+1 = N & = -> fix unassigned variable or conflict + nfixed+1 = N & != -> maybe forced unassigned to ensure disequal + minsum >= k -> T + maxsum < k -> F + */ + + void theory_pb::assign_watch(bool_var v, bool is_true, ineq& c) { + + context& ctx = get_context(); + unsigned i; + literal l = c.lit(); + lbool asgn = ctx.get_assignment(l); + + if (c.max_sum() < c.mpz_k() && asgn == l_false) { + return; + } + if (c.is_ge() && c.min_sum() >= c.mpz_k() && asgn == l_true) { + return; + } + for (i = 0; i < c.size(); ++i) { + if (c.lit(i).var() == v) { + break; + } + } + + TRACE("pb", display(tout << "assign watch " << literal(v,!is_true) << " ", c, true);); + + SASSERT(i < c.size()); + if (c.lit(i).sign() == is_true) { + ctx.push_trail(value_trail(c.m_max_sum)); + c.m_max_sum -= c.ncoeff(i); + } + else { + ctx.push_trail(value_trail(c.m_min_sum)); + c.m_min_sum += c.ncoeff(i); + } + DEBUG_CODE( + scoped_mpz sum(m_mpz_mgr); + scoped_mpz maxs(m_mpz_mgr); + for (unsigned i = 0; i < c.size(); ++i) { + if (ctx.get_assignment(c.lit(i)) == l_true) sum += c.ncoeff(i); + if (ctx.get_assignment(c.lit(i)) != l_false) maxs += c.ncoeff(i); + } + CTRACE("pb", (maxs > c.max_sum()), display(tout, c, true);); + SASSERT(c.min_sum() <= sum); + SASSERT(sum <= maxs); + SASSERT(maxs <= c.max_sum()); + ); + SASSERT(c.min_sum() <= c.max_sum()); + SASSERT(!m_mpz_mgr.is_neg(c.min_sum())); + ctx.push_trail(value_trail(c.m_nfixed)); + ++c.m_nfixed; + SASSERT(c.nfixed() <= c.size()); + if (c.is_ge() && c.min_sum() >= c.mpz_k() && asgn != l_true) { + TRACE("pb", display(tout << "Set " << l << "\n", c, true);); + add_assign(c, get_helpful_literals(c, false), l); + } + else if (c.max_sum() < c.mpz_k() && asgn != l_false) { + TRACE("pb", display(tout << "Set " << ~l << "\n", c, true);); + add_assign(c, get_unhelpful_literals(c, true), ~l); + } + else if (c.is_eq() && c.nfixed() == c.size() && c.min_sum() == c.mpz_k() && asgn != l_true) { + TRACE("pb", display(tout << "Set " << l << "\n", c, true);); + add_assign(c, get_all_literals(c, false), l); + } + else if (c.is_eq() && c.nfixed() == c.size() && c.min_sum() != c.mpz_k() && asgn != l_false) { + TRACE("pb", display(tout << "Set " << ~l << "\n", c, true);); + add_assign(c, get_all_literals(c, false), ~l); + } +#if 0 + else if (c.is_eq() && c.min_sum() > c.mpz_k() && asgn != l_false) { + TRACE("pb", display(tout << "Set " << ~l << "\n", c, true);); + add_assign(c, get_all_literals(c, false), ~l); + } + else if (c.is_eq() && asgn == l_true && c.min_sum() == c.mpz_k() && c.max_sum() > c.mpz_k()) { + literal_vector& lits = get_all_literals(c, false); + lits.push_back(c.lit()); + for (unsigned i = 0; i < c.size(); ++i) { + if (ctx.get_assignment(c.lit(i)) == l_undef) { + add_assign(c, lits, ~c.lit(i)); + } + } + } +#endif + else { + IF_VERBOSE(3, display(verbose_stream() << "no propagation ", c, true);); + } + } + + + /** + \brief v is assigned in inequality c. Update current bounds and watch list. + Optimize for case where the c.lit() is True. This covers the case where + inequalities are unit literals and formulas in negation normal form + (inequalities are closed under negation). + */ + bool theory_pb::assign_watch_ge(bool_var v, bool is_true, watch_list& watch, unsigned watch_index) { + bool removed = false; + context& ctx = get_context(); + ineq& c = *watch[watch_index]; + //display(std::cout << v << " ", c, true); + unsigned w = c.find_lit(v, 0, c.watch_size()); + SASSERT(ctx.get_assignment(c.lit()) == l_true); + SASSERT(is_true == c.lit(w).sign()); + + // + // watch_sum is decreased. + // Adjust set of watched literals. + // + + scoped_mpz k_coeff(m_mpz_mgr), k(m_mpz_mgr); + k = c.mpz_k(); + k_coeff = k; + k_coeff += c.ncoeff(w); + bool add_more = c.watch_sum() < k_coeff + c.max_watch(); + for (unsigned i = c.watch_size(); add_more && i < c.size(); ++i) { + if (ctx.get_assignment(c.lit(i)) != l_false) { + add_watch(c, i); + add_more = c.watch_sum() < k_coeff + c.max_watch(); + } + } + + if (c.watch_sum() < k_coeff) { + // + // L: 3*x1 + 2*x2 + x4 >= 3, but x1 <- 0, x2 <- 0 + // create clause x1 or x2 or ~L + // + literal_vector& lits = get_unhelpful_literals(c, false); + lits.push_back(~c.lit()); + add_clause(c, lits); + } + else { + del_watch(watch, watch_index, c, w); + removed = true; + SASSERT(c.watch_sum() >= k); + if (c.watch_sum() < k + c.max_watch()) { + + // + // opportunities for unit propagation for unassigned + // literals whose coefficients satisfy + // c.watch_sum() < k + // + // L: 3*x1 + 2*x2 + x4 >= 3, but x1 <- 0 + // Create clauses x1 or ~L or x2 + // x1 or ~L or x4 + // + + literal_vector& lits = get_unhelpful_literals(c, true); + lits.push_back(c.lit()); + scoped_mpz deficit(m_mpz_mgr); + deficit = c.watch_sum() - k; + for (unsigned i = 0; i < c.size(); ++i) { + if (ctx.get_assignment(c.lit(i)) == l_undef && deficit < c.ncoeff(i)) { + DEBUG_CODE(validate_assign(c, lits, c.lit(i));); + add_assign(c, lits, c.lit(i)); + // break; + } + } + } + // + // else: c.watch_sum() >= k + c.max_watch() + // + } + + TRACE("pb", + tout << "assign: " << literal(v,!is_true) << "\n"; + display(tout, c); ); + + + return removed; + } + + struct theory_pb::psort_expr { + context& ctx; + ast_manager& m; + theory_pb& th; + typedef smt::literal literal; + typedef smt::literal_vector literal_vector; + + psort_expr(context& c, theory_pb& th): + ctx(c), + m(c.get_manager()), + th(th) {} + + literal fresh() { + app_ref y(m); + y = m.mk_fresh_const("y", m.mk_bool_sort()); + return literal(ctx.mk_bool_var(y)); + } + + literal mk_max(literal a, literal b) { + if (a == b) return a; + expr_ref t1(m), t2(m), t3(m); + ctx.literal2expr(a, t1); + ctx.literal2expr(b, t2); + t3 = m.mk_or(t1, t2); + bool_var v = ctx.b_internalized(t3)?ctx.get_bool_var(t3):ctx.mk_bool_var(t3); + return literal(v); + } + + literal mk_min(literal a, literal b) { + if (a == b) return a; + expr_ref t1(m), t2(m), t3(m); + ctx.literal2expr(a, t1); + ctx.literal2expr(b, t2); + t3 = m.mk_and(t1, t2); + bool_var v = ctx.b_internalized(t3)?ctx.get_bool_var(t3):ctx.mk_bool_var(t3); + return literal(v); + } + + literal mk_not(literal a) { return ~a; } + + void mk_clause(unsigned n, literal const* ls) { + literal_vector tmp(n, ls); + ctx.mk_clause(n, tmp.c_ptr(), th.justify(tmp), CLS_AUX, 0); + } + + literal mk_false() { return false_literal; } + literal mk_true() { return true_literal; } + + std::ostream& pp(std::ostream& out, literal l) { return out << l; } + + }; + + // for testing + literal theory_pb::assert_ge(context& ctx, unsigned k, unsigned n, literal const* xs) { + theory_pb_params p; + theory_pb th(ctx.get_manager(), p); + psort_expr ps(ctx, th); + psort_nw sort(ps); + return sort.ge(false, k, n, xs); + } + + + void theory_pb::inc_propagations(ineq& c) { + ++c.m_num_propagations; + if (c.m_compiled == l_false && c.m_num_propagations > c.m_compilation_threshold) { + c.m_compiled = l_undef; + m_to_compile.push_back(&c); + } + } + + void theory_pb::restart_eh() { + for (unsigned i = 0; i < m_to_compile.size(); ++i) { + compile_ineq(*m_to_compile[i]); + } + m_to_compile.reset(); + } + + + void theory_pb::compile_ineq(ineq& c) { + ++m_stats.m_num_compiles; + context& ctx = get_context(); + // only cardinality constraints are compiled. + SASSERT(c.m_compilation_threshold < UINT_MAX); + DEBUG_CODE(for (unsigned i = 0; i < c.size(); ++i) SASSERT(c.coeff(i).is_int()); ); + unsigned k = c.k().get_unsigned(); + unsigned num_args = c.size(); + + + literal thl = c.lit(); + literal at_least_k; + + literal_vector in; + for (unsigned i = 0; i < num_args; ++i) { + rational n = c.coeff(i); + lbool val = ctx.get_assignment(c.lit()); + if (val != l_undef && + ctx.get_assign_level(thl) == ctx.get_base_level()) { + if (val == l_true) { + unsigned m = n.get_unsigned(); + if (k < m) { + return; + } + k -= m; + } + continue; + } + while (n.is_pos()) { + in.push_back(c.lit(i)); + n -= rational::one(); + } + } + if (ctx.get_assignment(thl) == l_true && + ctx.get_assign_level(thl) == ctx.get_base_level()) { + psort_expr ps(ctx, *this); + psort_nw sortnw(ps); + sortnw.m_stats.reset(); + at_least_k = sortnw.ge(false, k, in.size(), in.c_ptr()); + ctx.mk_clause(~thl, at_least_k, justify(~thl, at_least_k)); + m_stats.m_num_compiled_vars += sortnw.m_stats.m_num_compiled_vars; + m_stats.m_num_compiled_clauses += sortnw.m_stats.m_num_compiled_clauses; + } + else { + psort_expr ps(ctx, *this); + psort_nw sortnw(ps); + sortnw.m_stats.reset(); + literal at_least_k = sortnw.ge(true, k, in.size(), in.c_ptr()); + ctx.mk_clause(~thl, at_least_k, justify(~thl, at_least_k)); + ctx.mk_clause(~at_least_k, thl, justify(thl, ~at_least_k)); + m_stats.m_num_compiled_vars += sortnw.m_stats.m_num_compiled_vars; + m_stats.m_num_compiled_clauses += sortnw.m_stats.m_num_compiled_clauses; + } + IF_VERBOSE(1, verbose_stream() + << "(smt.pb compile sorting network bound: " + << k << " literals: " << in.size() << ")\n";); + + TRACE("pb", tout << thl << "\n";); + // auxiliary clauses get removed when popping scopes. + // we have to recompile the circuit after back-tracking. + c.m_compiled = l_false; + ctx.push_trail(value_trail(c.m_compiled)); + c.m_compiled = l_true; + } + + + void theory_pb::init_search_eh() { + m_to_compile.reset(); + } + + void theory_pb::push_scope_eh() { + m_ineqs_lim.push_back(m_ineqs_trail.size()); + } + + void theory_pb::pop_scope_eh(unsigned num_scopes) { + + // remove inequalities. + unsigned new_lim = m_ineqs_lim.size()-num_scopes; + unsigned sz = m_ineqs_lim[new_lim]; + while (m_ineqs_trail.size() > sz) { + bool_var v = m_ineqs_trail.back(); + ineq* c = 0; + VERIFY(m_ineqs.find(v, c)); + clear_watch(*c); + m_ineqs.remove(v); + m_ineqs_trail.pop_back(); + if (m_enable_simplex) { + row_info r_info; + VERIFY(m_ineq_row_info.find(v, r_info)); + m_ineq_row_info.erase(v); + bool_var v2 = m_ineq_rep.find(r_info.m_rep); + if (v == v2) { + m_simplex.del_row(r_info.m_slack); + m_ineq_rep.erase(r_info.m_rep); + } + } + dealloc(c); + } + m_ineqs_lim.resize(new_lim); + } + + void theory_pb::clear_watch(ineq& c) { + for (unsigned i = 0; i < c.size(); ++i) { + literal w = c.lit(i); + unwatch_var(w.var(), &c); + unwatch_literal(w, &c); + } + c.m_watch_sum.reset(); + c.m_watch_sz = 0; + c.m_max_watch.reset(); + c.m_nfixed = 0; + c.m_max_sum.reset(); + c.m_min_sum.reset(); + } + + class theory_pb::unwatch_ge : public trail { + theory_pb& pb; + ineq& c; + public: + unwatch_ge(theory_pb& p, ineq& c): pb(p), c(c) {} + + virtual void undo(context& ctx) { + for (unsigned i = 0; i < c.watch_size(); ++i) { + pb.unwatch_literal(c.lit(i), &c); + } + c.m_watch_sz = 0; + c.m_watch_sum.reset(); + c.m_max_watch.reset(); + } + }; + + + void theory_pb::init_watch_literal(ineq& c) { + context& ctx = get_context(); + scoped_mpz max_k(m_mpz_mgr); + c.m_watch_sum.reset(); + c.m_watch_sz = 0; + c.m_max_watch.reset(); + bool watch_more = true; + for (unsigned i = 0; watch_more && i < c.size(); ++i) { + if (ctx.get_assignment(c.lit(i)) != l_false) { + add_watch(c, i); + max_k = c.mpz_k(); + max_k += c.max_watch(); + watch_more = c.m_watch_sum < max_k; + } + } + ctx.push_trail(unwatch_ge(*this, c)); + } + + void theory_pb::init_watch_var(ineq& c) { + c.m_min_sum.reset(); + c.m_max_sum.reset(); + c.m_nfixed = 0; + c.m_watch_sum.reset(); + c.m_max_watch.reset(); + c.m_watch_sz = 0; + for (unsigned i = 0; i < c.size(); ++i) { + watch_var(c.lit(i).var(), &c); + c.m_max_sum += c.ncoeff(i); + } + } + + literal_vector& theory_pb::get_lits() { + m_literals.reset(); + return m_literals; + } + + class theory_pb::pb_justification : public theory_propagation_justification { + ineq& m_ineq; + public: + pb_justification(ineq& c, family_id fid, region & r, + unsigned num_lits, literal const * lits, literal consequent): + theory_propagation_justification(fid, r, num_lits, lits, consequent), + m_ineq(c) + {} + ineq& get_ineq() { return m_ineq; } + }; + + void theory_pb::add_assign(ineq& c, literal_vector const& lits, literal l) { + inc_propagations(c); + m_stats.m_num_propagations++; + context& ctx = get_context(); + TRACE("pb", tout << "#prop:" << c.m_num_propagations << " - "; + for (unsigned i = 0; i < lits.size(); ++i) { + tout << lits[i] << " "; + } + tout << "=> " << l << "\n"; + display(tout, c, true);); + + ctx.assign(l, ctx.mk_justification( + pb_justification( + c, get_id(), ctx.get_region(), lits.size(), lits.c_ptr(), l))); + } + + + + void theory_pb::add_clause(ineq& c, literal_vector const& lits) { + inc_propagations(c); + m_stats.m_num_conflicts++; + context& ctx = get_context(); +#if 0 + if (m_stats.m_num_conflicts == 1000) { + display(std::cout); + } +#endif + TRACE("pb", tout << "#prop:" << c.m_num_propagations << " - "; + for (unsigned i = 0; i < lits.size(); ++i) { + tout << lits[i] << " "; + } + tout << "\n"; + display(tout, c, true);); + + justification* js = 0; + + if (m_conflict_frequency == 0 || (m_conflict_frequency -1 == (c.m_num_propagations % m_conflict_frequency))) { + resolve_conflict(c); + } + if (proofs_enabled()) { + js = alloc(theory_lemma_justification, get_id(), ctx, lits.size(), lits.c_ptr()); + } + ctx.mk_clause(lits.size(), lits.c_ptr(), js, CLS_AUX_LEMMA, 0); + } + + + void theory_pb::set_mark(bool_var v, unsigned idx) { + SASSERT(v != null_bool_var); + if (v >= static_cast(m_conseq_index.size())) { + m_conseq_index.resize(v+1, null_index); + } + SASSERT(!is_marked(v) || m_conseq_index[v] == idx); + m_marked.push_back(v); + m_conseq_index[v] = idx; + } + + bool theory_pb::is_marked(bool_var v) const { + return + (v < static_cast(m_conseq_index.size())) && + (m_conseq_index[v] != null_index); + } + + void theory_pb::unset_mark(bool_var v) { + SASSERT(v != null_bool_var); + if (v < static_cast(m_conseq_index.size())) { + m_conseq_index[v] = null_index; + } + } + + void theory_pb::unset_marks() { + for (unsigned i = 0; i < m_marked.size(); ++i) { + unset_mark(m_marked[i]); + } + m_marked.reset(); + } + + void theory_pb::process_antecedent(literal l, numeral coeff) { + context& ctx = get_context(); + bool_var v = l.var(); + unsigned lvl = ctx.get_assign_level(v); + + if (ctx.get_assignment(l) != l_false) { + m_lemma.m_k -= coeff; + if (m_learn_complements && is_marked(v)) { + SASSERT(ctx.get_assignment(l) == l_true); + numeral& lcoeff = m_lemma[m_conseq_index[v]].second; + lcoeff -= coeff; + if (!lcoeff.is_pos()) { + // perhaps let lemma simplification change coefficient + // when negative? + remove_from_lemma(m_conseq_index[v]); + } + } + } + else if (lvl > ctx.get_base_level()) { + if (is_marked(v)) { + m_lemma[m_conseq_index[v]].second += coeff; + SASSERT(m_lemma[m_conseq_index[v]].second.is_pos()); + } + else { + if (lvl == m_conflict_lvl) { + TRACE("pb", tout << "add mark: " << l << " " << coeff << "\n";); + ++m_num_marks; + } + set_mark(v, m_lemma.size()); + m_lemma.push_back(std::make_pair(l, coeff)); + } + TRACE("pb_verbose", tout + << "ante: " << m_lemma.lit(m_conseq_index[v]) << "*" + << m_lemma.coeff(m_conseq_index[v]) << " " << lvl << "\n";); + } + } + + void theory_pb::process_ineq(ineq& c, literal conseq, numeral coeff1) { + + // + // Create CUT. + // + + // + // . find coeff2 + // . find lcm of coefficients to conseq. + // . multiply m_lemma by lcm/coeff coefficient to align. + // . create lcm/coeff_2 to multiply on this side. + // . cut resolve constraints. + // + + context& ctx = get_context(); + numeral coeff2 = (conseq==null_literal)?numeral::one():numeral::zero(); + for (unsigned i = 0; i < c.size(); ++i) { + if (c.lit(i) == conseq) { + coeff2 = c.coeff(i); + break; + } + } + SASSERT(coeff2.is_pos()); + numeral lc = lcm(coeff1, coeff2); + numeral g = lc/coeff1; + SASSERT(g.is_int()); + if (g > numeral::one()) { + for (unsigned i = 0; i < m_lemma.size(); ++i) { + m_lemma[i].second *= g; + } + m_lemma.m_k *= g; + } + g = lc/coeff2; + SASSERT(g.is_int()); + m_lemma.m_k += g*c.k(); + + for (unsigned i = 0; i < c.size(); ++i) { + process_antecedent(c.lit(i), g*c.coeff(i)); + } + + SASSERT(ctx.get_assignment(c.lit()) == l_true); + if (ctx.get_assign_level(c.lit()) > ctx.get_base_level()) { + m_ineq_literals.push_back(c.lit()); + } + } + + // + // modeled after sat_solver/smt_context + // + bool theory_pb::resolve_conflict(ineq& c) { + + if (!c.is_ge()) { + return false; + } + TRACE("pb", display(tout, c, true);); + + bool_var v; + literal conseq; + context& ctx = get_context(); + unsigned& lvl = m_conflict_lvl = 0; + for (unsigned i = 0; i < c.size(); ++i) { + if (ctx.get_assignment(c.lit(i)) == l_false) { + lvl = std::max(lvl, ctx.get_assign_level(c.lit(i))); + } + } + if (lvl < ctx.get_assign_level(c.lit()) || lvl == ctx.get_base_level()) { + return false; + } + + unset_marks(); + m_num_marks = 0; + m_lemma.reset(); + m_lemma.m_k.reset(); + m_ineq_literals.reset(); + process_ineq(c, null_literal, numeral::one()); // add consequent to lemma. + + // point into stack of assigned literals + literal_vector const& lits = ctx.assigned_literals(); + SASSERT(!lits.empty()); + unsigned idx = lits.size()-1; + + while (m_num_marks > 0) { + + TRACE("pb_verbose", display(tout << "lemma ", m_lemma);); + + lbool is_sat = m_lemma.normalize(false); + if (is_sat == l_false) { + break; + } + if (is_sat == l_true) { + IF_VERBOSE(0, verbose_stream() << "lemma already evaluated\n";); + TRACE("pb", tout << "lemma already evaluated\n";); + return false; + } + TRACE("pb", display(tout, m_lemma);); + SASSERT(m_lemma.well_formed()); + + // + // find the next marked variable in the assignment stack + // + do { + conseq = lits[idx]; + v = conseq.var(); + --idx; + } + while (!is_marked(v) && idx > 0); + if (idx == 0 && !is_marked(v)) { + // + // Yes, this can (currently) happen because + // the decisions for performing unit propagation + // are made asynchronously. + // In other words, PB unit propagation does not follow the + // same order as the assignment stack. + // It is not a correctness bug but causes to miss lemmas. + // + IF_VERBOSE(2, display_resolved_lemma(verbose_stream());); + TRACE("pb", display_resolved_lemma(tout);); + return false; + } + + unsigned conseq_index = m_conseq_index[v]; + numeral conseq_coeff = m_lemma.coeff(conseq_index); + + TRACE("pb", display(tout, m_lemma, true); + tout << "conseq: " << conseq << " at index: " << conseq_index << "\n";); + + SASSERT(~conseq == m_lemma.lit(conseq_index)); + + remove_from_lemma(conseq_index); + + b_justification js = ctx.get_justification(v); + + // + // Resolve selected conseq with antecedents. + // + + switch(js.get_kind()) { + + case b_justification::CLAUSE: { + clause& cls = *js.get_clause(); + justification* cjs = cls.get_justification(); + if (cjs && !is_proof_justification(*cjs)) { + TRACE("pb", tout << "skipping justification for clause over: " << conseq << " " + << typeid(*cjs).name() << "\n";); + m_ineq_literals.push_back(conseq); + break; + } + unsigned num_lits = cls.get_num_literals(); + if (cls.get_literal(0) == conseq) { + process_antecedent(cls.get_literal(1), conseq_coeff); + } + else { + SASSERT(cls.get_literal(1) == conseq); + process_antecedent(cls.get_literal(0), conseq_coeff); + } + for (unsigned i = 2; i < num_lits; ++i) { + process_antecedent(cls.get_literal(i), conseq_coeff); + } + TRACE("pb", for (unsigned i = 0; i < num_lits; ++i) tout << cls.get_literal(i) << " "; tout << "\n";); + break; + } + case b_justification::BIN_CLAUSE: + process_antecedent(~js.get_literal(), conseq_coeff); + TRACE("pb", tout << "binary: " << js.get_literal() << "\n";); + break; + case b_justification::AXIOM: + if (ctx.get_assign_level(v) > ctx.get_base_level()) { + m_ineq_literals.push_back(conseq); + } + TRACE("pb", tout << "axiom " << conseq << "\n";); + break; + case b_justification::JUSTIFICATION: { + justification* j = js.get_justification(); + pb_justification* pbj = 0; + + if (!conseq.sign() && j->get_from_theory() == get_id()) { + pbj = dynamic_cast(j); + } + if (pbj && pbj->get_ineq().is_eq()) { + // only resolve >= that are positive consequences. + pbj = 0; + } + if (pbj && pbj->get_ineq().lit() == conseq) { + // can't resolve against literal representing inequality. + pbj = 0; + } + if (pbj) { + // weaken the lemma and resolve. + TRACE("pb", display(tout << "resolve with inequality", pbj->get_ineq(), true);); + process_ineq(pbj->get_ineq(), conseq, conseq_coeff); + } + else { + TRACE("pb", tout << "skipping justification for " << conseq + << " from theory " << j->get_from_theory() << " " + << typeid(*j).name() << "\n";); + m_ineq_literals.push_back(conseq); + } + break; + } + default: + UNREACHABLE(); + } + } + + TRACE("pb", + for (unsigned i = 0; i < m_ineq_literals.size(); ++i) { + tout << m_ineq_literals[i] << " "; + } + display(tout << "=> ", m_lemma);); + + // 3x + 3y + z + u >= 4 + // ~x /\ ~y => z + u >= + + IF_VERBOSE(4, display(verbose_stream() << "lemma1: ", m_lemma);); + hoist_maximal_values(); + lbool is_true = m_lemma.normalize(false); + m_lemma.prune(false); + + IF_VERBOSE(4, display(verbose_stream() << "lemma2: ", m_lemma);); + //unsigned l_size = m_ineq_literals.size() + ((is_true==l_false)?0:m_lemma.size()); + //if (s_min_l_size >= l_size) { + // verbose_stream() << "(pb.conflict min size: " << l_size << ")\n"; + // s_min_l_size = l_size; + //} + //IF_VERBOSE(1, verbose_stream() << "(pb.conflict " << m_ineq_literals.size() << " " << m_lemma.size() << "\n";); + switch(is_true) { + case l_true: + UNREACHABLE(); + return false; + case l_false: + inc_propagations(c); + m_stats.m_num_conflicts++; + for (unsigned i = 0; i < m_ineq_literals.size(); ++i) { + m_ineq_literals[i].neg(); + } + ctx.mk_clause(m_ineq_literals.size(), m_ineq_literals.c_ptr(), justify(m_ineq_literals), CLS_AUX_LEMMA, 0); + break; + default: { + app_ref tmp = m_lemma.to_expr(false, ctx, get_manager()); + internalize_atom(tmp, false); + ctx.mark_as_relevant(tmp.get()); + literal l(ctx.get_bool_var(tmp)); + add_assign(c, m_ineq_literals, l); + break; + } + } + return true; + } + + bool theory_pb::is_proof_justification(justification const& j) const { + return typeid(smt::justification_proof_wrapper) == typeid(j); + } + + justification* theory_pb::justify(literal l1, literal l2) { + literal lits[2] = { l1, l2 }; + justification* js = 0; + if (proofs_enabled()) { + js = alloc(theory_axiom_justification, get_id(), get_context().get_region(), 2, lits); + } + return js; + } + + justification* theory_pb::justify(literal_vector const& lits) { + justification* js = 0; + if (proofs_enabled()) { + js = alloc(theory_lemma_justification, get_id(), get_context(), lits.size(), lits.c_ptr()); + } + return js; + } + + void theory_pb::hoist_maximal_values() { + for (unsigned i = 0; i < m_lemma.size(); ++i) { + if (m_lemma.coeff(i) >= m_lemma.k()) { + m_ineq_literals.push_back(~m_lemma.lit(i)); + std::swap(m_lemma[i], m_lemma[m_lemma.size()-1]); + m_lemma.pop_back(); + --i; + } + } + } + + void theory_pb::remove_from_lemma(unsigned idx) { + // Remove conseq from lemma: + literal lit = m_lemma.lit(idx); + unsigned last = m_lemma.size()-1; + if (idx != last) { + m_lemma[idx] = m_lemma[last]; + m_conseq_index[m_lemma.lit(idx).var()] = idx; + } + m_lemma.pop_back(); + unset_mark(lit.var()); + --m_num_marks; + } + + // debug methods + + void theory_pb::validate_watch(ineq const& c) const { + scoped_mpz sum(m_mpz_mgr), max(m_mpz_mgr); + for (unsigned i = 0; i < c.watch_size(); ++i) { + sum += c.ncoeff(i); + if (max < c.ncoeff(i)) { + max = c.ncoeff(i); + } + } + SASSERT(c.watch_sum() == sum); + SASSERT(sum >= c.mpz_k()); + SASSERT(max == c.max_watch()); + } + + void theory_pb::validate_assign(ineq const& c, literal_vector const& lits, literal l) const { + uint_set nlits; + context& ctx = get_context(); + for (unsigned i = 0; i < lits.size(); ++i) { + SASSERT(ctx.get_assignment(lits[i]) == l_true); + nlits.insert((~lits[i]).index()); + } + SASSERT(ctx.get_assignment(l) == l_undef); + SASSERT(ctx.get_assignment(c.lit()) == l_true); + nlits.insert(l.index()); + numeral sum = numeral::zero(); + for (unsigned i = 0; i < c.size(); ++i) { + literal lit = c.lit(i); + if (!nlits.contains(lit.index())) { + sum += c.coeff(i); + } + } + CTRACE("pb", (sum >= c.k()), + display(tout << "invalid assign" , c, true); + for (unsigned i = 0; i < lits.size(); ++i) { + tout << lits[i] << " "; + } + tout << " => " << l << "\n";); + SASSERT(sum < c.k()); + } + + void theory_pb::validate_final_check() { + u_map::iterator itc = m_ineqs.begin(), endc = m_ineqs.end(); + for (; itc != endc; ++itc) { + validate_final_check(*itc->m_value); + } + } + + void theory_pb::validate_final_check(ineq& c) { + context& ctx = get_context(); + + if (ctx.get_assignment(c.lit()) == l_undef) { + return; + } + if (!ctx.is_relevant(c.lit())) { + return; + } + numeral sum = numeral::zero(), maxsum = numeral::zero(); + for (unsigned i = 0; i < c.size(); ++i) { + switch(ctx.get_assignment(c.lit(i))) { + case l_true: + sum += c.coeff(i); + case l_undef: + maxsum += c.coeff(i); + break; + case l_false: + break; + } + } + TRACE("pb", display(tout << "validate: ", c, true); + tout << "sum: " << sum << " " << maxsum << " "; + tout << ctx.get_assignment(c.lit()) << "\n"; + ); + + SASSERT(sum <= maxsum); + SASSERT(!c.is_ge() || (sum >= c.k()) == (ctx.get_assignment(c.lit()) == l_true)); + SASSERT(!c.is_ge() || (maxsum < c.k()) == (ctx.get_assignment(c.lit()) == l_false)); + SASSERT(!c.is_eq() || (sum == c.k()) == (ctx.get_assignment(c.lit()) == l_true)); + } + + // display methods + + void theory_pb::display_resolved_lemma(std::ostream& out) const { + context& ctx = get_context(); + literal_vector const& lits = ctx.assigned_literals(); + bool_var v; + unsigned lvl; + out << "num marks: " << m_num_marks << "\n"; + out << "conflict level: " << m_conflict_lvl << "\n"; + for (unsigned i = 0; i < lits.size(); ++i) { + v = lits[i].var(); + lvl = ctx.get_assign_level(v); + out << lits[i] + << "@ " << lvl + << " " << (is_marked(v)?"m":"u") + << "\n"; + + if (lvl == m_conflict_lvl && is_marked(v)) { + out << "skipped: " << lits[i] << ":"<< i << "\n"; + } + } + display(out, m_lemma, true); + + unsigned nc = 0; + for (unsigned i = 0; i < m_lemma.size(); ++i) { + v = m_lemma.lit(i).var(); + lvl = ctx.get_assign_level(v); + if (lvl == m_conflict_lvl) ++nc; + out << m_lemma.lit(i) + << "@" << lvl + << " " << (is_marked(v)?"m":"u") + << " " << ctx.get_assignment(m_lemma.lit(i)) + << "\n"; + } + out << "num conflicts: " << nc << "\n"; + } + + std::ostream& theory_pb::display(std::ostream& out, arg_t const& c, bool values) const { + return c.display(get_context(), out, values); + } + + std::ostream& theory_pb::display(std::ostream& out, ineq const& c, bool values) const { + ast_manager& m = get_manager(); + context& ctx = get_context(); + out << c.lit(); + if (c.lit() != null_literal) { + if (values) { + out << "@(" << ctx.get_assignment(c.lit()); + if (ctx.get_assignment(c.lit()) != l_undef) { + out << ":" << ctx.get_assign_level(c.lit()); + } + out << ")"; + } + expr_ref tmp(m); + ctx.literal2expr(c.lit(), tmp); + out << " " << tmp << "\n"; + } + else { + out << " "; + } + for (unsigned i = 0; i < c.size(); ++i) { + literal l(c.lit(i)); + if (!c.coeff(i).is_one()) { + out << c.coeff(i) << "*"; + } + out << l; + if (values) { + out << "@(" << ctx.get_assignment(l); + if (ctx.get_assignment(l) != l_undef) { + out << ":" << ctx.get_assign_level(l); + } + out << ")"; + } + if (i + 1 == c.watch_size()) { + out << " .w "; + } + if (i + 1 < c.size()) { + out << " + "; + } + } + out << (c.is_ge()?" >= ":" = ") << c.k() << "\n"; + if (c.m_num_propagations) out << "propagations: " << c.m_num_propagations << " "; + if (c.m_max_watch.is_pos()) out << "max_watch: " << c.max_watch() << " "; + if (c.watch_size()) out << "watch size: " << c.watch_size() << " "; + if (c.m_watch_sum.is_pos()) out << "watch-sum: " << c.watch_sum() << " "; + if (!c.m_max_sum.is_zero()) out << "sum: [" << c.min_sum() << ":" << c.max_sum() << "] "; + if (c.m_num_propagations || c.m_max_watch.is_pos() || c.watch_size() || + c.m_watch_sum.is_pos() || !c.m_max_sum.is_zero()) out << "\n"; + return out; + } + + class theory_pb::pb_model_value_proc : public model_value_proc { + app* m_app; + svector m_dependencies; + public: + + pb_model_value_proc(app* a): + m_app(a) {} + + void add(enode* n) { + m_dependencies.push_back(model_value_dependency(n)); + } + + virtual void get_dependencies(buffer & result) { + result.append(m_dependencies.size(), m_dependencies.c_ptr()); + } + + virtual app * mk_value(model_generator & mg, ptr_vector & values) { + ast_manager& m = mg.get_manager(); + SASSERT(values.size() == m_dependencies.size()); + SASSERT(values.size() == m_app->get_num_args()); + pb_util u(m); + rational sum(0); + for (unsigned i = 0; i < m_app->get_num_args(); ++i) { + if (!m.is_true(values[i]) && !m.is_false(values[i])) { + return m_app; + } + if (m.is_true(values[i])) { + sum += u.get_coeff(m_app, i); + } + } + rational k = u.get_k(m_app); + switch(m_app->get_decl_kind()) { + case OP_AT_MOST_K: + return (sum <= k)?m.mk_true():m.mk_false(); + case OP_AT_LEAST_K: + return (sum >= k)?m.mk_true():m.mk_false(); + case OP_PB_LE: + return (sum <= k)?m.mk_true():m.mk_false(); + case OP_PB_GE: + return (sum >= k)?m.mk_true():m.mk_false(); + default: + UNREACHABLE(); + return 0; + } + return 0; + } + }; + + class pb_factory : public value_factory { + public: + pb_factory(ast_manager& m, family_id fid): + value_factory(m, fid) {} + + virtual expr * get_some_value(sort * s) { + return m_manager.mk_true(); + } + virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) { + v1 = m_manager.mk_true(); + v2 = m_manager.mk_false(); + return true; + } + virtual expr * get_fresh_value(sort * s) { + return 0; + } + virtual void register_value(expr * n) { } + }; + + void theory_pb::init_model(model_generator & m) { + m.register_factory(alloc(pb_factory, get_manager(), get_id())); + } + + model_value_proc * theory_pb::mk_value(enode * n, model_generator & mg) { + context& ctx = get_context(); + app* a = n->get_owner(); + pb_model_value_proc* p = alloc(pb_model_value_proc, a); + for (unsigned i = 0; i < a->get_num_args(); ++i) { + p->add(ctx.get_enode(a->get_arg(i))); + } + return p; + } + + void theory_pb::display(std::ostream& out) const { + u_map*>::iterator it = m_lwatch.begin(), end = m_lwatch.end(); + for (; it != end; ++it) { + out << "watch: " << to_literal(it->m_key) << " |-> "; + watch_list const& wl = *it->m_value; + for (unsigned i = 0; i < wl.size(); ++i) { + out << wl[i]->lit() << " "; + } + out << "\n"; + } + it = m_vwatch.begin(), end = m_vwatch.end(); + for (; it != end; ++it) { + out << "watch (v): " << literal(it->m_key) << " |-> "; + watch_list const& wl = *it->m_value; + for (unsigned i = 0; i < wl.size(); ++i) { + out << wl[i]->lit() << " "; + } + out << "\n"; + } + u_map::iterator itc = m_ineqs.begin(), endc = m_ineqs.end(); + for (; itc != endc; ++itc) { + ineq& c = *itc->m_value; + display(out, c, true); + } + } + + +} diff --git a/src/smt/theory_pb.h b/src/smt/theory_pb.h new file mode 100644 index 000000000..b9fddba38 --- /dev/null +++ b/src/smt/theory_pb.h @@ -0,0 +1,322 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + theory_pb.h + +Abstract: + + Cardinality theory plugin. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-05 + +Notes: + + This custom theory handles cardinality constraints + It performs unit propagation and switches to creating + sorting circuits if it keeps having to propagate (create new clauses). +--*/ + +#include "smt_theory.h" +#include "pb_decl_plugin.h" +#include "smt_clause.h" +#include "theory_pb_params.h" +#include "simplex.h" + +namespace smt { + class theory_pb : public theory { + + struct psort_expr; + class pb_justification; + class pb_model_value_proc; + class unwatch_ge; + class rewatch_vars; + class negate_ineq; + class remove_var; + class undo_bound; + typedef rational numeral; + typedef simplex::simplex simplex; + typedef simplex::row row; + typedef simplex::row_iterator row_iterator; + typedef unsynch_mpq_inf_manager eps_manager; + typedef _scoped_numeral scoped_eps_numeral; + + struct arg_t : public vector > { + numeral m_k; // invariants: m_k > 0, coeffs[i] > 0 + + unsigned get_hash() const; + bool operator==(arg_t const& other) const; + + numeral const& k() const { return m_k; } + + struct hash { + unsigned operator()(arg_t const& i) const { return i.get_hash(); } + }; + struct eq { + bool operator()(arg_t const& a, arg_t const& b) const { + return a == b; + } + }; + struct child_hash { + unsigned operator()(arg_t const& args, unsigned idx) const { + return args[idx].first.hash() ^ args[idx].second.hash(); + } + }; + struct kind_hash { + unsigned operator()(arg_t const& args) const { + return args.size(); + } + }; + + void remove_negations(); + + void negate(); + + lbool normalize(bool is_eq); + + void prune(bool is_eq); + + literal lit(unsigned i) const { + return (*this)[i].first; + } + + numeral const & coeff(unsigned i) const { return (*this)[i].second; } + + std::ostream& display(context& ctx, std::ostream& out, bool values = false) const; + + app_ref to_expr(bool is_eq, context& ctx, ast_manager& m); + + bool well_formed() const; + }; + + struct stats { + unsigned m_num_conflicts; + unsigned m_num_propagations; + unsigned m_num_predicates; + unsigned m_num_compiles; + unsigned m_num_compiled_vars; + unsigned m_num_compiled_clauses; + void reset() { memset(this, 0, sizeof(*this)); } + stats() { reset(); } + }; + + + struct ineq { + unsynch_mpz_manager& m_mpz; // mpz manager. + literal m_lit; // literal repesenting predicate + bool m_is_eq; // is this an = or >=. + arg_t m_args[2]; // encode args[0]*coeffs[0]+...+args[n-1]*coeffs[n-1] >= k(); + // Watch the first few positions until the sum satisfies: + // sum coeffs[i] >= m_lower + max_watch + scoped_mpz m_max_watch; // maximal coefficient. + unsigned m_watch_sz; // number of literals being watched. + scoped_mpz m_watch_sum; // maximal sum of watch literals. + // Watch infrastructure for = and unassigned >=: + unsigned m_nfixed; // number of variables that are fixed. + scoped_mpz m_max_sum; // maximal possible sum. + scoped_mpz m_min_sum; // minimal possible sum. + unsigned m_num_propagations; + unsigned m_compilation_threshold; + lbool m_compiled; + + ineq(unsynch_mpz_manager& m, literal l, bool is_eq) : + m_mpz(m), m_lit(l), m_is_eq(is_eq), + m_max_watch(m), m_watch_sum(m), + m_max_sum(m), m_min_sum(m) { + reset(); + } + + arg_t const& args() const { return m_args[m_lit.sign()]; } + arg_t& args() { return m_args[m_lit.sign()]; } + + literal lit() const { return m_lit; } + numeral const & k() const { return args().m_k; } + mpz const & mpz_k() const { return k().to_mpq().numerator(); } + + literal lit(unsigned i) const { return args()[i].first; } + numeral const & coeff(unsigned i) const { return args()[i].second; } + class mpz const& ncoeff(unsigned i) const { return coeff(i).to_mpq().numerator(); } + + unsigned size() const { return args().size(); } + + scoped_mpz const& watch_sum() const { return m_watch_sum; } + scoped_mpz const& max_watch() const { return m_max_watch; } + void set_max_watch(mpz const& n) { m_max_watch = n; } + unsigned watch_size() const { return m_watch_sz; } + + // variable watch infrastructure + scoped_mpz const& min_sum() const { return m_min_sum; } + scoped_mpz const& max_sum() const { return m_max_sum; } + unsigned nfixed() const { return m_nfixed; } + bool vwatch_initialized() const { return !m_mpz.is_zero(max_sum()); } + void vwatch_reset() { m_min_sum.reset(); m_max_sum.reset(); m_nfixed = 0; } + + unsigned find_lit(bool_var v, unsigned begin, unsigned end) { + while (lit(begin).var() != v) { + ++begin; + SASSERT(begin < end); + } + return begin; + } + + void reset(); + + void negate(); + + lbool normalize(); + + void unique(); + + void prune(); + + void post_prune(); + + app_ref to_expr(context& ctx, ast_manager& m); + + bool is_eq() const { return m_is_eq; } + bool is_ge() const { return !m_is_eq; } + + }; + + struct row_info { + unsigned m_slack; // slack variable in simplex tableau + numeral m_bound; // bound + arg_t m_rep; // representative + row_info(theory_var slack, numeral const& b, arg_t const& r): + m_slack(slack), m_bound(b), m_rep(r) {} + row_info(): m_slack(0) {} + }; + + typedef ptr_vector watch_list; + typedef map arg_map; + + theory_pb_params m_params; + u_map m_lwatch; // per literal. + u_map m_vwatch; // per variable. + u_map m_ineqs; // per inequality. + arg_map m_ineq_rep; // Simplex: representative inequality + u_map m_ineq_row_info; // Simplex: row information per variable + uint_set m_vars; // Simplex: 0-1 variables. + simplex m_simplex; // Simplex: tableau + literal_vector m_explain_lower; // Simplex: explanations for lower bounds + literal_vector m_explain_upper; // Simplex: explanations for upper bounds + unsynch_mpq_inf_manager m_mpq_inf_mgr; // Simplex: manage inf_mpq numerals + mutable unsynch_mpz_manager m_mpz_mgr; // Simplex: manager mpz numerals + unsigned_vector m_ineqs_trail; + unsigned_vector m_ineqs_lim; + literal_vector m_literals; // temporary vector + pb_util m_util; + stats m_stats; + ptr_vector m_to_compile; // inequalities to compile. + unsigned m_conflict_frequency; + bool m_learn_complements; + bool m_enable_compilation; + bool m_enable_simplex; + rational m_max_compiled_coeff; + + // internalize_atom: + literal compile_arg(expr* arg); + void add_watch(ineq& c, unsigned index); + void del_watch(watch_list& watch, unsigned index, ineq& c, unsigned ineq_index); + void init_watch_literal(ineq& c); + void init_watch_var(ineq& c); + void clear_watch(ineq& c); + void watch_literal(literal lit, ineq* c); + void watch_var(bool_var v, ineq* c); + void unwatch_literal(literal w, ineq* c); + void unwatch_var(bool_var v, ineq* c); + void remove(ptr_vector& ineqs, ineq* c); + bool assign_watch_ge(bool_var v, bool is_true, watch_list& watch, unsigned index); + void assign_watch(bool_var v, bool is_true, ineq& c); + void assign_ineq(ineq& c, bool is_true); + void assign_eq(ineq& c, bool is_true); + + // simplex: + literal set_explain(literal_vector& explains, unsigned var, literal expl); + bool update_bound(bool_var v, literal explain, bool is_lower, mpq_inf const& bound); + bool check_feasible(); + + std::ostream& display(std::ostream& out, ineq const& c, bool values = false) const; + std::ostream& display(std::ostream& out, arg_t const& c, bool values = false) const; + virtual void display(std::ostream& out) const; + void display_resolved_lemma(std::ostream& out) const; + + void add_clause(ineq& c, literal_vector const& lits); + void add_assign(ineq& c, literal_vector const& lits, literal l); + literal_vector& get_lits(); + + literal_vector& get_all_literals(ineq& c, bool negate); + literal_vector& get_helpful_literals(ineq& c, bool negate); + literal_vector& get_unhelpful_literals(ineq& c, bool negate); + + // + // Utilities to compile cardinality + // constraints into a sorting network. + // + void compile_ineq(ineq& c); + void inc_propagations(ineq& c); + unsigned get_compilation_threshold(ineq& c); + + // + // Conflict resolution, cutting plane derivation. + // + unsigned m_num_marks; + unsigned m_conflict_lvl; + arg_t m_lemma; + literal_vector m_ineq_literals; + svector m_marked; + + // bool_var |-> index into m_lemma + unsigned_vector m_conseq_index; + static const unsigned null_index; + bool is_marked(bool_var v) const; + void set_mark(bool_var v, unsigned idx); + void unset_mark(bool_var v); + void unset_marks(); + + bool resolve_conflict(ineq& c); + void process_antecedent(literal l, numeral coeff); + void process_ineq(ineq& c, literal conseq, numeral coeff); + void remove_from_lemma(unsigned idx); + bool is_proof_justification(justification const& j) const; + + void hoist_maximal_values(); + + void validate_final_check(); + void validate_final_check(ineq& c); + void validate_assign(ineq const& c, literal_vector const& lits, literal l) const; + void validate_watch(ineq const& c) const; + + bool proofs_enabled() const { return get_manager().proofs_enabled(); } + justification* justify(literal l1, literal l2); + justification* justify(literal_vector const& lits); + + public: + theory_pb(ast_manager& m, theory_pb_params& p); + + virtual ~theory_pb(); + + virtual theory * mk_fresh(context * new_ctx); + virtual bool internalize_atom(app * atom, bool gate_ctx); + virtual bool internalize_term(app * term) { UNREACHABLE(); return false; } + virtual void new_eq_eh(theory_var v1, theory_var v2); + virtual void new_diseq_eh(theory_var v1, theory_var v2) { } + virtual bool use_diseqs() const { return false; } + virtual bool build_models() const { return false; } + virtual final_check_status final_check_eh(); + virtual void reset_eh(); + virtual void assign_eh(bool_var v, bool is_true); + virtual void init_search_eh(); + virtual void push_scope_eh(); + virtual void pop_scope_eh(unsigned num_scopes); + virtual void restart_eh(); + virtual void collect_statistics(::statistics & st) const; + virtual model_value_proc * mk_value(enode * n, model_generator & mg); + virtual void init_model(model_generator & m); + + static literal assert_ge(context& ctx, unsigned k, unsigned n, literal const* xs); + }; +}; diff --git a/src/smt/theory_utvpi.h b/src/smt/theory_utvpi.h index 4a5d97d52..5358fb758 100644 --- a/src/smt/theory_utvpi.h +++ b/src/smt/theory_utvpi.h @@ -138,8 +138,7 @@ namespace smt { smt_params m_params; arith_util a; arith_eq_adapter m_arith_eq_adapter; - th_var m_zero_int; // cache the variable representing the zero variable. - th_var m_zero_real; // cache the variable representing the zero variable. + th_var m_zero; //cache the variable representing the zero variable. dl_graph m_graph; nc_functor m_nc_functor; @@ -304,7 +303,7 @@ namespace smt { void new_eq_or_diseq(bool is_eq, th_var v1, th_var v2, justification& eq_just); - th_var get_zero(sort* s) const { return a.is_int(s)?m_zero_int:m_zero_real; } + th_var get_zero(sort* s) const { return m_zero; } th_var get_zero(expr* e) const { return get_zero(get_manager().get_sort(e)); } diff --git a/src/smt/theory_utvpi_def.h b/src/smt/theory_utvpi_def.h index 6039b208a..e6ec7e387 100644 --- a/src/smt/theory_utvpi_def.h +++ b/src/smt/theory_utvpi_def.h @@ -62,8 +62,7 @@ namespace smt { theory(m.mk_family_id("arith")), a(m), m_arith_eq_adapter(*this, m_params, a), - m_zero_int(null_theory_var), - m_zero_real(null_theory_var), + m_zero(null_theory_var), m_nc_functor(*this), m_asserted_qhead(0), m_agility(0.5), @@ -134,8 +133,7 @@ namespace smt { template void theory_utvpi::reset_eh() { m_graph .reset(); - m_zero_int = null_theory_var; - m_zero_real = null_theory_var; + m_zero = null_theory_var; m_atoms .reset(); m_asserted_atoms .reset(); m_stats .reset(); @@ -261,8 +259,7 @@ namespace smt { template void theory_utvpi::init(context* ctx) { theory::init(ctx); - m_zero_int = mk_var(ctx->mk_enode(a.mk_numeral(rational(0), true), false, false, true)); - m_zero_real = mk_var(ctx->mk_enode(a.mk_numeral(rational(0), false), false, false, true)); + m_zero = mk_var(ctx->mk_enode(a.mk_numeral(rational(0), true), false, false, true)); } /** @@ -556,7 +553,7 @@ namespace smt { theory_var v = null_theory_var; context& ctx = get_context(); if (r.is_zero()) { - v = a.is_int(n)?m_zero_int:m_zero_real; + v = m_zero; } else if (ctx.e_internalized(n)) { enode* e = ctx.get_enode(n); @@ -778,9 +775,7 @@ namespace smt { m_factory = alloc(arith_factory, get_manager()); m.register_factory(m_factory); enforce_parity(); - m_graph.set_to_zero(to_var(m_zero_int), to_var(m_zero_real)); - m_graph.set_to_zero(neg(to_var(m_zero_int)), neg(to_var(m_zero_real))); - m_graph.set_to_zero(to_var(m_zero_int), neg(to_var(m_zero_int))); + m_graph.set_to_zero(to_var(m_zero), neg(to_var(m_zero))); compute_delta(); DEBUG_CODE(validate_model();); } diff --git a/src/smt/theory_wmaxsat.cpp b/src/smt/theory_wmaxsat.cpp new file mode 100644 index 000000000..539a3e909 --- /dev/null +++ b/src/smt/theory_wmaxsat.cpp @@ -0,0 +1,311 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + theory_wmaxsat.h + +Abstract: + + Weighted Max-SAT theory plugin. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-05 + +Notes: + +--*/ + +#include +#include "smt_context.h" +#include "ast_pp.h" +#include "theory_wmaxsat.h" + +namespace smt { + +theory_wmaxsat::theory_wmaxsat(ast_manager& m, filter_model_converter& mc): + theory(m.mk_family_id("weighted_maxsat")), + m_mc(mc), + m_vars(m), + m_fmls(m), + m_zweights(m_mpz), + m_old_values(m_mpz), + m_zcost(m_mpz), + m_zmin_cost(m_mpz), + m_found_optimal(false), + m_propagate(false), + m_normalize(false) +{} + +theory_wmaxsat::~theory_wmaxsat() { + m_old_values.reset(); +} + +/** + \brief return the complement of variables that are currently assigned. +*/ +void theory_wmaxsat::get_assignment(svector& result) { + result.reset(); + + if (!m_found_optimal) { + for (unsigned i = 0; i < m_vars.size(); ++i) { + result.push_back(false); + } + } + else { + std::sort(m_cost_save.begin(), m_cost_save.end()); + for (unsigned i = 0, j = 0; i < m_vars.size(); ++i) { + if (j < m_cost_save.size() && m_cost_save[j] == i) { + result.push_back(false); + ++j; + } + else { + result.push_back(true); + } + } + } + TRACE("opt", + tout << "cost save: "; + for (unsigned i = 0; i < m_cost_save.size(); ++i) { + tout << m_cost_save[i] << " "; + } + tout << "\nvars: "; + for (unsigned i = 0; i < m_vars.size(); ++i) { + tout << mk_pp(m_vars[i].get(), get_manager()) << " "; + } + tout << "\nassignment: "; + for (unsigned i = 0; i < result.size(); ++i) { + tout << result[i] << " "; + } + tout << "\n";); + +} + +void theory_wmaxsat::init_search_eh() { + m_propagate = true; +} + +bool_var theory_wmaxsat::assert_weighted(expr* fml, rational const& w) { + context & ctx = get_context(); + ast_manager& m = get_manager(); + app_ref var(m), wfml(m); + var = m.mk_fresh_const("w", m.mk_bool_sort()); + m_mc.insert(var->get_decl()); + wfml = m.mk_or(var, fml); + ctx.assert_expr(wfml); + m_rweights.push_back(w); + m_vars.push_back(var); + m_fmls.push_back(fml); + m_assigned.push_back(false); + m_rmin_cost += w; + m_normalize = true; + return register_var(var, true); +} + +bool_var theory_wmaxsat::register_var(app* var, bool attach) { + context & ctx = get_context(); + bool_var bv; + SASSERT(!ctx.e_internalized(var)); + enode* x = ctx.mk_enode(var, false, true, true); + if (ctx.b_internalized(var)) { + bv = ctx.get_bool_var(var); + } + else { + bv = ctx.mk_bool_var(var); + } + ctx.set_enode_flag(bv, true); + if (attach) { + ctx.set_var_theory(bv, get_id()); + theory_var v = mk_var(x); + ctx.attach_th_var(x, this, v); + m_bool2var.insert(bv, v); + SASSERT(v == m_var2bool.size()); + m_var2bool.push_back(bv); + SASSERT(ctx.bool_var2enode(bv)); + } + return bv; +} + +rational const& theory_wmaxsat::get_min_cost() { + unsynch_mpq_manager mgr; + scoped_mpq q(mgr); + mgr.set(q, m_zmin_cost, m_den.to_mpq().numerator()); + m_rmin_cost = rational(q); + return m_rmin_cost; +} + +void theory_wmaxsat::assign_eh(bool_var v, bool is_true) { + TRACE("opt", tout << "Assign " << mk_pp(m_vars[m_bool2var[v]].get(), get_manager()) << " " << is_true << "\n";); + if (is_true) { + if (m_normalize) normalize(); + context& ctx = get_context(); + theory_var tv = m_bool2var[v]; + if (m_assigned[tv]) return; + scoped_mpz w(m_mpz); + w = m_zweights[tv]; + ctx.push_trail(numeral_trail(m_zcost, m_old_values)); + ctx.push_trail(push_back_vector >(m_costs)); + ctx.push_trail(value_trail(m_assigned[tv])); + m_zcost += w; + m_costs.push_back(tv); + m_assigned[tv] = true; + if (m_zcost > m_zmin_cost) { + block(); + } + } +} + +final_check_status theory_wmaxsat::final_check_eh() { + if (m_normalize) normalize(); + return FC_DONE; +} + + +void theory_wmaxsat::reset_eh() { + theory::reset_eh(); + reset_local(); +} + +void theory_wmaxsat::reset_local() { + m_vars.reset(); + m_fmls.reset(); + m_rweights.reset(); + m_rmin_cost.reset(); + m_rcost.reset(); + m_zweights.reset(); + m_zcost.reset(); + m_zmin_cost.reset(); + m_cost_save.reset(); + m_bool2var.reset(); + m_var2bool.reset(); + m_propagate = false; + m_found_optimal = false; + m_assigned.reset(); +} + + +void theory_wmaxsat::propagate() { + context& ctx = get_context(); + for (unsigned i = 0; m_propagate && i < m_vars.size(); ++i) { + bool_var bv = m_var2bool[i]; + lbool asgn = ctx.get_assignment(bv); + if (asgn == l_true) { + assign_eh(bv, true); + } + } + m_propagate = false; +} + +bool theory_wmaxsat::is_optimal() const { + return !m_found_optimal || m_zcost < m_zmin_cost; +} + +expr_ref theory_wmaxsat::mk_block() { + ++m_stats.m_num_blocks; + ast_manager& m = get_manager(); + expr_ref_vector disj(m); + compare_cost compare_cost(*this); + svector costs(m_costs); + std::sort(costs.begin(), costs.end(), compare_cost); + scoped_mpz weight(m_mpz); + m_mpz.reset(weight); + for (unsigned i = 0; i < costs.size() && m_mpz.lt(weight, m_zmin_cost); ++i) { + weight += m_zweights[costs[i]]; + disj.push_back(m.mk_not(m_vars[costs[i]].get())); + } + if (is_optimal()) { + unsynch_mpq_manager mgr; + scoped_mpq q(mgr); + mgr.set(q, m_zmin_cost, m_den.to_mpq().numerator()); + rational rw = rational(q); + m_zmin_cost = weight; + m_found_optimal = true; + m_cost_save.reset(); + m_cost_save.append(m_costs); + TRACE("opt", + tout << "costs: "; + for (unsigned i = 0; i < m_costs.size(); ++i) { + tout << mk_pp(get_enode(m_costs[i])->get_owner(), get_manager()) << " "; + } + tout << "\n"; + get_context().display(tout); + ); + } + expr_ref result(m.mk_or(disj.size(), disj.c_ptr()), m); + TRACE("opt", + tout << result << " weight: " << weight << "\n"; + tout << "cost: " << m_zcost << " min-cost: " << m_zmin_cost << "\n";); + return result; +} + +expr_ref theory_wmaxsat::mk_optimal_block(svector const& ws, rational const& weight) { + ast_manager& m = get_manager(); + expr_ref_vector disj(m); + rational new_w = weight*m_den; + m_zmin_cost = new_w.to_mpq().numerator(); + m_cost_save.reset(); + for (unsigned i = 0; i < ws.size(); ++i) { + bool_var bv = ws[i]; + theory_var v = m_bool2var[bv]; + m_cost_save.push_back(v); + disj.push_back(m.mk_not(m_vars[v].get())); + } + expr_ref result(m.mk_or(disj.size(), disj.c_ptr()), m); + return result; +} + +void theory_wmaxsat::block() { + if (m_vars.empty()) { + return; + } + ++m_stats.m_num_blocks; + ast_manager& m = get_manager(); + context& ctx = get_context(); + literal_vector lits; + compare_cost compare_cost(*this); + svector costs(m_costs); + std::sort(costs.begin(), costs.end(), compare_cost); + + scoped_mpz weight(m_mpz); + m_mpz.reset(weight); + for (unsigned i = 0; i < costs.size() && weight < m_zmin_cost; ++i) { + weight += m_zweights[costs[i]]; + lits.push_back(~literal(m_var2bool[costs[i]])); + } + TRACE("opt", + tout << "block: "; + for (unsigned i = 0; i < lits.size(); ++i) { + expr_ref tmp(m); + ctx.literal2expr(lits[i], tmp); + tout << tmp << " "; + } + tout << "\n"; + ); + + ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr()); +} + + +void theory_wmaxsat::normalize() { + m_den = rational::one(); + for (unsigned i = 0; i < m_rweights.size(); ++i) { + m_den = lcm(m_den, denominator(m_rweights[i])); + } + m_den = lcm(m_den, denominator(m_rmin_cost)); + SASSERT(!m_den.is_zero()); + m_zweights.reset(); + for (unsigned i = 0; i < m_rweights.size(); ++i) { + rational r = m_rweights[i]*m_den; + SASSERT(r.is_int()); + mpq const& q = r.to_mpq(); + m_zweights.push_back(q.numerator()); + } + rational r = m_rcost* m_den; + m_zcost = r.to_mpq().numerator(); + r = m_rmin_cost * m_den; + m_zmin_cost = r.to_mpq().numerator(); + m_normalize = false; +} + +}; diff --git a/src/smt/theory_wmaxsat.h b/src/smt/theory_wmaxsat.h new file mode 100644 index 000000000..1ddb388ca --- /dev/null +++ b/src/smt/theory_wmaxsat.h @@ -0,0 +1,128 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + theory_wmaxsat.h + +Abstract: + + Weighted Max-SAT theory plugin. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-05 + +Notes: + +--*/ + +#ifndef _THEORY_WMAXSAT_H_ +#define _THEORY_WMAXSAT_H_ + +#include "smt_theory.h" +#include "smt_clause.h" +#include "filter_model_converter.h" + +namespace smt { + class theory_wmaxsat : public theory { + struct stats { + unsigned m_num_blocks; + void reset() { memset(this, 0, sizeof(*this)); } + stats() { reset(); } + }; + filter_model_converter& m_mc; + mutable unsynch_mpz_manager m_mpz; + app_ref_vector m_vars; // Auxiliary variables per soft clause + expr_ref_vector m_fmls; // Formulas per soft clause + vector m_rweights; // weights of theory variables. + scoped_mpz_vector m_zweights; + scoped_mpz_vector m_old_values; + svector m_costs; // set of asserted theory variables + svector m_cost_save; // set of asserted theory variables + rational m_rcost; // current sum of asserted costs + rational m_rmin_cost; // current maximal cost assignment. + scoped_mpz m_zcost; // current sum of asserted costs + scoped_mpz m_zmin_cost; // current maximal cost assignment. + bool m_found_optimal; + u_map m_bool2var; // bool_var -> theory_var + svector m_var2bool; // theory_var -> bool_var + bool m_propagate; + bool m_normalize; + rational m_den; // lcm of denominators for rational weights. + svector m_assigned; + stats m_stats; + public: + theory_wmaxsat(ast_manager& m, filter_model_converter& mc); + virtual ~theory_wmaxsat(); + void get_assignment(svector& result); + virtual void init_search_eh(); + bool_var assert_weighted(expr* fml, rational const& w); + bool_var register_var(app* var, bool attach); + rational const& get_min_cost(); + class numeral_trail : public trail { + typedef scoped_mpz T; + T & m_value; + scoped_mpz_vector& m_old_values; + public: + numeral_trail(T & value, scoped_mpz_vector& old): + m_value(value), + m_old_values(old) { + old.push_back(value); + } + + virtual ~numeral_trail() { + } + + virtual void undo(context & ctx) { + m_value = m_old_values.back(); + m_old_values.shrink(m_old_values.size() - 1); + } + }; + virtual void assign_eh(bool_var v, bool is_true); + virtual final_check_status final_check_eh(); + virtual bool use_diseqs() const { + return false; + } + virtual bool build_models() const { + return false; + } + void reset_local(); + virtual void reset_eh(); + virtual theory * mk_fresh(context * new_ctx) { return 0; } + virtual bool internalize_atom(app * atom, bool gate_ctx) { return false; } + virtual bool internalize_term(app * term) { return false; } + virtual void new_eq_eh(theory_var v1, theory_var v2) { } + virtual void new_diseq_eh(theory_var v1, theory_var v2) { } + + virtual void collect_statistics(::statistics & st) const { + st.update("wmaxsat num blocks", m_stats.m_num_blocks); + } + virtual bool can_propagate() { + return m_propagate; + } + + virtual void propagate(); + bool is_optimal() const; + expr_ref mk_block(); + + expr_ref mk_optimal_block(svector const& ws, rational const& weight); + private: + + void block(); + void normalize(); + + class compare_cost { + theory_wmaxsat& m_th; + public: + compare_cost(theory_wmaxsat& t):m_th(t) {} + bool operator() (theory_var v, theory_var w) const { + return m_th.m_mpz.gt(m_th.m_zweights[v], m_th.m_zweights[w]); + } + }; + + + }; +}; + +#endif diff --git a/src/solver/solver.h b/src/solver/solver.h index a95c649c0..1e310a484 100644 --- a/src/solver/solver.h +++ b/src/solver/solver.h @@ -129,6 +129,14 @@ public: \brief Display the content of this solver. */ virtual void display(std::ostream & out) const; + class scoped_push { + solver& s; + bool m_nopop; + public: + scoped_push(solver& s):s(s), m_nopop(false) { s.push(); } + ~scoped_push() { if (!m_nopop) s.pop(1); } + void disable_pop() { m_nopop = true; } + }; protected: virtual void set_cancel(bool f) = 0; diff --git a/src/solver/tactic2solver.cpp b/src/solver/tactic2solver.cpp index fb4898ecd..375f35ed1 100644 --- a/src/solver/tactic2solver.cpp +++ b/src/solver/tactic2solver.cpp @@ -40,6 +40,7 @@ class tactic2solver : public solver_na2as { bool m_produce_models; bool m_produce_proofs; bool m_produce_unsat_cores; + statistics m_stats; public: tactic2solver(ast_manager & m, tactic * t, params_ref const & p, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic); virtual ~tactic2solver(); @@ -161,6 +162,7 @@ lbool tactic2solver::check_sat_core(unsigned num_assumptions, expr * const * ass m_result->m_unknown = ex.msg(); } m_tactic->collect_statistics(m_result->m_stats); + m_tactic->collect_statistics(m_stats); m_result->m_model = md; m_result->m_proof = pr; if (m_produce_unsat_cores) { @@ -181,9 +183,9 @@ void tactic2solver::set_cancel(bool f) { } } -void tactic2solver::collect_statistics(statistics & st) const { - if (m_result.get()) - m_result->collect_statistics(st); +void tactic2solver::collect_statistics(statistics & st) const { + st.copy(m_stats); + //SASSERT(m_stats.size() > 0); } void tactic2solver::get_unsat_core(ptr_vector & r) { diff --git a/src/tactic/arith/card2bv_tactic.cpp b/src/tactic/arith/card2bv_tactic.cpp new file mode 100644 index 000000000..933b687b4 --- /dev/null +++ b/src/tactic/arith/card2bv_tactic.cpp @@ -0,0 +1,519 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + card2bv_tactic.cpp + +Abstract: + + Tactic for converting Pseudo-Boolean constraints to BV + +Author: + + Nikolaj Bjorner (nbjorner) 2014-03-20 + +Notes: + +--*/ +#include"tactical.h" +#include"cooperate.h" +#include"rewriter_def.h" +#include"ast_smt2_pp.h" +#include"expr_substitution.h" +#include"card2bv_tactic.h" +#include"pb_rewriter.h" +#include"ast_util.h" + +namespace pb { + unsigned card2bv_rewriter::get_num_bits(func_decl* f) { + rational r(0); + unsigned sz = f->get_arity(); + for (unsigned i = 0; i < sz; ++i) { + r += pb.get_coeff(f, i); + } + r = r > pb.get_k(f)? r : pb.get_k(f); + return r.get_num_bits(); + } + + card2bv_rewriter::card2bv_rewriter(ast_manager& m): + m(m), + au(m), + pb(m), + bv(m), + m_sort(*this), + m_lemmas(m), + m_trail(m) + {} + + void card2bv_rewriter::mk_assert(func_decl * f, unsigned sz, expr * const* args, expr_ref & result, expr_ref_vector& lemmas) { + m_lemmas.reset(); + SASSERT(f->get_family_id() == pb.get_family_id()); + if (is_or(f)) { + result = m.mk_or(sz, args); + } + else if (is_and(f)) { + result = m.mk_and(sz, args); + } + else if (pb.is_eq(f) && pb.get_k(f).is_unsigned() && pb.has_unit_coefficients(f)) { + result = m_sort.eq(pb.get_k(f).get_unsigned(), sz, args); + } + else if (pb.is_le(f) && pb.get_k(f).is_unsigned() && pb.has_unit_coefficients(f)) { + result = m_sort.le(false, pb.get_k(f).get_unsigned(), sz, args); + } + else if (pb.is_ge(f) && pb.get_k(f).is_unsigned() && pb.has_unit_coefficients(f)) { + result = m_sort.ge(false, pb.get_k(f).get_unsigned(), sz, args); + } + else { + br_status st = mk_shannon(f, sz, args, result); + if (st == BR_FAILED) { + mk_bv(f, sz, args, result); + } + } + lemmas.append(m_lemmas); + } + + std::ostream& card2bv_rewriter::pp(std::ostream& out, literal lit) { + return out << mk_ismt2_pp(lit, m); + } + + card2bv_rewriter::literal card2bv_rewriter::trail(literal l) { + m_trail.push_back(l); + return l; + } + card2bv_rewriter::literal card2bv_rewriter::fresh() { + return trail(m.mk_fresh_const("sn", m.mk_bool_sort())); + } + + void card2bv_rewriter::mk_clause(unsigned n, literal const* lits) { + m_lemmas.push_back(mk_or(m, n, lits)); + } + + + br_status card2bv_rewriter::mk_app_core(func_decl * f, unsigned sz, expr * const* args, expr_ref & result) { + if (f->get_family_id() == null_family_id) { + if (sz == 1) { + // Expecting minimize/maximize. + func_decl_ref fd(m); + fd = m.mk_func_decl(f->get_name(), m.get_sort(args[0]), f->get_range()); + result = m.mk_app(fd.get(), args[0]); + return BR_DONE; + } + else + return BR_FAILED; + } + else if (f->get_family_id() == m.get_basic_family_id()) { + result = m.mk_app(f, sz, args); + return BR_DONE; + } + else if (f->get_family_id() == pb.get_family_id()) { + if (is_or(f)) { + result = m.mk_or(sz, args); + return BR_DONE; + } + if (is_and(f)) { + result = m.mk_and(sz, args); + return BR_DONE; + } + br_status st = mk_shannon(f, sz, args, result); + if (st == BR_FAILED) { + mk_bv(f, sz, args, result); + return BR_DONE; + } + else { + return st; + } + } + // NSB: review + // we should remove this code and rely on a layer above to deal with + // whatever it accomplishes. It seems to break types. + // + else if (f->get_family_id() == au.get_family_id()) { + if (f->get_decl_kind() == OP_ADD) { + unsigned bits = 0; + for (unsigned i = 0; i < sz; i++) { + rational val1, val2; + if (au.is_int(args[i]) && au.is_numeral(args[i], val1)) { + bits += val1.get_num_bits(); + } + else if (m.is_ite(args[i]) && + au.is_numeral(to_app(args[i])->get_arg(1), val1) && val1.is_one() && + au.is_numeral(to_app(args[i])->get_arg(2), val2) && val2.is_zero()) { + bits++; + } + else + return BR_FAILED; + } + + result = 0; + for (unsigned i = 0; i < sz; i++) { + rational val1, val2; + expr * q; + if (au.is_int(args[i]) && au.is_numeral(args[i], val1)) + q = bv.mk_numeral(val1, bits); + else + q = mk_ite(to_app(args[i])->get_arg(0), bv.mk_numeral(1, bits), bv.mk_numeral(0, bits)); + result = (i == 0) ? q : bv.mk_bv_add(result.get(), q); + } + return BR_DONE; + } + else + return BR_FAILED; + } + else + return BR_FAILED; + } + + bool card2bv_rewriter::is_or(func_decl* f) { + switch (f->get_decl_kind()) { + case OP_AT_MOST_K: + case OP_PB_LE: + return false; + case OP_AT_LEAST_K: + case OP_PB_GE: + return pb.get_k(f).is_one(); + case OP_PB_EQ: + return false; + default: + UNREACHABLE(); + return false; + } + } + + bool card2bv_rewriter::is_and(func_decl* f) { + return false; + } + + void card2bv_rewriter::mk_bv(func_decl * f, unsigned sz, expr * const* args, expr_ref & result) { + expr_ref zero(m), a(m), b(m); + expr_ref_vector es(m); + unsigned bw = get_num_bits(f); + zero = bv.mk_numeral(rational(0), bw); + for (unsigned i = 0; i < sz; ++i) { + es.push_back(mk_ite(args[i], bv.mk_numeral(pb.get_coeff(f, i), bw), zero)); + } + switch (es.size()) { + case 0: a = zero; break; + case 1: a = es[0].get(); break; + default: + a = es[0].get(); + for (unsigned i = 1; i < es.size(); ++i) { + a = bv.mk_bv_add(a, es[i].get()); + } + break; + } + b = bv.mk_numeral(pb.get_k(f), bw); + + switch (f->get_decl_kind()) { + case OP_AT_MOST_K: + case OP_PB_LE: + UNREACHABLE(); + result = bv.mk_ule(a, b); + break; + case OP_AT_LEAST_K: + UNREACHABLE(); + case OP_PB_GE: + result = bv.mk_ule(b, a); + break; + case OP_PB_EQ: + result = m.mk_eq(a, b); + break; + default: + UNREACHABLE(); + } + TRACE("card2bv", tout << result << "\n";); + } + + struct argc_t { + expr* m_arg; + rational m_coeff; + argc_t():m_arg(0), m_coeff(0) {} + argc_t(expr* arg, rational const& r): m_arg(arg), m_coeff(r) {} + }; + struct argc_gt { + bool operator()(argc_t const& a, argc_t const& b) const { + return a.m_coeff > b.m_coeff; + } + }; + struct argc_entry { + unsigned m_index; + rational m_k; + expr* m_value; + argc_entry(unsigned i, rational const& k): m_index(i), m_k(k), m_value(0) {} + argc_entry():m_index(0), m_k(0), m_value(0) {} + + struct eq { + bool operator()(argc_entry const& a, argc_entry const& b) const { + return a.m_index == b.m_index && a.m_k == b.m_k; + } + }; + struct hash { + unsigned operator()(argc_entry const& a) const { + return a.m_index ^ a.m_k.hash(); + } + }; + }; + typedef hashtable argc_cache; + + br_status card2bv_rewriter::mk_shannon( + func_decl * f, unsigned sz, expr * const* args, expr_ref & result) { + + unsigned max_clauses = sz*10; + vector argcs; + for (unsigned i = 0; i < sz; ++i) { + argcs.push_back(argc_t(args[i], pb.get_coeff(f, i))); + } + std::sort(argcs.begin(), argcs.end(), argc_gt()); + DEBUG_CODE( + for (unsigned i = 0; i + 1 < sz; ++i) { + SASSERT(argcs[i].m_coeff >= argcs[i+1].m_coeff); + } + ); + result = m.mk_app(f, sz, args); + TRACE("card2bv", tout << result << "\n";); + argc_cache cache; + expr_ref_vector trail(m); + vector todo_k; + unsigned_vector todo_i; + todo_k.push_back(pb.get_k(f)); + todo_i.push_back(0); + decl_kind kind = f->get_decl_kind(); + argc_entry entry1; + while (!todo_i.empty()) { + SASSERT(todo_i.size() == todo_k.size()); + if (cache.size() > max_clauses) { + return BR_FAILED; + } + unsigned i = todo_i.back(); + rational k = todo_k.back(); + argc_entry entry(i, k); + if (cache.contains(entry)) { + todo_i.pop_back(); + todo_k.pop_back(); + continue; + } + SASSERT(i < sz); + SASSERT(!k.is_neg()); + rational const& coeff = argcs[i].m_coeff; + expr* arg = argcs[i].m_arg; + if (i + 1 == sz) { + switch(kind) { + case OP_AT_MOST_K: + case OP_PB_LE: + if (coeff <= k) { + entry.m_value = m.mk_true(); + } + else { + entry.m_value = negate(arg); + trail.push_back(entry.m_value); + } + break; + case OP_AT_LEAST_K: + case OP_PB_GE: + if (k.is_zero()) { + entry.m_value = m.mk_true(); + } + else if (coeff < k) { + entry.m_value = m.mk_false(); + } + else if (coeff.is_zero()) { + entry.m_value = m.mk_true(); + } + else { + SASSERT(coeff >= k && k.is_pos()); + entry.m_value = arg; + } + break; + case OP_PB_EQ: + if (coeff == k) { + entry.m_value = arg; + } + else if (k.is_zero()) { + entry.m_value = negate(arg); + trail.push_back(entry.m_value); + } + else { + entry.m_value = m.mk_false(); + } + break; + } + todo_i.pop_back(); + todo_k.pop_back(); + cache.insert(entry); + continue; + } + entry.m_index++; + expr* lo = 0, *hi = 0; + if (cache.find(entry, entry1)) { + lo = entry1.m_value; + } + else { + todo_i.push_back(i+1); + todo_k.push_back(k); + } + entry.m_k -= coeff; + if (kind != OP_PB_EQ && !entry.m_k.is_pos()) { + switch (kind) { + case OP_AT_MOST_K: + case OP_PB_LE: + hi = m.mk_false(); + break; + case OP_AT_LEAST_K: + case OP_PB_GE: + hi = m.mk_true(); + break; + default: + UNREACHABLE(); + } + } + else if (cache.find(entry, entry1)) { + hi = entry1.m_value; + } + else { + todo_i.push_back(i+1); + todo_k.push_back(entry.m_k); + } + if (hi && lo) { + todo_i.pop_back(); + todo_k.pop_back(); + entry.m_index = i; + entry.m_k = k; + entry.m_value = mk_ite(arg, hi, lo); + trail.push_back(entry.m_value); + cache.insert(entry); + } + } + argc_entry entry(0, pb.get_k(f)); + VERIFY(cache.find(entry, entry)); + result = entry.m_value; + TRACE("card2bv", tout << result << "\n";); + return BR_DONE; + } + + expr* card2bv_rewriter::negate(expr* e) { + if (m.is_not(e, e)) return e; + return m.mk_not(e); + } + + expr* card2bv_rewriter::mk_ite(expr* c, expr* hi, expr* lo) { + while (m.is_not(c, c)) { + std::swap(hi, lo); + } + if (hi == lo) return hi; + if (m.is_true(hi) && m.is_false(lo)) return c; + if (m.is_false(hi) && m.is_true(lo)) return negate(c); + if (m.is_true(hi)) return m.mk_or(c, lo); + if (m.is_false(lo)) return m.mk_and(c, hi); + if (m.is_false(hi)) return m.mk_and(negate(c), lo); + if (m.is_true(lo)) return m.mk_implies(c, hi); + return m.mk_ite(c, hi, lo); + } + + void card_pb_rewriter::rewrite(expr* e, expr_ref& result) { + if (pb.is_eq(e)) { + app* a = to_app(e); + ast_manager& m = m_lemmas.get_manager(); + unsigned sz = a->get_num_args(); + expr_ref_vector args(m); + expr_ref tmp(m); + for (unsigned i = 0; i < sz; ++i) { + (*this)(a->get_arg(i), tmp); + args.push_back(tmp); + } + m_cfg.m_r.mk_assert(a->get_decl(), sz, args.c_ptr(), result, m_lemmas); + } + else { + (*this)(e, result); + } + } + +}; + +template class rewriter_tpl; + + +class card2bv_tactic : public tactic { + ast_manager & m; + params_ref m_params; + th_rewriter m_rw1; + pb::card_pb_rewriter m_rw2; + +public: + + card2bv_tactic(ast_manager & m, params_ref const & p): + m(m), + m_params(p), + m_rw1(m), + m_rw2(m) { + } + + virtual tactic * translate(ast_manager & m) { + return alloc(card2bv_tactic, m, m_params); + } + + virtual ~card2bv_tactic() { + } + + virtual void updt_params(params_ref const & p) { + m_params = p; + } + + virtual void collect_param_descrs(param_descrs & r) { + } + + void set_cancel(bool f) { + m_rw1.set_cancel(f); + m_rw2.set_cancel(f); + } + + virtual void operator()(goal_ref const & g, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + TRACE("card2bv-before", g->display(tout);); + SASSERT(g->is_well_sorted()); + fail_if_proof_generation("card2bv", g); + mc = 0; pc = 0; core = 0; result.reset(); + tactic_report report("card2bv", *g); + m_rw1.reset(); + m_rw2.reset(); + m_rw2.lemmas().reset(); + + if (g->inconsistent()) { + result.push_back(g.get()); + return; + } + + unsigned size = g->size(); + expr_ref new_f1(m), new_f2(m); + proof_ref new_pr1(m), new_pr2(m); + for (unsigned idx = 0; idx < size; idx++) { + m_rw1(g->form(idx), new_f1, new_pr1); + TRACE("card2bv", tout << "Rewriting " << mk_ismt2_pp(new_f1.get(), m) << std::endl;); + m_rw2.rewrite(new_f1, new_f2); + if (m.proofs_enabled()) { + new_pr1 = m.mk_modus_ponens(g->pr(idx), new_pr1); + new_pr2 = m.mk_rewrite(new_f1, new_f2); + new_pr1 = m.mk_modus_ponens(new_pr1, new_pr2); + } + g->update(idx, new_f2, new_pr1, g->dep(idx)); + } + for (unsigned i = 0; i < m_rw2.lemmas().size(); ++i) { + g->assert_expr(m_rw2.lemmas()[i].get()); + } + + g->inc_depth(); + result.push_back(g.get()); + TRACE("card2bv", g->display(tout);); + SASSERT(g->is_well_sorted()); + } + + virtual void cleanup() { + } +}; + +tactic * mk_card2bv_tactic(ast_manager & m, params_ref const & p) { + return clean(alloc(card2bv_tactic, m, p)); +} + diff --git a/src/tactic/arith/card2bv_tactic.h b/src/tactic/arith/card2bv_tactic.h new file mode 100644 index 000000000..ed96376b5 --- /dev/null +++ b/src/tactic/arith/card2bv_tactic.h @@ -0,0 +1,108 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + card2bv_tactic.cpp + +Abstract: + + Tactic for converting Pseudo-Boolean constraints to BV + +Author: + + Nikolaj Bjorner (nbjorner) 2014-03-20 + +Notes: + +--*/ +#ifndef _CARD2BV_TACTIC_ +#define _CARD2BV_TACTIC_ + +#include"params.h" +#include"pb_decl_plugin.h" +#include"th_rewriter.h" +#include"rewriter.h" +#include +#include"sorting_network.h" + + +class ast_manager; +class tactic; + +namespace pb { + + class card2bv_rewriter { + public: + typedef expr* literal; + typedef ptr_vector literal_vector; + private: + ast_manager& m; + arith_util au; + pb_util pb; + bv_util bv; + psort_nw m_sort; + expr_ref_vector m_lemmas; + expr_ref_vector m_trail; + + unsigned get_num_bits(func_decl* f); + void mk_bv(func_decl * f, unsigned sz, expr * const* args, expr_ref & result); + br_status mk_shannon(func_decl * f, unsigned sz, expr * const* args, expr_ref & result); + expr* negate(expr* e); + expr* mk_ite(expr* c, expr* hi, expr* lo); + bool is_or(func_decl* f); + bool is_and(func_decl* f); + + public: + card2bv_rewriter(ast_manager& m); + br_status mk_app_core(func_decl * f, unsigned sz, expr * const* args, expr_ref & result); + void mk_assert(func_decl * f, unsigned sz, expr * const* args, expr_ref & result, expr_ref_vector& lemmas); + + // definitions used for sorting network + literal mk_false() { return m.mk_false(); } + literal mk_true() { return m.mk_true(); } + literal mk_max(literal a, literal b) { return trail(m.mk_or(a, b)); } + literal mk_min(literal a, literal b) { return trail(m.mk_and(a, b)); } + literal mk_not(literal a) { if (m.is_not(a,a)) return a; return trail(m.mk_not(a)); } + std::ostream& pp(std::ostream& out, literal lit); + literal fresh(); + literal trail(literal l); + void mk_clause(unsigned n, literal const* lits); + + }; + + struct card2bv_rewriter_cfg : public default_rewriter_cfg { + card2bv_rewriter m_r; + bool rewrite_patterns() const { return false; } + bool flat_assoc(func_decl * f) const { return false; } + br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { + result_pr = 0; + return m_r.mk_app_core(f, num, args, result); + } + card2bv_rewriter_cfg(ast_manager & m):m_r(m) {} + }; + + class card_pb_rewriter : public rewriter_tpl { + card2bv_rewriter_cfg m_cfg; + pb_util pb; + expr_ref_vector m_lemmas; + public: + card_pb_rewriter(ast_manager & m): + rewriter_tpl(m, false, m_cfg), + m_cfg(m), + pb(m), + m_lemmas(m) {} + + void rewrite(expr* e, expr_ref& result); + + expr_ref_vector& lemmas() { return m_lemmas; } + }; +}; + +tactic * mk_card2bv_tactic(ast_manager & m, params_ref const & p = params_ref()); +/* + ADD_TACTIC("card2bv", "convert pseudo-boolean constraints to bit-vectors.", "mk_card2bv_tactic(m, p)") +*/ + + +#endif diff --git a/src/tactic/arith/elim01_tactic.cpp b/src/tactic/arith/elim01_tactic.cpp new file mode 100644 index 000000000..dda3d8fc9 --- /dev/null +++ b/src/tactic/arith/elim01_tactic.cpp @@ -0,0 +1,270 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + elim01_tactic.cpp + +Abstract: + + Replace 0-1 integer variables by Booleans. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-12-7 + +Notes: + +--*/ +#include"tactical.h" +#include"cooperate.h" +#include"bound_manager.h" +#include"ast_pp.h" +#include"expr_safe_replace.h" // NB: should use proof-producing expr_substitute in polished version. +#include"arith_decl_plugin.h" +#include"elim01_tactic.h" +#include"model_smt2_pp.h" +#include"th_rewriter.h" + +class bool2int_model_converter : public model_converter { + ast_manager& m; + arith_util a; + func_decl_ref_vector m_refs; + obj_hashtable m_bools; + vector > m_nums_as_bool; + ptr_vector m_nums_as_int; +public: + + bool2int_model_converter(ast_manager& m): + m(m), + a(m), + m_refs(m) + {} + + virtual void operator()(model_ref & old_model, unsigned goal_idx) { + SASSERT(goal_idx == 0); + model * new_model = alloc(model, m); + unsigned num = old_model->get_num_constants(); + for (unsigned i = 0; i < m_nums_as_int.size(); ++i) { + func_decl* f_old = m_nums_as_int[i]; + rational val(0); + rational po(1); + bool is_value = true; + for (unsigned j = 0; is_value && j < m_nums_as_bool[i].size(); ++j) { + func_decl* f = m_nums_as_bool[i][j]; + expr* fi = old_model->get_const_interp(f); + if (!fi) { + is_value = false; + } + else if (m.is_true(fi)) { + val += po; + } + else if (!m.is_false(fi)) { + is_value = false; + } + po *= rational(2); + } + if (is_value) { + expr* fi = a.mk_numeral(val, true); + new_model->register_decl(f_old, fi); + } + } + for (unsigned i = 0; i < num; ++i) { + func_decl* f = old_model->get_constant(i); + expr* fi = old_model->get_const_interp(f); + if (!m_bools.contains(f)) { + new_model->register_decl(f, fi); + } + } + num = old_model->get_num_functions(); + for (unsigned i = 0; i < num; i++) { + func_decl * f = old_model->get_function(i); + func_interp * fi = old_model->get_func_interp(f); + new_model->register_decl(f, fi->copy()); + } + new_model->copy_usort_interps(*old_model); + old_model = new_model; + } + + void insert(func_decl* x_new, func_decl* x_old) { + m_refs.push_back(x_new); + m_refs.push_back(x_old); + m_bools.insert(x_new); + m_nums_as_int.push_back(x_old); + m_nums_as_bool.push_back(ptr_vector()); + m_nums_as_bool.back().push_back(x_new); + } + + void insert(func_decl* x_old, unsigned sz, func_decl * const* x_new) { + m_nums_as_int.push_back(x_old); + m_nums_as_bool.push_back(ptr_vector()); + m_refs.push_back(x_old); + for (unsigned i = 0; i < sz; ++i) { + m_refs.push_back(x_new[i]); + m_nums_as_bool.back().push_back(x_new[i]); + m_bools.insert(x_new[i]); + } + } + + virtual model_converter * translate(ast_translation & translator) { + bool2int_model_converter* mc = alloc(bool2int_model_converter, translator.to()); + for (unsigned i = 0; i < m_nums_as_int.size(); ++i) { + mc->insert(m_nums_as_int[i], m_nums_as_bool[i].size(), m_nums_as_bool[i].c_ptr()); + } + return mc; + } +}; + + +class elim01_tactic : public tactic { +public: + typedef obj_hashtable expr_set; + ast_manager & m; + arith_util a; + th_rewriter m_rewriter; + params_ref m_params; + unsigned m_max_hi_default; + rational m_max_hi; + + elim01_tactic(ast_manager & _m, params_ref const & p): + m(_m), + a(m), + m_rewriter(m), + m_max_hi_default(8), + m_max_hi(rational(m_max_hi_default)) { + } + + virtual ~elim01_tactic() { + } + + void set_cancel(bool f) { + } + + virtual void updt_params(params_ref const & p) { + m_max_hi = rational(p.get_uint("max_coefficient", m_max_hi_default)); + m_params = p; + } + + virtual void collect_param_descrs(param_descrs & r) { + r.insert("max_coefficient", CPK_UINT, "(default: 1) maximal upper bound for finite range -> Bool conversion"); + } + + + virtual void operator()(goal_ref const & g, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + SASSERT(g->is_well_sorted()); + mc = 0; pc = 0; core = 0; + + tactic_report report("elim01", *g); + + expr_safe_replace sub(m); + bool2int_model_converter* b2i = alloc(bool2int_model_converter, m); + mc = b2i; + bound_manager bounds(m); + expr_ref_vector axioms(m); + bounds(*g); + + rational zero(0); + bound_manager::iterator bit = bounds.begin(), bend = bounds.end(); + for (; bit != bend; ++bit) { + if (!is_app(*bit)) continue; + app* x = to_app(*bit); + bool s1, s2; + rational lo, hi; + if (a.is_int(x) && + bounds.has_lower(x, lo, s1) && !s1 && zero <= lo && + bounds.has_upper(x, hi, s2) && !s2 && hi <= m_max_hi && lo <= hi) { + add_variable(b2i, sub, x, lo.get_unsigned(), hi.get_unsigned(), axioms); + } + else if (a.is_int(x)) { + TRACE("pb", tout << "Not adding variable " << mk_pp(x, m) << " has lower: " + << bounds.has_lower(x, lo, s1) << " " << lo << " has upper: " + << bounds.has_upper(x, hi, s2) << " " << hi << "\n";); + } + } + + if (sub.empty()) { + result.push_back(g.get()); + return; + } + + expr_ref new_curr(m), tmp_curr(m); + proof_ref new_pr(m); + for (unsigned i = 0; i < g->size(); i++) { + expr * curr = g->form(i); + sub(curr, tmp_curr); + m_rewriter(tmp_curr, new_curr); + if (m.proofs_enabled()) { + new_pr = m.mk_rewrite(curr, new_curr); + new_pr = m.mk_modus_ponens(g->pr(i), new_pr); + } + g->update(i, new_curr, new_pr, g->dep(i)); + } + for (unsigned i = 0; i < axioms.size(); ++i) { + g->assert_expr(axioms[i].get()); + } + g->inc_depth(); + result.push_back(g.get()); + TRACE("pb", g->display(tout);); + SASSERT(g->is_well_sorted()); + + // TBD: support proof conversion (or not..) + } + + virtual tactic * translate(ast_manager & m) { + return alloc(elim01_tactic, m, m_params); + } + + virtual void cleanup() {} + + void add_variable(bool2int_model_converter* b2i, + expr_safe_replace& sub, + app* x, + unsigned min_value, + unsigned max_value, + expr_ref_vector& axioms) { + std::string name = x->get_decl()->get_name().str(); + unsigned sh = 0; + app_ref_vector xs(m), ites(m); + func_decl_ref_vector xfs(m); + app_ref zero(m), sum(m); + zero = a.mk_numeral(rational(0), true); + while (max_value >= (1ul << sh)) { + xs.push_back(m.mk_fresh_const(name.c_str(), m.mk_bool_sort())); + xfs.push_back(xs.back()->get_decl()); + ites.push_back(m.mk_ite(xs.back(), a.mk_numeral(rational(1 << sh), true), zero)); + ++sh; + } + switch (ites.size()) { + case 0: + sum = zero; + break; + case 1: + sum = ites[0].get(); + break; + default: + sum = a.mk_add(ites.size(), (expr*const*)ites.c_ptr()); + break; + } + TRACE("pb", tout << mk_pp(x, m) << " " << sum << " max: " << max_value << "\n";); + + sub.insert(x, sum); + b2i->insert(x->get_decl(), xfs.size(), xfs.c_ptr()); + // if max_value+1 is not a power of two: + if ((max_value & (max_value + 1)) != 0) { + axioms.push_back(a.mk_le(sum, a.mk_numeral(rational(max_value), true))); + } + if (min_value > 0) { + axioms.push_back(a.mk_ge(sum, a.mk_numeral(rational(min_value), true))); + } + } + +}; + +tactic * mk_elim01_tactic(ast_manager & m, params_ref const & p) { + return clean(alloc(elim01_tactic, m, p)); +} + diff --git a/src/tactic/arith/elim01_tactic.h b/src/tactic/arith/elim01_tactic.h new file mode 100644 index 000000000..867013ed0 --- /dev/null +++ b/src/tactic/arith/elim01_tactic.h @@ -0,0 +1,33 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + elim01_tactic.h + +Abstract: + + Replace 0-1 integer variables by Booleans. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-12-7 + +Notes: + +--*/ +#ifndef _ELIM01_TACTIC_H_ +#define _ELIM01_TACTIC_H_ + +#include"params.h" +class ast_manager; +class tactic; + +tactic * mk_elim01_tactic(ast_manager & m, params_ref const & p = params_ref()); + +/* + ADD_TACTIC("elim01", "eliminate 0-1 integer variables, replace them by Booleans.", "mk_elim01_tactic(m, p)") +*/ + + +#endif diff --git a/src/tactic/arith/lia2card_tactic.cpp b/src/tactic/arith/lia2card_tactic.cpp new file mode 100644 index 000000000..0afbe62f1 --- /dev/null +++ b/src/tactic/arith/lia2card_tactic.cpp @@ -0,0 +1,303 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + lia2card_tactic.cpp + +Abstract: + + Convert 0-1 integer variables cardinality constraints to built-in cardinality operator. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-5 + +Notes: + +--*/ +#include"tactical.h" +#include"cooperate.h" +#include"bound_manager.h" +#include"ast_pp.h" +#include"expr_safe_replace.h" // NB: should use proof-producing expr_substitute in polished version. +#include"pb_decl_plugin.h" +#include"arith_decl_plugin.h" + +class lia2card_tactic : public tactic { +public: + typedef obj_hashtable expr_set; + ast_manager & m; + arith_util a; + params_ref m_params; + pb_util m_pb; + mutable ptr_vector m_todo; + expr_set m_01s; + bool m_compile_equality; + + lia2card_tactic(ast_manager & _m, params_ref const & p): + m(_m), + a(m), + m_pb(m), + m_compile_equality(false) { + } + + virtual ~lia2card_tactic() { + } + + void set_cancel(bool f) { + } + + void updt_params(params_ref const & p) { + m_params = p; + m_compile_equality = p.get_bool("compile_equality", false); + } + + virtual void operator()(goal_ref const & g, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + SASSERT(g->is_well_sorted()); + mc = 0; pc = 0; core = 0; + m_01s.reset(); + + tactic_report report("cardinality-intro", *g); + + bound_manager bounds(m); + bounds(*g); + + + bound_manager::iterator bit = bounds.begin(), bend = bounds.end(); + for (; bit != bend; ++bit) { + expr* x = *bit; + bool s1, s2; + rational lo, hi; + if (a.is_int(x) && + bounds.has_lower(x, lo, s1) && !s1 && lo.is_zero() && + bounds.has_upper(x, hi, s2) && !s2 && hi.is_one()) { + m_01s.insert(x); + TRACE("pb", tout << "add bound " << mk_pp(x, m) << "\n";); + } + } + + expr_safe_replace sub(m); + extract_pb_substitution(g, sub); + + expr_ref new_curr(m); + proof_ref new_pr(m); + + for (unsigned i = 0; i < g->size(); i++) { + expr * curr = g->form(i); + sub(curr, new_curr); + if (m.proofs_enabled()) { + new_pr = m.mk_rewrite(curr, new_curr); + new_pr = m.mk_modus_ponens(g->pr(i), new_pr); + } + g->update(i, new_curr, new_pr, g->dep(i)); + } + g->inc_depth(); + result.push_back(g.get()); + TRACE("pb", g->display(tout);); + SASSERT(g->is_well_sorted()); + + // TBD: convert models for 0-1 variables. + // TBD: support proof conversion (or not..) + } + + void extract_pb_substitution(goal_ref const& g, expr_safe_replace& sub) { + ast_mark mark; + for (unsigned i = 0; i < g->size(); i++) { + extract_pb_substitution(mark, g->form(i), sub); + } + } + + void extract_pb_substitution(ast_mark& mark, expr* fml, expr_safe_replace& sub) { + expr_ref tmp(m); + m_todo.reset(); + m_todo.push_back(fml); + while (!m_todo.empty()) { + expr* e = m_todo.back(); + m_todo.pop_back(); + if (mark.is_marked(e) || !is_app(e)) { + continue; + } + mark.mark(e, true); + if (get_pb_relation(sub, e, tmp)) { + sub.insert(e, tmp); + continue; + } + app* ap = to_app(e); + m_todo.append(ap->get_num_args(), ap->get_args()); + } + } + + + bool is_01var(expr* x) const { + return m_01s.contains(x); + } + + expr_ref mk_01(expr* x) { + expr* r = m.mk_eq(x, a.mk_numeral(rational(1), m.get_sort(x))); + return expr_ref(r, m); + } + + bool get_pb_relation(expr_safe_replace& sub, expr* fml, expr_ref& result) { + expr* x, *y; + expr_ref_vector args(m); + vector coeffs; + rational coeff; + if ((a.is_le(fml, x, y) || a.is_ge(fml, y, x)) && + get_pb_sum(x, rational::one(), args, coeffs, coeff) && + get_pb_sum(y, -rational::one(), args, coeffs, coeff)) { + result = mk_le(coeffs.size(), coeffs.c_ptr(), args.c_ptr(), -coeff); + return true; + } + else if ((a.is_lt(fml, y, x) || a.is_gt(fml, x, y)) && + get_pb_sum(x, rational::one(), args, coeffs, coeff) && + get_pb_sum(y, -rational::one(), args, coeffs, coeff)) { + result = m.mk_not(mk_le(coeffs.size(), coeffs.c_ptr(), args.c_ptr(), -coeff)); + return true; + } + else if (m.is_eq(fml, x, y) && + get_pb_sum(x, rational::one(), args, coeffs, coeff) && + get_pb_sum(y, -rational::one(), args, coeffs, coeff)) { + result = mk_eq(coeffs.size(), coeffs.c_ptr(), args.c_ptr(), -coeff); + return true; + } + return false; + } + + expr* mk_le(unsigned sz, rational const* weights, expr* const* args, rational const& w) { + if (sz == 0) { + return w.is_neg()?m.mk_false():m.mk_true(); + } + if (sz == 1 && weights[0].is_one() && w >= rational::one()) { + return m.mk_true(); + } + if (sz == 1 && weights[0].is_one() && w.is_zero()) { + return m.mk_not(args[0]); + } + return m_pb.mk_le(sz, weights, args, w); + } + + expr* mk_eq(unsigned sz, rational const* weights, expr* const* args, rational const& w) { + if (m_compile_equality) { + return m_pb.mk_eq(sz, weights, args, w); + } + else { + return m.mk_and(mk_ge(sz, weights, args, w), mk_le(sz, weights, args, w)); + } + } + + expr* mk_ge(unsigned sz, rational const* weights, expr* const* args, rational const& w) { + if (sz == 0) { + return w.is_pos()?m.mk_false():m.mk_true(); + } + if (sz == 1 && weights[0].is_one() && w.is_one()) { + return args[0]; + } + if (sz == 1 && weights[0].is_one() && w.is_zero()) { + return m.mk_not(args[0]); + } + return m_pb.mk_ge(sz, weights, args, w); + } + + bool get_pb_sum(expr* x, rational const& mul, expr_ref_vector& args, vector& coeffs, rational& coeff) { + expr *y, *z, *u; + rational r, q; + app* f = to_app(x); + bool ok = true; + if (a.is_add(x)) { + for (unsigned i = 0; ok && i < f->get_num_args(); ++i) { + ok = get_pb_sum(f->get_arg(i), mul, args, coeffs, coeff); + } + } + else if (a.is_sub(x, y, z)) { + ok = get_pb_sum(y, mul, args, coeffs, coeff); + ok = ok && get_pb_sum(z, -mul, args, coeffs, coeff); + } + else if (a.is_uminus(x, y)) { + ok = get_pb_sum(y, -mul, args, coeffs, coeff); + } + else if (a.is_mul(x, y, z) && is_numeral(y, r)) { + ok = get_pb_sum(z, r*mul, args, coeffs, coeff); + } + else if (a.is_mul(x, z, y) && is_numeral(y, r)) { + ok = get_pb_sum(z, r*mul, args, coeffs, coeff); + } + else if (a.is_to_real(x, y)) { + ok = get_pb_sum(y, mul, args, coeffs, coeff); + } + else if (m.is_ite(x, y, z, u) && is_numeral(z, r) && is_numeral(u, q)) { + insert_arg(r*mul, y, args, coeffs, coeff); + // q*(1-y) = -q*y + q + coeff += q*mul; + insert_arg(-q*mul, y, args, coeffs, coeff); + } + else if (is_01var(x)) { + insert_arg(mul, mk_01(x), args, coeffs, coeff); + } + else if (is_numeral(x, r)) { + coeff += mul*r; + } + else { + TRACE("pb", tout << "Can't handle " << mk_pp(x, m) << "\n";); + ok = false; + } + return ok; + } + + bool is_numeral(expr* e, rational& r) { + if (a.is_uminus(e, e) && is_numeral(e, r)) { + r.neg(); + return true; + } + if (a.is_to_real(e, e)) { + return is_numeral(e, r); + } + return a.is_numeral(e, r); + } + + void insert_arg(rational const& p, expr* x, + expr_ref_vector& args, vector& coeffs, rational& coeff) { + if (p.is_neg()) { + // p*x = -p*(1-x) + p + args.push_back(m.mk_not(x)); + coeffs.push_back(-p); + coeff += p; + } + else if (p.is_pos()) { + args.push_back(x); + coeffs.push_back(p); + } + } + + virtual tactic * translate(ast_manager & m) { + return alloc(lia2card_tactic, m, m_params); + } + + virtual void collect_param_descrs(param_descrs & r) { + r.insert("compile_equality", CPK_BOOL, + "(default:false) compile equalities into pseudo-Boolean equality"); + } + + virtual void cleanup() { + #pragma omp critical (tactic_cancel) + { + m_01s.reset(); + m_todo.reset(); + } + } +}; + +tactic * mk_lia2card_tactic(ast_manager & m, params_ref const & p) { + return clean(alloc(lia2card_tactic, m, p)); +} + +bool get_pb_sum(expr* term, expr_ref_vector& args, vector& coeffs, rational& coeff) { + params_ref p; + ast_manager& m = args.get_manager(); + lia2card_tactic tac(m, p); + return tac.get_pb_sum(term, rational::one(), args, coeffs, coeff); +} diff --git a/src/tactic/arith/lia2card_tactic.h b/src/tactic/arith/lia2card_tactic.h new file mode 100644 index 000000000..de25ce409 --- /dev/null +++ b/src/tactic/arith/lia2card_tactic.h @@ -0,0 +1,35 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + lia2card_tactic.h + +Abstract: + + Extract 0-1 integer variables used in + cardinality constraints and replace them by Booleans. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-5 + +Notes: + +--*/ +#ifndef _LIA2CARD_TACTIC_H_ +#define _LIA2CARD_TACTIC_H_ + +#include"params.h" +class ast_manager; +class tactic; + +tactic * mk_lia2card_tactic(ast_manager & m, params_ref const & p = params_ref()); + +/* + ADD_TACTIC("lia2card", "introduce cardinality constraints from 0-1 integer.", "mk_lia2card_tactic(m, p)") +*/ + +bool get_pb_sum(expr* term, expr_ref_vector& args, vector& coeffs, rational& coeff); + +#endif diff --git a/src/tactic/arith/lia2pb_tactic.cpp b/src/tactic/arith/lia2pb_tactic.cpp index 33d5f138e..8d200c80d 100644 --- a/src/tactic/arith/lia2pb_tactic.cpp +++ b/src/tactic/arith/lia2pb_tactic.cpp @@ -293,9 +293,12 @@ class lia2pb_tactic : public tactic { m_rw(curr, new_curr, new_pr); if (m_produce_unsat_cores) { dep = m.mk_join(m_rw.get_used_dependencies(), g->dep(idx)); - m_rw.reset_used_dependencies(); + m_rw.reset_used_dependencies(); } - g->update(idx, new_curr, 0, dep); + if (m.proofs_enabled()) { + new_pr = m.mk_modus_ponens(g->pr(idx), new_pr); + } + g->update(idx, new_curr, new_pr, dep); } g->inc_depth(); result.push_back(g.get()); diff --git a/src/tactic/arith/purify_arith_tactic.cpp b/src/tactic/arith/purify_arith_tactic.cpp index f2ddd86ce..e18c6e90b 100644 --- a/src/tactic/arith/purify_arith_tactic.cpp +++ b/src/tactic/arith/purify_arith_tactic.cpp @@ -707,7 +707,7 @@ public: virtual void collect_param_descrs(param_descrs & r) { r.insert("complete", CPK_BOOL, - "(default: true) add constraints to make sure that any interpretation of a underspecified arithmetic operators is a functio. The result will include additional uninterpreted functions/constants: /0, div0, mod0, 0^0, neg-root"); + "(default: true) add constraints to make sure that any interpretation of a underspecified arithmetic operators is a function. The result will include additional uninterpreted functions/constants: /0, div0, mod0, 0^0, neg-root"); r.insert("elim_root_objects", CPK_BOOL, "(default: true) eliminate root objects."); r.insert("elim_inverses", CPK_BOOL, diff --git a/src/tactic/bv/bit_blaster_tactic.cpp b/src/tactic/bv/bit_blaster_tactic.cpp index 33423c8b1..5dbfc4ebd 100644 --- a/src/tactic/bv/bit_blaster_tactic.cpp +++ b/src/tactic/bv/bit_blaster_tactic.cpp @@ -69,6 +69,7 @@ class bit_blaster_tactic : public tactic { expr_ref new_curr(m()); proof_ref new_pr(m()); unsigned size = g->size(); + bool change = false; for (unsigned idx = 0; idx < size; idx++) { if (g->inconsistent()) break; @@ -79,10 +80,13 @@ class bit_blaster_tactic : public tactic { proof * pr = g->pr(idx); new_pr = m().mk_modus_ponens(pr, new_pr); } - g->update(idx, new_curr, new_pr, g->dep(idx)); + if (curr != new_curr) { + change = true; + g->update(idx, new_curr, new_pr, g->dep(idx)); + } } - if (g->models_enabled()) + if (change && g->models_enabled()) mc = mk_bit_blaster_model_converter(m(), m_rewriter.const2bits()); else mc = 0; diff --git a/src/tactic/bv/bv_size_reduction_tactic.cpp b/src/tactic/bv/bv_size_reduction_tactic.cpp index e149afc75..707a9284b 100644 --- a/src/tactic/bv/bv_size_reduction_tactic.cpp +++ b/src/tactic/bv/bv_size_reduction_tactic.cpp @@ -151,7 +151,7 @@ struct bv_size_reduction_tactic::imp { // bound is infeasible. } else { - update_signed_upper(to_app(lhs), val); + update_signed_upper(to_app(rhs), val); } } else update_signed_lower(to_app(rhs), val); @@ -229,17 +229,35 @@ struct bv_size_reduction_tactic::imp { else { // l < u if (l.is_neg()) { - unsigned i_nb = (u - l).get_num_bits(); + unsigned l_nb = (-l).get_num_bits(); unsigned v_nb = m_util.get_bv_size(v); - if (i_nb < v_nb) { - new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); - new_def = m_util.mk_sign_extend(v_nb - i_nb, new_const); + + if (u.is_neg()) + { + // l <= v <= u <= 0 + unsigned i_nb = l_nb; + TRACE("bv_size_reduction", tout << " l <= " << v->get_decl()->get_name() << " <= u <= 0 " << " --> " << i_nb << " bits\n";); + if (i_nb < v_nb) { + new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); + new_def = m_util.mk_concat(m_util.mk_numeral(numeral(-1), v_nb - i_nb), new_const); + } + } + else { + // l <= v <= 0 <= u + unsigned u_nb = u.get_num_bits(); + unsigned i_nb = ((l_nb > u_nb) ? l_nb : u_nb) + 1; + TRACE("bv_size_reduction", tout << " l <= " << v->get_decl()->get_name() << " <= 0 <= u " << " --> " << i_nb << " bits\n";); + if (i_nb < v_nb) { + new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); + new_def = m_util.mk_sign_extend(v_nb - i_nb, new_const); + } } } else { // 0 <= l <= v <= u unsigned u_nb = u.get_num_bits(); unsigned v_nb = m_util.get_bv_size(v); + TRACE("bv_size_reduction", tout << l << " <= " << v->get_decl()->get_name() << " <= " << u << " --> " << u_nb << " bits\n";); if (u_nb < v_nb) { new_const = m.mk_fresh_const(0, m_util.mk_sort(u_nb)); new_def = m_util.mk_concat(m_util.mk_numeral(numeral(0), v_nb - u_nb), new_const); diff --git a/src/tactic/core/blast_term_ite_tactic.cpp b/src/tactic/core/blast_term_ite_tactic.cpp new file mode 100644 index 000000000..fbc66c418 --- /dev/null +++ b/src/tactic/core/blast_term_ite_tactic.cpp @@ -0,0 +1,223 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + blast_term_ite_tactic.cpp + +Abstract: + + Blast term if-then-else by hoisting them up. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-4 + +Notes: + +--*/ +#include"tactical.h" +#include"defined_names.h" +#include"rewriter_def.h" +#include"filter_model_converter.h" +#include"cooperate.h" +#include"scoped_proof.h" + + + +// +// (f (if c1 (if c2 e1 e2) e3) b c) -> +// (if c1 (if c2 (f e1 b c) +// + + +class blast_term_ite_tactic : public tactic { + + struct rw_cfg : public default_rewriter_cfg { + ast_manager& m; + unsigned long long m_max_memory; // in bytes + unsigned m_num_fresh; // number of expansions + + rw_cfg(ast_manager & _m, params_ref const & p): + m(_m), + m_num_fresh(0) { + updt_params(p); + } + + void updt_params(params_ref const & p) { + m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX)); + } + + bool max_steps_exceeded(unsigned num_steps) const { + cooperate("blast term ite"); + // if (memory::get_allocation_size() > m_max_memory) + // throw tactic_exception(TACTIC_MAX_MEMORY_MSG); + return false; + } + + br_status mk_app_core(func_decl* f, unsigned num_args, expr* const* args, expr_ref& result) { + if (m.is_ite(f)) { + return BR_FAILED; + } + for (unsigned i = 0; i < num_args; ++i) { + expr* c, *t, *e; + if (!m.is_bool(args[i]) && m.is_ite(args[i], c, t, e)) { + enable_trace("blast_term_ite"); + TRACE("blast_term_ite", result = m.mk_app(f, num_args, args); tout << result << "\n";); + expr_ref e1(m), e2(m); + ptr_vector args1(num_args, args); + args1[i] = t; + ++m_num_fresh; + e1 = m.mk_app(f, num_args, args1.c_ptr()); + if (t == e) { + result = e1; + return BR_REWRITE1; + } + args1[i] = e; + e2 = m.mk_app(f, num_args, args1.c_ptr()); + result = m.mk_app(f, num_args, args); + result = m.mk_ite(c, e1, e2); + return BR_REWRITE3; + } + } + return BR_FAILED; + } + + bool rewrite_patterns() const { return false; } + + br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { + return mk_app_core(f, num, args, result); + } + + }; + + struct rw : public rewriter_tpl { + rw_cfg m_cfg; + + rw(ast_manager & m, params_ref const & p): + rewriter_tpl(m, m.proofs_enabled(), m_cfg), + m_cfg(m, p) { + } + }; + + struct imp { + ast_manager & m; + rw m_rw; + + imp(ast_manager & _m, params_ref const & p): + m(_m), + m_rw(m, p) { + } + + void set_cancel(bool f) { + m_rw.set_cancel(f); + } + + void updt_params(params_ref const & p) { + m_rw.cfg().updt_params(p); + } + + void operator()(goal_ref const & g, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + SASSERT(g->is_well_sorted()); + mc = 0; pc = 0; core = 0; + tactic_report report("blast-term-ite", *g); + bool produce_proofs = g->proofs_enabled(); + + expr_ref new_curr(m); + proof_ref new_pr(m); + unsigned size = g->size(); + for (unsigned idx = 0; idx < size; idx++) { + expr * curr = g->form(idx); + m_rw(curr, new_curr, new_pr); + if (produce_proofs) { + proof * pr = g->pr(idx); + new_pr = m.mk_modus_ponens(pr, new_pr); + } + g->update(idx, new_curr, new_pr, g->dep(idx)); + } + report_tactic_progress(":blast-term-ite-consts", m_rw.m_cfg.m_num_fresh); + g->inc_depth(); + result.push_back(g.get()); + TRACE("blast_term_ite", g->display(tout);); + SASSERT(g->is_well_sorted()); + } + }; + + imp * m_imp; + params_ref m_params; +public: + blast_term_ite_tactic(ast_manager & m, params_ref const & p): + m_params(p) { + m_imp = alloc(imp, m, p); + } + + virtual tactic * translate(ast_manager & m) { + return alloc(blast_term_ite_tactic, m, m_params); + } + + virtual ~blast_term_ite_tactic() { + dealloc(m_imp); + } + + virtual void updt_params(params_ref const & p) { + m_params = p; + m_imp->m_rw.cfg().updt_params(p); + } + + virtual void collect_param_descrs(param_descrs & r) { + insert_max_memory(r); + insert_max_steps(r); + r.insert("max_args", CPK_UINT, + "(default: 128) maximum number of arguments (per application) that will be considered by the greedy (quadratic) heuristic."); + } + + virtual void operator()(goal_ref const & in, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + (*m_imp)(in, result, mc, pc, core); + } + + virtual void cleanup() { + ast_manager & m = m_imp->m; + imp * d = m_imp; + #pragma omp critical (tactic_cancel) + { + m_imp = 0; + } + dealloc(d); + d = alloc(imp, m, m_params); + #pragma omp critical (tactic_cancel) + { + m_imp = d; + } + } + + virtual void set_cancel(bool f) { + if (m_imp) + m_imp->set_cancel(f); + } + + static void blast_term_ite(expr_ref& fml) { + ast_manager& m = fml.get_manager(); + scoped_no_proof _sp(m); + params_ref p; + rw ite_rw(m, p); + expr_ref tmp(m); + ite_rw(fml, tmp); + fml = tmp; + } +}; + +tactic * mk_blast_term_ite_tactic(ast_manager & m, params_ref const & p) { + return clean(alloc(blast_term_ite_tactic, m, p)); +} + +void blast_term_ite(expr_ref& fml) { + blast_term_ite_tactic::blast_term_ite(fml); +} diff --git a/src/tactic/core/blast_term_ite_tactic.h b/src/tactic/core/blast_term_ite_tactic.h new file mode 100644 index 000000000..6756b29d3 --- /dev/null +++ b/src/tactic/core/blast_term_ite_tactic.h @@ -0,0 +1,38 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + blast_term_ite_tactic.h + +Abstract: + + Blast term if-then-else by hoisting them up. + This is expensive but useful in some cases, such as + for enforcing constraints being in difference logic. + Use elim-term-ite elsewhere when possible. + + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-4 + +Notes: + +--*/ +#ifndef _BLAST_TERM_ITE_TACTIC_H_ +#define _BLAST_TERM_ITE_TACTIC_H_ + +#include"params.h" +class ast_manager; +class tactic; + +tactic * mk_blast_term_ite_tactic(ast_manager & m, params_ref const & p = params_ref()); + +/* + ADD_TACTIC("blast-term-ite", "blast term if-then-else by hoisting them.", "mk_blast_term_ite_tactic(m, p)") +*/ + +void blast_term_ite(expr_ref& fml); + +#endif diff --git a/src/tactic/core/pb_preprocess_tactic.cpp b/src/tactic/core/pb_preprocess_tactic.cpp new file mode 100644 index 000000000..51e92ef11 --- /dev/null +++ b/src/tactic/core/pb_preprocess_tactic.cpp @@ -0,0 +1,678 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + pb_preprocess_tactic.cpp + +Abstract: + + Pre-process pseudo-Boolean inequalities using + generalized Davis Putnam (resolution) to eliminate variables. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-12-23 + +Notes: + + Resolution for PB constraints require the implicit + inequalities that each variable ranges over [0,1] + so not all resolvents produce smaller sets of clauses. + + We here implement subsumption resolution. + + x + y >= 1 + A~x + B~y + Cz >= k + --------------------- + Cz >= k - B + + where A <= B, x, y do not occur elsewhere. + + +--*/ +#include "pb_preprocess_tactic.h" +#include "tactical.h" +#include "for_each_expr.h" +#include "pb_decl_plugin.h" +#include "th_rewriter.h" +#include "expr_substitution.h" +#include "ast_pp.h" + +class pb_preproc_model_converter : public model_converter { + ast_manager& m; + pb_util pb; + expr_ref_vector m_refs; + svector > m_const; + +public: + pb_preproc_model_converter(ast_manager& m):m(m), pb(m), m_refs(m) {} + + virtual void operator()(model_ref & mdl, unsigned goal_idx) { + SASSERT(goal_idx == 0); + for (unsigned i = 0; i < m_const.size(); ++i) { + mdl->register_decl(m_const[i].first->get_decl(), m_const[i].second); + } + } + + void set_value(expr* e, bool p) { + while (m.is_not(e, e)) { + p = !p; + } + SASSERT(is_app(e)); + set_value_p(to_app(e), p?m.mk_true():m.mk_false()); + } + + virtual model_converter * translate(ast_translation & translator) { + pb_preproc_model_converter* mc = alloc(pb_preproc_model_converter, translator.to()); + for (unsigned i = 0; i < m_const.size(); ++i) { + mc->set_value_p(translator(m_const[i].first), translator(m_const[i].second)); + } + return mc; + } + +private: + void set_value_p(app* e, expr* v) { + SASSERT(e->get_num_args() == 0); + SASSERT(is_uninterp_const(e)); + m_const.push_back(std::make_pair(e, v)); + m_refs.push_back(e); + m_refs.push_back(v); + } + +}; + +class pb_preprocess_tactic : public tactic { + struct rec { unsigned_vector pos, neg; rec() { } }; + typedef obj_map var_map; + ast_manager& m; + pb_util pb; + var_map m_vars; + unsigned_vector m_ge; + unsigned_vector m_other; + bool m_progress; + th_rewriter m_r; + + + struct declassifier { + var_map& m_vars; + declassifier(var_map& v): m_vars(v) {} + + void operator()(app* e) { + if (m_vars.contains(e)) { + m_vars.remove(e); + } + } + void operator()(var*) {} + void operator()(quantifier*) {} + }; + + void display_annotation(std::ostream& out, goal_ref const& g) { + for (unsigned i = 0; i < m_ge.size(); ++i) { + out << "ge " << m_ge[i] << ": " << mk_pp(g->form(m_ge[i]), m) << "\n"; + } + for (unsigned i = 0; i < m_other.size(); ++i) { + out << "ot " << m_other[i] << ": " << mk_pp(g->form(m_other[i]), m) << "\n"; + } + + var_map::iterator it = m_vars.begin(); + var_map::iterator end = m_vars.end(); + for (; it != end; ++it) { + app* e = it->m_key; + unsigned_vector const& pos = it->m_value.pos; + unsigned_vector const& neg = it->m_value.neg; + out << mk_pp(e, m) << ": "; + for (unsigned i = 0; i < pos.size(); ++i) { + out << "p: " << pos[i] << " "; + } + for (unsigned i = 0; i < neg.size(); ++i) { + out << "n: " << neg[i] << " "; + } + out << "\n"; + } + } + +public: + pb_preprocess_tactic(ast_manager& m, params_ref const& p = params_ref()): + m(m), pb(m), m_r(m) {} + + virtual ~pb_preprocess_tactic() {} + + virtual tactic * translate(ast_manager & m) { + return alloc(pb_preprocess_tactic, m); + } + + virtual void operator()( + goal_ref const & g, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + SASSERT(g->is_well_sorted()); + pc = 0; core = 0; + + if (g->unsat_core_enabled()) { + throw tactic_exception("pb-preprocess does not support cores"); + } + if (g->proofs_enabled()) { + throw tactic_exception("pb-preprocess does not support proofs"); + } + + pb_preproc_model_converter* pp = alloc(pb_preproc_model_converter, m); + mc = pp; + + g->inc_depth(); + result.push_back(g.get()); + while (simplify(g, *pp)); + // decompose(g); + } + + bool simplify(goal_ref const& g, pb_preproc_model_converter& mc) { + reset(); + normalize(g); + if (g->inconsistent()) { + return false; + } + for (unsigned i = 0; i < g->size(); ++i) { + process_vars(i, g); + } + + if (m_ge.empty()) { + return false; + } + + for (unsigned i = 0; i < m_ge.size(); ++i) { + classify_vars(i, to_app(g->form(m_ge[i]))); + } + + declassifier dcl(m_vars); + expr_mark visited; + for (unsigned i = 0; !m_vars.empty() && i < m_other.size(); ++i) { + for_each_expr(dcl, visited, g->form(m_other[i])); + } + + if (m_vars.empty()) { + return false; + } + + // display_annotation(tout, g); + m_progress = false; + // first eliminate variables + var_map::iterator it = next_resolvent(m_vars.begin()); + while (it != m_vars.end()) { + app * e = it->m_key; + rec const& r = it->m_value; + if (r.pos.empty()) { + replace(r.neg, e, m.mk_false(), g); + mc.set_value(e, false); + } + else if (r.neg.empty()) { + replace(r.pos, e, m.mk_true(), g); + mc.set_value(e, true); + } + if (g->inconsistent()) return false; + ++it; + it = next_resolvent(it); + } + // now resolve clauses. + it = next_resolvent(m_vars.begin()); + while (it != m_vars.end()) { + + app * e = it->m_key; + SASSERT(is_uninterp_const(e)); + rec const& r = it->m_value; + if (r.pos.size() == 1 && !r.neg.empty()) { + resolve(mc, r.pos[0], r.neg, e, true, g); + } + else if (r.neg.size() == 1 && !r.pos.empty()) { + resolve(mc, r.neg[0], r.pos, e, false, g); + } + if (g->inconsistent()) return false; + ++it; + it = next_resolvent(it); + } + + // now check for subsumption. + for (unsigned i = 0; i < m_ge.size(); ++i) { + + expr_ref_vector args1(m), args2(m); + vector coeffs1, coeffs2; + rational k1, k2; + expr* fml = g->form(m_ge[i]); + if (!to_ge(fml, args1, coeffs1, k1)) continue; + if (args1.empty()) continue; + expr* arg = args1[0].get(); + bool neg = m.is_not(arg, arg); + if (!is_uninterp_const(arg)) continue; + if (!m_vars.contains(to_app(arg))) continue; + rec const& r = m_vars.find(to_app(arg)); + unsigned_vector const& pos = neg?r.neg:r.pos; + for (unsigned j = 0; j < pos.size(); ++j) { + unsigned k = pos[j]; + if (k == i) continue; + if (!to_ge(g->form(k), args2, coeffs2, k2)) continue; + if (subsumes(args1, coeffs1, k1, args2, coeffs2, k2)) { + IF_VERBOSE(3, verbose_stream() << "replace " << mk_pp(g->form(k), m) << "\n";); + g->update(k, m.mk_true()); + m_progress = true; + } + } + } + + g->elim_true(); + + return m_progress; + } + + virtual void set_cancel(bool f) { + } + + virtual void updt_params(params_ref const & p) { + } + + virtual void cleanup() { + } + +private: + + void reset() { + m_ge.reset(); + m_other.reset(); + m_vars.reset(); + } + + expr* negate(expr* e) { + if (m.is_not(e, e)) return e; + return m.mk_not(e); + } + + void normalize(goal_ref const& g) { + expr* r; + expr_ref tmp(m); + for (unsigned i = 0; !g->inconsistent() && i < g->size(); ++i) { + expr* e = g->form(i); + if (m.is_not(e, r) && pb.is_ge(r)) { + rational k = pb.get_k(r); + rational sum(0); + expr_ref_vector args(m); + vector coeffs; + for (unsigned j = 0; j < to_app(r)->get_num_args(); ++j) { + sum += pb.get_coeff(r, j); + coeffs.push_back(pb.get_coeff(r, j)); + args.push_back(negate(to_app(r)->get_arg(j))); + } + tmp = pb.mk_ge(args.size(), coeffs.c_ptr(), args.c_ptr(), sum - k + rational::one()); + g->update(i, tmp); + } + } + } + + unsigned log2ceil(unsigned n) { + unsigned p = 1; + while (n > 0) { + n /= 2; + ++p; + } + return p; + } + + /** + \brief decompose large sums into smaller sums by intoducing + auxilary variables. + */ + void decompose(goal_ref const& g) { + expr_ref fml1(m), fml2(m); + for (unsigned i = 0; !g->inconsistent() && i < g->size(); ++i) { + expr* e = g->form(i); + unsigned_vector cuts; + if (cut(e, cuts)) { + app* a = to_app(e); + expr_ref_vector cut_args(m); + vector cut_coeffs; + if (cuts.size() < 2) continue; + unsigned start = 0; + for (unsigned j = 0; j < cuts.size(); ++j) { + unsigned end = cuts[j]; + fml1 = decompose_cut(a, start, end, cut_args, cut_coeffs); + g->assert_expr(fml1); + start = end; + TRACE("pb", tout << fml1 << "\n";); + } + fml2 = pb.mk_ge(cut_args.size(), cut_coeffs.c_ptr(), cut_args.c_ptr(), pb.get_k(e)); + g->update(i, fml2); + TRACE("pb", tout << fml2 << "\n";); + } + } + } + bool cut(expr* e, unsigned_vector& cuts) { + if (!pb.is_ge(e)) return false; + if (to_app(e)->get_num_args() <= 20) return false; + unsigned n = 0, cut = 0; + unsigned sz = to_app(e)->get_num_args(); + for (unsigned i = 0; i < sz; ++i) { + rational r = pb.get_coeff(e, i); + if (!r.is_unsigned()) { + return false; + } + n += r.get_unsigned(); + if (2*log2ceil(n) < cut) { + cuts.push_back(i+1); + n = 0; + cut = 0; + } + else { + ++cut; + } + } + if (!cuts.empty() && cuts.back() + 20 >= sz) { + cuts.pop_back(); + } + cuts.push_back(sz); + return true; + } + + expr_ref decompose_cut(app* e, unsigned start, unsigned end, + expr_ref_vector& cut_args, + vector& cut_coeffs) { + unsigned n = 0, j = 1; + vector coeffs; + expr_ref_vector args(m); + app_ref z(m); + expr_ref fml1(m), fml(m); + + for (unsigned i = start; i < end; ++i) { + rational r = pb.get_coeff(e, i); + n += r.get_unsigned(); + args.push_back(e->get_arg(i)); + coeffs.push_back(r); + } + + while (j <= n) { + z = m.mk_fresh_const("z", m.mk_bool_sort()); + coeffs.push_back(-rational(j)); + args.push_back(z); + cut_coeffs.push_back(rational(j)); + cut_args.push_back(z); + j <<= 1; + } + fml1 = pb.mk_ge(args.size(), coeffs.c_ptr(), args.c_ptr(), rational(0)); + m_r(fml1, fml); + return fml; + } + + + void process_vars(unsigned i, goal_ref const& g) { + expr* r, *e; + e = g->form(i); + + if (is_uninterp_const(e)) { + m_ge.push_back(i); + } + else if (pb.is_ge(e) && pure_args(to_app(e))) { + m_ge.push_back(i); + } + else if (m.is_or(e) && pure_args(to_app(e))) { + m_ge.push_back(i); + } + else if (m.is_not(e, r) && is_uninterp_const(r)) { + m_ge.push_back(i); + } + else { + m_other.push_back(i); + } + } + + void classify_vars(unsigned idx, app* e) { + expr* r; + if (m.is_not(e, r) && is_uninterp_const(r)) { + insert(idx, to_app(r), false); + return; + } + if (is_uninterp_const(e)) { + insert(idx, e, true); + return; + } + for (unsigned i = 0; i < e->get_num_args(); ++i) { + expr* arg = e->get_arg(i); + if (m.is_true(arg) || m.is_false(arg)) { + // no-op + } + else if (m.is_not(arg, r)) { + SASSERT(is_uninterp_const(r)); + insert(idx, to_app(r), false); + } + else { + SASSERT(is_uninterp_const(arg)); + insert(idx, to_app(arg), true); + } + } + } + + void insert(unsigned i, app* e, bool pos) { + SASSERT(is_uninterp_const(e)); + if (!m_vars.contains(e)) { + m_vars.insert(e, rec()); + } + if (pos) { + m_vars.find(e).pos.push_back(i); + } + else { + m_vars.find(e).neg.push_back(i); + } + } + + bool pure_args(app* a) const { + for (unsigned i = 0; i < a->get_num_args(); ++i) { + expr* e = a->get_arg(i); + m.is_not(e, e); + if (!is_uninterp_const(e) && !m.is_true(e) && !m.is_false(e)) { + return false; + } + } + return true; + } + + var_map::iterator next_resolvent(var_map::iterator it) { + if (it == m_vars.end()) { + return it; + } + while (it != m_vars.end() && it->m_value.pos.size() > 1 && it->m_value.neg.size() > 1) { + ++it; + } + return it; + } + + rational get_coeff(unsigned num_args, expr* const* args, rational const* coeffs, expr* e) { + for (unsigned i = 0; i < num_args; ++i) { + if (args[i] == e) return coeffs[i]; + } + return rational::zero(); + } + + // + // one of the formulas are replaced by T after resolution + // so if there is a pointer into that formula, we can no + // longer assume variables have unique occurrences. + // + bool is_valid(unsigned_vector const& positions, goal_ref const& g) const { + for (unsigned i = 0; i < positions.size(); ++i) { + unsigned idx = positions[i]; + if (m.is_true(g->form(idx))) return false; + } + return true; + } + + bool is_reduction(unsigned_vector const& pos, app* fml, goal_ref const& g) { + unsigned sz = fml->get_num_args(); + for (unsigned i = 0; i < pos.size(); ++i) { + if (!is_app(g->form(pos[i]))) return false; + if (to_app(g->form(pos[i]))->get_num_args() < sz) return false; + } + return true; + } + + // Implement very special case of resolution. + + void resolve(pb_preproc_model_converter& mc, unsigned idx1, + unsigned_vector const& positions, app* e, bool pos, goal_ref const& g) { + if (positions.size() != 1) return; + unsigned idx2 = positions[0]; + expr_ref tmp1(m), tmp2(m); + expr* fml1 = g->form(idx1); + expr* fml2 = g->form(idx2); + TRACE("pb", tout << mk_pp(fml1, m) << " " << mk_pp(fml2, m) << "\n";); + expr_ref_vector args1(m), args2(m); + vector coeffs1, coeffs2; + rational k1, k2; + if (!to_ge(fml1, args1, coeffs1, k1)) return; + if (!k1.is_one()) return; + if (!to_ge(g->form(idx2), args2, coeffs2, k2)) return; + // check that each variable in idx1 occurs only in idx2 + unsigned min_index = 0; + rational min_coeff(0); + unsigned_vector indices; + for (unsigned i = 0; i < args1.size(); ++i) { + expr* x = args1[i].get(); + m.is_not(x, x); + if (!is_app(x)) return; + if (!m_vars.contains(to_app(x))) return; + TRACE("pb", tout << mk_pp(x, m) << "\n";); + rec const& r = m_vars.find(to_app(x)); + if (r.pos.size() != 1 || r.neg.size() != 1) return; + if (r.pos[0] != idx2 && r.neg[0] != idx2) return; + for (unsigned j = 0; j < args2.size(); ++j) { + if (is_complement(args1[i].get(), args2[j].get())) { + if (i == 0) { + min_coeff = coeffs2[j]; + } + else if (min_coeff > coeffs2[j]) { + min_coeff = coeffs2[j]; + min_index = j; + } + indices.push_back(j); + } + } + } + for (unsigned i = 0; i < indices.size(); ++i) { + unsigned j = indices[i]; + expr* arg = args2[j].get(); + if (j == min_index) { + args2[j] = m.mk_false(); + } + else { + args2[j] = m.mk_true(); + } + mc.set_value(arg, j != min_index); + } + + tmp1 = pb.mk_ge(args2.size(), coeffs2.c_ptr(), args2.c_ptr(), k2); + IF_VERBOSE(3, verbose_stream() << " " << tmp1 << "\n"; + for (unsigned i = 0; i < args2.size(); ++i) { + verbose_stream() << mk_pp(args2[i].get(), m) << " "; + } + verbose_stream() << "\n"; + ); + m_r(tmp1, tmp2); + if (pb.is_ge(tmp2) && pb.get_k(to_app(tmp2)).is_one()) { + tmp2 = m.mk_or(to_app(tmp2)->get_num_args(), to_app(tmp2)->get_args()); + } + IF_VERBOSE(3, + verbose_stream() << "resolve: " << mk_pp(fml1, m) << "\n" << mk_pp(fml2, m) << "\n" << tmp1 << "\n"; + verbose_stream() << "to\n" << mk_pp(fml2, m) << " -> " << tmp2 << "\n";); + + g->update(idx1, m.mk_true()); // proof & dependencies + g->update(idx2, tmp2); // proof & dependencies + m_progress = true; + //IF_VERBOSE(0, if (!g->inconsistent()) display_annotation(verbose_stream(), g);); + } + + bool is_complement(expr* x, expr* y) const { + if (m.is_not(x,x)) return x == y; + if (m.is_not(y,y)) return x == y; + return false; + } + + bool to_ge(expr* e, expr_ref_vector& args, vector& coeffs, rational& k) { + expr* r; + if (is_uninterp_const(e)) { + args.push_back(e); + coeffs.push_back(rational::one()); + k = rational::one(); + } + else if (m.is_not(e, r) && is_uninterp_const(r)) { + args.push_back(e); + coeffs.push_back(rational::one()); + k = rational::one(); + } + else if (pb.is_ge(e)) { + app* a = to_app(e); + SASSERT(pure_args(a)); + for (unsigned i = 0; i < a->get_num_args(); ++i) { + args.push_back(a->get_arg(i)); + coeffs.push_back(pb.get_coeff(a, i)); + } + k = pb.get_k(e); + } + else if (m.is_or(e)) { + app* a = to_app(e); + SASSERT(pure_args(a)); + for (unsigned i = 0; i < a->get_num_args(); ++i) { + args.push_back(a->get_arg(i)); + coeffs.push_back(rational::one()); + } + k = rational::one(); + } + else { + return false; + } + return true; + } + + void replace(unsigned_vector const& positions, expr* e, expr* v, goal_ref const& g) { + if (!is_valid(positions, g)) return; + expr_substitution sub(m); + sub.insert(e, v); + expr_ref tmp(m); + m_r.set_substitution(&sub); + for (unsigned i = 0; i < positions.size(); ++i) { + unsigned idx = positions[i]; + expr_ref f(m); + f = g->form(idx); + if (!m.is_true(f)) { + m_r(f, tmp); + if (tmp != f) { + TRACE("pb", tout << mk_pp(f, m) << " -> " << tmp + << " by " << mk_pp(e, m) << " |-> " << mk_pp(v, m) << "\n";); + IF_VERBOSE(3, verbose_stream() << "replace " << mk_pp(f, m) << " -> " << tmp << "\n";); + g->update(idx, tmp); // proof & dependencies. + m_progress = true; + } + } + } + m_r.set_substitution(0); + } + + bool subsumes(expr_ref_vector const& args1, + vector const& coeffs1, rational const& k1, + expr_ref_vector const& args2, + vector const& coeffs2, rational const& k2) { + if (k2 > k1) return false; + for (unsigned i = 0; i < args1.size(); ++i) { + bool found = false; + for (unsigned j = 0; !found && j < args2.size(); ++j) { + if (args1[i] == args2[j]) { + if (coeffs1[i] > coeffs2[j]) return false; + found = true; + } + } + if (!found) return false; + } + return true; + } +}; + + +tactic * mk_pb_preprocess_tactic(ast_manager & m, params_ref const & p) { + return alloc(pb_preprocess_tactic, m); +} + diff --git a/src/tactic/core/pb_preprocess_tactic.h b/src/tactic/core/pb_preprocess_tactic.h new file mode 100644 index 000000000..5746779b7 --- /dev/null +++ b/src/tactic/core/pb_preprocess_tactic.h @@ -0,0 +1,34 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + pb_preprocess_tactic.h + +Abstract: + + Pre-process pseudo-Boolean inequalities using + generalized Davis Putnam (resolution) to eliminate variables. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-12-23 + +Notes: + +--*/ +#ifndef _PB_PREPROCESS_TACTIC_H_ +#define _PB_PREPROCESS_TACTIC_H_ + +#include"params.h" +class ast_manager; +class tactic; + +tactic * mk_pb_preprocess_tactic(ast_manager & m, params_ref const & p = params_ref()); + +/* + ADD_TACTIC("pb-preprocess", "pre-process pseudo-Boolean constraints a la Davis Putnam.", "mk_pb_preprocess_tactic(m, p)") +*/ + + +#endif diff --git a/src/tactic/core/propagate_values_tactic.cpp b/src/tactic/core/propagate_values_tactic.cpp index 5873efd61..39df3b174 100644 --- a/src/tactic/core/propagate_values_tactic.cpp +++ b/src/tactic/core/propagate_values_tactic.cpp @@ -135,6 +135,7 @@ class propagate_values_tactic : public tactic { TRACE("shallow_context_simplifier_bug", tout << mk_ismt2_pp(curr, m()) << "\n---->\n" << mk_ismt2_pp(new_curr, m()) << "\n";); push_result(new_curr, new_pr); + if (new_curr != curr) m_modified = true; } @@ -160,6 +161,9 @@ class propagate_values_tactic : public tactic { if (m_goal->inconsistent()) goto end; + if (m_max_rounds == 0) + goto end; + m_subst = alloc(expr_substitution, m(), g->unsat_core_enabled(), g->proofs_enabled()); m_r.set_substitution(m_subst.get()); m_occs(*m_goal); diff --git a/src/tactic/core/simplify_tactic.cpp b/src/tactic/core/simplify_tactic.cpp index 39f10e10c..80be97b0b 100644 --- a/src/tactic/core/simplify_tactic.cpp +++ b/src/tactic/core/simplify_tactic.cpp @@ -31,6 +31,9 @@ struct simplify_tactic::imp { m_num_steps(0) { } + ~imp() { + } + ast_manager & m() const { return m_manager; } void set_cancel(bool f) { diff --git a/src/tactic/fpa/fpa2bv_model_converter.cpp b/src/tactic/fpa/fpa2bv_model_converter.cpp index 9b4b5a70f..53fa2405b 100644 --- a/src/tactic/fpa/fpa2bv_model_converter.cpp +++ b/src/tactic/fpa/fpa2bv_model_converter.cpp @@ -111,14 +111,25 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { unsigned ebits = fu.get_ebits(var->get_range()); unsigned sbits = fu.get_sbits(var->get_range()); - expr_ref sgn(m), sig(m), exp(m); - sgn = bv_mdl->get_const_interp(to_app(a->get_arg(0))->get_decl()); - sig = bv_mdl->get_const_interp(to_app(a->get_arg(1))->get_decl()); - exp = bv_mdl->get_const_interp(to_app(a->get_arg(2))->get_decl()); + expr_ref sgn(m), sig(m), exp(m); + bv_mdl->eval(a->get_arg(0), sgn, true); + bv_mdl->eval(a->get_arg(1), sig, true); + bv_mdl->eval(a->get_arg(2), exp, true); + SASSERT(a->is_app_of(fu.get_family_id(), OP_TO_FLOAT)); + +#ifdef Z3DEBUG + SASSERT(to_app(a->get_arg(0))->get_decl()->get_arity() == 0); + SASSERT(to_app(a->get_arg(1))->get_decl()->get_arity() == 0); + SASSERT(to_app(a->get_arg(1))->get_decl()->get_arity() == 0); seen.insert(to_app(a->get_arg(0))->get_decl()); seen.insert(to_app(a->get_arg(1))->get_decl()); seen.insert(to_app(a->get_arg(2))->get_decl()); +#else + SASSERT(a->get_arg(0)->get_kind() == OP_EXTRACT); + SASSERT(to_app(a->get_arg(0))->get_arg(0)->get_kind() == OP_EXTRACT); + seen.insert(to_app(to_app(a->get_arg(0))->get_arg(0))->get_decl()); +#endif if (!sgn && !sig && !exp) continue; diff --git a/src/tactic/fpa/qffpa_tactic.cpp b/src/tactic/fpa/qffpa_tactic.cpp index f9b7f88a1..43c043081 100644 --- a/src/tactic/fpa/qffpa_tactic.cpp +++ b/src/tactic/fpa/qffpa_tactic.cpp @@ -78,7 +78,7 @@ struct is_non_qffpabv_predicate { void operator()(app * n) { sort * s = get_sort(n); - if (!m.is_bool(s) && !fu.is_float(s) && !fu.is_rm(s) && !bu.is_bv_sort(s)) + if (!(m.is_bool(s) || fu.is_float(s) || fu.is_rm(s) || bu.is_bv_sort(s))) throw found(); family_id fid = n->get_family_id(); if (fid == m.get_basic_family_id()) @@ -113,4 +113,4 @@ probe * mk_is_qffpa_probe() { probe * mk_is_qffpabv_probe() { return alloc(is_qffpabv_probe); } - \ No newline at end of file + diff --git a/src/tactic/horn_subsume_model_converter.cpp b/src/tactic/horn_subsume_model_converter.cpp index ced4e657b..25da094fa 100644 --- a/src/tactic/horn_subsume_model_converter.cpp +++ b/src/tactic/horn_subsume_model_converter.cpp @@ -43,7 +43,7 @@ bool horn_subsume_model_converter::mk_horn( app* head, expr* body, func_decl_ref& pred, expr_ref& body_res) { expr_ref_vector conjs(m), subst(m); - ptr_vector sorts, sorts2; + ptr_vector sorts2; var_subst vs(m, false); if (!is_uninterp(head)) { @@ -53,28 +53,27 @@ bool horn_subsume_model_converter::mk_horn( pred = head->get_decl(); unsigned arity = head->get_num_args(); - get_free_vars(head, sorts); - get_free_vars(body, sorts); + expr_free_vars fv; + fv(head); + fv.accumulate(body); - if (arity == 0 && sorts.empty()) { + if (arity == 0 && fv.empty()) { body_res = body; return true; } + fv.set_default_sort(m.mk_bool_sort()); svector names; - for (unsigned i = 0; i < sorts.size(); ++i) { - if (!sorts[i]) { - sorts[i] = m.mk_bool_sort(); - } + for (unsigned i = 0; i < fv.size(); ++i) { names.push_back(symbol(i)); } names.reverse(); - sorts.reverse(); + fv.reverse(); conjs.push_back(body); for (unsigned i = 0; i < arity; ++i) { expr* arg = head->get_arg(i); var_ref v(m); - v = m.mk_var(sorts.size()+i, m.get_sort(arg)); + v = m.mk_var(fv.size()+i, m.get_sort(arg)); if (is_var(arg)) { unsigned w = to_var(arg)->get_idx(); @@ -101,12 +100,12 @@ bool horn_subsume_model_converter::mk_horn( vs(tmp, subst.size(), subst.c_ptr(), body_expr); } - if (sorts.empty()) { + if (fv.empty()) { SASSERT(subst.empty()); body_res = body_expr; } else { - body_res = m.mk_exists(sorts.size(), sorts.c_ptr(), names.c_ptr(), body_expr.get()); + body_res = m.mk_exists(fv.size(), fv.c_ptr(), names.c_ptr(), body_expr.get()); m_rewrite(body_res); } @@ -120,10 +119,9 @@ bool horn_subsume_model_converter::mk_horn( bool horn_subsume_model_converter::mk_horn( expr* clause, func_decl_ref& pred, expr_ref& body) { - ptr_vector sorts; // formula is closed. - DEBUG_CODE(get_free_vars(clause, sorts); SASSERT(sorts.empty());); + DEBUG_CODE(expr_free_vars fv; fv(clause); SASSERT(fv.empty());); while (is_quantifier(clause) && to_quantifier(clause)->is_forall()) { quantifier* q = to_quantifier(clause); diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 9ecc16ecf..1cab40093 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -30,7 +30,7 @@ Notes: #include"qffpa_tactic.h" tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { - tactic * st = using_params(and_then(mk_simplify_tactic(m), + tactic * st = using_params(and_then(mk_simplify_tactic(m), cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index ae79446e3..a2f8a97f7 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -41,7 +41,7 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const if (logic=="QF_UF") return mk_qfuf_tactic(m, p); else if (logic=="QF_BV") - return mk_qfbv_tactic(m, p); + return mk_qfbv_tactic(m, p); else if (logic=="QF_IDL") return mk_qfidl_tactic(m, p); else if (logic=="QF_LIA") diff --git a/src/tactic/probe.cpp b/src/tactic/probe.cpp index 1a696dc78..9f1ed8c72 100644 --- a/src/tactic/probe.cpp +++ b/src/tactic/probe.cpp @@ -283,13 +283,12 @@ struct is_non_qfbv_predicate { if (!m.is_bool(n) && !u.is_bv(n)) throw found(); family_id fid = n->get_family_id(); - if (fid == m.get_basic_family_id()) + if (fid == m.get_basic_family_id()) return; if (fid == u.get_family_id()) return; if (is_uninterp_const(n)) return; - throw found(); } }; diff --git a/src/tactic/sls/bvsls_opt_engine.cpp b/src/tactic/sls/bvsls_opt_engine.cpp new file mode 100644 index 000000000..a674e8a25 --- /dev/null +++ b/src/tactic/sls/bvsls_opt_engine.cpp @@ -0,0 +1,366 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + bvsls_opt_engine.cpp + +Abstract: + + Optimization extensions to bvsls + +Author: + + Christoph (cwinter) 2014-03-28 + +Notes: + +--*/ +#include "nnf.h" +#include "bvsls_opt_engine.h" + +bvsls_opt_engine::bvsls_opt_engine(ast_manager & m, params_ref const & p) : + sls_engine(m, p), + m_hard_tracker(sls_engine::m_tracker), + m_obj_tracker(m, m_bv_util, m_mpz_manager, m_powers), + m_obj_evaluator(m, m_bv_util, m_obj_tracker, m_mpz_manager, m_powers) +{ + m_best_model = alloc(model, m); +} + +bvsls_opt_engine::~bvsls_opt_engine() +{ +} + +bvsls_opt_engine::optimization_result bvsls_opt_engine::optimize( + expr_ref const & objective, + model_ref initial_model, + bool _maximize) +{ + SASSERT(m_bv_util.is_bv(objective)); + TRACE("sls_opt", tout << "objective: " << (_maximize?"maximize":"minimize") << " " << + mk_ismt2_pp(objective, m()) << std::endl;); + m_hard_tracker.initialize(m_assertions); + setup_opt_tracker(objective, _maximize); + + if (initial_model.get() != 0) { + TRACE("sls_opt", tout << "Initial model provided: " << std::endl; + for (unsigned i = 0; i < initial_model->get_num_constants(); i++) { + func_decl * fd = initial_model->get_constant(i); + expr * val = initial_model->get_const_interp(fd); + tout << fd->get_name() << " := " << mk_ismt2_pp(val, m()) << std::endl; + }); + m_hard_tracker.set_model(initial_model); + m_evaluator.update_all(); + } + + optimization_result res(m_manager); + lbool is_sat = m_hard_tracker.is_sat() ? l_true : l_undef; + + TRACE("sls_opt", tout << "initial model is sat? " << is_sat << std::endl;); + + for (m_stats.m_restarts = 0; + m_stats.m_restarts < m_max_restarts; + m_stats.m_restarts++) + { + mpz old_best; + m_mpz_manager.set(old_best, m_best_model_score); + + if (is_sat != l_true) { + do { + checkpoint(); + + IF_VERBOSE(1, verbose_stream() << "Satisfying... restarts left:" << (m_max_restarts - m_stats.m_restarts) << std::endl;); + is_sat = search(); + + if (is_sat == l_undef) + m_hard_tracker.randomize(m_assertions); + } + while (is_sat != l_true && + m_stats.m_restarts++ < m_max_restarts); + } + + if (is_sat == l_true) { + IF_VERBOSE(1, verbose_stream() << "Optimizing... restarts left:" << (m_max_restarts - m_stats.m_restarts) << std::endl;); + res.is_sat = l_true; + m_obj_tracker.set_model(m_hard_tracker.get_model()); + m_obj_evaluator.update_all(); + expr_ref local_best = maximize(); + if ((_maximize && m_mpz_manager.gt(m_best_model_score, old_best)) || + (!_maximize && m_mpz_manager.lt(m_best_model_score, old_best))) + { + res.optimum = local_best; + } + } + + m_hard_tracker.randomize(m_assertions); + m_evaluator.update_all(); + is_sat = m_hard_tracker.is_sat() ? l_true : l_undef; + } + + TRACE("sls_opt", tout << "sat: " << res.is_sat << "; optimum: " << mk_ismt2_pp(res.optimum, m()) << std::endl;); + + return res; +} + +void bvsls_opt_engine::setup_opt_tracker(expr_ref const & objective, bool _max) +{ + expr_ref obj(m_manager); + obj = objective; + if (!_max) + obj = m_bv_util.mk_bv_neg(objective); + + m_obj_e = obj.get(); + m_obj_bv_sz = m_bv_util.get_bv_size(m_obj_e); + ptr_vector objs; + objs.push_back(m_obj_e); + m_obj_tracker.initialize(objs); +} + +expr_ref bvsls_opt_engine::maximize() +{ + SASSERT(m_hard_tracker.is_sat()); + + TRACE("sls_opt", tout << "Initial opt model:" << std::endl; m_obj_tracker.show_model(tout);); + + mpz score, old_score, max_score, new_value; + unsigned new_const = (unsigned)-1, new_bit = 0; + ptr_vector consts = m_obj_tracker.get_constants(); + move_type move; + m_mpz_manager.set(score, top_score()); + m_mpz_manager.set(max_score, m_powers(m_obj_bv_sz)); m_mpz_manager.dec(max_score); + + IF_VERBOSE(10, verbose_stream() << "Initial score: " << m_mpz_manager.to_string(score) << std::endl;); + + save_model(score); + + while (m_mpz_manager.lt(score, max_score) && check_restart(m_stats.m_moves)) + { + checkpoint(); + m_stats.m_moves++; + m_mpz_manager.set(old_score, score); + new_const = (unsigned)-1; + + mpz score(0); + m_mpz_manager.set(score, + find_best_move(consts, score, new_const, new_value, new_bit, move, max_score, m_obj_e)); + + if (new_const == static_cast(-1)) { + m_mpz_manager.set(score, old_score); + if (m_mpz_manager.gt(score, m_best_model_score)) + save_model(score); + if (!randomize_wrt_hard()) { + // Can't improve and can't randomize; can't do anything other than bail out. + TRACE("sls_opt", tout << "Got stuck; bailing out." << std::endl;); + IF_VERBOSE(10, verbose_stream() << "No local improvements possible." << std::endl;); + goto bailout; + } + m_mpz_manager.set(score, top_score()); + } + else { + m_stats.m_moves++; + TRACE("sls_opt", tout << "New optimum: " << m_mpz_manager.to_string(score) << std::endl;); + IF_VERBOSE(10, verbose_stream() << "New optimum: " << m_mpz_manager.to_string(score) << std::endl;); + func_decl * fd = consts[new_const]; + incremental_score(fd, new_value); + m_obj_evaluator.update(fd, new_value); + m_mpz_manager.set(score, top_score()); + } + } + +bailout: + m_mpz_manager.del(new_value); + + expr_ref res(m_manager); + res = m_bv_util.mk_numeral(m_best_model_score, m_obj_bv_sz); + return res; +} + +void bvsls_opt_engine::save_model(mpz const & score) { + model_ref mdl = m_hard_tracker.get_model(); + model_ref obj_mdl = m_obj_tracker.get_model(); + + for (unsigned i = 0; i < obj_mdl->get_num_constants(); i++) { + func_decl * fd = obj_mdl->get_constant(i); + expr * val = obj_mdl->get_const_interp(fd); + if (mdl->has_interpretation(fd)) { + if (mdl->get_const_interp(fd) != val) + TRACE("sls_opt", tout << "model disagreement on " << fd->get_name() << ": " << + mk_ismt2_pp(val, m()) << " != " << mk_ismt2_pp(mdl->get_const_interp(fd), m()) << std::endl;); + SASSERT(mdl->get_const_interp(fd) == val); + } + else + mdl->register_decl(fd, val); + } + + m_best_model = mdl; + m_mpz_manager.set(m_best_model_score, score); +} + +// checks whether the score outcome of a given move is better than the previous score +bool bvsls_opt_engine::what_if( + func_decl * fd, + const unsigned & fd_inx, + const mpz & temp, + mpz & best_score, + unsigned & best_const, + mpz & best_value) +{ +#if _EARLY_PRUNE_ + double r = incremental_score_prune(fd, temp); +#else + double r = incremental_score(fd, temp); +#endif + + if (r >= 1.0 && m_hard_tracker.is_sat()) { + m_obj_evaluator.update(fd, temp); + mpz cur_best(0); + m_mpz_manager.set(cur_best, top_score()); + + TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << + " --> " << r << "; score=" << m_mpz_manager.to_string(cur_best) << std::endl;); + + if (m_mpz_manager.gt(cur_best, best_score)) { + m_mpz_manager.set(best_score, cur_best); + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + } + else + { + TRACE("sls_whatif_failed", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << + " --> unsatisfied hard constraints" << std::endl;); + } + + return false; +} + +mpz bvsls_opt_engine::find_best_move( + ptr_vector & to_evaluate, + mpz score, + unsigned & best_const, + mpz & best_value, + unsigned & new_bit, + move_type & move, + mpz const & max_score, + expr * objective) +{ + mpz old_value, temp; +#if _USE_MUL3_ || _USE_UNARY_MINUS_ + mpz temp2; +#endif + unsigned bv_sz; + mpz new_score; + m_mpz_manager.set(new_score, score); + + for (unsigned i = 0; i < to_evaluate.size() && m_mpz_manager.lt(new_score, max_score); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_obj_tracker.get_value(fd)); + + // first try to flip every bit + for (unsigned j = 0; j < bv_sz && m_mpz_manager.lt(new_score, max_score); j++) { + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if(fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { +#if _USE_ADDSUB_ + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } +#endif + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + +#if _USE_UNARY_MINUS_ + mk_inc(bv_sz, temp, temp2); + if (what_if(fd, i, temp2, new_score, best_const, best_value)) + move = MV_UMIN; +#endif + +#if _USE_MUL2DIV2_ + // try multiplication by 2 + mk_mul2(bv_sz, old_value, temp); + if (what_if(fd, i, temp, new_score, best_const, best_value)) + move = MV_MUL2; + +#if _USE_MUL3_ + // try multiplication by 3 + mk_add(bv_sz, old_value, temp, temp2); + if (what_if(fd, i, temp2, new_score, best_const, best_value)) + move = MV_MUL3; +#endif + + // try division by 2 + mk_div2(bv_sz, old_value, temp); + if (what_if(fd, i, temp, new_score, best_const, best_value)) + move = MV_DIV2; +#endif + } + + // reset to what it was before + double check = incremental_score(fd, old_value); + m_obj_evaluator.update(fd, old_value); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); +#if _USE_MUL3_ + m_mpz_manager.del(temp2); +#endif + + return new_score; +} + +bool bvsls_opt_engine::randomize_wrt_hard() { + ptr_vector consts = m_obj_tracker.get_constants(); + unsigned csz = consts.size(); + unsigned retry_count = csz; + + while (retry_count-- > 0) + { + + unsigned ri = (m_obj_tracker.get_random_uint((csz < 16) ? 4 : (csz < 256) ? 8 : (csz < 4096) ? 12 : (csz < 65536) ? 16 : 32)) % csz; + func_decl * random_fd = consts[ri]; // Random constant + + mpz random_val; // random value. + m_mpz_manager.set(random_val, m_obj_tracker.get_random(random_fd->get_range())); + + mpz old_value; + m_mpz_manager.set(old_value, m_obj_tracker.get_value(random_fd)); + + if (!m_mpz_manager.eq(random_val, old_value)) { + m_evaluator.update(random_fd, random_val); + + if (m_hard_tracker.is_sat()) { + TRACE("sls_opt", tout << "Randomizing " << random_fd->get_name() << " to " << + m_mpz_manager.to_string(random_val) << std::endl;); + m_obj_evaluator.update(random_fd, random_val); + return true; + } + else + m_evaluator.update(random_fd, old_value); + } + } + + return false; +} \ No newline at end of file diff --git a/src/tactic/sls/bvsls_opt_engine.h b/src/tactic/sls/bvsls_opt_engine.h new file mode 100644 index 000000000..64a366d73 --- /dev/null +++ b/src/tactic/sls/bvsls_opt_engine.h @@ -0,0 +1,82 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + bvsls_opt_engine.h + +Abstract: + + Optimization extensions to bvsls + +Author: + + Christoph (cwinter) 2014-03-28 + +Notes: + +--*/ +#ifndef _BVSLS_OPT_ENGINE_H_ +#define _BVSLS_OPT_ENGINE_H_ + +#include "sls_engine.h" + +class bvsls_opt_engine : public sls_engine { + sls_tracker & m_hard_tracker; + sls_tracker m_obj_tracker; + sls_evaluator m_obj_evaluator; + model_ref m_best_model; + mpz m_best_model_score; + unsigned m_obj_bv_sz; + expr * m_obj_e; + +public: + bvsls_opt_engine(ast_manager & m, params_ref const & p); + ~bvsls_opt_engine(); + + class optimization_result { + public: + lbool is_sat; + expr_ref optimum; + optimization_result(ast_manager & m) : is_sat(l_undef), optimum(m) {} + optimization_result& operator=(optimization_result const& other) { + is_sat = other.is_sat; + optimum = other.optimum; + return *this; + } + optimization_result(optimization_result const& other): + is_sat(other.is_sat), + optimum(other.optimum) { + } + }; + + optimization_result optimize(expr_ref const & objective, model_ref initial_model = model_ref(), bool maximize=true); + + void get_model(model_ref & result) { result = m_best_model; } + +protected: + void setup_opt_tracker(expr_ref const & objective, bool _max); + expr_ref maximize(); + + bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, + mpz & best_score, unsigned & best_const, mpz & best_value); + + mpz find_best_move(ptr_vector & to_evaluate, mpz score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move, + mpz const & max_score, expr * objective); + + mpz top_score(void) { + mpz res(0); + obj_hashtable const & top_exprs = m_obj_tracker.get_top_exprs(); + for (obj_hashtable::iterator it = top_exprs.begin(); + it != top_exprs.end(); + it++) + m_mpz_manager.add(res, m_obj_tracker.get_value(*it), res); + return res; + } + + void save_model(mpz const & score); + bool randomize_wrt_hard(); +}; + +#endif diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp new file mode 100644 index 000000000..5e670672e --- /dev/null +++ b/src/tactic/sls/sls_engine.cpp @@ -0,0 +1,635 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + sls_engine.cpp + +Abstract: + + A Stochastic Local Search (SLS) engine + +Author: + + Christoph (cwinter) 2014-03-19 + +Notes: + +--*/ +#include +#include + +#include"map.h" +#include"ast_smt2_pp.h" +#include"ast_pp.h" +#include"var_subst.h" +#include"model_pp.h" +#include"tactic.h" +#include"cooperate.h" +#include"luby.h" + +#include"sls_params.hpp" +#include"sls_engine.h" + + +sls_engine::sls_engine(ast_manager & m, params_ref const & p) : + m_manager(m), + m_powers(m_mpz_manager), + m_zero(m_mpz_manager.mk_z(0)), + m_one(m_mpz_manager.mk_z(1)), + m_two(m_mpz_manager.mk_z(2)), + m_cancel(false), + m_bv_util(m), + m_tracker(m, m_bv_util, m_mpz_manager, m_powers), + m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) +{ + updt_params(p); + m_tracker.updt_params(p); +} + +sls_engine::~sls_engine() { + m_mpz_manager.del(m_zero); + m_mpz_manager.del(m_one); + m_mpz_manager.del(m_two); +} + +void sls_engine::updt_params(params_ref const & _p) { + sls_params p(_p); + m_produce_models = _p.get_bool("model", false); + m_max_restarts = p.max_restarts(); + m_tracker.set_random_seed(p.random_seed()); + m_walksat = p.walksat(); + m_walksat_repick = p.walksat_repick(); + m_paws_sp = p.paws_sp(); + m_paws = m_paws_sp < 1024; + m_wp = p.wp(); + m_vns_mc = p.vns_mc(); + m_vns_repick = p.vns_repick(); + + m_restart_base = p.restart_base(); + m_restart_next = m_restart_base; + m_restart_init = p.restart_init(); + + m_early_prune = p.early_prune(); + m_random_offset = p.random_offset(); + m_rescore = p.rescore(); + + // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. + if (m_walksat_repick && !m_walksat) + NOT_IMPLEMENTED_YET(); + if (m_vns_repick && !m_walksat) + NOT_IMPLEMENTED_YET(); +} + +void sls_engine::collect_statistics(statistics& st) const { + double seconds = m_stats.m_stopwatch.get_current_seconds(); + st.update("sls restarts", m_stats.m_restarts); + st.update("sls full evals", m_stats.m_full_evals); + st.update("sls incr evals", m_stats.m_incr_evals); + st.update("sls incr evals/sec", m_stats.m_incr_evals / seconds); + st.update("sls FLIP moves", m_stats.m_flips); + st.update("sls INC moves", m_stats.m_incs); + st.update("sls DEC moves", m_stats.m_decs); + st.update("sls INV moves", m_stats.m_invs); + st.update("sls moves", m_stats.m_moves); + st.update("sls moves/sec", m_stats.m_moves / seconds); +} + +void sls_engine::checkpoint() { + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + cooperate("sls"); +} + +bool sls_engine::full_eval(model & mdl) { + bool res = true; + + unsigned sz = m_assertions.size(); + for (unsigned i = 0; i < sz && res; i++) { + checkpoint(); + expr_ref o(m_manager); + + if (!mdl.eval(m_assertions[i], o, true)) + exit(ERR_INTERNAL_FATAL); + + res = m_manager.is_true(o.get()); + } + + TRACE("sls", tout << "Evaluation: " << res << std::endl;); + + return res; +} + +double sls_engine::top_score() { + double top_sum = 0.0; + unsigned sz = m_assertions.size(); + for (unsigned i = 0; i < sz; i++) { + expr * e = m_assertions[i]; + top_sum += m_tracker.get_score(e); + } + + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(m_assertions[i]); + tout << " AVG: " << top_sum / (double)sz << std::endl;); + + m_tracker.set_top_sum(top_sum); + + return top_sum; +} + +double sls_engine::rescore() { + m_evaluator.update_all(); + m_stats.m_full_evals++; + return top_score(); +} + +double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { + m_evaluator.serious_update(fd, new_value); + m_stats.m_incr_evals++; + return m_tracker.get_top_sum(); +} + +double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { + m_evaluator.update(fd, new_value); + m_stats.m_incr_evals++; + return m_tracker.get_top_sum(); +} + +double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { + m_stats.m_incr_evals++; + if (m_evaluator.update_prune(fd, new_value)) + return m_tracker.get_top_sum(); + else + return -DBL_MAX; +} + +// checks whether the score outcome of a given move is better than the previous score +bool sls_engine::what_if( + func_decl * fd, + const unsigned & fd_inx, + const mpz & temp, + double & best_score, + unsigned & best_const, + mpz & best_value) { + +#ifdef Z3DEBUG + mpz old_value; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); +#endif + + double r; + if (m_early_prune) + r = incremental_score_prune(fd, temp); + else + r = incremental_score(fd, temp); +#ifdef Z3DEBUG + TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << + " --> " << r << std::endl;); + + m_mpz_manager.del(old_value); +#endif + + // Andreas: Had this idea on my last day. Maybe we could add a noise here similar to the one that worked so well for ucb assertion selection. + // r += 0.0001 * m_tracker.get_random_uint(8); + + // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB. + if (r > best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; +} + +void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.add(old_value, add_value, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + +} + +void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + unsigned shift; + m_mpz_manager.add(old_value, m_one, incremented); + if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) + m_mpz_manager.set(incremented, m_zero); +} + +void sls_engine::mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { + if (m_mpz_manager.is_zero(old_value)) { + m_mpz_manager.set(decremented, m_powers(bv_sz)); + m_mpz_manager.dec(decremented); + } + else + m_mpz_manager.sub(old_value, m_one, decremented); +} + +void sls_engine::mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { + m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); +} + +void sls_engine::mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { + m_mpz_manager.set(flipped, m_zero); + + if (m_bv_util.is_bv_sort(s)) { + mpz mask; + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(old_value, mask, flipped); + m_mpz_manager.del(mask); + } + else if (m_manager.is_bool(s)) + m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); + else + NOT_IMPLEMENTED_YET(); +} + +void sls_engine::mk_random_move(ptr_vector & unsat_constants) +{ + unsigned rnd_mv = 0; + unsigned ucc = unsat_constants.size(); + unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; + func_decl * fd = unsat_constants[rc]; + + mpz new_value; + + sort * srt = fd->get_range(); + if (m_manager.is_bool(srt)) + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + + // Andreas: The other option would be to scale the probability for flips according to the bit-width. + /* unsigned bv_sz2 = m_bv_util.get_bv_size(srt); + rnd_mv = m_tracker.get_random_uint(16) % (bv_sz2 + 3); + if (rnd_mv > 3) rnd_mv = 0; */ + + move_type mt = (move_type)rnd_mv; + + // Andreas: Christoph claimed inversion doesn't make sense, let's do a flip instead. Is this really true? + if (mt == MV_INV) mt = MV_FLIP; + unsigned bit = 0; + + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } + + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout);); + } + + m_evaluator.serious_update(fd, new_value); + m_mpz_manager.del(new_value); +} + +// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. +double sls_engine::find_best_move( + ptr_vector & to_evaluate, + double score, + unsigned & best_const, + mpz & best_value, + unsigned & new_bit, + move_type & move) +{ + mpz old_value, temp; + unsigned bv_sz; + double new_score = score; + + // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list. + unsigned sz = to_evaluate.size(); + unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0; + for (unsigned j = 0; j < sz; j++) { + unsigned i = j + offset; + if (i >= sz) i -= sz; + //for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit + for (unsigned j = 0; j < bv_sz; j++) { + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if(fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + } + // reset to what it was before + incremental_score(fd, old_value); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + + return new_score; +} + +// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. +double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value) { + mpz old_value, temp, temp2; + unsigned bv_sz; + double new_score = score; + + // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list. + unsigned sz = to_evaluate.size(); + unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0; + for (unsigned j = 0; j < sz; j++) { + unsigned i = j + offset; + if (i >= sz) i -= sz; + //for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) { + for (unsigned j = 0; j < bv_sz; j++) { + mk_flip(srt, old_value, j, temp); + for (unsigned l = 0; l < m_vns_mc && l < bv_sz / 2; l++) + { + unsigned k = m_tracker.get_random_uint(16) % bv_sz; + while (k == j) + k = m_tracker.get_random_uint(16) % bv_sz; + mk_flip(srt, temp, k, temp2); + what_if(fd, i, temp2, new_score, best_const, best_value); + } + } + } + // reset to what it was before + incremental_score(fd, old_value); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + m_mpz_manager.del(temp2); + + return new_score; +} + +// main search loop +lbool sls_engine::search() { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit; + mpz new_value; + move_type move; + + score = rescore(); + unsigned sz = m_assertions.size(); + + while (check_restart(m_stats.m_moves)) { + checkpoint(); + m_stats.m_moves++; + + // Andreas: Every base restart interval ... + if (m_stats.m_moves % m_restart_base == 0) + { + // ... potentially smooth the touched counters ... + m_tracker.ucb_forget(m_assertions); + // ... or normalize the top-level score. + if (m_rescore) score = rescore(); + } + + // get candidate variables + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } + + // random walk with probability wp / 1024 + if (m_wp && m_tracker.get_random_uint(10) < m_wp) + { + mk_random_move(to_evaluate); + score = m_tracker.get_top_sum(); + continue; + } + + old_score = score; + new_const = (unsigned)-1; + + // find best increasing move + score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); + + // use Monte Carlo 2-bit-flip sampling if no increasing move was found previously + if (m_vns_mc && (new_const == static_cast(-1))) + score = find_best_move_mc(to_evaluate, score, new_const, new_value); + + // repick assertion if no increasing move was found previously + if (m_vns_repick && (new_const == static_cast(-1))) + { + expr * q = m_tracker.get_new_unsat_assertion(m_assertions); + // only apply if another unsatisfied assertion actually exists + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q); + score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move); + + if (new_const != static_cast(-1)) { + func_decl * fd = to_evaluate2[new_const]; + score = serious_score(fd, new_value); + continue; + } + } + } + + // randomize if no increasing move was found + if (new_const == static_cast(-1)) { + score = old_score; + if (m_walksat_repick) + m_evaluator.randomize_local(m_assertions); + else + m_evaluator.randomize_local(to_evaluate); + + score = m_tracker.get_top_sum(); + + // update assertion weights if a weigthing is enabled (sp < 1024) + if (m_paws) + { + for (unsigned i = 0; i < sz; i++) + { + expr * q = m_assertions[i]; + // smooth weights with probability sp / 1024 + if (m_tracker.get_random_uint(10) < m_paws_sp) + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) + m_tracker.decrease_weight(q); + } + // increase weights otherwise + else + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) + m_tracker.increase_weight(q); + } + } + } + } + // otherwise, apply most increasing move + else { + func_decl * fd = to_evaluate[new_const]; + score = serious_score(fd, new_value); + } + } + +bailout: + m_mpz_manager.del(new_value); + + return res; +} + +void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { + if (g->inconsistent()) { + mc = 0; + return; + } + + m_produce_models = g->models_enabled(); + + for (unsigned i = 0; i < g->size(); i++) + assert_expr(g->form(i)); + + lbool res = operator()(); + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + + if (m_produce_models) { + model_ref mdl = m_tracker.get_model(); + mc = model2model_converter(mdl.get()); + TRACE("sls_model", mc->display(tout);); + } + g->reset(); + } + else + mc = 0; +} + +lbool sls_engine::operator()() { + m_tracker.initialize(m_assertions); + lbool res = l_undef; + + do { + checkpoint(); + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + res = search(); + + if (res == l_undef) + { + if (m_restart_init) + m_tracker.randomize(m_assertions); + else + m_tracker.reset(m_assertions); + } + } while (res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + return res; +} + +/* Andreas: Needed for Armin's restart scheme if we don't want to use loops. +double sls_engine::get_restart_armin(unsigned cnt_restarts) +{ + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); +} +*/ + +unsigned sls_engine::check_restart(unsigned curr_value) +{ + if (curr_value > m_restart_next) + { + /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save one parameter. + I leave the other versions as comments in case you want to try it again somewhen. +#if _RESTART_SCHEME_ == 5 + m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); +#elif _RESTART_SCHEME_ == 4 + m_restart_next += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? m_restart_base : (m_restart_base * m_stats.m_restarts + 1); +#elif _RESTART_SCHEME_ == 3 + m_restart_next += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * m_restart_base; +#elif _RESTART_SCHEME_ == 2 + m_restart_next += get_luby(m_stats.m_restarts + 1) * m_restart_base; +#elif _RESTART_SCHEME_ == 1 + if (m_stats.m_restarts & 1) + m_restart_next += m_restart_base; + else + m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base; +#else + m_restart_limit += m_restart_base; +#endif */ + if (m_stats.m_restarts & 1) + m_restart_next += m_restart_base; + else + m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base; + return 0; + } + return 1; +} diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h new file mode 100644 index 000000000..e0a28a796 --- /dev/null +++ b/src/tactic/sls/sls_engine.h @@ -0,0 +1,145 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sls_engine.h + +Abstract: + + A Stochastic Local Search (SLS) engine + +Author: + + Christoph (cwinter) 2014-03-19 + +Notes: + +--*/ +#ifndef _SLS_ENGINE_H_ +#define _SLS_ENGINE_H_ + +#include"stopwatch.h" +#include"lbool.h" +#include"model_converter.h" +#include"goal.h" + +#include"sls_tracker.h" +#include"sls_evaluator.h" +#include"statistics.h" + +class sls_engine { +public: + class stats { + public: + unsigned m_restarts; + stopwatch m_stopwatch; + unsigned m_full_evals; + unsigned m_incr_evals; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs; + + stats() : + m_restarts(0), + m_full_evals(0), + m_incr_evals(0), + m_moves(0), + m_flips(0), + m_incs(0), + m_decs(0), + m_invs(0) { + m_stopwatch.reset(); + m_stopwatch.start(); + } + void reset() { + m_full_evals = m_flips = m_incr_evals = 0; + m_stopwatch.reset(); + m_stopwatch.start(); + } + }; + +protected: + ast_manager & m_manager; + stats m_stats; + unsynch_mpz_manager m_mpz_manager; + powers m_powers; + mpz m_zero, m_one, m_two; + bool m_produce_models; + volatile bool m_cancel; + bv_util m_bv_util; + sls_tracker m_tracker; + sls_evaluator m_evaluator; + ptr_vector m_assertions; + + unsigned m_max_restarts; + unsigned m_walksat; + unsigned m_walksat_repick; + unsigned m_wp; + unsigned m_vns_mc; + unsigned m_vns_repick; + unsigned m_paws; + unsigned m_paws_sp; + unsigned m_restart_base; + unsigned m_restart_next; + unsigned m_restart_init; + unsigned m_early_prune; + unsigned m_random_offset; + unsigned m_rescore; + + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; + +public: + sls_engine(ast_manager & m, params_ref const & p); + ~sls_engine(); + + ast_manager & m() const { return m_manager; } + + void set_cancel(bool f) { m_cancel = f; } + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } + + void updt_params(params_ref const & _p); + + void assert_expr(expr * e) { m_assertions.push_back(e); } + + // stats const & get_stats(void) { return m_stats; } + void collect_statistics(statistics & st) const; + void reset_statistics(void) { m_stats.reset(); } + + bool full_eval(model & mdl); + + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); + void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); + void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + + lbool search(void); + + lbool operator()(); + void operator()(goal_ref const & g, model_converter_ref & mc); + +protected: + void checkpoint(); + + bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value); + + double top_score(); + double rescore(); + double serious_score(func_decl * fd, const mpz & new_value); + double incremental_score(func_decl * fd, const mpz & new_value); + + double incremental_score_prune(func_decl * fd, const mpz & new_value); + double find_best_move(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + double find_best_move_mc(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value); + + void mk_random_move(ptr_vector & unsat_constants); + + //double get_restart_armin(unsigned cnt_restarts); + unsigned check_restart(unsigned curr_value); +}; + +#endif diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 77ff50454..ed4717641 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -20,6 +20,8 @@ Notes: #ifndef _SLS_EVALUATOR_H_ #define _SLS_EVALUATOR_H_ +#include"model_evaluator.h" + #include"sls_powers.h" #include"sls_tracker.h" @@ -34,6 +36,7 @@ class sls_evaluator { powers & m_powers; expr_ref_buffer m_temp_exprs; vector > m_traversal_stack; + vector > m_traversal_stack_bool; public: sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : @@ -93,7 +96,7 @@ public: SASSERT(n_args == 1); const mpz & child = m_tracker.get_value(args[0]); SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child)); - m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); + m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); break; } case OP_EQ: { @@ -117,6 +120,14 @@ public: } break; } + case OP_ITE: { + SASSERT(n_args = 3); + if (m_mpz_manager.is_one(m_tracker.get_value(args[0]))) + m_mpz_manager.set(result, m_tracker.get_value(args[1])); + else + m_mpz_manager.set(result, m_tracker.get_value(args[2])); + break; + } default: NOT_IMPLEMENTED_YET(); } @@ -519,11 +530,13 @@ public: } } - void run_update(unsigned cur_depth) { + void run_serious_update(unsigned cur_depth) { // precondition: m_traversal_stack contains the entry point(s) expr_fast_mark1 visited; mpz new_value; + double new_score; + SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; @@ -533,8 +546,61 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - m_tracker.set_score(cur, m_tracker.score(cur)); + new_score = m_tracker.score(cur); + if (m_tracker.is_top_expr(cur)) + { + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + if (m_mpz_manager.eq(new_value,m_one)) + m_tracker.make_assertion(cur); + else + m_tracker.break_assertion(cur); + } + + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); + + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack[next_d].push_back(next); + visited.mark(next); + } + } + } + } + + cur_depth_exprs.reset(); + cur_depth--; + } + + m_mpz_manager.del(new_value); + } + + void run_update(unsigned cur_depth) { + // precondition: m_traversal_stack contains the entry point(s) + expr_fast_mark1 visited; + mpz new_value; + + double new_score; + + SASSERT(cur_depth < m_traversal_stack.size()); + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + (*this)(to_app(cur), new_value); + m_tracker.set_value(cur, new_value); + new_score = m_tracker.score(cur); + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -569,8 +635,7 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } - - run_update(max_depth); + run_serious_update(max_depth); } void update(func_decl * fd, const mpz & new_value) { @@ -584,36 +649,174 @@ public: run_update(cur_depth); } - void randomize_local(goal_ref const & g) { - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g); + void serious_update(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + m_traversal_stack[cur_depth].push_back(ep); - // Randomize _all_ candidates: + run_serious_update(cur_depth); + } - //// bool did_something = false; - //for (unsigned i = 0; i < unsat_constants.size(); i++) { - // func_decl * fd = unsat_constants[i]; - // mpz temp = m_tracker.get_random(fd->get_range()); - // // if (m_mpz_manager.neq(temp, m_tracker.get_value(fd))) { - // // did_something = true; - // // } - // update(fd, temp); - // m_mpz_manager.del(temp); - //} + unsigned run_update_bool_prune(unsigned cur_depth) { + expr_fast_mark1 visited; + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); + + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + + prune_score = m_tracker.get_score_prune(cur); + m_tracker.set_score(cur, new_score); + + if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; + + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + + cur_depth_exprs.reset(); + cur_depth--; + + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); + + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } + + return pot_benefits; + } + + void run_update_prune(unsigned max_depth) { + // precondition: m_traversal_stack contains the entry point(s) + expr_fast_mark1 visited; + mpz new_value; + + unsigned cur_depth = max_depth; + SASSERT(cur_depth < m_traversal_stack.size()); + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + (*this)(to_app(cur), new_value); + m_tracker.set_value(cur, new_value); + // Andreas: Should actually always have uplinks ... + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + if (m_manager.is_bool(next)) + m_traversal_stack_bool[max_depth].push_back(next); + else + m_traversal_stack[next_d].push_back(next); + visited.mark(next); + } + } + } + } + + cur_depth_exprs.reset(); + cur_depth--; + } + + m_mpz_manager.del(new_value); + } + + unsigned update_prune(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + + if (m_traversal_stack_bool.size() <= cur_depth) + m_traversal_stack_bool.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune(cur_depth); + } + + void randomize_local(ptr_vector & unsat_constants) { // Randomize _one_ candidate: unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); func_decl * fd = unsat_constants[r]; mpz temp = m_tracker.get_random(fd->get_range()); - update(fd, temp); + + serious_update(fd, temp); + m_mpz_manager.del(temp); - TRACE("sls", /*tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl;*/ - tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; + TRACE("sls", tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + + } + + void randomize_local(expr * e) { + randomize_local(m_tracker.get_constants(e)); + } + + void randomize_local(ptr_vector const & as) { + randomize_local(m_tracker.get_unsat_constants(as)); } }; diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg index cc3e05966..bf5bd181a 100644 --- a/src/tactic/sls/sls_params.pyg +++ b/src/tactic/sls/sls_params.pyg @@ -2,7 +2,25 @@ def_module_params('sls', export=True, description='Experimental Stochastic Local Search Solver (for QFBV only).', params=(max_memory_param(), - ('restarts', UINT, UINT_MAX, '(max) number of restarts'), - ('plateau_limit', UINT, 10, 'pleateau limit'), - ('random_seed', UINT, 0, 'random seed') + ('max_restarts', UINT, UINT_MAX, 'maximum number of restarts'), + ('walksat', BOOL, 1, 'use walksat assertion selection (instead of gsat)'), + ('walksat_ucb', BOOL, 1, 'use bandit heuristic for walksat assertion selection (instead of random)'), + ('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'), + ('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'), + ('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'), + ('walksat_ucb_noise', DOUBLE, 0.0002, 'add noise 0 <= 256 * ucb_noise to ucb score for assertion selection'), + ('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'), + ('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'), + ('paws_init', UINT, 40, 'initial/minimum assertion weights'), + ('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'), + ('wp', UINT, 100, 'random walk with probability wp / 1024'), + ('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'), + ('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'), + ('restart_base', UINT, 100, 'base restart interval given by moves per run'), + ('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'), + ('early_prune', BOOL, 1, 'use early pruning for score prediction'), + ('random_offset', BOOL, 1, 'use random offset for candidate evaluation'), + ('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'), + ('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'), + ('random_seed', UINT, 0, 'random seed') )) diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 6783d9621..de8769c07 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -16,507 +16,30 @@ Author: Notes: --*/ -#include -#include"map.h" #include"nnf.h" -#include"cooperate.h" -#include"ast_smt2_pp.h" -#include"ast_pp.h" -#include"var_subst.h" -#include"model_pp.h" -#include"model_evaluator.h" #include"solve_eqs_tactic.h" -#include"elim_uncnstr_tactic.h" #include"bv_size_reduction_tactic.h" #include"max_bv_sharing_tactic.h" #include"simplify_tactic.h" -#include"stopwatch.h" #include"propagate_values_tactic.h" -#include"sls_tactic.h" +#include"ctx_simplify_tactic.h" +#include"elim_uncnstr_tactic.h" #include"nnf_tactic.h" - +#include"stopwatch.h" +#include"sls_tactic.h" #include"sls_params.hpp" -#include"sls_evaluator.h" -#include"sls_tracker.h" +#include"sls_engine.h" -class sls_tactic : public tactic { - class stats { - public: - unsigned m_restarts; - stopwatch m_stopwatch; - unsigned m_full_evals; - unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs; - stats() : - m_restarts(0), - m_full_evals(0), - m_incr_evals(0), - m_moves(0), - m_flips(0), - m_incs(0), - m_decs(0), - m_invs(0) { - m_stopwatch.reset(); - m_stopwatch.start(); - } - void reset() { - m_full_evals = m_flips = m_incr_evals = 0; - m_stopwatch.reset(); - m_stopwatch.start(); - } - }; - - struct imp { - ast_manager & m_manager; - stats & m_stats; - unsynch_mpz_manager m_mpz_manager; - powers m_powers; - mpz m_zero, m_one, m_two; - bool m_produce_models; - volatile bool m_cancel; - bv_util m_bv_util; - sls_tracker m_tracker; - sls_evaluator m_evaluator; - - unsigned m_max_restarts; - unsigned m_plateau_limit; - - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; - - imp(ast_manager & m, params_ref const & p, stats & s) : - m_manager(m), - m_stats(s), - m_powers(m_mpz_manager), - m_zero(m_mpz_manager.mk_z(0)), - m_one(m_mpz_manager.mk_z(1)), - m_two(m_mpz_manager.mk_z(2)), - m_cancel(false), - m_bv_util(m), - m_tracker(m, m_bv_util, m_mpz_manager, m_powers), - m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) - { - updt_params(p); - } - - ~imp() { - m_mpz_manager.del(m_zero); - m_mpz_manager.del(m_one); - m_mpz_manager.del(m_two); - } - - ast_manager & m() const { return m_manager; } - - void set_cancel(bool f) { m_cancel = f; } - void cancel() { set_cancel(true); } - void reset_cancel() { set_cancel(false); } - - static void collect_param_descrs(param_descrs & r) { - sls_params::collect_param_descrs(r); - } - - void updt_params(params_ref const & _p) { - sls_params p(_p); - m_produce_models = _p.get_bool("model", false); - m_max_restarts = p.restarts(); - m_tracker.set_random_seed(p.random_seed()); - m_plateau_limit = p.plateau_limit(); - } - - void checkpoint() { - if (m_cancel) - throw tactic_exception(TACTIC_CANCELED_MSG); - cooperate("sls"); - } - - bool full_eval(goal_ref const & g, model & mdl) { - bool res = true; - - unsigned sz = g->size(); - for (unsigned i = 0; i < sz && res; i++) { - checkpoint(); - expr_ref o(m_manager); - - if (!mdl.eval(g->form(i), o, true)) - exit(ERR_INTERNAL_FATAL); - - res = m_manager.is_true(o.get()); - } - - TRACE("sls", tout << "Evaluation: " << res << std::endl;); - - return res; - } - - double top_score(goal_ref const & g) { - #if 0 - double min = m_tracker.get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { - double q = m_tracker.get_score(g->form(i)); - if (q < min) min = q; - } - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " MIN: " << min << std::endl; ); - return min; - #else - double top_sum = 0.0; - unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - top_sum += m_tracker.get_score(g->form(i)); - } - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " AVG: " << top_sum / (double) sz << std::endl; ); - return top_sum / (double) sz; - #endif - } - - double rescore(goal_ref const & g) { - m_evaluator.update_all(); - m_stats.m_full_evals++; - return top_score(g); - } - - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); - m_stats.m_incr_evals++; - return top_score(g); - } - - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - - #ifdef Z3DEBUG - mpz old_value; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - #endif - - double r = incremental_score(g, fd, temp); - - #ifdef Z3DEBUG - TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << - " --> " << r << std::endl; ); - - m_mpz_manager.del(old_value); - #endif - - if (r >= best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { - unsigned shift; - m_mpz_manager.add(old_value, m_one, incremented); - if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) - m_mpz_manager.set(incremented, m_zero); - } - - void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { - if (m_mpz_manager.is_zero(old_value)) { - m_mpz_manager.set(decremented, m_powers(bv_sz)); - m_mpz_manager.dec(decremented); - } - else - m_mpz_manager.sub(old_value, m_one, decremented); - } - - void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { - m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); - } - - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { - m_mpz_manager.set(flipped, m_zero); - - if (m_bv_util.is_bv_sort(s)) { - mpz mask; - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(old_value, mask, flipped); - m_mpz_manager.del(mask); - } - else if (m_manager.is_bool(s)) - m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); - else - NOT_IMPLEMENTED_YET(); - } - - void mk_random_move(goal_ref const & g) { - unsigned rnd_mv = 0; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; - - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; - - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g); - unsigned ucc = unsat_constants.size(); - unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; - func_decl * fd = unsat_constants[rc]; - mpz new_value; - unsigned bit = 0; - - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(fd->get_range()); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } - - m_evaluator.update(fd, new_value); - - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - - m_mpz_manager.del(new_value); - } - - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - lbool search(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - - score = rescore(g); - TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; - tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - - unsigned plateau_cnt = 0; - - while (plateau_cnt < m_plateau_limit) { - - do { - checkpoint(); - - old_score = score; - new_const = (unsigned)-1; - - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g); - - TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; - for (unsigned i = 0 ; i < to_evaluate.size(); i++) - tout << to_evaluate[i]->get_name() << std::endl; ); - - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); - - if (new_const == static_cast(-1)) { - TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; - }); - - TRACE("sls_max", m_tracker.show_model(tout); - tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl; ); - score = old_score; - } - else { - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; - switch (move) { - case MV_FLIP: - tout << "Flip"; - if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; - break; - case MV_INC: - tout << "+1"; - break; - case MV_DEC: - tout << "-1"; - break; - case MV_INV: - tout << "NEG"; - break; - }; - tout << ") ; new score = " << std::setprecision(32) << score << std::endl; ); - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - } - - score = incremental_score(g, fd, new_value); - - TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - } - - if (score >= 1.0) { - // score could theoretically be imprecise. - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } - while (score > old_score && res == l_undef); - - if (score != old_score) - plateau_cnt = 0; - else { - plateau_cnt++; - if (plateau_cnt < m_plateau_limit) { - TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); - m_evaluator.randomize_local(g); - //mk_random_move(g); - score = top_score(g); - } - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - void operator()(goal_ref const & g, model_converter_ref & mc) { - if (g->inconsistent()) { - mc = 0; - return; - } - - m_tracker.initialize(g); - lbool res = l_undef; - - do { - checkpoint(); - if ((m_stats.m_restarts % 100) == 0) - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - - res = search(g); - - if (res == l_undef) - m_tracker.randomize(); - } - while (res != l_true && m_stats.m_restarts++ < m_max_restarts); - - if (res == l_true) { - if (m_produce_models) { - model_ref mdl = m_tracker.get_model(); - mc = model2model_converter(mdl.get()); - TRACE("sls_model", mc->display(tout); ); - } - g->reset(); - } - else - mc = 0; - } - }; - +class sls_tactic : public tactic { ast_manager & m; params_ref m_params; - imp * m_imp; - stats m_stats; + sls_engine * m_engine; public: sls_tactic(ast_manager & _m, params_ref const & p): m(_m), m_params(p) { - m_imp = alloc(imp, m, p, m_stats); + m_engine = alloc(sls_engine, m, p); } virtual tactic * translate(ast_manager & m) { @@ -524,16 +47,16 @@ public: } virtual ~sls_tactic() { - dealloc(m_imp); + dealloc(m_engine); } virtual void updt_params(params_ref const & p) { m_params = p; - m_imp->updt_params(p); + m_engine->updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - imp::collect_param_descrs(r); + sls_params::collect_param_descrs(r); } virtual void operator()(goal_ref const & g, @@ -541,14 +64,13 @@ public: model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { - SASSERT(g->is_well_sorted()); - m_imp->m_produce_models = g->models_enabled(); + SASSERT(g->is_well_sorted()); mc = 0; pc = 0; core = 0; result.reset(); TRACE("sls", g->display(tout);); tactic_report report("sls", *g); - m_imp->operator()(g, mc); + m_engine->operator()(g, mc); g->inc_depth(); result.push_back(g.get()); @@ -557,35 +79,25 @@ public: } virtual void cleanup() { - imp * d = alloc(imp, m, m_params, m_stats); + sls_engine * d = alloc(sls_engine, m, m_params); #pragma omp critical (tactic_cancel) { - std::swap(d, m_imp); + std::swap(d, m_engine); } dealloc(d); } virtual void collect_statistics(statistics & st) const { - double seconds = m_stats.m_stopwatch.get_current_seconds(); - st.update("sls restarts", m_stats.m_restarts); - st.update("sls full evals", m_stats.m_full_evals); - st.update("sls incr evals", m_stats.m_incr_evals); - st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds); - st.update("sls FLIP moves", m_stats.m_flips); - st.update("sls INC moves", m_stats.m_incs); - st.update("sls DEC moves", m_stats.m_decs); - st.update("sls INV moves", m_stats.m_invs); - st.update("sls moves", m_stats.m_moves); - st.update("sls moves/sec", m_stats.m_moves / seconds); + m_engine->collect_statistics(st); } virtual void reset_statistics() { - m_stats.reset(); + m_engine->reset_statistics(); } virtual void set_cancel(bool f) { - if (m_imp) - m_imp->set_cancel(f); + if (m_engine) + m_engine->set_cancel(f); } }; @@ -620,6 +132,9 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { // conservative gaussian elimination. gaussian_p.set_uint("gaussian_max_occs", 2); + params_ref ctx_p; + ctx_p.set_uint("max_depth", 32); + ctx_p.set_uint("max_steps", 5000000); return and_then(and_then(mk_simplify_tactic(m), mk_propagate_values_tactic(m), using_params(mk_solve_eqs_tactic(m), gaussian_p), @@ -633,6 +148,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m)); + //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); t->updt_params(p); return t; } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 7fbafec60..b675c15f4 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,6 +20,15 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ +#include +#include"for_each_expr.h" +#include"ast_smt2_pp.h" +#include"bv_decl_plugin.h" +#include"model.h" + +#include"sls_params.hpp" +#include"sls_powers.h" + class sls_tracker { ast_manager & m_manager; unsynch_mpz_manager & m_mpz_manager; @@ -28,21 +37,26 @@ class sls_tracker { random_gen m_rng; unsigned m_random_bits; unsigned m_random_bits_cnt; - mpz m_zero, m_one, m_two; - + mpz m_zero, m_one, m_two; + struct value_score { - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; double score; + double score_prune; + unsigned has_pos_occ; + unsigned has_neg_occ; unsigned distance; // max distance from any root + unsigned touched; value_score & operator=(const value_score & other) { SASSERT(m == 0 || m == other.m); if (m) m->set(value, 0); else m = other.m; m->set(value, other.value); score = other.score; distance = other.distance; + touched = other.touched; return *this; } }; @@ -54,12 +68,28 @@ private: typedef obj_map scores_type; typedef obj_map > uplinks_type; typedef obj_map > occ_type; + obj_hashtable m_top_expr; scores_type m_scores; uplinks_type m_uplinks; entry_point_type m_entry_points; ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; + unsigned m_last_pos; + unsigned m_walksat; + unsigned m_ucb; + double m_ucb_constant; + unsigned m_ucb_init; + double m_ucb_forget; + double m_ucb_noise; + unsigned m_touched; + double m_scale_unsat; + unsigned m_paws_init; + obj_map m_where_false; + expr** m_list_false; + unsigned m_track_unsat; + obj_map m_weights; + double m_top_sum; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -79,6 +109,72 @@ public: m_mpz_manager.del(m_two); } + void updt_params(params_ref const & _p) { + sls_params p(_p); + m_walksat = p.walksat(); + m_ucb = p.walksat_ucb(); + m_ucb_constant = p.walksat_ucb_constant(); + m_ucb_init = p.walksat_ucb_init(); + m_ucb_forget = p.walksat_ucb_forget(); + m_ucb_noise = p.walksat_ucb_noise(); + m_scale_unsat = p.scale_unsat(); + m_paws_init = p.paws_init(); + // Andreas: track_unsat is currently disabled because I cannot guarantee that it is not buggy. + // If you want to use it, you will also need to change comments in the assertion selection. + m_track_unsat = 0;//p.track_unsat(); + } + + /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently. + unsigned get_formula_size() { + return m_scores.size(); + } + + double get_avg_bw(goal_ref const & g) { + double sum = 0.0; + unsigned count = 0; + + for (unsigned i = 0; i < g->size(); i++) + { + m_temp_constants.reset(); + ptr_vector const & this_decls = m_constants_occ.find(g->form(i)); + unsigned sz = this_decls.size(); + for (unsigned i = 0; i < sz; i++) { + func_decl * fd = this_decls[i]; + m_temp_constants.push_back(fd); + sort * srt = fd->get_range(); + sum += (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + count++; + } + } + + return sum / count; + }*/ + + inline void adapt_top_sum(expr * e, double add, double sub) { + m_top_sum += m_weights.find(e) * (add - sub); + } + + inline void set_top_sum(double new_score) { + m_top_sum = new_score; + } + + inline double get_top_sum() { + return m_top_sum; + } + + inline obj_hashtable const & get_top_exprs() { + return m_top_expr; + } + + inline bool is_sat() { + for (obj_hashtable::iterator it = m_top_expr.begin(); + it != m_top_expr.end(); + it++) + if (!m_mpz_manager.is_one(get_value(*it))) + return false; + return true; + } + inline void set_value(expr * n, const mpz & r) { SASSERT(m_scores.contains(n)); m_mpz_manager.set(m_scores.find(n).value, r); @@ -123,6 +219,26 @@ public: return get_score(ep); } + inline void set_score_prune(expr * n, double score) { + SASSERT(m_scores.contains(n)); + m_scores.find(n).score_prune = score; + } + + inline double & get_score_prune(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).score_prune; + } + + inline unsigned has_pos_occ(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).has_pos_occ; + } + + inline unsigned has_neg_occ(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).has_neg_occ; + } + inline unsigned get_distance(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).distance; @@ -146,11 +262,32 @@ public: return m_uplinks.contains(n); } + inline bool is_top_expr(expr * n) { + return m_top_expr.contains(n); + } + inline ptr_vector & get_uplinks(expr * n) { SASSERT(m_uplinks.contains(n)); return m_uplinks.find(n); } + inline void ucb_forget(ptr_vector & as) { + if (m_ucb_forget < 1.0) + { + expr * e; + unsigned touched_old, touched_new; + + for (unsigned i = 0; i < as.size(); i++) + { + e = as[i]; + touched_old = m_scores.find(e).touched; + touched_new = (unsigned)((touched_old - 1) * m_ucb_forget + 1); + m_scores.find(e).touched = touched_new; + m_touched += touched_new - touched_old; + } + } + } + void initialize(app * n) { // Build score table if (!m_scores.contains(n)) { @@ -226,12 +363,12 @@ public: } }; - void calculate_expr_distances(goal_ref const & g) { + void calculate_expr_distances(ptr_vector const & as) { // precondition: m_scores is set up. - unsigned sz = g->size(); + unsigned sz = as.size(); ptr_vector stack; for (unsigned i = 0; i < sz; i++) - stack.push_back(to_app(g->form(i))); + stack.push_back(to_app(as[i])); while (!stack.empty()) { app * cur = stack.back(); stack.pop_back(); @@ -249,19 +386,53 @@ public: } } - void initialize(goal_ref const & g) { + /* Andreas: Used this at some point to have values for the non-top-level expressions. + However, it did not give better performance but even cause some additional m/o - is not used currently. + void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(proc, visited, q); + } + } + for_each_expr(proc, visited, e); + } + + void initialize_recursive(expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(q); + } + } + ptr_vector t; + m_constants_occ.insert_if_not_there(e, t); + find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); + expr_fast_mark1 visited; + quick_for_each_expr(ffd_proc, visited, e); + }*/ + + void initialize(ptr_vector const & as) { init_proc proc(m_manager, *this); expr_mark visited; - unsigned sz = g->size(); + unsigned sz = as.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; + if (!m_top_expr.contains(e)) + m_top_expr.insert(e); for_each_expr(proc, visited, e); } visited.reset(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); @@ -269,9 +440,81 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - calculate_expr_distances(g); + calculate_expr_distances(as); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); + + if (m_track_unsat) + { + m_list_false = new expr*[sz]; + for (unsigned i = 0; i < sz; i++) + { + if (m_mpz_manager.eq(get_value(as[i]), m_zero)) + break_assertion(as[i]); + } + } + + for (unsigned i = 0; i < sz; i++) + { + expr * e = as[i]; + + // initialize weights + if (!m_weights.contains(e)) + m_weights.insert(e, m_paws_init); + + // positive/negative occurences used for early pruning + setup_occs(as[i]); + } + + // initialize ucb total touched value (individual ones are always initialized to 1) + m_touched = m_ucb_init ? as.size() : 1; + } + + void increase_weight(expr * e) + { + m_weights.find(e)++; + } + + void decrease_weight(expr * e) + { + unsigned old_weight = m_weights.find(e); + m_weights.find(e) = old_weight > m_paws_init ? old_weight - 1 : m_paws_init; + } + + unsigned get_weight(expr * e) + { + return m_weights.find(e); + } + + void make_assertion(expr * e) + { + if (m_track_unsat) + { + if (m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + } + } + } + } + + void break_assertion(expr * e) + { + if (m_track_unsat) + { + if (!m_where_false.contains(e)) + { + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + } + } } void show_model(std::ostream & out) { @@ -282,6 +525,28 @@ public: } } + void set_model(model_ref const & mdl) { + for (unsigned i = 0; i < mdl->get_num_constants(); i++) { + func_decl * fd = mdl->get_constant(i); + expr * val = mdl->get_const_interp(fd); + if (m_entry_points.contains(fd)) { + if (m_manager.is_bool(val)) { + set_value(fd, m_manager.is_true(val) ? m_mpz_manager.mk_z(1) : m_mpz_manager.mk_z(0)); + } + else if (m_bv_util.is_numeral(val)) { + rational r_val; + unsigned bv_sz; + m_bv_util.is_numeral(val, r_val, bv_sz); + mpq q = r_val.to_mpq(); + SASSERT(m_mpz_manager.is_one(q.denominator())); + set_value(fd, q.numerator()); + } + else + NOT_IMPLEMENTED_YET(); + } + } + } + model_ref get_model() { model_ref res = alloc(model, m_manager); unsigned sz = get_num_constants(); @@ -368,7 +633,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize() { + void randomize(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -382,7 +647,51 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); } -#define _SCORE_AND_MIN + void reset(ptr_vector const & as) { + TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); + + for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { + mpz temp = m_zero; + set_value(it->m_value, temp); + m_mpz_manager.del(temp); + } + } + + void setup_occs(expr * n, bool negated = false) { + if (m_manager.is_bool(n)) + { + if (m_manager.is_and(n) || m_manager.is_or(n)) + { + SASSERT(!negated); + app * a = to_app(n); + expr * const * args = a->get_args(); + for (unsigned i = 0; i < a->get_num_args(); i++) + setup_occs(args[i]); + } + else if (m_manager.is_not(n)) + { + SASSERT(!negated); + app * a = to_app(n); + SASSERT(a->get_num_args() == 1); + expr * child = a->get_arg(0); + if (m_manager.is_and(child) || m_manager.is_or(child)) + NOT_IMPLEMENTED_YET(); + setup_occs(child, true); + } + else + { + if (negated) + m_scores.find(n).has_neg_occ = 1; + else + m_scores.find(n).has_pos_occ = 1; + } + } + else if (m_bv_util.is_bv(n)) { + /* CMW: I need this for optimization. Safe to ignore? */ + } + else + NOT_IMPLEMENTED_YET(); + } double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); @@ -400,19 +709,17 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - #ifdef _SCORE_AND_MIN + /* Andreas: Seems to have no effect. But maybe you want to try it again at some point. + double sum = 0.0; + for (unsigned i = 0; i < a->get_num_args(); i++) + sum += get_score(args[i]); + res = sum / (double) a->get_num_args(); */ double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur < min) min = cur; } res = min; - #else - double sum = 0.0; - for (unsigned i = 0; i < a->get_num_args(); i++) - sum += get_score(args[i]); - res = sum / (double) a->get_num_args(); - #endif } else if (m_manager.is_or(n)) { SASSERT(!negated); @@ -441,7 +748,7 @@ public: expr * arg1 = a->get_arg(1); const mpz & v0 = get_value(arg0); const mpz & v1 = get_value(arg1); - + if (negated) { res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << @@ -457,24 +764,14 @@ public: m_mpz_manager.bitwise_xor(v0, v1, diff); unsigned hamming_distance = 0; unsigned bv_sz = m_bv_util.get_bv_size(arg0); - #if 1 // unweighted hamming distance + // unweighted hamming distance while (!m_mpz_manager.is_zero(diff)) { - //m_mpz_manager.set(diff_m1, diff); - //m_mpz_manager.dec(diff_m1); - //m_mpz_manager.bitwise_and(diff, diff_m1, diff); - //hamming_distance++; if (!m_mpz_manager.is_even(diff)) { hamming_distance++; } m_mpz_manager.machine_div(diff, m_two, diff); } - res = 1.0 - (hamming_distance / (double) bv_sz); - #else - rational r(diff); - r /= m_powers(bv_sz); - double dbl = r.get_double(); - res = (dbl < 0.0) ? 1.0 : (dbl > 1.0) ? 0.0 : 1.0 - dbl; - #endif + res = 1.0 - (hamming_distance / (double) bv_sz); TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << m_mpz_manager.to_string(v1) << " ; HD = " << hamming_distance << " ; SZ = " << bv_sz << std::endl; ); @@ -489,7 +786,7 @@ public: SASSERT(a->get_num_args() == 2); const mpz & x = get_value(a->get_arg(0)); const mpz & y = get_value(a->get_arg(1)); - unsigned bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); + int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); if (negated) { if (m_mpz_manager.gt(x, y)) @@ -515,7 +812,7 @@ public: rational n(diff); n /= rational(m_powers(bv_sz)); double dbl = n.get_double(); - res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); } } @@ -535,7 +832,7 @@ public: if (negated) { if (x > y) - res = 1.0; + res = 1.0; else { mpz diff; m_mpz_manager.sub(y, x, diff); @@ -551,14 +848,15 @@ public: } else { if (x <= y) - res = 1.0; + res = 1.0; else { mpz diff; m_mpz_manager.sub(x, y, diff); + SASSERT(!m_mpz_manager.is_neg(diff)); rational n(diff); n /= p; double dbl = n.get_double(); - res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << @@ -572,7 +870,9 @@ public: app * a = to_app(n); SASSERT(a->get_num_args() == 1); expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF. + // Precondition: Assertion set is in NNF. + // Also: careful about the unsat assertion scaling further down. + if (m_manager.is_and(child) || m_manager.is_or(child)) NOT_IMPLEMENTED_YET(); res = score_bool(child, true); } @@ -598,10 +898,16 @@ public: SASSERT(res >= 0.0 && res <= 1.0); + app * a = to_app(n); + family_id afid = a->get_family_id(); + + if (afid == m_bv_util.get_family_id()) + if (res < 1.0) res *= m_scale_unsat; + TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } - + double score_bv(expr * n) { return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores. } @@ -647,29 +953,143 @@ public: NOT_IMPLEMENTED_YET(); } - ptr_vector & get_unsat_constants(goal_ref const & g) { - unsigned sz = g->size(); - - if (sz == 1) { - return get_constants(); + ptr_vector & get_constants(expr * e) { + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz = this_decls.size(); + for (unsigned i = 0; i < sz; i++) { + func_decl * fd = this_decls[i]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); } - else { - m_temp_constants.reset(); - for (unsigned i = 0; i < sz; i++) { - expr * q = g->form(i); - if (m_mpz_manager.eq(get_value(q), m_one)) - continue; - ptr_vector const & this_decls = m_constants_occ.find(q); - unsigned sz2 = this_decls.size(); - for (unsigned j = 0; j < sz2; j++) { - func_decl * fd = this_decls[j]; - if (!m_temp_constants.contains(fd)) - m_temp_constants.push_back(fd); - } + return m_temp_constants; + } + + ptr_vector & get_unsat_constants_gsat(ptr_vector const & as) { + unsigned sz = as.size(); + if (sz == 1) { + if (m_mpz_manager.neq(get_value(as[0]), m_one)) + return get_constants(); + } + + m_temp_constants.reset(); + + for (unsigned i = 0; i < sz; i++) { + expr * q = as[i]; + if (m_mpz_manager.eq(get_value(q), m_one)) + continue; + ptr_vector const & this_decls = m_constants_occ.find(q); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + } + return m_temp_constants; + } + + ptr_vector & get_unsat_constants_walksat(expr * e) { + if (!e || m_temp_constants.size()) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz = this_decls.size(); + for (unsigned j = 0; j < sz; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); } return m_temp_constants; + } + + ptr_vector & get_unsat_constants(ptr_vector const & as) { + if (m_walksat) + { + expr * e = get_unsat_assertion(as); + + if (!e) + { + m_temp_constants.reset(); + return m_temp_constants; + } + + return get_unsat_constants_walksat(e); } + else + return get_unsat_constants_gsat(as); + } + + expr * get_unsat_assertion(ptr_vector const & as) { + unsigned sz = as.size(); + if (sz == 1) { + if (m_mpz_manager.neq(get_value(as[0]), m_one)) + return as[0]; + else + return 0; + } + m_temp_constants.reset(); + + unsigned pos = -1; + if (m_ucb) + { + value_score vscore; + double max = -1.0; + // Andreas: Commented things here might be used for track_unsat data structures as done in SLS for SAT. But seems to have no benefit. + /* for (unsigned i = 0; i < m_where_false.size(); i++) { + expr * e = m_list_false[i]; */ + for (unsigned i = 0; i < sz; i++) { + expr * e = as[i]; + if (m_mpz_manager.neq(get_value(e), m_one)) + { + vscore = m_scores.find(e); + // Andreas: Select the assertion with the greatest ucb score. Potentially add some noise. + // double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); + double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + m_ucb_noise * get_random_uint(8); + if (q > max) { max = q; pos = i; } + } + } + if (pos == static_cast(-1)) + return 0; + + m_touched++; + m_scores.find(as[pos]).touched++; + // Andreas: Also part of track_unsat data structures. Additionally disable the previous line! + /* m_last_pos = pos; + m_scores.find(m_list_false[pos]).touched++; + return m_list_false[pos]; */ + } + else + { + // Andreas: The track_unsat data structures for random assertion selection. + /* sz = m_where_false.size(); + if (sz == 0) + return 0; + return m_list_false[get_random_uint(16) % sz]; */ + + unsigned cnt_unsat = 0; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return 0; + } + + m_last_pos = pos; + return as[pos]; + } + + expr * get_new_unsat_assertion(ptr_vector const & as) { + unsigned sz = as.size(); + if (sz == 1) + return 0; + m_temp_constants.reset(); + + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if ((i != m_last_pos) && m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + + if (pos == static_cast(-1)) + return 0; + return as[pos]; } }; -#endif \ No newline at end of file +#endif diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp index ac53ca0c8..b63cfcad3 100644 --- a/src/tactic/smtlogics/qfbv_tactic.cpp +++ b/src/tactic/smtlogics/qfbv_tactic.cpp @@ -31,12 +31,12 @@ Notes: #define MEMLIMIT 300 -tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) { - params_ref main_p; - main_p.set_bool("elim_and", true); - main_p.set_bool("push_ite_bv", true); - main_p.set_bool("blast_distinct", true); +tactic * mk_qfbv_preamble(ast_manager& m, params_ref const& p) { + params_ref solve_eq_p; + // conservative guassian elimination. + solve_eq_p.set_uint("solve_eqs_max_occs", 2); + params_ref simp2_p = p; simp2_p.set_bool("som", true); simp2_p.set_bool("pull_cheap_ite", true); @@ -46,6 +46,40 @@ tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) { simp2_p.set_bool("flat", true); // required by som simp2_p.set_bool("hoist_mul", false); // required by som + + params_ref hoist_p; + hoist_p.set_bool("hoist_mul", true); + hoist_p.set_bool("som", false); + + return + and_then( + mk_simplify_tactic(m), + mk_propagate_values_tactic(m), + using_params(mk_solve_eqs_tactic(m), solve_eq_p), + mk_elim_uncnstr_tactic(m), + if_no_proofs(if_no_unsat_cores(mk_bv_size_reduction_tactic(m))), + using_params(mk_simplify_tactic(m), simp2_p), + // + // Z3 can solve a couple of extra benchmarks by using hoist_mul + // but the timeout in SMT-COMP is too small. + // Moreover, it impacted negatively some easy benchmarks. + // We should decide later, if we keep it or not. + // + using_params(mk_simplify_tactic(m), hoist_p), + mk_max_bv_sharing_tactic(m)); +} + +static tactic * main_p(tactic* t) { + params_ref p; + p.set_bool("elim_and", true); + p.set_bool("push_ite_bv", true); + p.set_bool("blast_distinct", true); + return using_params(t, p); +} + + +tactic * mk_qfbv_tactic(ast_manager& m, params_ref const & p, tactic* sat, tactic* smt) { + params_ref local_ctx_p = p; local_ctx_p.set_bool("local_ctx", true); @@ -59,62 +93,55 @@ tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) { ctx_simp_p.set_uint("max_depth", 32); ctx_simp_p.set_uint("max_steps", 50000000); - params_ref hoist_p; - hoist_p.set_bool("hoist_mul", true); - hoist_p.set_bool("som", false); - - params_ref solve_eq_p; - // conservative guassian elimination. - solve_eq_p.set_uint("solve_eqs_max_occs", 2); params_ref big_aig_p; big_aig_p.set_bool("aig_per_assertion", false); + + tactic* preamble_st = mk_qfbv_preamble(m, p); + + tactic * st = main_p(and_then(preamble_st, + // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function + // symbols. In this case, we should not use + cond(mk_is_qfbv_probe(), + cond(mk_is_qfbv_eq_probe(), + and_then(mk_bv1_blaster_tactic(m), + using_params(smt, solver_p)), + and_then(mk_bit_blaster_tactic(m), + when(mk_lt(mk_memory_probe(), mk_const_probe(MEMLIMIT)), + and_then(using_params(and_then(mk_simplify_tactic(m), + mk_solve_eqs_tactic(m)), + local_ctx_p), + if_no_proofs(cond(mk_produce_unsat_cores_probe(), + mk_aig_tactic(), + using_params(mk_aig_tactic(), + big_aig_p))))), + sat)), + smt))); + + st->updt_params(p); + return st; + +} - tactic * preamble_st = and_then(and_then(mk_simplify_tactic(m), - mk_propagate_values_tactic(m), - using_params(mk_solve_eqs_tactic(m), solve_eq_p), - mk_elim_uncnstr_tactic(m), - if_no_proofs(if_no_unsat_cores(mk_bv_size_reduction_tactic(m))), - using_params(mk_simplify_tactic(m), simp2_p)), - // Z3 can solve a couple of extra benchmarks by using hoist_mul - // but the timeout in SMT-COMP is too small. - // Moreover, it impacted negatively some easy benchmarks. - // We should decide later, if we keep it or not. - using_params(mk_simplify_tactic(m), hoist_p), - mk_max_bv_sharing_tactic(m)); - -#ifdef USE_OLD_SAT_SOLVER - tactic * new_sat = and_then(mk_simplify_tactic(m), - mk_smt_tactic()); -#else - tactic * new_sat = cond(mk_or(mk_produce_proofs_probe(), mk_produce_unsat_cores_probe()), - and_then(mk_simplify_tactic(m), - mk_smt_tactic()), + +tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) { + + tactic * new_sat = cond(mk_produce_proofs_probe(), + and_then(mk_simplify_tactic(m), mk_smt_tactic()), mk_sat_tactic(m)); -#endif - tactic * st = using_params(and_then(preamble_st, - // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function - // symbols. In this case, we should not use + return mk_qfbv_tactic(m, p, new_sat, mk_smt_tactic()); + +} + +/* use full sls + tactic * st = main_p(and_then(preamble_st, cond(mk_is_qfbv_probe(), cond(mk_is_qfbv_eq_probe(), and_then(mk_bv1_blaster_tactic(m), using_params(mk_smt_tactic(), solver_p)), - and_then(mk_bit_blaster_tactic(m), - when(mk_lt(mk_memory_probe(), mk_const_probe(MEMLIMIT)), - and_then(using_params(and_then(mk_simplify_tactic(m), - mk_solve_eqs_tactic(m)), - local_ctx_p), - if_no_proofs(cond(mk_produce_unsat_cores_probe(), - mk_aig_tactic(), - using_params(mk_aig_tactic(), - big_aig_p))))), - new_sat)), - mk_smt_tactic())), - main_p); - - st->updt_params(p); - return st; -} + and_then(mk_nnf_tactic(m, p), mk_sls_tactic(m))), + mk_smt_tactic()))); +*/ diff --git a/src/tactic/smtlogics/qfbv_tactic.h b/src/tactic/smtlogics/qfbv_tactic.h index 7210f6f25..98b3e2289 100644 --- a/src/tactic/smtlogics/qfbv_tactic.h +++ b/src/tactic/smtlogics/qfbv_tactic.h @@ -24,8 +24,13 @@ class ast_manager; class tactic; tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p = params_ref()); + /* ADD_TACTIC("qfbv", "builtin strategy for solving QF_BV problems.", "mk_qfbv_tactic(m, p)") */ +tactic * mk_qfbv_preamble(ast_manager& m, params_ref const& p); + +tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p, tactic* sat, tactic* smt); + #endif diff --git a/src/test/dl_query.cpp b/src/test/dl_query.cpp index bb991c65f..39ea06959 100644 --- a/src/test/dl_query.cpp +++ b/src/test/dl_query.cpp @@ -58,8 +58,12 @@ void dl_query_test(ast_manager & m, smt_params & fparams, params_ref& params, ctx_q.updt_params(params); { parser* p = parser::create(ctx_q,m); - TRUSTME( p->parse_file(problem_file) ); + bool ok = p->parse_file(problem_file); dealloc(p); + if (!ok) { + std::cout << "Could not parse: " << problem_file << "\n"; + return; + } } relation_manager & rel_mgr_q = ctx_b.get_rel_context()->get_rmanager(); @@ -143,8 +147,12 @@ void dl_query_test_wpa(smt_params & fparams, params_ref& params) { ctx.updt_params(params); { wpa_parser* p = wpa_parser::create(ctx, m); - TRUSTME( p->parse_directory(problem_dir) ); + bool ok = p->parse_directory(problem_dir); dealloc(p); + if (!ok) { + std::cout << "Could not parse: " << problem_dir << "\n"; + return; + } } const unsigned attempts = 10; @@ -213,8 +221,12 @@ void tst_dl_query() { ctx_base.updt_params(params); { parser* p = parser::create(ctx_base,m); - TRUSTME( p->parse_file(problem_file) ); + bool ok = p->parse_file(problem_file); dealloc(p); + if (!ok) { + std::cout << "Could not parse: " << problem_file << "\n"; + return; + } } ctx_base.get_rel_context()->saturate(); diff --git a/src/test/doc.cpp b/src/test/doc.cpp new file mode 100644 index 000000000..593d09cfe --- /dev/null +++ b/src/test/doc.cpp @@ -0,0 +1,487 @@ +#include "doc.h" +#include "trace.h" +#include "vector.h" +#include "ast.h" +#include "ast_pp.h" +#include "reg_decl_plugins.h" +#include "sorting_network.h" +#include "smt_kernel.h" +#include "model_smt2_pp.h" +#include "smt_params.h" +#include "ast_util.h" +#include "expr_safe_replace.h" +#include "th_rewriter.h" + + +static void tst_doc1(unsigned n) { + doc_manager m(n); + + doc_ref d(m, m.allocate()); + doc_ref d1(m, m.allocate1()); + doc_ref d0(m, m.allocate0()); + doc_ref dX(m, m.allocateX()); + doc_ref dXc(m, m.allocate(*dX)); + doc_ref d10(m, m.allocate(10)); + doc_ref d20(m, m.allocate(rational(20))); + m.display(std::cout, *d1) << "\n"; + m.display(std::cout, *d0) << "\n"; + m.display(std::cout, *dX) << "\n"; + m.display(std::cout, *d10) << "\n"; + m.display(std::cout, *d20) << "\n"; + if (n < 64) { + unsigned hi = 3, lo = 1; + SASSERT(hi <= n); + doc_ref d111X(m, m.allocate(0xFF, hi, lo)); + } + m.copy(*d, *d10); + SASSERT(m.equals(*d, *d10)); + m.reset(*d); + SASSERT(!m.equals(*d, *d10)); + m.fill0(*d10); + SASSERT(m.equals(*d, *d10)); + m.fill1(*d); + d10 = m.allocate(10); + SASSERT(!m.equals(*d, *d10)); + SASSERT(m.equals(*d, *d1)); + m.fillX(*d); + SASSERT(m.equals(*d, *dX)); + SASSERT(m.is_full(*dX)); + SASSERT(!m.is_full(*d1)); + + VERIFY(m.set_and(*dX,*dX)); + SASSERT(m.equals(*dXc,*dX)); + VERIFY(m.set_and(*dX,*d1)); + SASSERT(!m.equals(*dXc,*dX)); + SASSERT(m.equals(*dX,*d1)); + VERIFY(m.fold_neg(*dX)); + ptr_vector result; + // VERIFY(!m.intersect(*d1,*d0, result)); + // m.subtract(*d1,*d0, result); + SASSERT(result.empty()); + dX = m.allocateX(); + m.display(std::cout, *d0) << "\n"; + m.display(std::cout, *dX) << "\n"; + SASSERT(m.contains(*dX,*d1)); + SASSERT(m.contains(*dX,*d0)); + SASSERT(!m.contains(*d0,*d1)); + SASSERT(!m.contains(*d1,*d0)); + + + d1->neg().push_back(m.tbvm().allocate0()); + m.display(std::cout, *d1) << " -> "; + VERIFY(m.fold_neg(*d1)); + m.display(std::cout, *d1) << "\n"; + + + bit_vector to_delete; + to_delete.resize(n, false); + to_delete.set(1); + to_delete.set(3); + doc_manager m1(n-2); + doc_ref d1_1(m1, m.project(m1, to_delete, *d1)); + doc_ref d1_2(m1, m1.allocate1()); + m.display(std::cout, *d1) << " -> "; + m1.display(std::cout, *d1_1) << "\n"; + SASSERT(m1.equals(*d1_1,*d1_2)); + m.set(*d1,2,BIT_x); + m.set(*d1,4,BIT_x); + d1_1 = m.project(m1, to_delete, *d1); + m.display(std::cout, *d1) << " -> "; + m1.display(std::cout, *d1_1) << "\n"; + d1->neg().push_back(m.tbvm().allocate1()); + SASSERT(m.well_formed(*d1)); + d1_1 = m.project(m1, to_delete, *d1); + m.display(std::cout, *d1) << " -> "; + m1.display(std::cout, *d1_1) << "\n"; +} + + +// generate "all" clauses over num_vars +// create XXXX \ clauses +// project 0, 1, 2, 3 variables +// check that result is the same as QE over those clauses. + +class test_doc_cls { + random_gen m_ran; + ast_manager m; + doc_manager dm; + expr_ref_vector m_vars; + + tbit choose_tbit() { + switch (m_ran(3)) { + case 0: return BIT_0; + case 1: return BIT_1; + default : return BIT_x; + } + } + + tbv* mk_rand_tbv() { + tbv* result = dm.tbvm().allocate(); + for (unsigned i = 0; i < dm.num_tbits(); ++i) { + dm.tbvm().set(*result, i, choose_tbit()); + } + return result; + } + + tbv* mk_rand_tbv(tbv const& pos) { + tbv* result = dm.tbvm().allocate(); + for (unsigned i = 0; i < dm.num_tbits(); ++i) { + if (pos[i] == BIT_x) { + dm.tbvm().set(*result, i, choose_tbit()); + } + else { + dm.tbvm().set(*result, i, pos[i]); + } + } + return result; + } + + doc* mk_rand_doc(unsigned num_diff) { + tbv_ref t(dm.tbvm()); + t = mk_rand_tbv(); + doc* result = dm.allocate(*t); + SASSERT(dm.tbvm().equals(*t, result->pos())); + for (unsigned i = 0; i < num_diff; ++i) { + result->neg().push_back(mk_rand_tbv(result->pos())); + } + SASSERT(dm.well_formed(*result)); + return result; + } + + void mk_rand_udoc(unsigned num_elems, unsigned num_diff, udoc& result) { + result.reset(dm); + for (unsigned i = 0; i < num_elems; ++i) { + result.push_back(mk_rand_doc(num_diff)); + } + } + + expr_ref mk_conj(tbv& t) { + expr_ref result(m); + expr_ref_vector conjs(m); + for (unsigned i = 0; i < m_vars.size(); ++i) { + tbit b = choose_tbit(); + dm.tbvm().set(t, i, b); + switch (b) { + case BIT_1: conjs.push_back(m_vars[i].get()); break; + case BIT_0: conjs.push_back(m.mk_not(m_vars[i].get())); break; + default: break; + } + } + result = mk_and(m, conjs.size(), conjs.c_ptr()); + return result; + } + + expr_ref to_formula(tbv const& t, doc_manager& m2) { + expr_ref result(m); + expr_ref_vector conjs(m); + unsigned n = m2.num_tbits(); + tbv_manager& tm = m2.tbvm(); + SASSERT(n <= m_vars.size()); + for (unsigned i = 0; i < n; ++i) { + switch (t[i]) { + case BIT_x: + break; + case BIT_1: + conjs.push_back(m_vars[i].get()); + break; + case BIT_0: + conjs.push_back(m.mk_not(m_vars[i].get())); + break; + default: + UNREACHABLE(); + break; + } + } + result = mk_and(m, conjs.size(), conjs.c_ptr()); + return result; + } + + expr_ref to_formula(doc const& d, doc_manager& m2) { + expr_ref result(m); + expr_ref_vector conjs(m); + conjs.push_back(to_formula(d.pos(), m2)); + for (unsigned i = 0; i < d.neg().size(); ++i) { + conjs.push_back(m.mk_not(to_formula(d.neg()[i], m2))); + } + result = mk_and(m, conjs.size(), conjs.c_ptr()); + return result; + } + + expr_ref to_formula(udoc const& ud, doc_manager& m2) { + expr_ref result(m); + expr_ref_vector disjs(m); + for (unsigned i = 0; i < ud.size(); ++i) { + disjs.push_back(to_formula(ud[i], m2)); + } + result = mk_or(m, disjs.size(), disjs.c_ptr()); + return result; + } + + void project(doc const& d, doc_manager& m2, const bit_vector& to_delete, doc_ref& result) { + result = dm.project(m2, to_delete, d); + TRACE("doc", + for (unsigned i = 0; i < m_vars.size(); ++i) { + tout << (to_delete.get(i)?"0":"1"); + } + tout << " "; + dm.display(tout, d) << " -> "; + m2.display(tout, *result) << "\n"; + ); + } + + + void test_project(unsigned num_clauses) { + doc_ref d(dm); + d = mk_rand_doc(3); + expr_ref fml1(m), fml2(m), fml3(m), tmp1(m), tmp2(m), fml(m); + fml1 = to_formula(*d, dm); + bit_vector to_delete; + to_delete.reserve(m_vars.size(), false); + unsigned num_bits = 1; + for (unsigned i = 1; i < to_delete.size(); ++i) { + to_delete.set(i, m_ran(2) == 0); + if (!to_delete.get(i)) ++num_bits; + } + doc_manager m2(num_bits); + doc_ref result(m2); + project(*d, m2, to_delete, result); + TRACE("doc", + dm.display(tout, *d) << "\n"; + m2.display(tout, *result) << "\n";); + fml2 = to_formula(*result, m2); + project_expand(fml1, to_delete); + project_rename(fml2, to_delete); + check_equiv(fml1, fml2); + } + + void project_expand(expr_ref& fml, bit_vector const& to_delete) { + expr_ref tmp1(m), tmp2(m); + for (unsigned i = 0; i < m_vars.size(); ++i) { + if (to_delete.get(i)) { + expr_safe_replace rep1(m), rep2(m); + rep1.insert(m_vars[i].get(), m.mk_true()); + rep1(fml, tmp1); + rep2.insert(m_vars[i].get(), m.mk_false()); + rep2(fml, tmp2); + if (tmp1 == tmp2) { + fml = tmp1; + } + else { + fml = m.mk_or(tmp1, tmp2); + } + } + } + } + + void project_rename(expr_ref& fml, bit_vector const& to_delete) { + expr_safe_replace rep(m); + for (unsigned i = 0, j = 0; i < m_vars.size(); ++i) { + if (!to_delete.get(i)) { + rep.insert(m_vars[j].get(), m_vars[i].get()); + ++j; + } + } + rep(fml); + } + + void test_merge(unsigned num_clauses) { + doc_ref d(dm, dm.allocateX()); + expr_ref_vector fmls(m), eqs(m); + unsigned N = m_vars.size(); + expr_ref fml1(m), fml2(m), fml3(m), tmp1(m), tmp2(m), fml(m); + for (unsigned i = 0; i < num_clauses; ++i) { + tbv* t = dm.tbvm().allocate(); + fmls.push_back(m.mk_not(mk_conj(*t))); + d->neg().push_back(t); + } + fml1 = mk_and(m, fmls.size(), fmls.c_ptr()); + svector to_merge(N, false); + bit_vector discard_cols; + discard_cols.resize(N, false); + unsigned num_bits = 1; + union_find_default_ctx union_ctx; + subset_ints equalities(union_ctx); + unsigned lo = N; + equalities.mk_var(); + for (unsigned i = 1; i < N; ++i) { + to_merge[i] = (m_ran(2) == 0); + if (!to_merge[i]) ++num_bits; else lo = i; + equalities.mk_var(); + } + if (lo == N) return; + for (unsigned i = 0; i < N; ++i) { + if (to_merge[i] && i != lo) { + equalities.merge(i, lo); + eqs.push_back(m.mk_eq(m_vars[i].get(), m_vars[lo].get())); + } + } + eqs.push_back(to_formula(*d, dm)); + fml1 = mk_and(m, eqs.size(), eqs.c_ptr()); + if (dm.merge(*d, lo, 1, equalities, discard_cols)) { + fml2 = to_formula(*d, dm); + } + else { + fml2 = m.mk_false(); + } + check_equiv(fml1, fml2); + } + + void check_equiv(expr_ref& fml1, expr_ref& fml2) { + th_rewriter rw(m); + rw(fml1); + rw(fml2); + smt_params fp; + smt::kernel solver(m, fp); + expr_ref fml(m); + fml = m.mk_not(m.mk_eq(fml1, fml2)); + solver.assert_expr(fml); + lbool res = solver.check(); + if (res != l_false) { + TRACE("doc", + tout << mk_pp(fml1, m) << "\n"; + tout << mk_pp(fml2, m) << "\n"; + ); + } + SASSERT(res == l_false); + } + + +public: + test_doc_cls(unsigned num_vars): dm(num_vars), m_vars(m) { + reg_decl_plugins(m); + for (unsigned i = 0; i < num_vars; ++i) { + m_vars.push_back(m.mk_fresh_const("b", m.mk_bool_sort())); + } + } + + void test_project(unsigned num_rounds, unsigned num_clauses) { + for (unsigned i = 0; i < num_rounds; ++i) { + test_project(num_clauses); + } + } + + void test_merge(unsigned num_rounds, unsigned num_clauses) { + for (unsigned i = 0; i < num_rounds; ++i) { + test_merge(num_clauses); + } + } + + void test_project1() { + expr_ref fml1(m), fml2(m); + doc_ref d(dm, dm.allocateX()); + tbv_ref t(dm.tbvm(), dm.tbvm().allocateX()); + dm.tbvm().set(*t, 0, BIT_0); + d->neg().push_back(t.detach()); + unsigned num_bits = dm.num_tbits(); + bit_vector to_delete; + to_delete.reserve(num_bits, false); + fml1 = to_formula(*d, dm); + to_delete.set(0, true); + doc_manager m2(num_bits-1); + doc_ref result(m2); + project(*d, m2, to_delete, result); + dm.display(std::cout, *d) << "\n"; + m2.display(std::cout, *result) << "\n"; + fml2 = to_formula(*result, m2); + project_rename(fml2, to_delete); + project_expand(fml1, to_delete); + std::cout << fml1 << " " << fml2 << "\n"; + check_equiv(fml1, fml2); + } + + + void test_subtract() { + doc_ref d1(dm); + doc_ref d2(dm); + doc_ref d3(dm); + udoc ds1, ds2; + d1 = dm.allocateX(); + d2 = dm.allocateX(); + d3 = dm.allocateX(); + dm.set(*d1, 0, BIT_1); + dm.set(*d1, 1, BIT_0); + dm.set(*d2, 0, BIT_0); + dm.set(*d2, 1, BIT_1); + //ds1.push_back(d1.detach()); + ds1.push_back(d2.detach()); + // ds1 = {10x, 01x} + d1 = dm.allocateX(); + tbv_ref t1(dm.tbvm()); + tbv_ref t2(dm.tbvm()); + t1 = dm.tbvm().allocateX(); + t2 = dm.tbvm().allocateX(); + dm.tbvm().set(*t1, 0, BIT_1); + dm.tbvm().set(*t1, 2, BIT_0); + dm.tbvm().set(*t2, 0, BIT_0); + dm.tbvm().set(*t2, 2, BIT_1); + d1->neg().push_back(t1.detach()); + d1->neg().push_back(t2.detach()); + ds2.push_back(d1.detach()); + ds1.display(dm, std::cout) << "\n"; + ds2.display(dm, std::cout) << "\n"; + expr_ref fml1 = to_formula(ds1, dm); + expr_ref fml2 = to_formula(ds2, dm); + ds1.subtract(dm, ds2); + ds1.display(dm, std::cout) << "\n"; + expr_ref fml3 = to_formula(ds1, dm); + fml1 = m.mk_and(fml1, m.mk_not(fml2)); + check_equiv(fml1, fml3); + ds1.reset(dm); + ds2.reset(dm); + //sub:{xxx \ {1x0, 0x1}} + //result:{100} + + for (unsigned i = 0; i < 1000; ++i) { + udoc d1, d2; + mk_rand_udoc(3, 3, d1); + mk_rand_udoc(3, 3, d2); + fml1 = to_formula(d1, dm); + fml2 = to_formula(d2, dm); + d1.subtract(dm, d2); + fml3 = to_formula(d1, dm); + fml1 = m.mk_and(fml1, m.mk_not(fml2)); + check_equiv(fml1, fml3); + d1.reset(dm); + d2.reset(dm); + } + } + + void test_intersect() { + expr_ref fml1(m), fml2(m), fml3(m); + for (unsigned i = 0; i < 10000; ++i) { + udoc d1, d2; + mk_rand_udoc(3, 3, d1); + mk_rand_udoc(3, 3, d2); + fml1 = to_formula(d1, dm); + fml2 = to_formula(d2, dm); + TRACE("doc", + d1.display(dm, tout) << "\n"; + d2.display(dm, tout) << "\n";); + d1.intersect(dm, d2); + TRACE("doc", d1.display(dm, tout) << "\n";); + SASSERT(d1.well_formed(dm)); + fml3 = to_formula(d1, dm); + fml1 = m.mk_and(fml1, fml2); + check_equiv(fml1, fml3); + d1.reset(dm); + d2.reset(dm); + } + } + +}; + + +void tst_doc() { + + test_doc_cls tp(4); + tp.test_project1(); + tp.test_project(200,7); + + tp.test_intersect(); + tp.test_subtract(); + tp.test_merge(200,7); + + tst_doc1(5); + tst_doc1(10); + tst_doc1(70); +} diff --git a/src/test/fixed_bit_vector.cpp b/src/test/fixed_bit_vector.cpp new file mode 100644 index 000000000..7bd9e62c3 --- /dev/null +++ b/src/test/fixed_bit_vector.cpp @@ -0,0 +1,118 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + fixed_bit_vector.cpp + +Abstract: + + Test fixed-size bit vector module + +Author: + + Nikolaj Bjorner (nbjorner) 2014-9-15. + +Revision History: + + based on bit_vector.cpp + +--*/ +#include +#include +#include"fixed_bit_vector.h" +#include"vector.h" + + +static void tst1() { + fixed_bit_vector_manager m(30); + fixed_bit_vector *b; + b = m.allocate0(); + m.set(*b, 0, true); + m.set(*b, 1, false); + m.set(*b, 2, true); + SASSERT(b->get(0) == true); + SASSERT(b->get(1) == false); + SASSERT(b->get(2) == true); + SASSERT(b->get(3) == false); + SASSERT(b->get(29) == false); + m.deallocate(b); +} + +static void tst_or() { + { + fixed_bit_vector_manager m(10); + fixed_bit_vector *b1, *b2; + b1 = m.allocate0(); + b2 = m.allocate0(); + + m.set(*b1, 4); + m.set(*b2, 8); + m.set(*b2, 3); + m.set(*b2, 2); + m.set(*b2, 1); + m.display(std::cout, *b1) << "\n"; + m.display(std::cout, *b2) << "\n"; + m.set_or(*b1, *b2); + m.display(std::cout, *b1) << "\n"; + SASSERT(!m.equals(*b1, *b2)); + m.unset(*b1, 4); + SASSERT(m.equals(*b1, *b2)); + m.unset(*b1, 3); + SASSERT(!m.equals(*b1, *b2)); + m.deallocate(b1); + m.deallocate(b2); + } +} + +static void tst_and() { + +} + + + +static void tst_eq(unsigned num_bits) { + fixed_bit_vector_manager m(num_bits); + fixed_bit_vector* b1 = m.allocate0(); + fixed_bit_vector* b2 = m.allocate0(); + fixed_bit_vector* b3 = m.allocate0(); + + m.set(*b1, 3, true); + SASSERT(!m.equals(*b1, *b2)); + SASSERT(m.equals(*b2, *b3)); + + m.set(*b3, 3, true); + SASSERT(m.equals(*b1, *b3)); + + m.set(*b2, num_bits-1, true); + m.set(*b3, num_bits-1); + m.unset(*b3, 3); + SASSERT(m.equals(*b2, *b3)); + m.fill0(*b1); + m.set_neg(*b1); + m.fill1(*b2); + SASSERT(m.equals(*b1, *b2)); + m.fill0(*b1); + for (unsigned i = 0; i < num_bits; ++i) { + m.set(*b1, i, true); + } + SASSERT(m.equals(*b1, *b2)); + m.deallocate(b1); + m.deallocate(b2); + m.deallocate(b3); +} + +void tst_fixed_bit_vector() { + tst1(); + tst_or(); + tst_and(); + tst_eq(15); + tst_eq(16); + tst_eq(17); + tst_eq(31); + tst_eq(32); + tst_eq(33); + tst_eq(63); + tst_eq(64); + tst_eq(65); +} diff --git a/src/test/hilbert_basis.cpp b/src/test/hilbert_basis.cpp index 4752dd78d..6fdfb1560 100644 --- a/src/test/hilbert_basis.cpp +++ b/src/test/hilbert_basis.cpp @@ -540,6 +540,33 @@ static void tst19() { saturate_basis(hb); } +static void test_A_5_5_3() { + hilbert_basis hb; + for (unsigned i = 0; i < 15; ++i) { + vector v; + for (unsigned j = 0; j < 5; ++j) { + for (unsigned k = 0; k < 15; ++k) { + v.push_back(rational(k == i)); + } + } + hb.add_ge(v, R(0)); + } + for (unsigned i = 1; i <= 15; ++i) { + vector v; + for (unsigned k = 1; k <= 5; ++k) { + for (unsigned l = 1; l <= 5; ++l) { + for (unsigned j = 1; j <= 3; ++j) { + bool one = ((j*k <= i) && (((i - j) % 3) == 0)); // fixme + v.push_back(rational(one)); + } + } + } + hb.add_ge(v, R(0)); + } + // etc. + saturate_basis(hb); +} + void tst_hilbert_basis() { std::cout << "hilbert basis test\n"; // tst3(); @@ -547,6 +574,9 @@ void tst_hilbert_basis() { g_use_ordered_support = true; + test_A_5_5_3(); + return; + tst18(); return; diff --git a/src/test/main.cpp b/src/test/main.cpp index bc7e04124..d5608a7d4 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -140,6 +140,10 @@ int main(int argc, char ** argv) { TST(ast); TST(optional); TST(bit_vector); + TST(fixed_bit_vector); + TST(tbv); + TST(doc); + TST(udoc_relation); TST(string_buffer); TST(map); TST(diff_logic); @@ -216,6 +220,11 @@ int main(int argc, char ** argv) { TST(polynorm); TST(qe_arith); TST(expr_substitution); + TST(sorting_network); + TST(theory_pb); + TST(simplex); + TST(sat_user_scope); + //TST_ARGV(hs); } void initialize_mam() {} diff --git a/src/test/sat_user_scope.cpp b/src/test/sat_user_scope.cpp new file mode 100644 index 000000000..e39059563 --- /dev/null +++ b/src/test/sat_user_scope.cpp @@ -0,0 +1,102 @@ +#include "sat_solver.h" +#include "util.h" + +typedef sat::literal_vector clause_t; +typedef vector clauses_t; +typedef vector trail_t; + +// [ [c1, c2, ..], [ ...] ] + +static unsigned s_num_vars = 6; +static unsigned s_num_clauses_per_frame = 8; +static unsigned s_num_frames = 7; + +static void add_literal(random_gen& r, clause_t& c) { + c.push_back(sat::literal(r(s_num_vars) + 1, r(2) == 0)); +} + +static clause_t& last_clause(trail_t& t) { + return t.back().back(); +} + +static void add_clause(sat::solver& s, random_gen& r, trail_t& t) { + t.back().push_back(sat::literal_vector()); + clause_t& cls = last_clause(t); + for (unsigned i = 0; i < 3; ++i) { + add_literal(r, cls); + } + s.mk_clause(cls.size(), cls.c_ptr()); +} + +static void display_state(std::ostream& out, sat::solver& s, trail_t& t) { + s.display(out); +} + +static void pop_user_scope(sat::solver& s, trail_t& t) { + std::cout << "pop\n"; + s.user_pop(1); + t.pop_back(); +} + +static void push_user_scope(sat::solver& s, trail_t& t) { + std::cout << "push\n"; + s.user_push(); + t.push_back(clauses_t()); +} + +static void init_vars(sat::solver& s) { + for (unsigned i = 0; i <= s_num_vars; ++i) { + s.mk_var(); + } +} + +static void check_coherence(sat::solver& s1, trail_t& t) { + params_ref p; + sat::solver s2(p, 0); + init_vars(s2); + sat::literal_vector cls; + for (unsigned i = 0; i < t.size(); ++i) { + clauses_t& clss = t[i]; + for (unsigned j = 0; j < clss.size(); ++j) { + cls.reset(); + cls.append(clss[j]); + s2.mk_clause(cls.size(), cls.c_ptr()); + } + } + lbool is_sat1 = s1.check(); + lbool is_sat2 = s2.check(); + if (is_sat1 != is_sat2) { + s1.display(std::cout); + s2.display(std::cout); + } + std::cout << is_sat1 << "\n"; + SASSERT(is_sat1 == is_sat2); +} + +void tst_sat_user_scope() { + random_gen r(0); + trail_t trail; + params_ref p; + sat::solver s(p, 0); // incremental solver + init_vars(s); + while (true) { + for (unsigned i = 0; i < s_num_frames; ++i) { + // push 3 frames, pop 2 + for (unsigned k = 0; k < 3; ++k) { + push_user_scope(s, trail); + for (unsigned j = 0; j < s_num_clauses_per_frame; ++j) { + add_clause(s, r, trail); + } + check_coherence(s, trail); + } + for (unsigned k = 0; k < 2; ++k) { + pop_user_scope(s, trail); + check_coherence(s, trail); + } + } + for (unsigned i = 0; i < s_num_frames; ++i) { + pop_user_scope(s, trail); + check_coherence(s, trail); + } + } +} diff --git a/src/test/simplex.cpp b/src/test/simplex.cpp new file mode 100644 index 000000000..a70d0d8cf --- /dev/null +++ b/src/test/simplex.cpp @@ -0,0 +1,162 @@ +#include "sparse_matrix.h" +#include "sparse_matrix_def.h" +#include "simplex.h" +#include "simplex_def.h" +#include "mpq_inf.h" +#include "vector.h" +#include "rational.h" + +#define R rational +typedef simplex::simplex Simplex; +typedef simplex::sparse_matrix sparse_matrix; + +static vector vec(int i, int j) { + vector nv; + nv.resize(2); + nv[0] = R(i); + nv[1] = R(j); + return nv; +} + +static vector vec(int i, int j, int k) { + vector nv = vec(i, j); + nv.push_back(R(k)); + return nv; +} + +static vector vec(int i, int j, int k, int l) { + vector nv = vec(i, j, k); + nv.push_back(R(l)); + return nv; +} + +static vector vec(int i, int j, int k, int l, int x) { + vector nv = vec(i, j, k, l); + nv.push_back(R(x)); + return nv; +} + +static vector vec(int i, int j, int k, int l, int x, int y) { + vector nv = vec(i, j, k, l, x); + nv.push_back(R(y)); + return nv; +} + +static vector vec(int i, int j, int k, int l, int x, int y, int z) { + vector nv = vec(i, j, k, l, x, y); + nv.push_back(R(z)); + return nv; +} + + + +void add_row(Simplex& S, vector const& _v, R const& _b, bool is_eq = false) { + unsynch_mpz_manager m; + unsigned_vector vars; + vector v(_v); + R b(_b); + R l(denominator(b)); + scoped_mpz_vector coeffs(m); + for (unsigned i = 0; i < v.size(); ++i) { + l = lcm(l, denominator(v[i])); + vars.push_back(i); + S.ensure_var(i); + } + b *= l; + b.neg(); + for (unsigned i = 0; i < v.size(); ++i) { + v[i] *= l; + coeffs.push_back(v[i].to_mpq().numerator()); + } + unsigned nv = S.get_num_vars(); + vars.push_back(nv); + vars.push_back(nv+1); + S.ensure_var(nv); + S.ensure_var(nv+1); + coeffs.push_back(mpz(-1)); + coeffs.push_back(b.to_mpq().numerator()); + mpq_inf one(mpq(1),mpq(0)); + mpq_inf zero(mpq(0),mpq(0)); + SASSERT(vars.size() == coeffs.size()); + S.set_lower(nv, zero); + if (is_eq) S.set_upper(nv, zero); + S.set_lower(nv+1, one); + S.set_upper(nv+1, one); + S.add_row(nv, coeffs.size(), vars.c_ptr(), coeffs.c_ptr()); +} + +static void feas(Simplex& S) { + S.display(std::cout); + lbool is_sat = S.make_feasible(); + std::cout << "feasible: " << is_sat << "\n"; + S.display(std::cout); +} + +static void test1() { + Simplex S; + add_row(S, vec(1,0), R(1)); + add_row(S, vec(0,1), R(1)); + add_row(S, vec(1,1), R(1)); + feas(S); +} + +static void test2() { + Simplex S; + add_row(S, vec(1, 0), R(1)); + add_row(S, vec(0, 1), R(1)); + add_row(S, vec(1, 1), R(1), true); + feas(S); +} + +static void test3() { + Simplex S; + add_row(S, vec(-1, 0), R(-1)); + add_row(S, vec(0, -1), R(-1)); + add_row(S, vec(1, 1), R(1), true); + feas(S); +} + +static void test4() { + Simplex S; + add_row(S, vec(1, 0), R(1)); + add_row(S, vec(0, -1), R(-1)); + add_row(S, vec(1, 1), R(1), true); + feas(S); +} + +void tst_simplex() { + Simplex S; + + std::cout << "simplex\n"; + + lbool is_sat = S.make_feasible(); + std::cout << "feasible: " << is_sat << "\n"; + + unsynch_mpz_manager m; + unsynch_mpq_inf_manager em; + scoped_mpz_vector coeffs(m); + svector vars; + for (unsigned i = 0; i < 5; ++i) { + S.ensure_var(i); + vars.push_back(i); + coeffs.push_back(mpz(i+1)); + } + + Simplex::row r = S.add_row(1, coeffs.size(), vars.c_ptr(), coeffs.c_ptr()); + is_sat = S.make_feasible(); + std::cout << "feasible: " << is_sat << "\n"; + S.display(std::cout); + _scoped_numeral num(em); + num = std::make_pair(mpq(1), mpq(0)); + S.set_lower(0, num); + S.set_upper(0, num); + + is_sat = S.make_feasible(); + std::cout << "feasible: " << is_sat << "\n"; + S.display(std::cout); + + test1(); + test2(); + test3(); + test4(); +} diff --git a/src/test/sorting_network.cpp b/src/test/sorting_network.cpp new file mode 100644 index 000000000..dd46b61df --- /dev/null +++ b/src/test/sorting_network.cpp @@ -0,0 +1,340 @@ +#include "trace.h" +#include "vector.h" +#include "ast.h" +#include "ast_pp.h" +#include "reg_decl_plugins.h" +#include "sorting_network.h" +#include "smt_kernel.h" +#include "model_smt2_pp.h" +#include "smt_params.h" +#include "ast_util.h" + + + +struct ast_ext { + ast_manager& m; + ast_ext(ast_manager& m):m(m) {} + typedef expr* T; + typedef expr_ref_vector vector; + T mk_ite(T a, T b, T c) { + return m.mk_ite(a, b, c); + } + T mk_le(T a, T b) { + if (m.is_bool(a)) { + return m.mk_implies(a, b); + } + UNREACHABLE(); + return 0; + } + T mk_default() { + return m.mk_false(); + } +}; + + + +struct unsigned_ext { + unsigned_ext() {} + typedef unsigned T; + typedef svector vector; + T mk_ite(T a, T b, T c) { + return (a==1)?b:c; + } + T mk_le(T a, T b) { + return (a <= b)?1:0; + } + T mk_default() { + return 0; + } +}; + + +static void is_sorted(svector const& v) { + for (unsigned i = 0; i + 1 < v.size(); ++i) { + SASSERT(v[i] <= v[i+1]); + } +} + +static void test_sorting1() { + svector in, out; + unsigned_ext uext; + sorting_network sn(uext); + + in.push_back(0); + in.push_back(1); + in.push_back(0); + in.push_back(1); + in.push_back(1); + in.push_back(0); + + sn(in, out); + + is_sorted(out); + for (unsigned i = 0; i < out.size(); ++i) { + std::cout << out[i]; + } + std::cout << "\n"; +} + +static void test_sorting2() { + svector in, out; + unsigned_ext uext; + sorting_network sn(uext); + + in.push_back(0); + in.push_back(1); + in.push_back(2); + in.push_back(1); + in.push_back(1); + in.push_back(3); + + sn(in, out); + + is_sorted(out); + + for (unsigned i = 0; i < out.size(); ++i) { + std::cout << out[i]; + } + std::cout << "\n"; +} + +static void test_sorting4_r(unsigned i, svector& in) { + if (i == in.size()) { + svector out; + unsigned_ext uext; + sorting_network sn(uext); + sn(in, out); + is_sorted(out); + std::cout << "sorted\n"; + } + else { + in[i] = 0; + test_sorting4_r(i+1, in); + in[i] = 1; + test_sorting4_r(i+1, in); + } +} + +static void test_sorting4() { + svector in; + in.resize(5); + test_sorting4_r(0, in); + in.resize(8); + test_sorting4_r(0, in); +} + +void test_sorting3() { + ast_manager m; + reg_decl_plugins(m); + expr_ref_vector in(m), out(m); + for (unsigned i = 0; i < 7; ++i) { + in.push_back(m.mk_fresh_const("a",m.mk_bool_sort())); + } + for (unsigned i = 0; i < in.size(); ++i) { + std::cout << mk_pp(in[i].get(), m) << "\n"; + } + ast_ext aext(m); + sorting_network sn(aext); + sn(in, out); + std::cout << "size: " << out.size() << "\n"; + for (unsigned i = 0; i < out.size(); ++i) { + std::cout << mk_pp(out[i].get(), m) << "\n"; + } +} + + +struct ast_ext2 { + ast_manager& m; + expr_ref_vector m_clauses; + expr_ref_vector m_trail; + ast_ext2(ast_manager& m):m(m), m_clauses(m), m_trail(m) {} + typedef expr* literal; + typedef ptr_vector literal_vector; + + expr* trail(expr* e) { + m_trail.push_back(e); + return e; + } + + literal mk_false() { return m.mk_false(); } + literal mk_true() { return m.mk_true(); } + literal mk_max(literal a, literal b) { + return trail(m.mk_or(a, b)); + } + literal mk_min(literal a, literal b) { return trail(m.mk_and(a, b)); } + literal mk_not(literal a) { if (m.is_not(a,a)) return a; + return trail(m.mk_not(a)); + } + std::ostream& pp(std::ostream& out, literal lit) { + return out << mk_pp(lit, m); + } + literal fresh() { + return trail(m.mk_fresh_const("x", m.mk_bool_sort())); + } + void mk_clause(unsigned n, literal const* lits) { + m_clauses.push_back(mk_or(m, n, lits)); + } +}; + + +static void test_sorting_eq(unsigned n, unsigned k) { + SASSERT(k < n); + ast_manager m; + reg_decl_plugins(m); + ast_ext2 ext(m); + expr_ref_vector in(m), out(m); + for (unsigned i = 0; i < n; ++i) { + in.push_back(m.mk_fresh_const("a",m.mk_bool_sort())); + } + smt_params fp; + smt::kernel solver(m, fp); + psort_nw sn(ext); + expr_ref result(m); + + // equality: + std::cout << "eq " << k << "\n"; + solver.push(); + result = sn.eq(k, in.size(), in.c_ptr()); + solver.assert_expr(result); + for (unsigned i = 0; i < ext.m_clauses.size(); ++i) { + solver.assert_expr(ext.m_clauses[i].get()); + } + lbool res = solver.check(); + SASSERT(res == l_true); + + solver.push(); + for (unsigned i = 0; i < k; ++i) { + solver.assert_expr(in[i].get()); + } + res = solver.check(); + SASSERT(res == l_true); + solver.assert_expr(in[k].get()); + res = solver.check(); + if (res == l_true) { + TRACE("pb", + unsigned sz = solver.size(); + for (unsigned i = 0; i < sz; ++i) { + tout << mk_pp(solver.get_formulas()[i], m) << "\n"; + }); + model_ref model; + solver.get_model(model); + model_smt2_pp(std::cout, m, *model, 0); + TRACE("pb", model_smt2_pp(tout, m, *model, 0);); + } + SASSERT(res == l_false); + solver.pop(1); + ext.m_clauses.reset(); +} + +static void test_sorting_le(unsigned n, unsigned k) { + ast_manager m; + reg_decl_plugins(m); + ast_ext2 ext(m); + expr_ref_vector in(m), out(m); + for (unsigned i = 0; i < n; ++i) { + in.push_back(m.mk_fresh_const("a",m.mk_bool_sort())); + } + smt_params fp; + smt::kernel solver(m, fp); + psort_nw sn(ext); + expr_ref result(m); + // B <= k + std::cout << "le " << k << "\n"; + solver.push(); + result = sn.le(false, k, in.size(), in.c_ptr()); + solver.assert_expr(result); + for (unsigned i = 0; i < ext.m_clauses.size(); ++i) { + solver.assert_expr(ext.m_clauses[i].get()); + } + lbool res = solver.check(); + SASSERT(res == l_true); + + for (unsigned i = 0; i < k; ++i) { + solver.assert_expr(in[i].get()); + } + res = solver.check(); + SASSERT(res == l_true); + solver.assert_expr(in[k].get()); + res = solver.check(); + if (res == l_true) { + TRACE("pb", + unsigned sz = solver.size(); + for (unsigned i = 0; i < sz; ++i) { + tout << mk_pp(solver.get_formulas()[i], m) << "\n"; + }); + model_ref model; + solver.get_model(model); + model_smt2_pp(std::cout, m, *model, 0); + TRACE("pb", model_smt2_pp(tout, m, *model, 0);); + } + SASSERT(res == l_false); + solver.pop(1); + ext.m_clauses.reset(); +} + + +void test_sorting_ge(unsigned n, unsigned k) { + ast_manager m; + reg_decl_plugins(m); + ast_ext2 ext(m); + expr_ref_vector in(m), out(m); + for (unsigned i = 0; i < n; ++i) { + in.push_back(m.mk_fresh_const("a",m.mk_bool_sort())); + } + smt_params fp; + smt::kernel solver(m, fp); + psort_nw sn(ext); + expr_ref result(m); + // k <= B + std::cout << "ge " << k << "\n"; + solver.push(); + result = sn.ge(false, k, in.size(), in.c_ptr()); + solver.assert_expr(result); + for (unsigned i = 0; i < ext.m_clauses.size(); ++i) { + solver.assert_expr(ext.m_clauses[i].get()); + } + lbool res = solver.check(); + SASSERT(res == l_true); + + solver.push(); + for (unsigned i = 0; i < n - k; ++i) { + solver.assert_expr(m.mk_not(in[i].get())); + } + res = solver.check(); + SASSERT(res == l_true); + solver.assert_expr(m.mk_not(in[n - k].get())); + res = solver.check(); + if (res == l_true) { + TRACE("pb", + unsigned sz = solver.size(); + for (unsigned i = 0; i < sz; ++i) { + tout << mk_pp(solver.get_formulas()[i], m) << "\n"; + }); + model_ref model; + solver.get_model(model); + model_smt2_pp(std::cout, m, *model, 0); + TRACE("pb", model_smt2_pp(tout, m, *model, 0);); + } + SASSERT(res == l_false); + solver.pop(1); +} + +void test_sorting5(unsigned n, unsigned k) { + std::cout << "n: " << n << " k: " << k << "\n"; + test_sorting_le(n, k); + test_sorting_eq(n, k); + test_sorting_ge(n, k); +} + +void tst_sorting_network() { + test_sorting_eq(11,7); + for (unsigned n = 3; n < 20; n += 2) { + for (unsigned k = 1; k < n; ++k) { + test_sorting5(n, k); + } + } + test_sorting1(); + test_sorting2(); + test_sorting3(); + test_sorting4(); +} diff --git a/src/test/tbv.cpp b/src/test/tbv.cpp new file mode 100644 index 000000000..c53eb3671 --- /dev/null +++ b/src/test/tbv.cpp @@ -0,0 +1,85 @@ +#include "tbv.h" + +static void tst1(unsigned num_bits) { + tbv_manager m(num_bits); + + tbv* b1 = m.allocate1(); + tbv* b0 = m.allocate0(); + tbv* bX = m.allocateX(); + tbv* bN = m.allocate(31); + m.display(std::cout, *b0) << "\n"; + m.display(std::cout, *b1) << "\n"; + m.display(std::cout, *bX) << "\n"; + m.display(std::cout, *bN) << "\n"; + SASSERT(!m.equals(*b1,*b0)); + SASSERT(!m.equals(*b1,*bX)); + SASSERT(!m.equals(*b0,*bX)); + m.set_and(*bX,*b0); + SASSERT(m.equals(*b0,*bX)); + SASSERT(!m.equals(*b1,*bX)); + m.copy(*bX,*b1); + SASSERT(m.equals(*b1,*bX)); + SASSERT(!m.equals(*b0,*bX)); + m.fillX(*bX); + VERIFY(m.intersect(*bX,*b0,*bN)); + SASSERT(m.equals(*b0, *bN)); + VERIFY(!m.intersect(*b0,*b1,*bN)); + m.fill1(*b1); + bit_vector to_delete; + to_delete.reserve(num_bits, false); + tbv_manager m2(num_bits-2); + to_delete.set(1); + to_delete.set(3); + m.set(*b1, 2, BIT_0); + m.set(*b1, 4, BIT_x); + tbv_ref b2(m2, m2.project(to_delete, *b1)); + m.display(std::cout, *b1) << " -> "; + m2.display(std::cout, *b2) << "\n"; + m.deallocate(b0); + m.deallocate(b1); + m.deallocate(bX); + m.deallocate(bN); + +} + +static void tst0() { + tbv_manager m(0); + + tbv_ref t1(m), t2(m), t3(m); + t1 = m.allocate1(); + t2 = m.allocate0(); + t3 = m.allocateX(); + m.display(std::cout, *t1) << "\n"; + m.display(std::cout, *t2) << "\n"; + m.display(std::cout, *t3) << "\n"; + SASSERT(m.equals(*t1, *t2)); + SASSERT(m.equals(*t1, *t3)); +} + +static void tst2(unsigned num_bits) { + tbv_manager m(num_bits); + tbv_ref t(m), t2(m); + for (unsigned i = 0; i < 55; ++i) { + t = m.allocate(i); + SASSERT(m.is_well_formed(*t)); + t2 = m.allocate(i+1); + VERIFY(!m.set_and(*t2, *t)); + SASSERT(!m.is_well_formed(*t2)); + } +} + +void tst_tbv() { + tst0(); + + tst1(31); + tst1(11); + tst1(15); + tst1(16); + tst1(17); + + tst2(31); + tst2(11); + tst2(15); + tst2(16); + tst2(17); +} diff --git a/src/test/theory_pb.cpp b/src/test/theory_pb.cpp new file mode 100644 index 000000000..ee1ec126a --- /dev/null +++ b/src/test/theory_pb.cpp @@ -0,0 +1,164 @@ +#include "smt_context.h" +#include "ast_pp.h" +#include "model_v2_pp.h" +#include "reg_decl_plugins.h" +#include "theory_pb.h" +#include "th_rewriter.h" + +unsigned populate_literals(unsigned k, smt::literal_vector& lits) { + SASSERT(k < (1u << lits.size())); + unsigned t = 0; + for (unsigned i = 0; i < lits.size(); ++i) { + if (k & (1 << i)) { + lits[i] = smt::true_literal; + t++; + } + else { + lits[i] = smt::false_literal; + } + } + return t; +} + +class pb_fuzzer { + ast_manager& m; + random_gen rand; + smt_params params; + smt::context ctx; + expr_ref_vector vars; + +public: + pb_fuzzer(ast_manager& m): m(m), rand(0), ctx(m, params), vars(m) { + params.m_model = true; + params.m_pb_enable_simplex = true; + unsigned N = 3; + for (unsigned i = 0; i < N; ++i) { + std::stringstream strm; + strm << "b" << i; + vars.push_back(m.mk_const(symbol(strm.str().c_str()), m.mk_bool_sort())); + std::cout << "(declare-const " << strm.str() << " Bool)\n"; + } + } + + void fuzz() { + enable_trace("pb"); + enable_trace("simplex"); + unsigned nr = 0; + for (unsigned i = 0; i < 100000; ++i) { + fuzz_round(nr, 2); + } + } + +private: + + void add_ineq() { + pb_util pb(m); + expr_ref fml(m), tmp(m); + th_rewriter rw(m); + vector coeffs(vars.size()); + expr_ref_vector args(vars); + while (true) { + rational k(rand(6)); + for (unsigned i = 0; i < coeffs.size(); ++i) { + int v = 3 - rand(5); + coeffs[i] = rational(v); + if (coeffs[i].is_neg()) { + args[i] = m.mk_not(args[i].get()); + coeffs[i].neg(); + k += coeffs[i]; + } + } + fml = pb.mk_ge(args.size(), coeffs.c_ptr(), args.c_ptr(), k); + rw(fml, tmp); + rw(tmp, tmp); + if (pb.is_ge(tmp)) { + fml = tmp; + break; + } + } + std::cout << "(assert " << fml << ")\n"; + ctx.assert_expr(fml); + } + + + + void fuzz_round(unsigned& num_rounds, unsigned lvl) { + unsigned num_rounds2 = 0; + lbool is_sat = l_true; + std::cout << "(push)\n"; + ctx.push(); + unsigned r = 0; + while (is_sat == l_true && r <= num_rounds + 1) { + add_ineq(); + std::cout << "(check-sat)\n"; + is_sat = ctx.check(); + if (lvl > 0 && is_sat == l_true) { + fuzz_round(num_rounds2, lvl-1); + } + ++r; + } + num_rounds = r; + std::cout << "; number of rounds: " << num_rounds << " level: " << lvl << "\n"; + ctx.pop(1); + std::cout << "(pop)\n"; + } + +}; + + + +static void fuzz_pb() +{ + ast_manager m; + reg_decl_plugins(m); + pb_fuzzer fuzzer(m); + fuzzer.fuzz(); +} + +void tst_theory_pb() { + + fuzz_pb(); + + ast_manager m; + smt_params params; + params.m_model = true; + reg_decl_plugins(m); + expr_ref tmp(m); + + enable_trace("pb"); + for (unsigned N = 4; N < 11; ++N) { + for (unsigned i = 0; i < (1u << N); ++i) { + smt::literal_vector lits(N, smt::false_literal); + unsigned k = populate_literals(i, lits); + std::cout << "k:" << k << " " << N << "\n"; + std::cout.flush(); + TRACE("pb", tout << "k " << k << ": "; + for (unsigned j = 0; j < lits.size(); ++j) { + tout << lits[j] << " "; + } + tout << "\n";); + { + smt::context ctx(m, params); + ctx.push(); + smt::literal l = smt::theory_pb::assert_ge(ctx, k+1, lits.size(), lits.c_ptr()); + if (l != smt::false_literal) { + ctx.assign(l, 0, false); + TRACE("pb", tout << "assign: " << l << "\n"; + ctx.display(tout);); + VERIFY(l_false == ctx.check()); + } + ctx.pop(1); + } + { + smt::context ctx(m, params); + ctx.push(); + smt::literal l = smt::theory_pb::assert_ge(ctx, k, lits.size(), lits.c_ptr()); + SASSERT(l != smt::false_literal); + ctx.assign(l, 0, false); + TRACE("pb", ctx.display(tout);); + VERIFY(l_true == ctx.check()); + ctx.pop(1); + } + } + } +} diff --git a/src/test/udoc_relation.cpp b/src/test/udoc_relation.cpp new file mode 100644 index 000000000..7be048c73 --- /dev/null +++ b/src/test/udoc_relation.cpp @@ -0,0 +1,875 @@ +#include "udoc_relation.h" +#include "trace.h" +#include "vector.h" +#include "ast.h" +#include "ast_pp.h" +#include "reg_decl_plugins.h" +#include "sorting_network.h" +#include "smt_kernel.h" +#include "model_smt2_pp.h" +#include "smt_params.h" +#include "ast_util.h" +#include "expr_safe_replace.h" +#include "th_rewriter.h" +#include "dl_relation_manager.h" +#include "dl_register_engine.h" +#include "rel_context.h" +#include "bv_decl_plugin.h" +#include "check_relation.h" + + +class udoc_tester { + typedef datalog::relation_base relation_base; + typedef datalog::udoc_relation udoc_relation; + typedef datalog::udoc_plugin udoc_plugin; + typedef datalog::relation_signature relation_signature; + typedef datalog::relation_fact relation_fact; + typedef scoped_ptr rel_mut; + typedef scoped_ptr rel_union; + + struct init { + init(ast_manager& m) { + reg_decl_plugins(m); + } + }; + random_gen m_rand; + ast_manager m; + init m_init; + bv_util bv; + expr_ref_vector m_vars; + smt_params m_smt_params; + datalog::register_engine m_reg; + datalog::context m_ctx; + datalog::rel_context rc; + udoc_plugin& p; + datalog::check_relation_plugin& cr; + + + tbit choose_tbit() { + switch (m_rand(3)) { + case 0: return BIT_0; + case 1: return BIT_1; + default : return BIT_x; + } + } + + tbv* mk_rand_tbv(doc_manager& dm) { + tbv* result = dm.tbvm().allocate(); + for (unsigned i = 0; i < dm.num_tbits(); ++i) { + dm.tbvm().set(*result, i, choose_tbit()); + } + return result; + } + + tbv* mk_rand_tbv(doc_manager& dm, tbv const& pos) { + tbv* result = dm.tbvm().allocate(); + for (unsigned i = 0; i < dm.num_tbits(); ++i) { + if (pos[i] == BIT_x) { + dm.tbvm().set(*result, i, choose_tbit()); + } + else { + dm.tbvm().set(*result, i, pos[i]); + } + } + return result; + } + + doc* mk_rand_doc(doc_manager& dm, unsigned num_diff) { + tbv_ref t(dm.tbvm()); + doc_ref result(dm); + t = mk_rand_tbv(dm); + result = dm.allocate(*t); + SASSERT(dm.tbvm().equals(*t, result->pos())); + for (unsigned i = 0; i < num_diff; ++i) { + t = mk_rand_tbv(dm, result->pos()); + if (dm.tbvm().equals(*t, result->pos())) { + return 0; + } + if (!result->neg().is_empty() && + dm.tbvm().equals(*t, result->neg()[0])) { + continue; + } + result->neg().push_back(t.detach()); + } + SASSERT(dm.well_formed(*result)); + return result.detach(); + } + + void mk_rand_udoc(doc_manager& dm, unsigned num_elems, unsigned num_diff, udoc& result) { + result.reset(dm); + for (unsigned i = 0; i < num_elems; ++i) { + doc* d = mk_rand_doc(dm, num_diff); + if (d) { + result.push_back(d); + } + } + } + +public: + udoc_tester(): + m_init(m), bv(m), m_vars(m), m_ctx(m, m_reg, m_smt_params), rc(m_ctx), + p(dynamic_cast(*rc.get_rmanager().get_relation_plugin(symbol("doc")))), + cr(dynamic_cast(*rc.get_rmanager().get_relation_plugin(symbol("check_relation")))) + { + cr.set_plugin(&p); + } + + udoc_relation* mk_empty(relation_signature const& sig) { + SASSERT(p.can_handle_signature(sig)); + relation_base* empty = p.mk_empty(sig); + return dynamic_cast(empty); + } + + udoc_relation* mk_full(relation_signature const& sig) { + func_decl_ref fn(m); + fn = m.mk_func_decl(symbol("full"), sig.size(), sig.c_ptr(), m.mk_bool_sort()); + relation_base* full = p.mk_full(fn, sig); + return dynamic_cast(full); + } + + void test1() { + datalog::relation_signature sig; + sig.push_back(bv.mk_sort(12)); + sig.push_back(bv.mk_sort(6)); + sig.push_back(bv.mk_sort(12)); + + + datalog::relation_fact fact1(m), fact2(m), fact3(m); + fact1.push_back(bv.mk_numeral(rational(1), 12)); + fact1.push_back(bv.mk_numeral(rational(6), 6)); + fact1.push_back(bv.mk_numeral(rational(56), 12)); + fact2.push_back(bv.mk_numeral(rational(8), 12)); + fact2.push_back(bv.mk_numeral(rational(16), 6)); + fact2.push_back(bv.mk_numeral(rational(32), 12)); + fact3.push_back(bv.mk_numeral(rational(32), 12)); + fact3.push_back(bv.mk_numeral(rational(16), 6)); + fact3.push_back(bv.mk_numeral(rational(4), 12)); + + relation_signature sig2; + sig2.push_back(bv.mk_sort(3)); + sig2.push_back(bv.mk_sort(6)); + sig2.push_back(bv.mk_sort(3)); + sig2.push_back(bv.mk_sort(3)); + sig2.push_back(bv.mk_sort(3)); + + relation_base* t; + udoc_relation* t1, *t2, *t3; + expr_ref fml(m); + + test_filter_neg2(); + + test_join_project(); + test_join_project2(); + + test_filter_neg4(false); + test_filter_neg4(true); + test_filter_neg5(false); + test_filter_neg5(true); + + test_filter_neg(); + test_filter_neg3(); + + test_join(1000); + + test_rename(); + + + // empty + { + std::cout << "empty\n"; + t = mk_empty(sig); + t->display(std::cout); std::cout << "\n"; + t->to_formula(fml); + std::cout << fml << "\n"; + t->deallocate(); + } + + // full + { + std::cout << "full\n"; + t = mk_full(sig); + t->display(std::cout); std::cout << "\n"; + t->to_formula(fml); + std::cout << fml << "\n"; + t->deallocate(); + } + + // join + { + t1 = mk_full(sig); + t2 = mk_full(sig); + t3 = mk_empty(sig); + unsigned_vector jc1, jc2; + jc1.push_back(1); + jc2.push_back(1); + datalog::relation_join_fn* join_fn = p.mk_join_fn(*t1, *t2, jc1.size(), jc1.c_ptr(), jc2.c_ptr()); + SASSERT(join_fn); + t = (*join_fn)(*t1, *t2); + cr.verify_join(*t1, *t2, *t, jc1, jc2); + t->display(std::cout); std::cout << "\n"; + t->deallocate(); + + t = (*join_fn)(*t1, *t3); + cr.verify_join(*t1, *t3, *t, jc1, jc2); + SASSERT(t->empty()); + t->display(std::cout); std::cout << "\n"; + t->deallocate(); + + t = (*join_fn)(*t3, *t3); + cr.verify_join(*t3, *t3, *t, jc1, jc2); + SASSERT(t->empty()); + t->display(std::cout); std::cout << "\n"; + t->deallocate(); + + dealloc(join_fn); + t1->deallocate(); + t2->deallocate(); + t3->deallocate(); + } + + // project + { + std::cout << "project\n"; + t1 = mk_full(sig); + unsigned_vector pc; + pc.push_back(0); + datalog::relation_transformer_fn* proj_fn = p.mk_project_fn(*t1, pc.size(), pc.c_ptr()); + t = (*proj_fn)(*t1); + cr.verify_project(*t1, *t, pc); + t->display(std::cout); std::cout << "\n"; + t->deallocate(); + + t1->reset(); + t = (*proj_fn)(*t1); + cr.verify_project(*t1, *t, pc); + t->display(std::cout); std::cout << "\n"; + t->deallocate(); + + t1->add_fact(fact1); + t1->add_fact(fact2); + t1->add_fact(fact3); + t = (*proj_fn)(*t1); + cr.verify_project(*t1, *t, pc); + t1->display(std::cout); std::cout << "\n"; + t->display(std::cout); std::cout << "\n"; + t->deallocate(); + + dealloc(proj_fn); + t1->deallocate(); + } + + // union + { + t1 = mk_empty(sig); + t2 = mk_empty(sig); + udoc_relation* delta = mk_full(sig); + t2->add_fact(fact1); + t2->add_fact(fact2); + t1->add_fact(fact3); + + expr_ref t10(m); + t1->to_formula(t10); + expr_ref delta0(m); + delta->to_formula(delta0); + rel_union union_fn = p.mk_union_fn(*t1, *t2, 0); + + t1->display(std::cout << "t1 before:"); std::cout << "\n"; + (*union_fn)(*t1, *t2, delta); + cr.verify_union(t10, *t2, *t1, delta0, delta); + t1->display(std::cout << "t1 after:"); std::cout << "\n"; + delta->display(std::cout << "delta:"); std::cout << "\n"; + + t1->deallocate(); + t2->deallocate(); + delta->deallocate(); + } + + // filter_identical + { + t1 = mk_empty(sig2); + unsigned_vector id; + id.push_back(0); + id.push_back(2); + id.push_back(4); + rel_mut filter_id = p.mk_filter_identical_fn(*t1, id.size(), id.c_ptr()); + relation_fact f1(m); + f1.push_back(bv.mk_numeral(rational(1),3)); + f1.push_back(bv.mk_numeral(rational(1),6)); + f1.push_back(bv.mk_numeral(rational(1),3)); + f1.push_back(bv.mk_numeral(rational(1),3)); + f1.push_back(bv.mk_numeral(rational(1),3)); + t1->add_fact(f1); + f1[4] = bv.mk_numeral(rational(2),3); + t1->add_fact(f1); + t1->display(std::cout); std::cout << "\n"; + (*filter_id)(*t1); + t1->display(std::cout); std::cout << "\n"; + t1->deallocate(); + } + + // tbv_manager::debug_alloc(); + { + relation_signature sig3; + sig3.push_back(m.mk_bool_sort()); + sig3.push_back(m.mk_bool_sort()); + sig3.push_back(m.mk_bool_sort()); + var_ref v0(m.mk_var(0, m.mk_bool_sort()),m); + var_ref v1(m.mk_var(1, m.mk_bool_sort()),m); + var_ref v2(m.mk_var(2, m.mk_bool_sort()),m); + app_ref cond1(m); + t1 = mk_full(sig3); + cond1 = m.mk_eq(v0,v1); + apply_filter(*t1, cond1); + t1->deallocate(); + } + + { + relation_signature sig3; + sig3.push_back(m.mk_bool_sort()); + sig3.push_back(m.mk_bool_sort()); + sig3.push_back(m.mk_bool_sort()); + var_ref v0(m.mk_var(0, m.mk_bool_sort()),m); + var_ref v1(m.mk_var(1, m.mk_bool_sort()),m); + var_ref v2(m.mk_var(2, m.mk_bool_sort()),m); + app_ref cond1(m); + t1 = mk_full(sig3); + cond1 = m.mk_or(m.mk_eq(v0,v1),m.mk_eq(v0,v2)); + apply_filter(*t1, cond1); + t1->deallocate(); + } + + { + relation_signature sig3; + sig3.push_back(bv.mk_sort(1)); + sig3.push_back(bv.mk_sort(1)); + sig3.push_back(bv.mk_sort(1)); + var_ref v0(m.mk_var(0, bv.mk_sort(1)),m); + var_ref v1(m.mk_var(1, bv.mk_sort(1)),m); + var_ref v2(m.mk_var(2, bv.mk_sort(1)),m); + app_ref cond1(m); + cond1 = m.mk_or(m.mk_eq(v0,v1),m.mk_eq(v0,v2)); + t1 = mk_full(sig3); + apply_filter(*t1, cond1); + t1->deallocate(); + } + + + app_ref_vector conds(m); + app_ref cond1(m); + var_ref v0(m.mk_var(0, bv.mk_sort(3)),m); + var_ref v1(m.mk_var(1, bv.mk_sort(6)),m); + var_ref v2(m.mk_var(2, bv.mk_sort(3)),m); + var_ref v3(m.mk_var(3, bv.mk_sort(3)),m); + var_ref v4(m.mk_var(4, bv.mk_sort(3)),m); + conds.push_back(m.mk_true()); + conds.push_back(m.mk_false()); + conds.push_back(m.mk_eq(v0, v2)); + conds.push_back(m.mk_not(m.mk_eq(v0, v2))); + conds.push_back(m.mk_eq(v0, bv.mk_numeral(rational(2), 3))); + cond1 = m.mk_eq(ex(2,1,v0),bv.mk_numeral(rational(3),2)); + conds.push_back(cond1); + conds.push_back(m.mk_or(cond1,m.mk_eq(v3,v4))); + conds.push_back(m.mk_eq(ex(2,1,v3),ex(1,0,v4))); + conds.push_back(m.mk_or(cond1,m.mk_eq(ex(2,1,v3),ex(1,0,v4)))); + conds.push_back(m.mk_or(m.mk_eq(v0,v2),m.mk_eq(v0,v4))); + conds.push_back(m.mk_or(m.mk_eq(v0,v2),m.mk_eq(v3,v4))); + conds.push_back(m.mk_or(m.mk_eq(ex(2,1,v0),ex(1,0,v2)),m.mk_eq(v3,v4))); + conds.push_back(m.mk_or(m.mk_eq(ex(2,1,v0),bv.mk_numeral(rational(3),2)), + m.mk_eq(v3,v4))); + conds.push_back(m.mk_or(m.mk_eq(ex(2,1,v0),bv.mk_numeral(rational(3),2)), + m.mk_eq(v3,bv.mk_numeral(rational(3),3)))); + conds.push_back(m.mk_or(m.mk_eq(v0,bv.mk_numeral(rational(5),3)), + m.mk_eq(v3,bv.mk_numeral(rational(5),3)))); + conds.push_back(m.mk_or(m.mk_eq(v0,bv.mk_numeral(rational(7),3)), + m.mk_eq(v3,bv.mk_numeral(rational(7),3)))); + conds.push_back(m.mk_not(m.mk_or(m.mk_eq(v0,v2),m.mk_eq(v3,v4)))); + + + // filter_interpreted + { + std::cout << "filter interpreted\n"; + t1 = mk_full(sig2); + + for (unsigned i = 0; i < conds.size(); ++i) { + apply_filter(*t1, conds[i].get()); + } + + t1->deallocate(); + + } + + // filter_interpreted_project + { + unsigned_vector remove; + remove.push_back(0); + remove.push_back(2); + + t1 = mk_full(sig2); + apply_filter(*t1, conds[2].get()); + apply_filter_project(*t1, remove, conds[2].get()); + apply_filter_project(*t1, remove, conds[3].get()); + t1->deallocate(); + + t1 = mk_full(sig2); + apply_filter(*t1, conds[3].get()); + apply_filter_project(*t1, remove, conds[2].get()); + apply_filter_project(*t1, remove, conds[3].get()); + t1->deallocate(); + + for (unsigned i = 0; i < conds.size(); ++i) { + t1 = mk_full(sig2); + apply_filter_project(*t1, remove, conds[i].get()); + t1->deallocate(); + } + + remove[1] = 1; + for (unsigned i = 0; i < conds.size(); ++i) { + t1 = mk_full(sig2); + apply_filter_project(*t1, remove, conds[i].get()); + t1->deallocate(); + } + } + + + } + + // {11xx \ {111x}, x011 \ {x011}, 0111} + // {xx11 \ {0011, 1111, x111}} + // 0111 + // {1x1x \ {1x1x}, 1111 \ {1111}, x1x1 \ {x1x1}} + + void test_join_project() + { + datalog::relation_signature sig; + sig.push_back(bv.mk_sort(2)); + sig.push_back(bv.mk_sort(2)); + //sig.push_back(bv.mk_sort(3)); + + unsigned_vector jc1, jc2, pc; + jc1.push_back(0); + jc2.push_back(0); + pc.push_back(1); + pc.push_back(3); + //pc.push_back(4); + udoc_relation* t1, *t2; + relation_base* t; + + scoped_ptr join_project_fn; + + for (unsigned i = 0; i < 200; ++i) { + t1 = mk_rand(sig); + t2 = mk_rand(sig); + t1->display(std::cout); + t2->display(std::cout); + join_project_fn = p.mk_join_project_fn(*t1, *t2, jc1.size(), jc1.c_ptr(), jc2.c_ptr(), pc.size(), pc.c_ptr()); + t = (*join_project_fn)(*t1, *t2); + t->display(std::cout); + cr.verify_join_project(*t1, *t2, *t, jc1, jc2, pc); + t->deallocate(); + t1->deallocate(); + t2->deallocate(); + } + } + + void test_join_project2() + { + relation_signature sig3; + sig3.push_back(bv.mk_sort(1)); + sig3.push_back(bv.mk_sort(1)); + sig3.push_back(bv.mk_sort(1)); + + /// xxx \ x11 + udoc_relation *t1 = mk_full(sig3); + { + udoc_relation *neg = mk_full(sig3); + doc& n = neg->get_udoc()[0]; + neg->get_dm().set(n, 1, BIT_1); + neg->get_dm().set(n, 2, BIT_1); + + unsigned_vector allcols; + allcols.push_back(0); + allcols.push_back(1); + allcols.push_back(2); + apply_filter_neg(*t1, *neg, allcols, allcols); + neg->deallocate(); + } + + // 11x + udoc_relation *t2 = mk_full(sig3); + { + doc& n = t2->get_udoc()[0]; + t2->get_dm().set(n, 0, BIT_1); + t2->get_dm().set(n, 1, BIT_1); + } + + unsigned_vector jc1, jc2, pc; + jc1.push_back(1); + jc1.push_back(2); + jc2.push_back(0); + jc2.push_back(1); + pc.push_back(1); + pc.push_back(2); + + scoped_ptr join_project_fn; + join_project_fn = p.mk_join_project_fn(*t1, *t2, jc1.size(), jc1.c_ptr(), jc2.c_ptr(), pc.size(), pc.c_ptr()); + relation_base *t = (*join_project_fn)(*t1, *t2); + cr.verify_join_project(*t1, *t2, *t, jc1, jc2, pc); + t->deallocate(); + t1->deallocate(); + t2->deallocate(); + } + + void test_rename() { + udoc_relation* t1; + // rename + datalog::relation_signature sig; + sig.push_back(bv.mk_sort(12)); + sig.push_back(bv.mk_sort(6)); + sig.push_back(bv.mk_sort(2)); + datalog::relation_fact fact1(m); + fact1.push_back(bv.mk_numeral(rational(1), 12)); + fact1.push_back(bv.mk_numeral(rational(6), 6)); + fact1.push_back(bv.mk_numeral(rational(3), 2)); + t1 = mk_empty(sig); + t1->add_fact(fact1); + unsigned_vector cycle; + cycle.push_back(0); + cycle.push_back(2); + check_permutation(t1, cycle); + + sig.reset(); + sig.push_back(bv.mk_sort(2)); + sig.push_back(bv.mk_sort(6)); + sig.push_back(bv.mk_sort(12)); + fact1.reset(); + fact1.push_back(bv.mk_numeral(rational(3), 2)); + fact1.push_back(bv.mk_numeral(rational(6), 6)); + fact1.push_back(bv.mk_numeral(rational(1), 12)); + t1 = mk_empty(sig); + t1->add_fact(fact1); + cycle.reset(); + cycle.push_back(0); + cycle.push_back(2); + check_permutation(t1, cycle); + + t1 = mk_empty(sig); + t1->add_fact(fact1); + cycle.reset(); + cycle.push_back(0); + cycle.push_back(1); + cycle.push_back(2); + check_permutation(t1, cycle); + } + + void test_join(unsigned num_rounds) { + for (unsigned i = 0; i < num_rounds; ++i) { + test_join(); + } + } + + void test_join() { + relation_signature sig; + sig.push_back(bv.mk_sort(2)); + sig.push_back(bv.mk_sort(3)); + udoc_relation* t1, *t2; + relation_base* t; + + t1 = mk_rand(sig); + t2 = mk_rand(sig); + + unsigned_vector jc1, jc2; + jc1.push_back(0); + jc2.push_back(0); + scoped_ptr join_fn; + + join_fn = p.mk_join_fn(*t1, *t2, jc1.size(), jc1.c_ptr(), jc2.c_ptr()); + t = (*join_fn)(*t1, *t2); + + cr.verify_join(*t1, *t2, *t, jc1, jc2); + t1->display(std::cout); + t2->display(std::cout); + t->display(std::cout); + std::cout << "\n"; + t1->deallocate(); + t2->deallocate(); + t->deallocate(); + } + + udoc_relation* mk_rand(relation_signature const& sig) { + udoc_relation* t = mk_empty(sig); + mk_rand_udoc(t->get_dm(), 3, 3, t->get_udoc()); + return t; + } + + void check_permutation(relation_base* t1, unsigned_vector const& cycle) { + scoped_ptr rename; + rename = p.mk_rename_fn(*t1, cycle.size(), cycle.c_ptr()); + relation_base* t = (*rename)(*t1); + cr.verify_permutation(*t1,*t, cycle); + t1->display(std::cout); std::cout << "\n"; + t->display(std::cout); std::cout << "\n"; + t->deallocate(); + t1->deallocate(); + } + + /* + The filter_by_negation postcondition: + filter_by_negation(tgt, neg, columns in tgt: c1,...,cN, + corresponding columns in neg: d1,...,dN): + tgt_1:={x: x\in tgt_0 && ! \exists y: ( y \in neg & pi_c1(x)= pi_d1(y) & ... & pi_cN(x)= pi_dN(y) ) } + */ + + void test_filter_neg() { + // filter_by_negation + + relation_signature sig4; + sig4.push_back(bv.mk_sort(1)); + sig4.push_back(bv.mk_sort(1)); + sig4.push_back(bv.mk_sort(1)); + udoc_relation* t1 = mk_empty(sig4); + udoc_relation* t2 = mk_empty(sig4); + unsigned_vector cols1, cols2; + unsigned num_bits = t1->get_dm().num_tbits(); + + cols1.push_back(0); + cols2.push_back(1); + for (unsigned i = 0; i < 100; ++i) { + set_random(*t1, 2*num_bits/3); + set_random(*t2, 2*num_bits/3); + apply_filter_neg(*t1,*t2, cols1, cols2); + } + cols1.push_back(1); + cols2.push_back(2); + for (unsigned i = 0; i < 200; ++i) { + set_random(*t1, 2*num_bits/3); + set_random(*t2, 2*num_bits/3); + apply_filter_neg(*t1,*t2, cols1, cols2); + } + t1->deallocate(); + t2->deallocate(); + } + + void test_filter_neg2() { + // filter_by_negation + relation_signature sig4; + sig4.push_back(bv.mk_sort(1)); + sig4.push_back(bv.mk_sort(1)); + sig4.push_back(bv.mk_sort(1)); + unsigned_vector cols, allcols; + + cols.push_back(0); + cols.push_back(2); + allcols.push_back(0); + allcols.push_back(1); + allcols.push_back(2); + + /// xxx \ 1x0 + udoc_relation* t1 = mk_full(sig4); + { + udoc_relation* neg = mk_full(sig4); + doc& n = neg->get_udoc()[0]; + neg->get_dm().set(n, 0, BIT_1); + neg->get_dm().set(n, 2, BIT_0); + apply_filter_neg(*t1, *neg, allcols, allcols); + neg->deallocate(); + } + + /// xxx \ (1x1 u 0x0) + udoc_relation* t2 = mk_full(sig4); + { + udoc_relation* neg = mk_full(sig4); + doc& n = neg->get_udoc()[0]; + neg->get_dm().set(n, 0, BIT_0); + neg->get_dm().set(n, 2, BIT_0); + apply_filter_neg(*t2, *neg, allcols, allcols); + neg->deallocate(); + } + { + udoc_relation* neg = mk_full(sig4); + doc& n = neg->get_udoc()[0]; + neg->get_dm().set(n, 0, BIT_1); + neg->get_dm().set(n, 2, BIT_1); + apply_filter_neg(*t2, *neg, allcols, allcols); + neg->deallocate(); + } + t1->display(std::cout); + t2->display(std::cout); + + apply_filter_neg(*t2, *t1, cols, cols); + t1->deallocate(); + t2->deallocate(); + } + + void test_filter_neg3() { + // filter_by_negation + relation_signature sig; + sig.push_back(bv.mk_sort(1)); + sig.push_back(bv.mk_sort(1)); + sig.push_back(bv.mk_sort(1)); + unsigned_vector cols1, cols2; + + cols1.push_back(0); + cols1.push_back(0); + cols2.push_back(0); + cols2.push_back(1); + + /// 1xx + udoc_relation* t1 = mk_full(sig); + { + doc& d = t1->get_udoc()[0]; + t1->get_dm().set(d, 0, BIT_1); + } + + /// 10x + udoc_relation* t2 = mk_full(sig); + { + doc& d = t2->get_udoc()[0]; + t1->get_dm().set(d, 0, BIT_1); + t1->get_dm().set(d, 1, BIT_0); + } + + apply_filter_neg(*t1, *t2, cols1, cols2); + t1->deallocate(); + t2->deallocate(); + } + + void test_filter_neg4(bool disable_fast) { + relation_signature sig1, sig2; + sig1.push_back(bv.mk_sort(2)); + sig1.push_back(bv.mk_sort(2)); + sig2.push_back(bv.mk_sort(2)); + unsigned_vector cols1, cols2; + + cols1.push_back(0); + cols1.push_back(1); + cols2.push_back(0); + cols2.push_back(0); + udoc_relation* tgt = mk_full(sig1); + udoc_relation* neg = mk_full(sig2); + if (disable_fast) p.disable_fast_pass(); + apply_filter_neg(*tgt, *neg, cols1, cols2); + tgt->deallocate(); + + tgt = mk_full(sig1); + apply_filter_neg(*neg, *tgt, cols2, cols1); + tgt->deallocate(); + neg->deallocate(); + } + + void test_filter_neg5(bool disable_fast) { + relation_signature sig1, sig2; + sig1.push_back(bv.mk_sort(2)); + sig1.push_back(bv.mk_sort(2)); + sig2.push_back(bv.mk_sort(2)); + sig2.push_back(bv.mk_sort(2)); + sig2.push_back(bv.mk_sort(2)); + unsigned_vector cols1, cols2, cols3; + + cols1.push_back(0); + cols1.push_back(1); + cols2.push_back(0); + cols2.push_back(2); + cols3.push_back(0); + cols3.push_back(1); + udoc_relation* tgt = mk_full(sig1); + udoc_relation* neg = mk_full(sig2); + rel_mut filter_id = p.mk_filter_identical_fn(*tgt, cols3.size(), cols3.c_ptr()); + (*filter_id)(*tgt); + if (disable_fast) p.disable_fast_pass(); + apply_filter_neg(*tgt, *neg, cols1, cols2); + tgt->deallocate(); + neg->deallocate(); + } + + void set_random(udoc_relation& r, unsigned num_vals) { + unsigned num_bits = r.get_dm().num_tbits(); + udoc_relation* full = mk_full(r.get_signature()); + rel_union union_fn = p.mk_union_fn(r, r, 0); + (*union_fn)(r, *full); + doc_manager& dm = r.get_dm(); + SASSERT(r.get_udoc().size() == 1); + doc& d0 = r.get_udoc()[0]; + SASSERT(dm.is_full(d0)); + for (unsigned i = 0; i < num_vals; ++i) { + unsigned idx = m_rand(num_bits); + unsigned val = m_rand(2); + tbit b = (val == 0)?BIT_0:BIT_1; + dm.set(d0, idx, b); + } + full->deallocate(); + } + + void apply_filter_neg(udoc_relation& dst, udoc_relation& neg, + unsigned_vector const& cols1, unsigned_vector const& cols2) { + + scoped_ptr negf; + negf = p.mk_filter_by_negation_fn(dst, neg, cols1.size(), cols1.c_ptr(), cols2.c_ptr()); + expr_ref dst0(m); + dst.to_formula(dst0); + (*negf)(dst, neg); + cr.verify_filter_by_negation(dst0, dst, neg, cols1, cols2); + + /* + + tgt_1:={ x: x\in tgt_0 && ! \exists y: + ( y \in neg & pi_c1(x)= pi_d1(y) & ... & pi_cN(x)= pi_dN(y) ) } + */ + } + + expr_ref ex(unsigned hi, unsigned lo, expr* e) { + expr_ref result(m); + result = bv.mk_extract(hi, lo, e); + return result; + } + + void apply_filter_project(udoc_relation& t, unsigned_vector const& rm, app* cond) { + scoped_ptr rt; + rt = p.mk_filter_interpreted_and_project_fn(t, cond, rm.size(), rm.c_ptr()); + datalog::relation_base* result = (*rt)(t); + cr.verify_filter_project(t, *result, cond, rm); + result->deallocate(); + } + + void project_var(unsigned i, sort* s, expr_ref& fml) { + var_ref v(m); + v = m.mk_var(i, s); + unsigned num_bits = bv.get_bv_size(s); + unsigned p = 1 << num_bits; + expr_ref_vector disj(m); + expr_ref tmp(m); + for (unsigned i = 0; i < p; ++i) { + expr_safe_replace repl(m); + repl.insert(v, bv.mk_numeral(rational(i), s)); + tmp = fml; + repl(tmp); + disj.push_back(tmp); + } + fml = mk_or(m, disj.size(), disj.c_ptr()); + } + + void apply_filter(udoc_relation& t, app* cond) { + udoc_relation* full = mk_full(t.get_signature()); + rel_union union_fn = p.mk_union_fn(t, *full, 0); + (*union_fn)(t, *full, 0); + expr_ref fml0(m); + t.to_formula(fml0); + rel_mut fint = p.mk_filter_interpreted_fn(t, cond); + (*fint)(t); + t.display(std::cout << "filter: " << mk_pp(cond, m) << " "); std::cout << "\n"; + cr.verify_filter(fml0, t, cond); + full->deallocate(); + } + + +}; + +void tst_udoc_relation() { + udoc_tester tester; + + try { + tester.test1(); + } + catch (z3_exception& ex) { + std::cout << ex.msg() << "\n"; + } +} diff --git a/src/util/bit_vector.cpp b/src/util/bit_vector.cpp index 1490b9628..f0e9e9c67 100644 --- a/src/util/bit_vector.cpp +++ b/src/util/bit_vector.cpp @@ -207,6 +207,34 @@ void bit_vector::display(std::ostream & out) const { #endif } +bool bit_vector::contains(bit_vector const& other) const { + unsigned n = num_words(); + if (n == 0) + return true; + + for (unsigned i = 0; i < n - 1; ++i) { + if ((m_data[i] & other.m_data[i]) != other.m_data[i]) + return false; + } + unsigned bit_rest = m_num_bits % 32; + unsigned mask = (1U << bit_rest) - 1; + if (mask == 0) mask = UINT_MAX; + unsigned other_data = other.m_data[n-1] & mask; + return (m_data[n-1] & other_data) == other_data; +} + +unsigned bit_vector::get_hash() const { + return string_hash(reinterpret_cast(m_data), size()/8, 0); +} + +bit_vector& bit_vector::neg() { + unsigned n = num_words(); + for (unsigned i = 0; i < n; ++i) { + m_data[i] = ~m_data[i]; + } + return *this; +} + void fr_bit_vector::reset() { unsigned sz = size(); unsigned_vector::const_iterator it = m_one_idxs.begin(); diff --git a/src/util/bit_vector.h b/src/util/bit_vector.h index 0ccdeae9e..6bfccd914 100644 --- a/src/util/bit_vector.h +++ b/src/util/bit_vector.h @@ -125,6 +125,8 @@ public: unsigned get_word(unsigned word_idx) const { return m_data[word_idx]; } + + unsigned get_hash() const; bool get(unsigned bit_idx) const { SASSERT(bit_idx < size()); @@ -198,8 +200,13 @@ public: bit_vector & operator|=(bit_vector const & source); bit_vector & operator&=(bit_vector const & source); + + bit_vector & neg(); void display(std::ostream & out) const; + + bool contains(const bit_vector & other) const; + }; inline std::ostream & operator<<(std::ostream & out, bit_vector const & b) { diff --git a/src/util/fixed_bit_vector.cpp b/src/util/fixed_bit_vector.cpp new file mode 100644 index 000000000..8843db736 --- /dev/null +++ b/src/util/fixed_bit_vector.cpp @@ -0,0 +1,168 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + fixed_bit_vector.cpp + +Abstract: + + Simple bitvector implementation for fixed size bit-vectors. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-9-15. + Leonardo de Moura (leonardo) 2006-10-03. + +Revision History: + Based on bit_vector.cpp + +--*/ + +#include +#include"fixed_bit_vector.h" +#include"trace.h" +#include"hash.h" + +void fixed_bit_vector::set(fixed_bit_vector const& other, unsigned hi, unsigned lo) { + if ((lo % 32) == 0) { + unsigned sz32 = (hi-lo+1)/32; + unsigned lo32 = lo/32; + for (unsigned i = 0; i < sz32; ++i) { + m_data[lo32 + i] = other.m_data[i]; + } + for (unsigned i = sz32*32; i < hi - lo + 1; ++i) { + set(lo + i, other.get(i)); + } + return; + } + for (unsigned i = 0; i < hi - lo + 1; ++i) { + set(lo + i, other.get(i)); + } +} + +fixed_bit_vector_manager::fixed_bit_vector_manager(unsigned num_bits): + m_alloc("fixed_bit_vector") { + m_num_bits = num_bits; + m_num_words = num_words(num_bits); + m_num_bytes = m_num_words * sizeof(unsigned); + unsigned bit_rest = m_num_bits % 32; + m_mask = (1U << bit_rest) - 1; + if (m_mask == 0) m_mask = UINT_MAX; +} + + +fixed_bit_vector* fixed_bit_vector_manager::allocate() { + if (m_num_bytes == 0) return &m_0; + return static_cast(m_alloc.allocate(m_num_bytes)); +} + +fixed_bit_vector* fixed_bit_vector_manager::allocate0() { + fixed_bit_vector* result = allocate(); + fill0(*result); + return result; +} + +fixed_bit_vector* fixed_bit_vector_manager::allocate1() { + fixed_bit_vector* result = allocate(); + fill1(*result); + return result; +} + +fixed_bit_vector* fixed_bit_vector_manager::allocate(fixed_bit_vector const& bv) { + fixed_bit_vector* result = allocate(); + copy(*result, bv); + return result; +} + +void fixed_bit_vector_manager::deallocate(fixed_bit_vector* bv) { + if (m_num_bytes > 0) m_alloc.deallocate(m_num_bytes, bv); +} + + +void fixed_bit_vector_manager::copy(fixed_bit_vector& dst, fixed_bit_vector const& src) const { + memcpy(dst.m_data, src.m_data, num_bytes()); +} + + +fixed_bit_vector& +fixed_bit_vector_manager::fill0(fixed_bit_vector& bv) const { + memset(bv.m_data, 0, num_bytes()); + return bv; +} + +fixed_bit_vector& +fixed_bit_vector_manager::fill1(fixed_bit_vector& bv) const { + memset(bv.m_data, 0xFF, num_bytes()); + return bv; +} + +fixed_bit_vector& +fixed_bit_vector_manager::set_and(fixed_bit_vector& dst, fixed_bit_vector const& src) const { + for (unsigned i = 0; i < m_num_words; i++) + dst.m_data[i] &= src.m_data[i]; + return dst; +} + +fixed_bit_vector& +fixed_bit_vector_manager::set_or(fixed_bit_vector& dst, fixed_bit_vector const& src) const { + for (unsigned i = 0; i < m_num_words; i++) + dst.m_data[i] |= src.m_data[i]; + return dst; +} + +fixed_bit_vector& +fixed_bit_vector_manager::set_neg(fixed_bit_vector& dst) const { + for (unsigned i = 0; i < m_num_words; i++) + dst.m_data[i] = ~dst.m_data[i]; + return dst; +} + +unsigned fixed_bit_vector_manager::last_word(fixed_bit_vector const& bv) const { + unsigned n = num_words(); + if (n == 0) return 0; + return bv.m_data[n-1] & m_mask; +} + +bool fixed_bit_vector_manager::equals(fixed_bit_vector const& a, fixed_bit_vector const& b) const { + if (&a == &b) return true; + unsigned n = num_words(); + if (n == 0) + return true; + for (unsigned i = 0; i < n - 1; i++) { + if (a.m_data[i] != b.m_data[i]) + return false; + } + return last_word(a) == last_word(b); +} +unsigned fixed_bit_vector_manager::hash(fixed_bit_vector const& src) const { + return string_hash(reinterpret_cast(src.m_data), num_bits()/8, num_bits()); +} + +bool fixed_bit_vector_manager::contains(fixed_bit_vector const& a, fixed_bit_vector const& b) const { + unsigned n = num_words(); + if (n == 0) + return true; + + for (unsigned i = 0; i < n - 1; ++i) { + if ((a.m_data[i] & b.m_data[i]) != b.m_data[i]) + return false; + } + unsigned b_data = last_word(b); + return (last_word(a) & b_data) == b_data; +} + +std::ostream& fixed_bit_vector_manager::display(std::ostream& out, fixed_bit_vector const& b) const { + unsigned i = num_bits(); + while (i > 0) { + --i; + if (b.get(i)) + out << "1"; + else + out << "0"; + } + return out; +} + + + diff --git a/src/util/fixed_bit_vector.h b/src/util/fixed_bit_vector.h new file mode 100644 index 000000000..933299925 --- /dev/null +++ b/src/util/fixed_bit_vector.h @@ -0,0 +1,146 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + fixed_bit_vector.h + +Abstract: + + Simple bitvector implementation for fixed size bit-vectors. + +Author: + + Nikolaj Bjorner (nbjorner) 2014-9-15. + +Revision History: + + Related to bit_vector, but is based on a manager. + +--*/ +#ifndef _FIXED_BIT_VECTOR_H_ +#define _FIXED_BIT_VECTOR_H_ + +#include +#include"debug.h" +#include"small_object_allocator.h" + +class fixed_bit_vector { + friend class fixed_bit_vector_manager; + friend class tbv_manager; + unsigned m_data[1]; + + static unsigned get_pos_mask(unsigned bit_idx) { + return 1 << (bit_idx % 32); + } + + + unsigned get_bit_word(unsigned bit_idx) const { + return m_data[bit_idx / 32]; + } + + unsigned & get_bit_word(unsigned bit_idx) { + return m_data[bit_idx / 32]; + } + +public: + + fixed_bit_vector() {} + + ~fixed_bit_vector() {} + + unsigned get_word(unsigned word_idx) const { return m_data[word_idx]; } + + bool operator[](unsigned bit_idx) const { + return get(bit_idx); + } + + bool get(unsigned bit_idx) const { + return (get_bit_word(bit_idx) & get_pos_mask(bit_idx)) != 0; + } + +private: + void set(unsigned bit_idx) { + get_bit_word(bit_idx) |= get_pos_mask(bit_idx); + } + + void unset(unsigned bit_idx) { + get_bit_word(bit_idx) &= ~get_pos_mask(bit_idx); + } + + void set(unsigned bit_idx, bool val) { + int _val = static_cast(val); + get_bit_word(bit_idx) ^= (-_val ^ get_bit_word(bit_idx)) & get_pos_mask(bit_idx); + } + + // assign bits this[lo:hi] := other[0:hi-lo+1] + void set(fixed_bit_vector const& other, unsigned hi, unsigned lo); + +}; + +class fixed_bit_vector_manager { + friend class fixed_bit_vector; + small_object_allocator m_alloc; + unsigned m_num_bits; + unsigned m_num_bytes; + unsigned m_num_words; + unsigned m_mask; + fixed_bit_vector m_0; + + static unsigned num_words(unsigned num_bits) { + return (num_bits + 31) / 32; + } + +public: + fixed_bit_vector_manager(unsigned num_bits); + + void reset() { m_alloc.reset(); } + fixed_bit_vector* allocate(); + fixed_bit_vector* allocate1(); + fixed_bit_vector* allocate0(); + fixed_bit_vector* allocate(fixed_bit_vector const& bv); + void deallocate(fixed_bit_vector* bv); + + void copy(fixed_bit_vector& dst, fixed_bit_vector const& src) const; + unsigned num_words() const { return m_num_words; } + unsigned num_bytes() const { return m_num_bytes; } + unsigned num_bits() const { return m_num_bits; } + fixed_bit_vector& reset(fixed_bit_vector& bv) const { return fill0(bv); } + fixed_bit_vector& fill0(fixed_bit_vector& bv) const; + fixed_bit_vector& fill1(fixed_bit_vector& bv) const; + fixed_bit_vector& set_and(fixed_bit_vector& dst, fixed_bit_vector const& src) const; + fixed_bit_vector& set_or(fixed_bit_vector& dst, fixed_bit_vector const& src) const; + fixed_bit_vector& set_neg(fixed_bit_vector& dst) const; + unsigned last_word(fixed_bit_vector const& bv) const; + unsigned get_mask() const { return m_mask; } + bool equals(fixed_bit_vector const& a, fixed_bit_vector const& b) const; + unsigned hash(fixed_bit_vector const& src) const; + bool contains(fixed_bit_vector const& a, fixed_bit_vector const& b) const; + std::ostream& display(std::ostream& out, fixed_bit_vector const& b) const; + void set(fixed_bit_vector& dst, unsigned bit_idx) { + SASSERT(bit_idx < num_bits()); + dst.set(bit_idx); + } + void unset(fixed_bit_vector& dst, unsigned bit_idx) { + SASSERT(bit_idx < num_bits()); + dst.unset(bit_idx); + } + + void set(fixed_bit_vector& dst, unsigned bit_idx, bool val) { + SASSERT(bit_idx < num_bits()); + dst.set(bit_idx, val); + } + + // assign bits this[lo:hi] := other[0:hi-lo+1] + void set(fixed_bit_vector& dst, fixed_bit_vector const& other, unsigned hi, unsigned lo) { + SASSERT(lo <= hi && hi < num_bits()); + dst.set(other, hi, lo); + } + +}; + + + + +#endif /* _FIXED_BIT_VECTOR_H_ */ + diff --git a/src/util/gparams.cpp b/src/util/gparams.cpp index adffe6bde..69f596c5d 100644 --- a/src/util/gparams.cpp +++ b/src/util/gparams.cpp @@ -266,6 +266,7 @@ public: } } + void set(param_descrs const & d, symbol const & param_name, char const * value, symbol const & mod_name) { param_kind k = d.get_kind(param_name); params_ref & ps = get_params(mod_name); diff --git a/src/util/inf_eps_rational.h b/src/util/inf_eps_rational.h index 659fdc400..698075e01 100644 --- a/src/util/inf_eps_rational.h +++ b/src/util/inf_eps_rational.h @@ -127,6 +127,10 @@ class inf_eps_rational { return m_r.get_uint64(); } + Numeral const& get_numeral() const { + return m_r; + } + rational const& get_rational() const { return m_r.get_rational(); } @@ -139,16 +143,37 @@ class inf_eps_rational { return m_infty; } + bool is_finite() const { + return m_infty.is_zero(); + } + + static inf_eps_rational zero() { + return inf_eps_rational(Numeral::zero()); + } + + static inf_eps_rational one() { + return inf_eps_rational(Numeral::one()); + } + + static inf_eps_rational minus_one() { + return inf_eps_rational(Numeral::minus_one()); + } + + static inf_eps_rational infinity() { + return inf_eps_rational(rational::one(), Numeral::zero()); + } + + inf_eps_rational & operator=(const inf_eps_rational & r) { m_infty = r.m_infty; m_r = r.m_r; return *this; } - inf_eps_rational & operator=(const rational & r) { + inf_eps_rational & operator=(const Numeral & r) { m_infty.reset(); m_r = r; - return *this; + return *this; } inf_eps_rational & operator+=(const inf_eps_rational & r) { @@ -163,6 +188,16 @@ class inf_eps_rational { return *this; } + inf_eps_rational & operator-=(const inf_rational & r) { + m_r -= r; + return *this; + } + + inf_eps_rational & operator+=(const inf_rational & r) { + m_r += r; + return *this; + } + inf_eps_rational & operator+=(const rational & r) { m_r += r; return *this; @@ -272,12 +307,12 @@ class inf_eps_rational { } friend inline rational floor(const inf_eps_rational & r) { - SASSERT(r.m_infty.is_zero()); + // SASSERT(r.m_infty.is_zero()); return floor(r.m_r); } friend inline rational ceil(const inf_eps_rational & r) { - SASSERT(r.m_infty.is_zero()); + // SASSERT(r.m_infty.is_zero()); return ceil(r.m_r); } diff --git a/src/util/inf_int_rational.h b/src/util/inf_int_rational.h index c9879f0ee..b1b1fb89f 100644 --- a/src/util/inf_int_rational.h +++ b/src/util/inf_int_rational.h @@ -155,6 +155,17 @@ class inf_int_rational { return *this; } + inf_int_rational & operator*=(const rational & r) { + if (!r.is_int32()) { + throw default_exception("multiplication with large rational is not possible"); + } + m_first *= r; + m_second *= r.get_int32(); + return *this; + } + + + inf_int_rational & operator-=(const inf_int_rational & r) { m_first -= r.m_first; m_second -= r.m_second; @@ -344,6 +355,10 @@ inline inf_int_rational operator+(const inf_int_rational & r1, const inf_int_rat return inf_int_rational(r1) += r2; } +inline inf_int_rational operator*(const rational & r1, const inf_int_rational & r2) { + return inf_int_rational(r2) *= r1; +} + inline inf_int_rational operator-(const inf_int_rational & r1, const inf_int_rational & r2) { return inf_int_rational(r1) -= r2; } diff --git a/src/util/inf_rational.h b/src/util/inf_rational.h index 5cdfe9e93..2da99cca5 100644 --- a/src/util/inf_rational.h +++ b/src/util/inf_rational.h @@ -88,7 +88,7 @@ class inf_rational { m_second(pos_inf?rational(1):rational(-1)) {} - explicit inf_rational(rational const& r): + inf_rational(rational const& r): m_first(r) { m_second.reset(); diff --git a/src/util/mpq_inf.cpp b/src/util/mpq_inf.cpp index 6f6d805f2..19289b737 100644 --- a/src/util/mpq_inf.cpp +++ b/src/util/mpq_inf.cpp @@ -19,7 +19,7 @@ Revision History: #include"mpq_inf.h" template -std::string mpq_inf_manager::to_string(mpq_inf const & a) const { +std::string mpq_inf_manager::to_string(mpq_inf const & a) { if (m.is_zero(a.second)) return m.to_string(a.first); @@ -38,5 +38,6 @@ std::string mpq_inf_manager::to_string(mpq_inf const & a) const { return s; } + template class mpq_inf_manager; template class mpq_inf_manager; diff --git a/src/util/mpq_inf.h b/src/util/mpq_inf.h index 217b58567..640c827ae 100644 --- a/src/util/mpq_inf.h +++ b/src/util/mpq_inf.h @@ -26,12 +26,12 @@ typedef std::pair mpq_inf; template class mpq_inf_manager { - mpq_manager & m; + mpq_manager m; double m_inf; public: typedef mpq_inf numeral; - mpq_inf_manager(mpq_manager & _m, double inf = 0.0001):m(_m) { + mpq_inf_manager(double inf = 0.0001) { set_inf(inf); } @@ -83,6 +83,14 @@ public: } bool is_int(mpq_inf const & a) const { return m.is_int(a.first) && m.is_zero(a.second); } + + bool is_pos(mpq_inf const & a) const { + return m.is_pos(a.first) || (m.is_zero(a.first) && m.is_pos(a.second)); + } + + bool is_neg(mpq_inf const & a) const { + return m.is_neg(a.first) || (m.is_zero(a.first) && m.is_neg(a.second)); + } bool is_rational(mpq_inf const & a) const { return m.is_zero(a.second); } @@ -104,15 +112,15 @@ public: return m.is_zero(a.first) && m.is_zero(a.second); } - bool eq(mpq_inf const & a, mpq_inf const & b) const { + bool eq(mpq_inf const & a, mpq_inf const & b) { return m.eq(a.first, b.first) && m.eq(a.second, b.second); } - bool eq(mpq_inf const & a, mpq const & b) const { + bool eq(mpq_inf const & a, mpq const & b) { return m.eq(a.first, b) && m.is_zero(a.second); } - bool eq(mpq_inf const & a, mpq const & b, inf_kind k) const { + bool eq(mpq_inf const & a, mpq const & b, inf_kind k) { if (!m.eq(a.first, b)) return false; switch (k) { @@ -124,15 +132,15 @@ public: return false; } - bool lt(mpq_inf const & a, mpq_inf const & b) const { + bool lt(mpq_inf const & a, mpq_inf const & b) { return m.lt(a.first, b.first) || (m.lt(a.second, b.second) && m.eq(a.first, b.first)); } - bool lt(mpq_inf const & a, mpq const & b) const { + bool lt(mpq_inf const & a, mpq const & b) { return m.lt(a.first, b) || (m.is_neg(a.second) && m.eq(a.first, b)); } - bool lt(mpq_inf const & a, mpq const & b, inf_kind k) const { + bool lt(mpq_inf const & a, mpq const & b, inf_kind k) { if (m.lt(a.first, b)) return true; if (m.eq(a.first, b)) { @@ -146,13 +154,13 @@ public: return false; } - bool gt(mpq_inf const & a, mpq_inf const & b) const { return lt(b, a); } + bool gt(mpq_inf const & a, mpq_inf const & b) { return lt(b, a); } - bool gt(mpq_inf const & a, mpq const & b) const { + bool gt(mpq_inf const & a, mpq const & b) { return m.gt(a.first, b) || (m.is_pos(a.second) && m.eq(a.first, b)); } - bool gt(mpq_inf const & a, mpq const & b, inf_kind k) const { + bool gt(mpq_inf const & a, mpq const & b, inf_kind k) { if (m.gt(a.first, b)) return true; if (m.eq(a.first, b)) { @@ -166,17 +174,17 @@ public: return false; } - bool le(mpq_inf const & a, mpq_inf const & b) const { return !gt(a, b); } + bool le(mpq_inf const & a, mpq_inf const & b) { return !gt(a, b); } - bool le(mpq_inf const & a, mpq const & b) const { return !gt(a, b); } + bool le(mpq_inf const & a, mpq const & b) { return !gt(a, b); } - bool le(mpq_inf const & a, mpq const & b, inf_kind k) const { return !gt(a, b, k); } + bool le(mpq_inf const & a, mpq const & b, inf_kind k) { return !gt(a, b, k); } - bool ge(mpq_inf const & a, mpq_inf const & b) const { return !lt(a, b); } + bool ge(mpq_inf const & a, mpq_inf const & b) { return !lt(a, b); } - bool ge(mpq_inf const & a, mpq const & b) const { return !lt(a, b); } + bool ge(mpq_inf const & a, mpq const & b) { return !lt(a, b); } - bool ge(mpq_inf const & a, mpq const & b, inf_kind k) const { return !lt(a, b, k); } + bool ge(mpq_inf const & a, mpq const & b, inf_kind k) { return !lt(a, b, k); } void add(mpq_inf const & a, mpq_inf const & b, mpq_inf & c) { m.add(a.first, b.first, c.first); @@ -208,6 +216,16 @@ public: m.mul(b, a.second, c.second); } + void div(mpq_inf const & a, mpq const & b, mpq_inf & c) { + m.div(a.first, b, c.first); + m.div(a.second, b, c.second); + } + + void div(mpq_inf const & a, mpz const & b, mpq_inf & c) { + m.div(a.first, b, c.first); + m.div(a.second, b, c.second); + } + void inc(mpq_inf & a) { m.inc(a.first); } @@ -221,10 +239,16 @@ public: m.neg(a.second); } + void abs(mpq_inf & a) { + if (is_neg(a)) { + neg(a); + } + } + void ceil(mpq_inf const & a, mpq & b) { if (m.is_int(a.first)) { // special cases for k - delta*epsilon where k is an integer - if (m.is_pos(a.first)) + if (m.is_pos(a.second)) m.add(a.first, mpq(1), b); // ceil(k + delta*epsilon) --> k+1 else m.set(b, a.first); @@ -246,7 +270,13 @@ public: } } - std::string to_string(mpq_inf const & a) const; + std::string to_string(mpq_inf const & a); + + void display(std::ostream & out, mpq_inf const & a) { + out << to_string(a); + } + + mpq_manager& get_mpq_manager() { return m; } }; typedef mpq_inf_manager synch_mpq_inf_manager; diff --git a/src/util/rational.h b/src/util/rational.h index 0d8a23e81..379f4868c 100644 --- a/src/util/rational.h +++ b/src/util/rational.h @@ -111,6 +111,11 @@ public: return INT_MIN <= v && v <= INT_MAX; } + int get_int32() const { + SASSERT(is_int32()); + return (int)get_int64(); + } + double get_double() const { return m().get_double(m_val); } rational const & get_rational() const { return *this; } diff --git a/src/util/region.h b/src/util/region.h index 7f6bc787e..5be2ae4d3 100644 --- a/src/util/region.h +++ b/src/util/region.h @@ -53,6 +53,7 @@ public: m_scopes.push_back(m_chuncks.size()); } + void pop_scope() { unsigned old_size = m_scopes.back(); m_scopes.pop_back(); diff --git a/src/util/s_integer.h b/src/util/s_integer.h index 4e50269c5..92321a7c3 100644 --- a/src/util/s_integer.h +++ b/src/util/s_integer.h @@ -67,7 +67,7 @@ public: s_integer const& get_s_integer() const { return *this; } s_integer const& get_infinitesimal() const { return zero(); } static bool is_rational() { return true; } - s_integer const& get_rational() const { return *this; } + s_integer const& get_rational() const { return *this; } s_integer & operator=(const s_integer & r) { m_val = r.m_val; return *this; } friend inline s_integer numerator(const s_integer & r) { return r; } friend inline s_integer denominator(const s_integer & r) { return one(); } diff --git a/src/util/scoped_numeral.h b/src/util/scoped_numeral.h index 25e6422df..0023be7e2 100644 --- a/src/util/scoped_numeral.h +++ b/src/util/scoped_numeral.h @@ -39,7 +39,7 @@ public: numeral const & get() const { return m_num; } numeral & get() { return m_num; } - _scoped_numeral & operator=(_scoped_numeral & n) { + _scoped_numeral & operator=(_scoped_numeral const & n) { if (this == &n) return *this; m().set(m_num, n.m_num); @@ -97,6 +97,10 @@ public: return a.m().eq(a, b); } + friend bool operator!=(_scoped_numeral const & a, numeral const & b) { + return !a.m().eq(a, b); + } + friend bool operator<(_scoped_numeral const & a, numeral const & b) { return a.m().lt(a, b); } @@ -113,6 +117,26 @@ public: return a.m().ge(a, b); } + bool is_zero() const { + return m().is_zero(*this); + } + + bool is_pos() const { + return m().is_pos(*this); + } + + bool is_neg() const { + return m().is_neg(*this); + } + + bool is_nonpos() const { + return m().is_nonpos(*this); + } + + bool is_nonneg() const { + return m().is_nonneg(*this); + } + friend bool is_zero(_scoped_numeral const & a) { return a.m().is_zero(a); } @@ -133,6 +157,12 @@ public: return a.m().is_nonpos(a); } + friend _scoped_numeral abs(_scoped_numeral const& a) { + _scoped_numeral res(a); + a.m().abs(res); + return res; + } + void neg() { m().neg(m_num); } diff --git a/src/util/scoped_numeral_vector.h b/src/util/scoped_numeral_vector.h index 4375babb3..f982a7cae 100644 --- a/src/util/scoped_numeral_vector.h +++ b/src/util/scoped_numeral_vector.h @@ -46,6 +46,10 @@ public: m_manager.set(this->back(), v); } + void pop_back() { + shrink(this->size()-1); + } + void shrink(unsigned sz) { unsigned old_sz = this->size(); if (old_sz == sz) diff --git a/src/util/sorting_network.h b/src/util/sorting_network.h new file mode 100644 index 000000000..ee01d2cd2 --- /dev/null +++ b/src/util/sorting_network.h @@ -0,0 +1,767 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + sorting_network.h + +Abstract: + + Utility for creating a sorting network. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-11-07 + +Notes: + + Same routine is used in Formula. + +--*/ + +#include "vector.h" + +#ifndef _SORTING_NETWORK_H_ +#define _SORTING_NETWORK_H_ + + + template + class sorting_network { + typedef typename Ext::vector vect; + Ext& m_ext; + svector m_currentv; + svector m_nextv; + svector* m_current; + svector* m_next; + + unsigned& current(unsigned i) { return (*m_current)[i]; } + unsigned& next(unsigned i) { return (*m_next)[i]; } + + void exchange(unsigned i, unsigned j, vect& out) { + SASSERT(i <= j); + if (i < j) { + typename Ext::T ei = out.get(i); + typename Ext::T ej = out.get(j); + out.set(i, m_ext.mk_ite(m_ext.mk_le(ei, ej), ei, ej)); + out.set(j, m_ext.mk_ite(m_ext.mk_le(ej, ei), ei, ej)); + } + } + + void sort(unsigned k, vect& out) { + SASSERT(is_power_of2(k) && k > 0); + if (k == 2) { + for (unsigned i = 0; i < out.size()/2; ++i) { + exchange(current(2*i), current(2*i+1), out); + next(2*i) = current(2*i); + next(2*i+1) = current(2*i+1); + } + std::swap(m_current, m_next); + } + else { + + for (unsigned i = 0; i < out.size()/k; ++i) { + unsigned ki = k * i; + for (unsigned j = 0; j < k / 2; ++j) { + next(ki + j) = current(ki + (2 * j)); + next(ki + (k / 2) + j) = current(ki + (2 * j) + 1); + } + } + + std::swap(m_current, m_next); + sort(k / 2, out); + for (unsigned i = 0; i < out.size() / k; ++i) { + unsigned ki = k * i; + for (unsigned j = 0; j < k / 2; ++j) { + next(ki + (2 * j)) = current(ki + j); + next(ki + (2 * j) + 1) = current(ki + (k / 2) + j); + } + + for (unsigned j = 0; j < (k / 2) - 1; ++j) { + exchange(next(ki + (2 * j) + 1), next(ki + (2 * (j + 1))), out); + } + } + std::swap(m_current, m_next); + } + } + + bool is_power_of2(unsigned n) const { + return n != 0 && ((n-1) & n) == 0; + } + + public: + sorting_network(Ext& ext): + m_ext(ext), + m_current(&m_currentv), + m_next(&m_nextv) + {} + + void operator()(vect const& in, vect& out) { + out.reset(); + out.append(in); + if (in.size() <= 1) { + return; + } + while (!is_power_of2(out.size())) { + out.push_back(m_ext.mk_default()); + } + for (unsigned i = 0; i < out.size(); ++i) { + m_currentv.push_back(i); + m_nextv.push_back(i); + } + unsigned k = 2; + while (k <= out.size()) { + sort(k, out); + k *= 2; + } + } + }; + + // parametric sorting network + // Described in Abio et.al. CP 2013. + template + class psort_nw { + typedef typename psort_expr::literal literal; + typedef typename psort_expr::literal_vector literal_vector; + + class vc { + unsigned v; // number of vertices + unsigned c; // number of clauses + static const unsigned lambda = 5; + public: + vc(unsigned v, unsigned c):v(v), c(c) {} + + bool operator<(vc const& other) const { + return to_int() < other.to_int(); + } + vc operator+(vc const& other) const { + return vc(v + other.v, c + other.c); + } + unsigned to_int() const { + return lambda*v + c; + } + vc operator*(unsigned n) const { + return vc(n*v, n*c); + } + }; + + static vc mk_min(vc const& v1, vc const& v2) { + return (v1.to_int() < v2.to_int())?v1:v2; + } + + + enum cmp_t { LE, GE, EQ, GE_FULL, LE_FULL }; + psort_expr& ctx; + cmp_t m_t; + + // for testing + static const bool m_disable_dcard = false; + static const bool m_disable_dsorting = false; + static const bool m_disable_dsmerge = false; + static const bool m_force_dcard = false; + static const bool m_force_dsorting = false; + static const bool m_force_dsmerge = false; + + public: + struct stats { + unsigned m_num_compiled_vars; + unsigned m_num_compiled_clauses; + void reset() { memset(this, 0, sizeof(*this)); } + stats() { reset(); } + }; + stats m_stats; + + psort_nw(psort_expr& c): ctx(c) {} + + literal ge(bool full, unsigned k, unsigned n, literal const* xs) { + if (k > n) { + return ctx.mk_false(); + } + if (k == 0) { + return ctx.mk_true(); + } + SASSERT(0 < k && k <= n); + literal_vector in, out; + if (dualize(k, n, xs, in)) { + return le(full, k, in.size(), in.c_ptr()); + } + else { + SASSERT(2*k <= n); + m_t = full?GE_FULL:GE; + psort_nw::card(k, n, xs, out); + return out[k-1]; + } + } + + literal le(bool full, unsigned k, unsigned n, literal const* xs) { + if (k >= n) { + return ctx.mk_true(); + } + SASSERT(k < n); + literal_vector in, out; + if (dualize(k, n, xs, in)) { + return ge(full, k, n, in.c_ptr()); + } + else { + SASSERT(2*k <= n); + m_t = full?LE_FULL:LE; + card(k + 1, n, xs, out); + return ctx.mk_not(out[k]); + } + } + + literal eq(unsigned k, unsigned n, literal const* xs) { + if (k > n) { + return ctx.mk_false(); + } + SASSERT(k <= n); + literal_vector in, out; + if (dualize(k, n, xs, in)) { + return eq(k, n, in.c_ptr()); + } + else { + SASSERT(2*k <= n); + m_t = EQ; + card(k+1, n, xs, out); + SASSERT(out.size() >= k+1); + return ctx.mk_min(out[k-1], ctx.mk_not(out[k])); + } + } + + + private: + + std::ostream& pp(std::ostream& out, unsigned n, literal const* lits) { + for (unsigned i = 0; i < n; ++i) ctx.pp(out, lits[i]) << " "; + return out; + } + + std::ostream& pp(std::ostream& out, literal_vector const& lits) { + for (unsigned i = 0; i < lits.size(); ++i) ctx.pp(out, lits[i]) << " "; + return out; + } + + // 0 <= k <= N + // SUM x_i >= k + // <=> + // SUM ~x_i <= N - k + // suppose k > N/2, then it is better to solve dual. + + bool dualize(unsigned& k, unsigned N, literal const* xs, literal_vector& in) { + SASSERT(0 <= k && k <= N); + if (2*k <= N) { + return false; + } + k = N - k; + for (unsigned i = 0; i < N; ++i) { + in.push_back(ctx.mk_not(xs[i])); + } + TRACE("pb", + pp(tout << N << ": ", in); + tout << " ~ " << k << "\n";); + return true; + } + + + bool even(unsigned n) const { return (0 == (n & 0x1)); } + bool odd(unsigned n) const { return !even(n); } + unsigned ceil2(unsigned n) const { return n/2 + odd(n); } + unsigned floor2(unsigned n) const { return n/2; } + unsigned power2(unsigned n) const { SASSERT(n < 10); return 1 << n; } + + + literal mk_max(literal a, literal b) { + if (a == b) return a; + m_stats.m_num_compiled_vars++; + return ctx.mk_max(a, b); + } + + literal mk_min(literal a, literal b) { + if (a == b) return a; + m_stats.m_num_compiled_vars++; + return ctx.mk_min(a, b); + } + + literal fresh() { + m_stats.m_num_compiled_vars++; + return ctx.fresh(); + } + void add_clause(literal l1, literal l2, literal l3) { + literal lits[3] = { l1, l2, l3 }; + add_clause(3, lits); + } + void add_clause(literal l1, literal l2) { + literal lits[2] = { l1, l2 }; + add_clause(2, lits); + } + void add_clause(unsigned n, literal const* ls) { + m_stats.m_num_compiled_clauses++; + literal_vector tmp(n, ls); + ctx.mk_clause(n, tmp.c_ptr()); + } + + // y1 <= mk_max(x1,x2) + // y2 <= mk_min(x1,x2) + void cmp_ge(literal x1, literal x2, literal y1, literal y2) { + add_clause(ctx.mk_not(y2), x1); + add_clause(ctx.mk_not(y2), x2); + add_clause(ctx.mk_not(y1), x1, x2); + } + + // mk_max(x1,x2) <= y1 + // mk_min(x1,x2) <= y2 + void cmp_le(literal x1, literal x2, literal y1, literal y2) { + add_clause(ctx.mk_not(x1), y1); + add_clause(ctx.mk_not(x2), y1); + add_clause(ctx.mk_not(x1), ctx.mk_not(x2), y2); + } + + void cmp_eq(literal x1, literal x2, literal y1, literal y2) { + cmp_ge(x1, x2, y1, y2); + cmp_le(x1, x2, y1, y2); + } + + void cmp(literal x1, literal x2, literal y1, literal y2) { + switch(m_t) { + case LE: case LE_FULL: cmp_le(x1, x2, y1, y2); break; + case GE: case GE_FULL: cmp_ge(x1, x2, y1, y2); break; + case EQ: cmp_eq(x1, x2, y1, y2); break; + } + } + vc vc_cmp() { + return vc(2, (m_t==EQ)?6:3); + } + + void card(unsigned k, unsigned n, literal const* xs, literal_vector& out) { + TRACE("pb", tout << "card k:" << k << " n: " << n << "\n";); + if (n <= k) { + psort_nw::sorting(n, xs, out); + } + else if (use_dcard(k, n)) { + dsorting(k, n, xs, out); + } + else { + literal_vector out1, out2; + unsigned l = n/2; // TBD + card(k, l, xs, out1); + card(k, n-l, xs + l, out2); + smerge(k, out1.size(), out1.c_ptr(), out2.size(), out2.c_ptr(), out); + } + TRACE("pb", tout << "card k:" << k << " n: " << n << "\n"; + pp(tout << "in:", n, xs) << "\n"; + pp(tout << "out:", out) << "\n";); + + } + vc vc_card(unsigned k, unsigned n) { + if (n <= k) { + return vc_sorting(n); + } + else if (use_dcard(k, n)) { + return vc_dsorting(k, n); + } + else { + return vc_card_rec(k, n); + } + } + vc vc_card_rec(unsigned k, unsigned n) { + unsigned l = n/2; + return vc_card(k, l) + vc_card(k, n-l) + vc_smerge(k, l, n-l); + } + bool use_dcard(unsigned k, unsigned n) { + return m_force_dcard || (!m_disable_dcard && n < 10 && vc_dsorting(k, n) < vc_card_rec(k, n)); + } + + + void merge(unsigned a, literal const* as, + unsigned b, literal const* bs, + literal_vector& out) { + TRACE("pb", tout << "merge a: " << a << " b: " << b << "\n";); + if (a == 1 && b == 1) { + literal y1 = mk_max(as[0], bs[0]); + literal y2 = mk_min(as[0], bs[0]); + out.push_back(y1); + out.push_back(y2); + psort_nw::cmp(as[0], bs[0], y1, y2); + } + else if (a == 0) { + out.append(b, bs); + } + else if (b == 0) { + out.append(a, as); + } + else if (use_dsmerge(a, b, a + b)) { + dsmerge(a + b, a, as, b, bs, out); + } + else if (even(a) && odd(b)) { + merge(b, bs, a, as, out); + } + else { + literal_vector even_a, odd_a; + literal_vector even_b, odd_b; + literal_vector out1, out2; + SASSERT(a > 1 || b > 1); + split(a, as, even_a, odd_a); + split(b, bs, even_b, odd_b); + SASSERT(!even_a.empty()); + SASSERT(!even_b.empty()); + merge(even_a.size(), even_a.c_ptr(), + even_b.size(), even_b.c_ptr(), out1); + merge(odd_a.size(), odd_a.c_ptr(), + odd_b.size(), odd_b.c_ptr(), out2); + interleave(out1, out2, out); + } + TRACE("pb", tout << "merge a: " << a << " b: " << b << "\n"; + pp(tout << "a:", a, as) << "\n"; + pp(tout << "b:", b, bs) << "\n"; + pp(tout << "out:", out) << "\n";); + } + vc vc_merge(unsigned a, unsigned b) { + if (a == 1 && b == 1) { + return vc_cmp(); + } + else if (a == 0 || b == 0) { + return vc(0, 0); + } + else if (use_dsmerge(a, b, a + b)) { + return vc_dsmerge(a, b, a + b); + } + else { + return vc_merge_rec(a, b); + } + } + vc vc_merge_rec(unsigned a, unsigned b) { + return + vc_merge(ceil2(a), ceil2(b)) + + vc_merge(floor2(a), floor2(b)) + + vc_interleave(ceil2(a) + ceil2(b), floor2(a) + floor2(b)); + } + void split(unsigned n, literal const* ls, literal_vector& even, literal_vector& odd) { + for (unsigned i = 0; i < n; i += 2) { + even.push_back(ls[i]); + } + for (unsigned i = 1; i < n; i += 2) { + odd.push_back(ls[i]); + } + } + + void interleave(literal_vector const& as, + literal_vector const& bs, + literal_vector& out) { + TRACE("pb", tout << "interleave: " << as.size() << " " << bs.size() << "\n";); + SASSERT(as.size() >= bs.size()); + SASSERT(as.size() <= bs.size() + 2); + SASSERT(!as.empty()); + out.push_back(as[0]); + unsigned sz = std::min(as.size()-1, bs.size()); + for (unsigned i = 0; i < sz; ++i) { + literal y1 = mk_max(as[i+1],bs[i]); + literal y2 = mk_min(as[i+1],bs[i]); + psort_nw::cmp(as[i+1], bs[i], y1, y2); + out.push_back(y1); + out.push_back(y2); + } + if (as.size() == bs.size()) { + out.push_back(bs[sz]); + } + else if (as.size() == bs.size() + 2) { + out.push_back(as[sz+1]); + } + SASSERT(out.size() == as.size() + bs.size()); + TRACE("pb", tout << "interleave: " << as.size() << " " << bs.size() << "\n"; + pp(tout << "a: ", as) << "\n"; + pp(tout << "b: ", bs) << "\n"; + pp(tout << "out: ", out) << "\n";); + + } + vc vc_interleave(unsigned a, unsigned b) { + return vc_cmp()*std::min(a-1,b); + } + + void sorting(unsigned n, literal const* xs, literal_vector& out) { + TRACE("pb", tout << "sorting: " << n << "\n";); + switch(n) { + case 0: + break; + case 1: + out.push_back(xs[0]); + break; + case 2: + psort_nw::merge(1, xs, 1, xs+1, out); + break; + default: + if (use_dsorting(n)) { + dsorting(n, n, xs, out); + } + else { + literal_vector out1, out2; + unsigned l = n/2; // TBD + sorting(l, xs, out1); + sorting(n-l, xs+l, out2); + merge(out1.size(), out1.c_ptr(), + out2.size(), out2.c_ptr(), + out); + } + break; + } + TRACE("pb", tout << "sorting: " << n << "\n"; + pp(tout << "in:", n, xs) << "\n"; + pp(tout << "out:", out) << "\n";); + + } + vc vc_sorting(unsigned n) { + switch(n) { + case 0: return vc(0,0); + case 1: return vc(0,0); + case 2: return vc_merge(1,1); + default: + if (use_dsorting(n)) { + return vc_dsorting(n, n); + } + else { + return vc_sorting_rec(n); + } + } + } + vc vc_sorting_rec(unsigned n) { + SASSERT(n > 2); + unsigned l = n/2; + return vc_sorting(l) + vc_sorting(n-l) + vc_merge(l, n-l); + } + + bool use_dsorting(unsigned n) { + SASSERT(n > 2); + return m_force_dsorting || + (!m_disable_dsorting && n < 10 && vc_dsorting(n, n) < vc_sorting_rec(n)); + } + + void smerge(unsigned c, + unsigned a, literal const* as, + unsigned b, literal const* bs, + literal_vector& out) { + TRACE("pb", tout << "smerge: c:" << c << " a:" << a << " b:" << b << "\n";); + if (a == 1 && b == 1 && c == 1) { + literal y = mk_max(as[0], bs[0]); + if (m_t != GE) { + // x1 <= mk_max(x1,x2) + // x2 <= mk_max(x1,x2) + add_clause(ctx.mk_not(as[0]), y); + add_clause(ctx.mk_not(bs[0]), y); + } + if (m_t != LE) { + // mk_max(x1,x2) <= x1, x2 + add_clause(ctx.mk_not(y), as[0], bs[0]); + } + out.push_back(y); + } + else if (a == 0) { + out.append(std::min(c, b), bs); + } + else if (b == 0) { + out.append(std::min(c, a), as); + } + else if (a > c) { + smerge(c, c, as, b, bs, out); + } + else if (b > c) { + smerge(c, a, as, c, bs, out); + } + else if (a + b <= c) { + merge(a, as, b, bs, out); + } + else if (use_dsmerge(a, b, c)) { + dsmerge(c, a, as, b, bs, out); + } + else { + literal_vector even_a, odd_a; + literal_vector even_b, odd_b; + literal_vector out1, out2; + split(a, as, even_a, odd_a); + split(b, bs, even_b, odd_b); + SASSERT(!even_a.empty()); + SASSERT(!even_b.empty()); + unsigned c1, c2; + if (even(c)) { + c1 = 1 + c/2; c2 = c/2; + } + else { + c1 = (c + 1)/2; c2 = (c - 1)/2; + } + smerge(c1, even_a.size(), even_a.c_ptr(), + even_b.size(), even_b.c_ptr(), out1); + smerge(c2, odd_a.size(), odd_a.c_ptr(), + odd_b.size(), odd_b.c_ptr(), out2); + SASSERT(out1.size() == std::min(even_a.size()+even_b.size(), c1)); + SASSERT(out2.size() == std::min(odd_a.size()+odd_b.size(), c2)); + literal y; + if (even(c)) { + literal z1 = out1.back(); + literal z2 = out2.back(); + out1.pop_back(); + out2.pop_back(); + y = mk_max(z1, z2); + if (m_t != GE) { + add_clause(ctx.mk_not(z1), y); + add_clause(ctx.mk_not(z2), y); + } + if (m_t != LE) { + add_clause(ctx.mk_not(y), z1, z2); + } + } + interleave(out1, out2, out); + if (even(c)) { + out.push_back(y); + } + } + TRACE("pb", tout << "smerge: c:" << c << " a:" << a << " b:" << b << "\n"; + pp(tout << "a:", a, as) << "\n"; + pp(tout << "b:", b, bs) << "\n"; + pp(tout << "out:", out) << "\n"; + ); + SASSERT(out.size() == std::min(a + b, c)); + } + + vc vc_smerge(unsigned a, unsigned b, unsigned c) { + if (a == 1 && b == 1 && c == 1) { + vc v(1,0); + if (m_t != GE) v = v + vc(0, 2); + if (m_t != LE) v = v + vc(0, 1); + return v; + } + if (a == 0 || b == 0) return vc(0, 0); + if (a > c) return vc_smerge(c, b, c); + if (b > c) return vc_smerge(a, c, c); + if (a + b <= c) return vc_merge(a, b); + if (use_dsmerge(a, b, c)) return vc_dsmerge(a, b, c); + return vc_smerge_rec(a, b, c); + } + vc vc_smerge_rec(unsigned a, unsigned b, unsigned c) { + return + vc_smerge(ceil2(a), ceil2(b), even(c)?(1+c/2):((c+1)/2)) + + vc_smerge(floor2(a), floor2(b), even(c)?(c/2):((c-1)/2)) + + vc_interleave(ceil2(a)+ceil2(b),floor2(a)+floor2(b)) + + vc(1, 0) + + ((m_t != GE)?vc(0, 2):vc(0, 0)) + + ((m_t != LE)?vc(0, 1):vc(0, 0)); + } + bool use_dsmerge(unsigned a, unsigned b, unsigned c) { + return + m_force_dsmerge || + (!m_disable_dsmerge && + a < (1 << 15) && b < (1 << 15) && + vc_dsmerge(a, b, a + b) < vc_smerge_rec(a, b, c)); + } + + void dsmerge( + unsigned c, + unsigned a, literal const* as, + unsigned b, literal const* bs, + literal_vector& out) { + TRACE("pb", tout << "dsmerge: c:" << c << " a:" << a << " b:" << b << "\n";); + SASSERT(a <= c); + SASSERT(b <= c); + SASSERT(a + b >= c); + for (unsigned i = 0; i < c; ++i) { + out.push_back(fresh()); + } + if (m_t != GE) { + for (unsigned i = 0; i < a; ++i) { + add_clause(ctx.mk_not(as[i]), out[i]); + } + for (unsigned i = 0; i < b; ++i) { + add_clause(ctx.mk_not(bs[i]), out[i]); + } + for (unsigned i = 1; i <= a; ++i) { + for (unsigned j = 1; j <= b && i + j <= c; ++j) { + add_clause(ctx.mk_not(as[i-1]),ctx.mk_not(bs[j-1]),out[i+j-1]); + } + } + } + if (m_t != LE) { + literal_vector ls; + for (unsigned k = 0; k < c; ++k) { + ls.reset(); + ls.push_back(ctx.mk_not(out[k])); + if (a <= k) { + add_clause(ctx.mk_not(out[k]), bs[k-a]); + } + if (b <= k) { + add_clause(ctx.mk_not(out[k]), as[k-b]); + } + for (unsigned i = 0; i < std::min(a,k + 1); ++i) { + unsigned j = k - i; + SASSERT(i + j == k); + if (j < b) { + ls.push_back(as[i]); + ls.push_back(bs[j]); + add_clause(ls.size(), ls.c_ptr()); + ls.pop_back(); + ls.pop_back(); + } + } + } + } + } + vc vc_dsmerge(unsigned a, unsigned b, unsigned c) { + vc v(c, 0); + if (m_t != GE) { + v = v + vc(0, a + b + std::min(a, c)*std::min(b, c)/2); + } + if (m_t != LE) { + v = v + vc(0, std::min(a, c)*std::min(b, c)/2); + } + return v; + } + + + void dsorting(unsigned m, unsigned n, literal const* xs, + literal_vector& out) { + TRACE("pb", tout << "dsorting m: " << m << " n: " << n << "\n";); + SASSERT(m <= n); + literal_vector lits; + for (unsigned i = 0; i < m; ++i) { + out.push_back(fresh()); + } + if (m_t != GE) { + for (unsigned k = 1; k <= m; ++k) { + lits.push_back(out[k-1]); + add_subset(true, k, 0, lits, n, xs); + lits.pop_back(); + } + } + if (m_t != LE) { + for (unsigned k = 1; k <= m; ++k) { + lits.push_back(ctx.mk_not(out[k-1])); + add_subset(false, n-k+1, 0, lits, n, xs); + lits.pop_back(); + } + } + } + vc vc_dsorting(unsigned m, unsigned n) { + SASSERT(m <= n && n < 10); + vc v(m, 0); + if (m_t != GE) { + v = v + vc(0, power2(n-1)); + } + if (m_t != LE) { + v = v + vc(0, power2(n-1)); + } + return v; + } + + void add_subset(bool polarity, unsigned k, unsigned offset, literal_vector& lits, + unsigned n, literal const* xs) { + TRACE("pb", tout << "k:" << k << " offset: " << offset << " n: " << n << " "; + pp(tout, lits) << "\n";); + SASSERT(k + offset <= n); + if (k == 0) { + add_clause(lits.size(), lits.c_ptr()); + return; + } + for (unsigned i = offset; i < n - k + 1; ++i) { + lits.push_back(polarity?ctx.mk_not(xs[i]):xs[i]); + add_subset(polarity, k-1, i+1, lits, n, xs); + lits.pop_back(); + } + } + }; + +#endif diff --git a/src/util/stopwatch.h b/src/util/stopwatch.h index 425a13567..2b3c24911 100644 --- a/src/util/stopwatch.h +++ b/src/util/stopwatch.h @@ -69,6 +69,7 @@ public: #undef ARRAYSIZE #define ARRAYSIZE ARRAYSIZE_TEMP #undef max +#undef min #elif defined(__APPLE__) && defined (__MACH__) // Mac OS X diff --git a/src/util/trace.h b/src/util/trace.h index 0c8c2e5b6..e92eb9d44 100644 --- a/src/util/trace.h +++ b/src/util/trace.h @@ -24,6 +24,10 @@ Revision History: #undef max #undef min #endif +#ifdef __APPLE__ +#undef max +#undef min +#endif #include #ifdef _TRACE diff --git a/src/ast/trail.h b/src/util/trail.h similarity index 89% rename from src/ast/trail.h rename to src/util/trail.h index ac03f9fce..116b3241e 100644 --- a/src/ast/trail.h +++ b/src/util/trail.h @@ -19,9 +19,9 @@ Revision History: #ifndef _TRAIL_H_ #define _TRAIL_H_ -#include"ast.h" #include"obj_hashtable.h" #include"region.h" +#include"obj_ref.h" template class trail { @@ -208,50 +208,6 @@ public: }; -template -class ast2ast_trailmap { - ref_vector m_domain; - ref_vector m_range; - obj_map m_map; -public: - ast2ast_trailmap(ast_manager& m): - m_domain(m), - m_range(m), - m_map() - {} - - bool find(S* s, T*& t) { - return m_map.find(s,t); - } - - void insert(S* s, T* t) { - SASSERT(!m_map.contains(s)); - m_domain.push_back(s); - m_range.push_back(t); - m_map.insert(s,t); - } - - void pop() { - SASSERT(!m_domain.empty()); - m_map.remove(m_domain.back()); - m_domain.pop_back(); - m_range.pop_back(); - } -}; - -template -class ast2ast_trail : public trail { - ast2ast_trailmap& m_map; -public: - ast2ast_trail(ast2ast_trailmap& m, S* s, T* t) : - m_map(m) { - m.insert(s,t); - } - - virtual void undo(Ctx& ctx) { - m_map.pop(); - } -}; template class push_back_trail : public trail { diff --git a/src/smt/union_find.h b/src/util/union_find.h similarity index 89% rename from src/smt/union_find.h rename to src/util/union_find.h index cb2ce68c8..32de6846a 100644 --- a/src/smt/union_find.h +++ b/src/util/union_find.h @@ -20,6 +20,7 @@ Revision History: #define _UNION_FIND_H_ #include "trail.h" +#include "trace.h" class union_find_default_ctx { public: @@ -98,6 +99,7 @@ public: unsigned get_num_vars() const { return m_find.size(); } + unsigned find(unsigned v) const { while (true) { unsigned new_v = m_find[v]; @@ -109,6 +111,8 @@ public: unsigned next(unsigned v) const { return m_next[v]; } + unsigned size(unsigned v) const { return m_size[find(v)]; } + bool is_root(unsigned v) const { return m_find[v] == v; } void merge(unsigned v1, unsigned v2) { @@ -128,10 +132,23 @@ public: CASSERT("union_find", check_invariant()); } + // dissolve equivalence class of v + // this method cannot be used with backtracking. + void dissolve(unsigned v) { + unsigned w; + do { + w = next(v); + m_size[v] = 1; + m_find[v] = v; + m_next[v] = v; + } + while (w != v); + } + void display(std::ostream & out) const { unsigned num = get_num_vars(); for (unsigned v = 0; v < num; v++) { - out << "v" << v << " --> v" << m_find[v] << "\n"; + out << "v" << v << " --> v" << m_find[v] << " (" << size(v) << ")\n"; } } diff --git a/tests/chat1.smt2 b/tests/chat1.smt2 new file mode 100644 index 000000000..e6e11076b --- /dev/null +++ b/tests/chat1.smt2 @@ -0,0 +1,3380 @@ +(declare-const |dn([7,Main.main],41)| Bool) +(declare-const |dn([3,7],24)| Bool) +(declare-const |dn([7,Main.main],47)| Bool) +(declare-const |dn([9,Main.main],86)| Bool) +(declare-const |dn([7,Main.main],51)| Bool) +(declare-const |dn([3,7],20)| Bool) +(declare-const |dn([6,9],91)| Bool) +(declare-const |scc(3)| Bool) +(declare-const |dn([6,9],92)| Bool) +(declare-const |scc(4)| Bool) +(declare-const |dn([7,Main.main],54)| Bool) +(declare-const |scc(0)| Bool) +(declare-const |dn([Main.main],109)| Bool) +(declare-const |dn([7,Main.main],58)| Bool) +(declare-const |dn([Main.main],104)| Bool) +(declare-const |dn([Main.main],102)| Bool) +(declare-const |dn([8,Main.main],101)| Bool) +(declare-const |dn([6,9],95)| Bool) +(declare-const |dn([8,Main.main],96)| Bool) +(declare-const |dn([3,7],28)| Bool) +(declare-const |dn([Main.main],106)| Bool) +(declare-const |dn([2,3],36)| Bool) +(declare-const |dn([4,1],78)| Bool) +(declare-const |dn([Main.main],114)| Bool) +(declare-const |dn([2,3],35)| Bool) +(declare-const |dn([2,3],38)| Bool) +(declare-const |dn([5,1],63)| Bool) +(declare-const |dn([7,Main.main],39)| Bool) +(declare-const |dn([3,7],33)| Bool) +(declare-const |dn([9,Main.main],88)| Bool) +(declare-const |dn([4,1],80)| Bool) +(declare-const |dn([Main.main],116)| Bool) +(declare-const |dn([Main.main],111)| Bool) +(declare-const |dn([7,Main.main],42)| Bool) +(declare-const |dn([9,Main.main],85)| Bool) +(declare-const |dn([3,7],27)| Bool) +(declare-const |dn([1,3],64)| Bool) +(declare-const |dn([9,Main.main],83)| Bool) +(declare-const |dn([1,3],67)| Bool) +(declare-const |dn([7,Main.main],40)| Bool) +(declare-const |dn([3,7],25)| Bool) +(declare-const |dn([6,9],90)| Bool) +(declare-const |dn([7,Main.main],60)| Bool) +(declare-const |dn([7,Main.main],50)| Bool) +(declare-const |dn([5,1],62)| Bool) +(declare-const |dn([3,7],22)| Bool) +(declare-const |dn([7,Main.main],53)| Bool) +(declare-const |dn([6,9],93)| Bool) +(declare-const |dn([7,Main.main],57)| Bool) +(declare-const |dn([Main.main],108)| Bool) +(declare-const |dn([7,Main.main],55)| Bool) +(declare-const |scc(1)| Bool) +(declare-const |dn([Main.main],105)| Bool) +(declare-const |scc(2)| Bool) +(declare-const |dn([8,Main.main],97)| Bool) +(declare-const |dn([Main.main],103)| Bool) +(declare-const |scc(5)| Bool) +(declare-const |dn([4,1],70)| Bool) +(declare-const |dn([6,9],94)| Bool) +(declare-const |dn([8,Main.main],100)| Bool) +(declare-const |dn([7,Main.main],59)| Bool) +(declare-const |dn([5,1],61)| Bool) +(declare-const |dn([4,1],69)| Bool) +(declare-const |dn([3,7],29)| Bool) +(declare-const |dn([3,7],31)| Bool) +(declare-const |dn([Main.main],113)| Bool) +(declare-const |dn([4,1],79)| Bool) +(declare-const |dn([2,3],34)| Bool) +(declare-const |dn([Main.main],115)| Bool) +(declare-const |dn([2,3],37)| Bool) +(declare-const |dn([1,3],68)| Bool) +(declare-const |dn([4,1],81)| Bool) +(declare-const |scc(7)| Bool) +(declare-const |dn([9,Main.main],89)| Bool) +(declare-const |dn([1,3],66)| Bool) +(declare-const |dn([9,Main.main],84)| Bool) +(declare-const |dn([1,3],65)| Bool) +(declare-const |dn([7,Main.main],43)| Bool) +(declare-const |dn([9,Main.main],82)| Bool) +(declare-const |dn([7,Main.main],45)| Bool) +(declare-const |dn([3,7],30)| Bool) +(declare-const |scc(8)| Bool) +(declare-const |dn([9,Main.main],87)| Bool) +(declare-const |dn([3,7],21)| Bool) +(declare-const |dn([7,Main.main],49)| Bool) +(declare-const |scc(6)| Bool) +(declare-const |dn([7,Main.main],41)_dn([3,7],20)| Bool) +(declare-const |dn([7,Main.main],41)_dn([7,Main.main],42)| Bool) +(declare-const |dn([3,7],24)_dn([3,7],25)| Bool) +(declare-const |dn([3,7],24)_dn([4,1],80)| Bool) +(declare-const |dn([7,Main.main],47)_dn([7,Main.main],41)| Bool) +(declare-const |dn([7,Main.main],47)_dn([7,Main.main],45)| Bool) +(declare-const |dn([9,Main.main],86)_dn([9,Main.main],87)| Bool) +(declare-const |dn([9,Main.main],86)_dn([6,9],91)| Bool) +(declare-const |dn([7,Main.main],51)_dn([9,Main.main],84)| Bool) +(declare-const |dn([3,7],20)_dn([3,7],21)| Bool) +(declare-const |dn([3,7],20)_dn([1,3],64)| Bool) +(declare-const |dn([6,9],91)_dn([7,Main.main],54)| Bool) +(declare-const |dn([6,9],91)_dn([6,9],92)| Bool) +(declare-const |scc(3)_dn([3,7],20)| Bool) +(declare-const |scc(3)_dn([3,7],22)| Bool) +(declare-const |scc(3)_dn([3,7],27)| Bool) +(declare-const |scc(3)_dn([3,7],29)| Bool) +(declare-const |scc(3)_dn([3,7],31)| Bool) +(declare-const |scc(3)_dn([3,7],33)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],90)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],95)| Bool) +(declare-const |scc(4)_dn([2,3],35)| Bool) +(declare-const |scc(4)_dn([4,1],70)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],51)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],55)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],58)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],59)| Bool) +(declare-const |dn([7,Main.main],54)_scc(1)| Bool) +(declare-const |dn([7,Main.main],54)_scc(7)| Bool) +(declare-const |scc(0)_dn([3,7],24)| Bool) +(declare-const |scc(0)_dn([2,3],34)| Bool) +(declare-const |dn([Main.main],109)_dn([Main.main],111)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],51)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],55)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],59)| Bool) +(declare-const |dn([7,Main.main],58)_scc(1)| Bool) +(declare-const |dn([7,Main.main],58)_scc(7)| Bool) +(declare-const |dn([Main.main],104)_dn([7,Main.main],49)| Bool) +(declare-const |dn([Main.main],104)_dn([Main.main],105)| Bool) +(declare-const |dn([8,Main.main],101)_dn([8,Main.main],96)| Bool) +(declare-const |dn([8,Main.main],101)_dn([8,Main.main],97)| Bool) +(declare-const |dn([6,9],95)_dn([6,9],90)| Bool) +(declare-const |dn([6,9],95)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],95)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],95)_scc(1)| Bool) +(declare-const |dn([8,Main.main],96)_dn([8,Main.main],97)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],33)| Bool) +(declare-const |dn([3,7],28)_scc(6)| Bool) +(declare-const |dn([Main.main],106)_dn([7,Main.main],47)| Bool) +(declare-const |dn([2,3],36)_dn([3,7],31)| Bool) +(declare-const |dn([2,3],36)_dn([2,3],37)| Bool) +(declare-const |dn([4,1],78)_dn([4,1],79)| Bool) +(declare-const |dn([4,1],78)_scc(4)| Bool) +(declare-const |dn([Main.main],114)_dn([9,Main.main],83)| Bool) +(declare-const |dn([Main.main],114)_dn([Main.main],115)| Bool) +(declare-const |dn([2,3],35)_dn([3,7],33)| Bool) +(declare-const |dn([2,3],35)_dn([2,3],36)| Bool) +(declare-const |dn([2,3],38)_dn([2,3],34)| Bool) +(declare-const |dn([2,3],38)_dn([2,3],35)| Bool) +(declare-const |dn([5,1],63)_dn([5,1],61)| Bool) +(declare-const |dn([5,1],63)_dn([5,1],62)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],58)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],31)| Bool) +(declare-const |dn([9,Main.main],88)_dn([9,Main.main],89)| Bool) +(declare-const |dn([4,1],80)_dn([4,1],81)| Bool) +(declare-const |dn([Main.main],116)_dn([Main.main],113)| Bool) +(declare-const |dn([Main.main],111)_dn([Main.main],102)| Bool) +(declare-const |dn([Main.main],111)_dn([Main.main],103)| Bool) +(declare-const |dn([7,Main.main],42)_dn([3,7],22)| Bool) +(declare-const |dn([7,Main.main],42)_dn([7,Main.main],43)| Bool) +(declare-const |dn([9,Main.main],85)_dn([9,Main.main],86)| Bool) +(declare-const |dn([9,Main.main],85)_dn([6,9],90)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],28)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],30)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],33)| Bool) +(declare-const |dn([1,3],64)_dn([1,3],65)| Bool) +(declare-const |dn([1,3],64)_dn([1,3],67)| Bool) +(declare-const |dn([9,Main.main],83)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],83)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],83)_dn([9,Main.main],88)| Bool) +(declare-const |dn([1,3],67)_dn([5,1],61)| Bool) +(declare-const |dn([1,3],67)_dn([1,3],68)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],58)| Bool) +(declare-const |dn([3,7],25)_dn([1,3],67)| Bool) +(declare-const |dn([6,9],90)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],90)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],90)_dn([6,9],95)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],58)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],51)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],55)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],58)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],59)| Bool) +(declare-const |dn([7,Main.main],50)_scc(1)| Bool) +(declare-const |dn([7,Main.main],50)_scc(7)| Bool) +(declare-const |dn([5,1],62)_dn([5,1],61)| Bool) +(declare-const |dn([5,1],62)_dn([5,1],63)| Bool) +(declare-const |dn([5,1],62)_scc(2)| Bool) +(declare-const |dn([3,7],22)_dn([1,3],65)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],58)| Bool) +(declare-const |dn([6,9],93)_dn([9,Main.main],88)| Bool) +(declare-const |dn([6,9],93)_dn([6,9],94)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],58)| Bool) +(declare-const |dn([Main.main],108)_dn([8,Main.main],97)| Bool) +(declare-const |dn([Main.main],108)_dn([Main.main],109)| Bool) +(declare-const |dn([7,Main.main],55)_dn([6,9],95)| Bool) +(declare-const |scc(1)_dn([7,Main.main],39)| Bool) +(declare-const |scc(1)_dn([7,Main.main],47)| Bool) +(declare-const |scc(1)_dn([7,Main.main],49)| Bool) +(declare-const |scc(1)_dn([7,Main.main],50)| Bool) +(declare-const |scc(1)_dn([7,Main.main],51)| Bool) +(declare-const |scc(1)_dn([7,Main.main],54)| Bool) +(declare-const |scc(1)_dn([7,Main.main],55)| Bool) +(declare-const |scc(1)_dn([7,Main.main],57)| Bool) +(declare-const |scc(1)_dn([7,Main.main],58)| Bool) +(declare-const |scc(1)_dn([7,Main.main],59)| Bool) +(declare-const |scc(1)_dn([6,9],93)| Bool) +(declare-const |scc(1)_scc(7)| Bool) +(declare-const |dn([Main.main],105)_dn([7,Main.main],50)| Bool) +(declare-const |dn([Main.main],105)_dn([Main.main],106)| Bool) +(declare-const |scc(2)_dn([3,7],20)| Bool) +(declare-const |scc(2)_dn([3,7],22)| Bool) +(declare-const |scc(2)_dn([3,7],27)| Bool) +(declare-const |scc(2)_dn([3,7],29)| Bool) +(declare-const |scc(2)_dn([3,7],31)| Bool) +(declare-const |scc(2)_dn([3,7],33)| Bool) +(declare-const |dn([8,Main.main],97)_dn([3,7],27)| Bool) +(declare-const |dn([Main.main],103)_dn([7,Main.main],39)| Bool) +(declare-const |dn([Main.main],103)_dn([Main.main],104)| Bool) +(declare-const |scc(5)_dn([5,1],63)| Bool) +(declare-const |scc(5)_dn([8,Main.main],100)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],90)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],95)| Bool) +(declare-const |dn([8,Main.main],100)_dn([4,1],78)| Bool) +(declare-const |dn([8,Main.main],100)_dn([8,Main.main],101)| Bool) +(declare-const |dn([7,Main.main],59)_dn([7,Main.main],60)| Bool) +(declare-const |dn([7,Main.main],59)_dn([6,9],95)| Bool) +(declare-const |dn([5,1],61)_dn([5,1],62)| Bool) +(declare-const |dn([5,1],61)_dn([5,1],63)| Bool) +(declare-const |dn([4,1],69)_dn([4,1],78)| Bool) +(declare-const |dn([4,1],69)_dn([4,1],80)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],28)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],30)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],33)| Bool) +(declare-const |dn([3,7],31)_dn([5,1],62)| Bool) +(declare-const |dn([Main.main],113)_dn([9,Main.main],82)| Bool) +(declare-const |dn([Main.main],113)_dn([Main.main],114)| Bool) +(declare-const |dn([4,1],79)_dn([4,1],69)| Bool) +(declare-const |dn([4,1],79)_dn([4,1],78)| Bool) +(declare-const |dn([4,1],79)_dn([4,1],80)| Bool) +(declare-const |dn([2,3],34)_dn([2,3],35)| Bool) +(declare-const |dn([Main.main],115)_dn([Main.main],111)| Bool) +(declare-const |dn([Main.main],115)_dn([Main.main],116)| Bool) +(declare-const |dn([2,3],37)_dn([2,3],38)| Bool) +(declare-const |dn([2,3],37)_dn([7,Main.main],58)| Bool) +(declare-const |dn([1,3],68)_dn([1,3],64)| Bool) +(declare-const |dn([1,3],68)_dn([1,3],65)| Bool) +(declare-const |dn([1,3],68)_dn([1,3],67)| Bool) +(declare-const |dn([4,1],81)_dn([4,1],69)| Bool) +(declare-const |dn([4,1],81)_dn([4,1],78)| Bool) +(declare-const |dn([4,1],81)_dn([4,1],80)| Bool) +(declare-const |scc(7)_dn([7,Main.main],39)| Bool) +(declare-const |scc(7)_dn([7,Main.main],47)| Bool) +(declare-const |scc(7)_dn([7,Main.main],49)| Bool) +(declare-const |scc(7)_dn([7,Main.main],50)| Bool) +(declare-const |scc(7)_dn([7,Main.main],51)| Bool) +(declare-const |scc(7)_dn([7,Main.main],53)| Bool) +(declare-const |scc(7)_dn([7,Main.main],54)| Bool) +(declare-const |scc(7)_dn([7,Main.main],55)| Bool) +(declare-const |scc(7)_dn([7,Main.main],58)| Bool) +(declare-const |scc(7)_dn([7,Main.main],59)| Bool) +(declare-const |scc(7)_scc(1)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],88)| Bool) +(declare-const |dn([1,3],66)_dn([1,3],64)| Bool) +(declare-const |dn([1,3],66)_dn([1,3],65)| Bool) +(declare-const |dn([1,3],66)_dn([1,3],67)| Bool) +(declare-const |dn([1,3],66)_scc(0)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],85)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],88)| Bool) +(declare-const |dn([1,3],65)_dn([1,3],66)| Bool) +(declare-const |dn([1,3],65)_dn([4,1],69)| Bool) +(declare-const |dn([7,Main.main],43)_dn([7,Main.main],40)| Bool) +(declare-const |dn([9,Main.main],82)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],82)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],82)_dn([9,Main.main],88)| Bool) +(declare-const |dn([7,Main.main],45)_dn([7,Main.main],40)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],33)| Bool) +(declare-const |dn([3,7],30)_scc(5)| Bool) +(declare-const |scc(8)_dn([8,Main.main],96)| Bool) +(declare-const |scc(8)_dn([Main.main],108)| Bool) +(declare-const |dn([9,Main.main],87)_dn([7,Main.main],53)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],88)| Bool) +(declare-const |dn([9,Main.main],87)_scc(7)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],33)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],58)| Bool) +(declare-const |scc(6)_dn([3,7],29)| Bool) +(assert |dn([Main.main],113)|) +(assert (= |dn([7,Main.main],41)| (or |dn([7,Main.main],41)_dn([3,7],20)| |dn([7,Main.main],41)_dn([7,Main.main],42)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([7,Main.main],41)_dn([7,Main.main],42)|))) +(assert (not (and |dn([7,Main.main],41)_dn([7,Main.main],42)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (= |dn([3,7],24)| (or |dn([3,7],24)_dn([3,7],25)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([3,7],25)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([3,7],24)_dn([3,7],25)|))) +(assert (= |dn([7,Main.main],47)| (or |dn([7,Main.main],47)_dn([7,Main.main],41)| |dn([7,Main.main],47)_dn([7,Main.main],45)|))) +(assert (not (and |dn([7,Main.main],47)_dn([7,Main.main],41)| |dn([7,Main.main],47)_dn([7,Main.main],45)|))) +(assert (not (and |dn([7,Main.main],47)_dn([7,Main.main],45)| |dn([7,Main.main],47)_dn([7,Main.main],41)|))) +(assert (= |dn([9,Main.main],86)| (or |dn([9,Main.main],86)_dn([9,Main.main],87)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([9,Main.main],87)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([9,Main.main],86)_dn([9,Main.main],87)|))) +(assert (= |dn([7,Main.main],51)| (or |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (= |dn([3,7],20)| (or |dn([3,7],20)_dn([3,7],21)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([3,7],21)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([1,3],64)| |dn([3,7],20)_dn([3,7],21)|))) +(assert (= |dn([6,9],91)| (or |dn([6,9],91)_dn([7,Main.main],54)| |dn([6,9],91)_dn([6,9],92)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([6,9],91)_dn([6,9],92)|))) +(assert (not (and |dn([6,9],91)_dn([6,9],92)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (= |scc(3)| (or |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],31)|))) +(assert (= |dn([6,9],92)| (or |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (= |scc(4)| (or |scc(4)_dn([2,3],35)| |scc(4)_dn([4,1],70)|))) +(assert (not (and |scc(4)_dn([2,3],35)| |scc(4)_dn([4,1],70)|))) +(assert (not (and |scc(4)_dn([4,1],70)| |scc(4)_dn([2,3],35)|))) +(assert (= |dn([7,Main.main],54)| (or |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_scc(1)|))) +(assert (= |scc(0)| (or |scc(0)_dn([3,7],24)| |scc(0)_dn([2,3],34)|))) +(assert (not (and |scc(0)_dn([3,7],24)| |scc(0)_dn([2,3],34)|))) +(assert (not (and |scc(0)_dn([2,3],34)| |scc(0)_dn([3,7],24)|))) +(assert (= |dn([Main.main],109)| (or |dn([Main.main],109)_dn([Main.main],111)|))) +(assert (= |dn([7,Main.main],58)| (or |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_scc(1)|))) +(assert (= |dn([Main.main],104)| (or |dn([Main.main],104)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([Main.main],105)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([Main.main],105)|))) +(assert (not (and |dn([Main.main],104)_dn([Main.main],105)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not |dn([Main.main],102)|)) +(assert (= |dn([8,Main.main],101)| (or |dn([8,Main.main],101)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],96)|))) +(assert (= |dn([6,9],95)| (or |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (= |dn([8,Main.main],96)| (or |dn([8,Main.main],96)_dn([8,Main.main],97)|))) +(assert (= |dn([3,7],28)| (or |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (= |dn([Main.main],106)| (or |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (= |dn([2,3],36)| (or |dn([2,3],36)_dn([3,7],31)| |dn([2,3],36)_dn([2,3],37)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([2,3],36)_dn([2,3],37)|))) +(assert (not (and |dn([2,3],36)_dn([2,3],37)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (= |dn([4,1],78)| (or |dn([4,1],78)_dn([4,1],79)| |dn([4,1],78)_scc(4)|))) +(assert (not (and |dn([4,1],78)_dn([4,1],79)| |dn([4,1],78)_scc(4)|))) +(assert (not (and |dn([4,1],78)_scc(4)| |dn([4,1],78)_dn([4,1],79)|))) +(assert (= |dn([Main.main],114)| (or |dn([Main.main],114)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([Main.main],115)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([Main.main],115)|))) +(assert (not (and |dn([Main.main],114)_dn([Main.main],115)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (= |dn([2,3],35)| (or |dn([2,3],35)_dn([3,7],33)| |dn([2,3],35)_dn([2,3],36)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([2,3],35)_dn([2,3],36)|))) +(assert (not (and |dn([2,3],35)_dn([2,3],36)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (= |dn([2,3],38)| (or |dn([2,3],38)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],34)|))) +(assert (= |dn([5,1],63)| (or |dn([5,1],63)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (= |dn([7,Main.main],39)| (or |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (= |dn([3,7],33)| (or |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (= |dn([9,Main.main],88)| (or |dn([9,Main.main],88)_dn([9,Main.main],89)|))) +(assert (= |dn([4,1],80)| (or |dn([4,1],80)_dn([4,1],81)|))) +(assert (= |dn([Main.main],116)| (or |dn([Main.main],116)_dn([Main.main],113)|))) +(assert (= |dn([Main.main],111)| (or |dn([Main.main],111)_dn([Main.main],102)| |dn([Main.main],111)_dn([Main.main],103)|))) +(assert (not (and |dn([Main.main],111)_dn([Main.main],102)| |dn([Main.main],111)_dn([Main.main],103)|))) +(assert (not (and |dn([Main.main],111)_dn([Main.main],103)| |dn([Main.main],111)_dn([Main.main],102)|))) +(assert (= |dn([7,Main.main],42)| (or |dn([7,Main.main],42)_dn([3,7],22)| |dn([7,Main.main],42)_dn([7,Main.main],43)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([7,Main.main],42)_dn([7,Main.main],43)|))) +(assert (not (and |dn([7,Main.main],42)_dn([7,Main.main],43)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (= |dn([9,Main.main],85)| (or |dn([9,Main.main],85)_dn([9,Main.main],86)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([9,Main.main],86)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([9,Main.main],85)_dn([9,Main.main],86)|))) +(assert (= |dn([3,7],27)| (or |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (= |dn([1,3],64)| (or |dn([1,3],64)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (= |dn([9,Main.main],83)| (or |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (= |dn([1,3],67)| (or |dn([1,3],67)_dn([5,1],61)| |dn([1,3],67)_dn([1,3],68)|))) +(assert (not (and |dn([1,3],67)_dn([5,1],61)| |dn([1,3],67)_dn([1,3],68)|))) +(assert (not (and |dn([1,3],67)_dn([1,3],68)| |dn([1,3],67)_dn([5,1],61)|))) +(assert (= |dn([7,Main.main],40)| (or |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (= |dn([3,7],25)| (or |dn([3,7],25)_dn([1,3],67)|))) +(assert (= |dn([6,9],90)| (or |dn([6,9],90)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (= |dn([7,Main.main],60)| (or |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (= |dn([7,Main.main],50)| (or |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_scc(1)|))) +(assert (= |dn([5,1],62)| (or |dn([5,1],62)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],63)| |dn([5,1],62)_scc(2)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([5,1],62)_scc(2)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |dn([5,1],62)_scc(2)|))) +(assert (not (and |dn([5,1],62)_scc(2)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_scc(2)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (= |dn([3,7],22)| (or |dn([3,7],22)_dn([1,3],65)|))) +(assert (= |dn([7,Main.main],53)| (or |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (= |dn([6,9],93)| (or |dn([6,9],93)_dn([9,Main.main],88)| |dn([6,9],93)_dn([6,9],94)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([6,9],93)_dn([6,9],94)|))) +(assert (not (and |dn([6,9],93)_dn([6,9],94)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (= |dn([7,Main.main],57)| (or |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (= |dn([Main.main],108)| (or |dn([Main.main],108)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([Main.main],109)|))) +(assert (not (and |dn([Main.main],108)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([Main.main],109)|))) +(assert (not (and |dn([Main.main],108)_dn([Main.main],109)| |dn([Main.main],108)_dn([8,Main.main],97)|))) +(assert (= |dn([7,Main.main],55)| (or |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (= |scc(1)| (or |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([6,9],93)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([6,9],93)|))) +(assert (= |dn([Main.main],105)| (or |dn([Main.main],105)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([Main.main],106)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([Main.main],106)|))) +(assert (not (and |dn([Main.main],105)_dn([Main.main],106)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (= |scc(2)| (or |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],31)|))) +(assert (= |dn([8,Main.main],97)| (or |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (= |dn([Main.main],103)| (or |dn([Main.main],103)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([Main.main],104)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([Main.main],104)|))) +(assert (not (and |dn([Main.main],103)_dn([Main.main],104)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (= |scc(5)| (or |scc(5)_dn([5,1],63)| |scc(5)_dn([8,Main.main],100)|))) +(assert (not (and |scc(5)_dn([5,1],63)| |scc(5)_dn([8,Main.main],100)|))) +(assert (not (and |scc(5)_dn([8,Main.main],100)| |scc(5)_dn([5,1],63)|))) +(assert (not |dn([4,1],70)|)) +(assert (= |dn([6,9],94)| (or |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (= |dn([8,Main.main],100)| (or |dn([8,Main.main],100)_dn([4,1],78)| |dn([8,Main.main],100)_dn([8,Main.main],101)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([8,Main.main],100)_dn([8,Main.main],101)|))) +(assert (not (and |dn([8,Main.main],100)_dn([8,Main.main],101)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (= |dn([7,Main.main],59)| (or |dn([7,Main.main],59)_dn([7,Main.main],60)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([7,Main.main],60)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([7,Main.main],59)_dn([7,Main.main],60)|))) +(assert (= |dn([5,1],61)| (or |dn([5,1],61)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],62)|))) +(assert (= |dn([4,1],69)| (or |dn([4,1],69)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (= |dn([3,7],29)| (or |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (= |dn([3,7],31)| (or |dn([3,7],31)_dn([5,1],62)|))) +(assert (= |dn([Main.main],113)| (or |dn([Main.main],113)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([Main.main],114)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([Main.main],114)|))) +(assert (not (and |dn([Main.main],113)_dn([Main.main],114)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (= |dn([4,1],79)| (or |dn([4,1],79)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (= |dn([2,3],34)| (or |dn([2,3],34)_dn([2,3],35)|))) +(assert (= |dn([Main.main],115)| (or |dn([Main.main],115)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],116)|))) +(assert (not (and |dn([Main.main],115)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],116)|))) +(assert (not (and |dn([Main.main],115)_dn([Main.main],116)| |dn([Main.main],115)_dn([Main.main],111)|))) +(assert (= |dn([2,3],37)| (or |dn([2,3],37)_dn([2,3],38)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([2,3],38)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([2,3],37)_dn([2,3],38)|))) +(assert (= |dn([1,3],68)| (or |dn([1,3],68)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (= |dn([4,1],81)| (or |dn([4,1],81)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (= |scc(7)| (or |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],59)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],59)|))) +(assert (= |dn([9,Main.main],89)| (or |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (= |dn([1,3],66)| (or |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_scc(0)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_scc(0)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_scc(0)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (= |dn([9,Main.main],84)| (or |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (= |dn([1,3],65)| (or |dn([1,3],65)_dn([1,3],66)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([1,3],66)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([4,1],69)| |dn([1,3],65)_dn([1,3],66)|))) +(assert (= |dn([7,Main.main],43)| (or |dn([7,Main.main],43)_dn([7,Main.main],40)|))) +(assert (= |dn([9,Main.main],82)| (or |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (= |dn([7,Main.main],45)| (or |dn([7,Main.main],45)_dn([7,Main.main],40)|))) +(assert (= |dn([3,7],30)| (or |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (= |scc(8)| (or |scc(8)_dn([8,Main.main],96)| |scc(8)_dn([Main.main],108)|))) +(assert (not (and |scc(8)_dn([8,Main.main],96)| |scc(8)_dn([Main.main],108)|))) +(assert (not (and |scc(8)_dn([Main.main],108)| |scc(8)_dn([8,Main.main],96)|))) +(assert (= |dn([9,Main.main],87)| (or |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (= |dn([7,Main.main],49)| (or |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (= |scc(6)| (or |scc(6)_dn([3,7],29)|))) +(assert (= |dn([7,Main.main],41)| (or |dn([7,Main.main],47)_dn([7,Main.main],41)|))) +(assert (= |dn([3,7],24)| (or |scc(0)_dn([3,7],24)|))) +(assert (= |dn([7,Main.main],47)| (or |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (= |dn([9,Main.main],86)| (or |dn([9,Main.main],85)_dn([9,Main.main],86)|))) +(assert (= |dn([7,Main.main],51)| (or |dn([7,Main.main],50)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (= |dn([3,7],20)| (or |dn([7,Main.main],41)_dn([3,7],20)| |scc(2)_dn([3,7],20)| |scc(3)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (= |dn([6,9],91)| (or |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not |scc(3)|)) +(assert (= |dn([6,9],92)| (or |dn([6,9],91)_dn([6,9],92)|))) +(assert (= |scc(4)| (or |dn([4,1],78)_scc(4)|))) +(assert (= |dn([7,Main.main],54)| (or |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (= |scc(0)| (or |dn([1,3],66)_scc(0)|))) +(assert (= |dn([Main.main],109)| (or |dn([Main.main],108)_dn([Main.main],109)|))) +(assert (= |dn([7,Main.main],58)| (or |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (= |dn([Main.main],104)| (or |dn([Main.main],103)_dn([Main.main],104)|))) +(assert (= |dn([Main.main],102)| (or |dn([Main.main],111)_dn([Main.main],102)|))) +(assert (= |dn([8,Main.main],101)| (or |dn([8,Main.main],100)_dn([8,Main.main],101)|))) +(assert (= |dn([6,9],95)| (or |dn([7,Main.main],55)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (= |dn([8,Main.main],96)| (or |scc(8)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],96)|))) +(assert (not (and |scc(8)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],96)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],96)| |scc(8)_dn([8,Main.main],96)|))) +(assert (= |dn([3,7],28)| (or |dn([3,7],27)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (= |dn([Main.main],106)| (or |dn([Main.main],105)_dn([Main.main],106)|))) +(assert (= |dn([2,3],36)| (or |dn([2,3],35)_dn([2,3],36)|))) +(assert (= |dn([4,1],78)| (or |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (= |dn([Main.main],114)| (or |dn([Main.main],113)_dn([Main.main],114)|))) +(assert (= |dn([2,3],35)| (or |scc(4)_dn([2,3],35)| |dn([2,3],34)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |scc(4)_dn([2,3],35)| |dn([2,3],34)_dn([2,3],35)|))) +(assert (not (and |scc(4)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],34)_dn([2,3],35)| |scc(4)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],34)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],35)| |scc(4)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],35)| |dn([2,3],34)_dn([2,3],35)|))) +(assert (= |dn([2,3],38)| (or |dn([2,3],37)_dn([2,3],38)|))) +(assert (= |dn([5,1],63)| (or |scc(5)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |scc(5)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (not (and |scc(5)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],63)| |scc(5)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |scc(5)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (= |dn([7,Main.main],39)| (or |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (= |dn([3,7],33)| (or |dn([2,3],35)_dn([3,7],33)| |scc(2)_dn([3,7],33)| |scc(3)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (= |dn([9,Main.main],88)| (or |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (= |dn([4,1],80)| (or |dn([3,7],24)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (= |dn([Main.main],116)| (or |dn([Main.main],115)_dn([Main.main],116)|))) +(assert (= |dn([Main.main],111)| (or |dn([Main.main],109)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],111)|))) +(assert (not (and |dn([Main.main],109)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],111)|))) +(assert (not (and |dn([Main.main],115)_dn([Main.main],111)| |dn([Main.main],109)_dn([Main.main],111)|))) +(assert (= |dn([7,Main.main],42)| (or |dn([7,Main.main],41)_dn([7,Main.main],42)|))) +(assert (= |dn([9,Main.main],85)| (or |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (= |dn([3,7],27)| (or |dn([8,Main.main],97)_dn([3,7],27)| |scc(2)_dn([3,7],27)| |scc(3)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (= |dn([1,3],64)| (or |dn([3,7],20)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (= |dn([9,Main.main],83)| (or |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (= |dn([1,3],67)| (or |dn([3,7],25)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([3,7],25)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([3,7],25)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([3,7],25)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([3,7],25)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([3,7],25)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([3,7],25)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (= |dn([7,Main.main],40)| (or |dn([7,Main.main],43)_dn([7,Main.main],40)| |dn([7,Main.main],45)_dn([7,Main.main],40)|))) +(assert (not (and |dn([7,Main.main],43)_dn([7,Main.main],40)| |dn([7,Main.main],45)_dn([7,Main.main],40)|))) +(assert (not (and |dn([7,Main.main],45)_dn([7,Main.main],40)| |dn([7,Main.main],43)_dn([7,Main.main],40)|))) +(assert (= |dn([3,7],25)| (or |dn([3,7],24)_dn([3,7],25)|))) +(assert (= |dn([6,9],90)| (or |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (= |dn([7,Main.main],60)| (or |dn([7,Main.main],59)_dn([7,Main.main],60)|))) +(assert (= |dn([7,Main.main],50)| (or |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (= |dn([5,1],62)| (or |dn([3,7],31)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([3,7],31)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],62)|))) +(assert (not (and |dn([3,7],31)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],62)| |dn([3,7],31)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],62)| |dn([3,7],31)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],62)|))) +(assert (= |dn([3,7],22)| (or |dn([7,Main.main],42)_dn([3,7],22)| |scc(2)_dn([3,7],22)| |scc(3)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (= |dn([7,Main.main],53)| (or |dn([9,Main.main],87)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (= |dn([6,9],93)| (or |scc(1)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (= |dn([7,Main.main],57)| (or |scc(1)_dn([7,Main.main],57)|))) +(assert (= |dn([Main.main],108)| (or |scc(8)_dn([Main.main],108)|))) +(assert (= |dn([7,Main.main],55)| (or |dn([7,Main.main],54)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (= |scc(1)| (or |dn([6,9],95)_scc(1)| |scc(7)_scc(1)| |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (= |dn([Main.main],105)| (or |dn([Main.main],104)_dn([Main.main],105)|))) +(assert (= |scc(2)| (or |dn([5,1],62)_scc(2)|))) +(assert (= |dn([8,Main.main],97)| (or |dn([Main.main],108)_dn([8,Main.main],97)| |dn([8,Main.main],96)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([Main.main],108)_dn([8,Main.main],97)| |dn([8,Main.main],96)_dn([8,Main.main],97)|))) +(assert (not (and |dn([Main.main],108)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],96)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],96)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],97)| |dn([8,Main.main],96)_dn([8,Main.main],97)|))) +(assert (= |dn([Main.main],103)| (or |dn([Main.main],111)_dn([Main.main],103)|))) +(assert (= |scc(5)| (or |dn([3,7],30)_scc(5)|))) +(assert (= |dn([4,1],70)| (or |scc(4)_dn([4,1],70)|))) +(assert (= |dn([6,9],94)| (or |dn([6,9],93)_dn([6,9],94)|))) +(assert (= |dn([8,Main.main],100)| (or |scc(5)_dn([8,Main.main],100)|))) +(assert (= |dn([7,Main.main],59)| (or |dn([7,Main.main],58)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (= |dn([5,1],61)| (or |dn([1,3],67)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (not (and |dn([1,3],67)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (not (and |dn([1,3],67)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([1,3],67)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],61)| |dn([1,3],67)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (= |dn([4,1],69)| (or |dn([1,3],65)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (= |dn([3,7],29)| (or |scc(6)_dn([3,7],29)| |scc(2)_dn([3,7],29)| |scc(3)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (= |dn([3,7],31)| (or |dn([2,3],36)_dn([3,7],31)| |scc(2)_dn([3,7],31)| |scc(3)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (= |dn([4,1],79)| (or |dn([4,1],78)_dn([4,1],79)|))) +(assert (= |dn([2,3],34)| (or |scc(0)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],34)|))) +(assert (not (and |scc(0)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],34)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],34)| |scc(0)_dn([2,3],34)|))) +(assert (= |dn([Main.main],115)| (or |dn([Main.main],114)_dn([Main.main],115)|))) +(assert (= |dn([2,3],37)| (or |dn([2,3],36)_dn([2,3],37)|))) +(assert (= |dn([1,3],68)| (or |dn([1,3],67)_dn([1,3],68)|))) +(assert (= |dn([4,1],81)| (or |dn([4,1],80)_dn([4,1],81)|))) +(assert (= |scc(7)| (or |dn([9,Main.main],87)_scc(7)| |scc(1)_scc(7)| |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (= |dn([9,Main.main],89)| (or |dn([9,Main.main],88)_dn([9,Main.main],89)|))) +(assert (= |dn([1,3],66)| (or |dn([1,3],65)_dn([1,3],66)|))) +(assert (= |dn([9,Main.main],84)| (or |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (= |dn([1,3],65)| (or |dn([3,7],22)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([3,7],22)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (not (and |dn([3,7],22)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([3,7],22)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([3,7],22)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([3,7],22)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([3,7],22)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (= |dn([7,Main.main],43)| (or |dn([7,Main.main],42)_dn([7,Main.main],43)|))) +(assert (= |dn([9,Main.main],82)| (or |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (= |dn([7,Main.main],45)| (or |dn([7,Main.main],47)_dn([7,Main.main],45)|))) +(assert (= |dn([3,7],30)| (or |dn([3,7],29)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not |scc(8)|)) +(assert (= |dn([9,Main.main],87)| (or |dn([9,Main.main],86)_dn([9,Main.main],87)|))) +(assert (= |dn([3,7],21)| (or |dn([3,7],20)_dn([3,7],21)|))) +(assert (= |dn([7,Main.main],49)| (or |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (= |scc(6)| (or |dn([3,7],28)_scc(6)|))) +(assert-soft |dn([7,Main.main],41)_dn([3,7],20)| :weight 1) +(assert-soft |scc(2)_dn([3,7],20)| :weight 1) +(assert-soft |scc(3)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],33)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],20)_dn([3,7],21)| :weight 1) +(assert-soft |dn([7,Main.main],42)_dn([3,7],22)| :weight 1) +(assert-soft |scc(2)_dn([3,7],22)| :weight 1) +(assert-soft |scc(3)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],33)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],22)| :weight 1) +(assert-soft |scc(0)_dn([3,7],24)| :weight 1) +(assert-soft |dn([3,7],24)_dn([3,7],25)| :weight 1) +(assert-soft |dn([8,Main.main],97)_dn([3,7],27)| :weight 2) +(assert-soft |scc(2)_dn([3,7],27)| :weight 2) +(assert-soft |scc(3)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],21)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],28)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],30)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],33)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],29)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],27)_dn([3,7],28)| :weight 6) +(assert-soft |dn([3,7],29)_dn([3,7],28)| :weight 6) +(assert-soft |scc(6)_dn([3,7],29)| :weight 2) +(assert-soft |scc(2)_dn([3,7],29)| :weight 2) +(assert-soft |scc(3)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],21)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],28)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],30)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],33)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],27)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],29)_dn([3,7],30)| :weight 6) +(assert-soft |dn([3,7],27)_dn([3,7],30)| :weight 6) +(assert-soft |dn([2,3],36)_dn([3,7],31)| :weight 1) +(assert-soft |scc(2)_dn([3,7],31)| :weight 1) +(assert-soft |scc(3)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],33)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],31)| :weight 1) +(assert-soft |dn([2,3],35)_dn([3,7],33)| :weight 1) +(assert-soft |scc(2)_dn([3,7],33)| :weight 1) +(assert-soft |scc(3)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],33)| :weight 1) +(assert-soft |scc(0)_dn([2,3],34)| :weight 1) +(assert-soft |dn([2,3],38)_dn([2,3],34)| :weight 1) +(assert-soft |scc(4)_dn([2,3],35)| :weight 1) +(assert-soft |dn([2,3],34)_dn([2,3],35)| :weight 1) +(assert-soft |dn([2,3],38)_dn([2,3],35)| :weight 1) +(assert-soft |dn([2,3],35)_dn([2,3],36)| :weight 1) +(assert-soft |dn([2,3],36)_dn([2,3],37)| :weight 1) +(assert-soft |dn([2,3],37)_dn([2,3],38)| :weight 1) +(assert-soft |dn([Main.main],103)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],39)| :weight 6) +(assert-soft |scc(1)_dn([7,Main.main],39)| :weight 6) +(assert-soft |scc(7)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],43)_dn([7,Main.main],40)| :weight 4) +(assert-soft |dn([7,Main.main],45)_dn([7,Main.main],40)| :weight 4) +(assert-soft |dn([7,Main.main],47)_dn([7,Main.main],41)| :weight 1) +(assert-soft |dn([7,Main.main],41)_dn([7,Main.main],42)| :weight 1) +(assert-soft |dn([7,Main.main],42)_dn([7,Main.main],43)| :weight 1) +(assert-soft |dn([7,Main.main],47)_dn([7,Main.main],45)| :weight 4) +(assert-soft |dn([Main.main],106)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],47)| :weight 8) +(assert-soft |scc(1)_dn([7,Main.main],47)| :weight 8) +(assert-soft |scc(7)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([Main.main],104)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],49)| :weight 8) +(assert-soft |scc(1)_dn([7,Main.main],49)| :weight 8) +(assert-soft |scc(7)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([Main.main],105)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],50)| :weight 2) +(assert-soft |scc(1)_dn([7,Main.main],50)| :weight 2) +(assert-soft |scc(7)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],51)| :weight 6) +(assert-soft |scc(1)_dn([7,Main.main],51)| :weight 6) +(assert-soft |scc(7)_dn([7,Main.main],51)| :weight 6) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],51)| :weight 6) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],51)| :weight 6) +(assert-soft |dn([9,Main.main],87)_dn([7,Main.main],53)| :weight 6) +(assert-soft |scc(7)_dn([7,Main.main],53)| :weight 6) +(assert-soft |dn([6,9],91)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],54)| :weight 2) +(assert-soft |scc(1)_dn([7,Main.main],54)| :weight 2) +(assert-soft |scc(7)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],55)| :weight 18) +(assert-soft |scc(1)_dn([7,Main.main],55)| :weight 18) +(assert-soft |scc(7)_dn([7,Main.main],55)| :weight 18) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],55)| :weight 18) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],55)| :weight 18) +(assert-soft |scc(1)_dn([7,Main.main],57)| :weight 4) +(assert-soft |dn([2,3],37)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],58)| :weight 1) +(assert-soft |scc(1)_dn([7,Main.main],58)| :weight 1) +(assert-soft |scc(7)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],59)| :weight 1) +(assert-soft |scc(1)_dn([7,Main.main],59)| :weight 1) +(assert-soft |scc(7)_dn([7,Main.main],59)| :weight 1) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],59)| :weight 1) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],59)| :weight 1) +(assert-soft |dn([7,Main.main],59)_dn([7,Main.main],60)| :weight 1) +(assert-soft |dn([1,3],67)_dn([5,1],61)| :weight 1) +(assert-soft |dn([5,1],62)_dn([5,1],61)| :weight 1) +(assert-soft |dn([5,1],63)_dn([5,1],61)| :weight 1) +(assert-soft |dn([3,7],31)_dn([5,1],62)| :weight 1) +(assert-soft |dn([5,1],61)_dn([5,1],62)| :weight 1) +(assert-soft |dn([5,1],63)_dn([5,1],62)| :weight 1) +(assert-soft |scc(5)_dn([5,1],63)| :weight 8) +(assert-soft |dn([5,1],61)_dn([5,1],63)| :weight 8) +(assert-soft |dn([5,1],62)_dn([5,1],63)| :weight 8) +(assert-soft |dn([3,7],20)_dn([1,3],64)| :weight 1) +(assert-soft |dn([1,3],66)_dn([1,3],64)| :weight 1) +(assert-soft |dn([1,3],68)_dn([1,3],64)| :weight 1) +(assert-soft |dn([3,7],22)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],64)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],66)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],68)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],65)_dn([1,3],66)| :weight 1) +(assert-soft |dn([3,7],25)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],64)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],66)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],68)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],67)_dn([1,3],68)| :weight 1) +(assert-soft |dn([1,3],65)_dn([4,1],69)| :weight 1) +(assert-soft |dn([4,1],79)_dn([4,1],69)| :weight 1) +(assert-soft |dn([4,1],81)_dn([4,1],69)| :weight 1) +(assert-soft |scc(4)_dn([4,1],70)| :weight 2) +(assert-soft |dn([8,Main.main],100)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],69)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],79)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],81)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],78)_dn([4,1],79)| :weight 4) +(assert-soft |dn([3,7],24)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],69)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],79)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],81)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],80)_dn([4,1],81)| :weight 1) +(assert-soft |dn([Main.main],113)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],83)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([Main.main],114)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],82)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([7,Main.main],51)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],82)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],83)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],85)| :weight 6) +(assert-soft |dn([9,Main.main],85)_dn([9,Main.main],86)| :weight 6) +(assert-soft |dn([9,Main.main],86)_dn([9,Main.main],87)| :weight 2) +(assert-soft |dn([6,9],93)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],82)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],83)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],88)_dn([9,Main.main],89)| :weight 6) +(assert-soft |dn([9,Main.main],85)_dn([6,9],90)| :weight 8) +(assert-soft |dn([6,9],92)_dn([6,9],90)| :weight 8) +(assert-soft |dn([6,9],94)_dn([6,9],90)| :weight 8) +(assert-soft |dn([6,9],95)_dn([6,9],90)| :weight 8) +(assert-soft |dn([9,Main.main],86)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],90)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],92)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],94)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],95)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],91)_dn([6,9],92)| :weight 4) +(assert-soft |scc(1)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],90)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],92)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],94)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],95)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],93)_dn([6,9],94)| :weight 4) +(assert-soft |dn([7,Main.main],55)_dn([6,9],95)| :weight 6) +(assert-soft |dn([7,Main.main],59)_dn([6,9],95)| :weight 6) +(assert-soft |dn([6,9],90)_dn([6,9],95)| :weight 6) +(assert-soft |dn([6,9],92)_dn([6,9],95)| :weight 6) +(assert-soft |dn([6,9],94)_dn([6,9],95)| :weight 6) +(assert-soft |scc(8)_dn([8,Main.main],96)| :weight 4) +(assert-soft |dn([8,Main.main],101)_dn([8,Main.main],96)| :weight 4) +(assert-soft |dn([Main.main],108)_dn([8,Main.main],97)| :weight 8) +(assert-soft |dn([8,Main.main],96)_dn([8,Main.main],97)| :weight 8) +(assert-soft |dn([8,Main.main],101)_dn([8,Main.main],97)| :weight 8) +(assert-soft |scc(5)_dn([8,Main.main],100)| :weight 4) +(assert-soft |dn([8,Main.main],100)_dn([8,Main.main],101)| :weight 4) +(assert-soft |dn([Main.main],111)_dn([Main.main],102)| :weight 1) +(assert-soft |dn([Main.main],111)_dn([Main.main],103)| :weight 6) +(assert-soft |dn([Main.main],103)_dn([Main.main],104)| :weight 2) +(assert-soft |dn([Main.main],104)_dn([Main.main],105)| :weight 2) +(assert-soft |dn([Main.main],105)_dn([Main.main],106)| :weight 2) +(assert-soft |scc(8)_dn([Main.main],108)| :weight 2) +(assert-soft |dn([Main.main],108)_dn([Main.main],109)| :weight 6) +(assert-soft |dn([Main.main],109)_dn([Main.main],111)| :weight 6) +(assert-soft |dn([Main.main],115)_dn([Main.main],111)| :weight 6) +(assert-soft |dn([Main.main],116)_dn([Main.main],113)| :weight 3) +(assert-soft |dn([Main.main],113)_dn([Main.main],114)| :weight 1) +(assert-soft |dn([Main.main],114)_dn([Main.main],115)| :weight 1) +(assert-soft |dn([Main.main],115)_dn([Main.main],116)| :weight 2) +(assert-soft |dn([1,3],66)_scc(0)| :weight 1) +(assert-soft |dn([6,9],95)_scc(1)| :weight 6) +(assert-soft |scc(7)_scc(1)| :weight 6) +(assert-soft |dn([7,Main.main],50)_scc(1)| :weight 6) +(assert-soft |dn([7,Main.main],54)_scc(1)| :weight 6) +(assert-soft |dn([7,Main.main],58)_scc(1)| :weight 6) +(assert-soft |dn([5,1],62)_scc(2)| :weight 1) +(assert-soft |dn([4,1],78)_scc(4)| :weight 4) +(assert-soft |dn([3,7],30)_scc(5)| :weight 8) +(assert-soft |dn([3,7],28)_scc(6)| :weight 6) +(assert-soft |dn([9,Main.main],87)_scc(7)| :weight 2) +(assert-soft |scc(1)_scc(7)| :weight 2) +(assert-soft |dn([7,Main.main],50)_scc(7)| :weight 2) +(assert-soft |dn([7,Main.main],54)_scc(7)| :weight 2) +(assert-soft |dn([7,Main.main],58)_scc(7)| :weight 2) +(optimize +; :wmaxsat_engine wpm2 +; :wmaxsat_engine pwmax +; :wmaxsat_engine bvmax + :print_statistics true + :timeout 1200000 +) diff --git a/tests/chat_pb.smt2 b/tests/chat_pb.smt2 new file mode 100644 index 000000000..8f32a6328 --- /dev/null +++ b/tests/chat_pb.smt2 @@ -0,0 +1,3382 @@ +(declare-const |dn([7,Main.main],41)| Bool) +(declare-const |dn([3,7],24)| Bool) +(declare-const |dn([7,Main.main],47)| Bool) +(declare-const |dn([9,Main.main],86)| Bool) +(declare-const |dn([7,Main.main],51)| Bool) +(declare-const |dn([3,7],20)| Bool) +(declare-const |dn([6,9],91)| Bool) +(declare-const |scc(3)| Bool) +(declare-const |dn([6,9],92)| Bool) +(declare-const |scc(4)| Bool) +(declare-const |dn([7,Main.main],54)| Bool) +(declare-const |scc(0)| Bool) +(declare-const |dn([Main.main],109)| Bool) +(declare-const |dn([7,Main.main],58)| Bool) +(declare-const |dn([Main.main],104)| Bool) +(declare-const |dn([Main.main],102)| Bool) +(declare-const |dn([8,Main.main],101)| Bool) +(declare-const |dn([6,9],95)| Bool) +(declare-const |dn([8,Main.main],96)| Bool) +(declare-const |dn([3,7],28)| Bool) +(declare-const |dn([Main.main],106)| Bool) +(declare-const |dn([2,3],36)| Bool) +(declare-const |dn([4,1],78)| Bool) +(declare-const |dn([Main.main],114)| Bool) +(declare-const |dn([2,3],35)| Bool) +(declare-const |dn([2,3],38)| Bool) +(declare-const |dn([5,1],63)| Bool) +(declare-const |dn([7,Main.main],39)| Bool) +(declare-const |dn([3,7],33)| Bool) +(declare-const |dn([9,Main.main],88)| Bool) +(declare-const |dn([4,1],80)| Bool) +(declare-const |dn([Main.main],116)| Bool) +(declare-const |dn([Main.main],111)| Bool) +(declare-const |dn([7,Main.main],42)| Bool) +(declare-const |dn([9,Main.main],85)| Bool) +(declare-const |dn([3,7],27)| Bool) +(declare-const |dn([1,3],64)| Bool) +(declare-const |dn([9,Main.main],83)| Bool) +(declare-const |dn([1,3],67)| Bool) +(declare-const |dn([7,Main.main],40)| Bool) +(declare-const |dn([3,7],25)| Bool) +(declare-const |dn([6,9],90)| Bool) +(declare-const |dn([7,Main.main],60)| Bool) +(declare-const |dn([7,Main.main],50)| Bool) +(declare-const |dn([5,1],62)| Bool) +(declare-const |dn([3,7],22)| Bool) +(declare-const |dn([7,Main.main],53)| Bool) +(declare-const |dn([6,9],93)| Bool) +(declare-const |dn([7,Main.main],57)| Bool) +(declare-const |dn([Main.main],108)| Bool) +(declare-const |dn([7,Main.main],55)| Bool) +(declare-const |scc(1)| Bool) +(declare-const |dn([Main.main],105)| Bool) +(declare-const |scc(2)| Bool) +(declare-const |dn([8,Main.main],97)| Bool) +(declare-const |dn([Main.main],103)| Bool) +(declare-const |scc(5)| Bool) +(declare-const |dn([4,1],70)| Bool) +(declare-const |dn([6,9],94)| Bool) +(declare-const |dn([8,Main.main],100)| Bool) +(declare-const |dn([7,Main.main],59)| Bool) +(declare-const |dn([5,1],61)| Bool) +(declare-const |dn([4,1],69)| Bool) +(declare-const |dn([3,7],29)| Bool) +(declare-const |dn([3,7],31)| Bool) +(declare-const |dn([Main.main],113)| Bool) +(declare-const |dn([4,1],79)| Bool) +(declare-const |dn([2,3],34)| Bool) +(declare-const |dn([Main.main],115)| Bool) +(declare-const |dn([2,3],37)| Bool) +(declare-const |dn([1,3],68)| Bool) +(declare-const |dn([4,1],81)| Bool) +(declare-const |scc(7)| Bool) +(declare-const |dn([9,Main.main],89)| Bool) +(declare-const |dn([1,3],66)| Bool) +(declare-const |dn([9,Main.main],84)| Bool) +(declare-const |dn([1,3],65)| Bool) +(declare-const |dn([7,Main.main],43)| Bool) +(declare-const |dn([9,Main.main],82)| Bool) +(declare-const |dn([7,Main.main],45)| Bool) +(declare-const |dn([3,7],30)| Bool) +(declare-const |scc(8)| Bool) +(declare-const |dn([9,Main.main],87)| Bool) +(declare-const |dn([3,7],21)| Bool) +(declare-const |dn([7,Main.main],49)| Bool) +(declare-const |scc(6)| Bool) +(declare-const |dn([7,Main.main],41)_dn([3,7],20)| Bool) +(declare-const |dn([7,Main.main],41)_dn([7,Main.main],42)| Bool) +(declare-const |dn([3,7],24)_dn([3,7],25)| Bool) +(declare-const |dn([3,7],24)_dn([4,1],80)| Bool) +(declare-const |dn([7,Main.main],47)_dn([7,Main.main],41)| Bool) +(declare-const |dn([7,Main.main],47)_dn([7,Main.main],45)| Bool) +(declare-const |dn([9,Main.main],86)_dn([9,Main.main],87)| Bool) +(declare-const |dn([9,Main.main],86)_dn([6,9],91)| Bool) +(declare-const |dn([7,Main.main],51)_dn([9,Main.main],84)| Bool) +(declare-const |dn([3,7],20)_dn([3,7],21)| Bool) +(declare-const |dn([3,7],20)_dn([1,3],64)| Bool) +(declare-const |dn([6,9],91)_dn([7,Main.main],54)| Bool) +(declare-const |dn([6,9],91)_dn([6,9],92)| Bool) +(declare-const |scc(3)_dn([3,7],20)| Bool) +(declare-const |scc(3)_dn([3,7],22)| Bool) +(declare-const |scc(3)_dn([3,7],27)| Bool) +(declare-const |scc(3)_dn([3,7],29)| Bool) +(declare-const |scc(3)_dn([3,7],31)| Bool) +(declare-const |scc(3)_dn([3,7],33)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],90)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],95)| Bool) +(declare-const |scc(4)_dn([2,3],35)| Bool) +(declare-const |scc(4)_dn([4,1],70)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],51)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],55)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],58)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],59)| Bool) +(declare-const |dn([7,Main.main],54)_scc(1)| Bool) +(declare-const |dn([7,Main.main],54)_scc(7)| Bool) +(declare-const |scc(0)_dn([3,7],24)| Bool) +(declare-const |scc(0)_dn([2,3],34)| Bool) +(declare-const |dn([Main.main],109)_dn([Main.main],111)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],51)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],55)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],59)| Bool) +(declare-const |dn([7,Main.main],58)_scc(1)| Bool) +(declare-const |dn([7,Main.main],58)_scc(7)| Bool) +(declare-const |dn([Main.main],104)_dn([7,Main.main],49)| Bool) +(declare-const |dn([Main.main],104)_dn([Main.main],105)| Bool) +(declare-const |dn([8,Main.main],101)_dn([8,Main.main],96)| Bool) +(declare-const |dn([8,Main.main],101)_dn([8,Main.main],97)| Bool) +(declare-const |dn([6,9],95)_dn([6,9],90)| Bool) +(declare-const |dn([6,9],95)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],95)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],95)_scc(1)| Bool) +(declare-const |dn([8,Main.main],96)_dn([8,Main.main],97)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],33)| Bool) +(declare-const |dn([3,7],28)_scc(6)| Bool) +(declare-const |dn([Main.main],106)_dn([7,Main.main],47)| Bool) +(declare-const |dn([2,3],36)_dn([3,7],31)| Bool) +(declare-const |dn([2,3],36)_dn([2,3],37)| Bool) +(declare-const |dn([4,1],78)_dn([4,1],79)| Bool) +(declare-const |dn([4,1],78)_scc(4)| Bool) +(declare-const |dn([Main.main],114)_dn([9,Main.main],83)| Bool) +(declare-const |dn([Main.main],114)_dn([Main.main],115)| Bool) +(declare-const |dn([2,3],35)_dn([3,7],33)| Bool) +(declare-const |dn([2,3],35)_dn([2,3],36)| Bool) +(declare-const |dn([2,3],38)_dn([2,3],34)| Bool) +(declare-const |dn([2,3],38)_dn([2,3],35)| Bool) +(declare-const |dn([5,1],63)_dn([5,1],61)| Bool) +(declare-const |dn([5,1],63)_dn([5,1],62)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],58)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],31)| Bool) +(declare-const |dn([9,Main.main],88)_dn([9,Main.main],89)| Bool) +(declare-const |dn([4,1],80)_dn([4,1],81)| Bool) +(declare-const |dn([Main.main],116)_dn([Main.main],113)| Bool) +(declare-const |dn([Main.main],111)_dn([Main.main],102)| Bool) +(declare-const |dn([Main.main],111)_dn([Main.main],103)| Bool) +(declare-const |dn([7,Main.main],42)_dn([3,7],22)| Bool) +(declare-const |dn([7,Main.main],42)_dn([7,Main.main],43)| Bool) +(declare-const |dn([9,Main.main],85)_dn([9,Main.main],86)| Bool) +(declare-const |dn([9,Main.main],85)_dn([6,9],90)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],28)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],30)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],33)| Bool) +(declare-const |dn([1,3],64)_dn([1,3],65)| Bool) +(declare-const |dn([1,3],64)_dn([1,3],67)| Bool) +(declare-const |dn([9,Main.main],83)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],83)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],83)_dn([9,Main.main],88)| Bool) +(declare-const |dn([1,3],67)_dn([5,1],61)| Bool) +(declare-const |dn([1,3],67)_dn([1,3],68)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],58)| Bool) +(declare-const |dn([3,7],25)_dn([1,3],67)| Bool) +(declare-const |dn([6,9],90)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],90)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],90)_dn([6,9],95)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],58)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],51)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],55)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],58)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],59)| Bool) +(declare-const |dn([7,Main.main],50)_scc(1)| Bool) +(declare-const |dn([7,Main.main],50)_scc(7)| Bool) +(declare-const |dn([5,1],62)_dn([5,1],61)| Bool) +(declare-const |dn([5,1],62)_dn([5,1],63)| Bool) +(declare-const |dn([5,1],62)_scc(2)| Bool) +(declare-const |dn([3,7],22)_dn([1,3],65)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],58)| Bool) +(declare-const |dn([6,9],93)_dn([9,Main.main],88)| Bool) +(declare-const |dn([6,9],93)_dn([6,9],94)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],58)| Bool) +(declare-const |dn([Main.main],108)_dn([8,Main.main],97)| Bool) +(declare-const |dn([Main.main],108)_dn([Main.main],109)| Bool) +(declare-const |dn([7,Main.main],55)_dn([6,9],95)| Bool) +(declare-const |scc(1)_dn([7,Main.main],39)| Bool) +(declare-const |scc(1)_dn([7,Main.main],47)| Bool) +(declare-const |scc(1)_dn([7,Main.main],49)| Bool) +(declare-const |scc(1)_dn([7,Main.main],50)| Bool) +(declare-const |scc(1)_dn([7,Main.main],51)| Bool) +(declare-const |scc(1)_dn([7,Main.main],54)| Bool) +(declare-const |scc(1)_dn([7,Main.main],55)| Bool) +(declare-const |scc(1)_dn([7,Main.main],57)| Bool) +(declare-const |scc(1)_dn([7,Main.main],58)| Bool) +(declare-const |scc(1)_dn([7,Main.main],59)| Bool) +(declare-const |scc(1)_dn([6,9],93)| Bool) +(declare-const |scc(1)_scc(7)| Bool) +(declare-const |dn([Main.main],105)_dn([7,Main.main],50)| Bool) +(declare-const |dn([Main.main],105)_dn([Main.main],106)| Bool) +(declare-const |scc(2)_dn([3,7],20)| Bool) +(declare-const |scc(2)_dn([3,7],22)| Bool) +(declare-const |scc(2)_dn([3,7],27)| Bool) +(declare-const |scc(2)_dn([3,7],29)| Bool) +(declare-const |scc(2)_dn([3,7],31)| Bool) +(declare-const |scc(2)_dn([3,7],33)| Bool) +(declare-const |dn([8,Main.main],97)_dn([3,7],27)| Bool) +(declare-const |dn([Main.main],103)_dn([7,Main.main],39)| Bool) +(declare-const |dn([Main.main],103)_dn([Main.main],104)| Bool) +(declare-const |scc(5)_dn([5,1],63)| Bool) +(declare-const |scc(5)_dn([8,Main.main],100)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],90)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],95)| Bool) +(declare-const |dn([8,Main.main],100)_dn([4,1],78)| Bool) +(declare-const |dn([8,Main.main],100)_dn([8,Main.main],101)| Bool) +(declare-const |dn([7,Main.main],59)_dn([7,Main.main],60)| Bool) +(declare-const |dn([7,Main.main],59)_dn([6,9],95)| Bool) +(declare-const |dn([5,1],61)_dn([5,1],62)| Bool) +(declare-const |dn([5,1],61)_dn([5,1],63)| Bool) +(declare-const |dn([4,1],69)_dn([4,1],78)| Bool) +(declare-const |dn([4,1],69)_dn([4,1],80)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],28)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],30)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],33)| Bool) +(declare-const |dn([3,7],31)_dn([5,1],62)| Bool) +(declare-const |dn([Main.main],113)_dn([9,Main.main],82)| Bool) +(declare-const |dn([Main.main],113)_dn([Main.main],114)| Bool) +(declare-const |dn([4,1],79)_dn([4,1],69)| Bool) +(declare-const |dn([4,1],79)_dn([4,1],78)| Bool) +(declare-const |dn([4,1],79)_dn([4,1],80)| Bool) +(declare-const |dn([2,3],34)_dn([2,3],35)| Bool) +(declare-const |dn([Main.main],115)_dn([Main.main],111)| Bool) +(declare-const |dn([Main.main],115)_dn([Main.main],116)| Bool) +(declare-const |dn([2,3],37)_dn([2,3],38)| Bool) +(declare-const |dn([2,3],37)_dn([7,Main.main],58)| Bool) +(declare-const |dn([1,3],68)_dn([1,3],64)| Bool) +(declare-const |dn([1,3],68)_dn([1,3],65)| Bool) +(declare-const |dn([1,3],68)_dn([1,3],67)| Bool) +(declare-const |dn([4,1],81)_dn([4,1],69)| Bool) +(declare-const |dn([4,1],81)_dn([4,1],78)| Bool) +(declare-const |dn([4,1],81)_dn([4,1],80)| Bool) +(declare-const |scc(7)_dn([7,Main.main],39)| Bool) +(declare-const |scc(7)_dn([7,Main.main],47)| Bool) +(declare-const |scc(7)_dn([7,Main.main],49)| Bool) +(declare-const |scc(7)_dn([7,Main.main],50)| Bool) +(declare-const |scc(7)_dn([7,Main.main],51)| Bool) +(declare-const |scc(7)_dn([7,Main.main],53)| Bool) +(declare-const |scc(7)_dn([7,Main.main],54)| Bool) +(declare-const |scc(7)_dn([7,Main.main],55)| Bool) +(declare-const |scc(7)_dn([7,Main.main],58)| Bool) +(declare-const |scc(7)_dn([7,Main.main],59)| Bool) +(declare-const |scc(7)_scc(1)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],88)| Bool) +(declare-const |dn([1,3],66)_dn([1,3],64)| Bool) +(declare-const |dn([1,3],66)_dn([1,3],65)| Bool) +(declare-const |dn([1,3],66)_dn([1,3],67)| Bool) +(declare-const |dn([1,3],66)_scc(0)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],85)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],88)| Bool) +(declare-const |dn([1,3],65)_dn([1,3],66)| Bool) +(declare-const |dn([1,3],65)_dn([4,1],69)| Bool) +(declare-const |dn([7,Main.main],43)_dn([7,Main.main],40)| Bool) +(declare-const |dn([9,Main.main],82)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],82)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],82)_dn([9,Main.main],88)| Bool) +(declare-const |dn([7,Main.main],45)_dn([7,Main.main],40)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],33)| Bool) +(declare-const |dn([3,7],30)_scc(5)| Bool) +(declare-const |scc(8)_dn([8,Main.main],96)| Bool) +(declare-const |scc(8)_dn([Main.main],108)| Bool) +(declare-const |dn([9,Main.main],87)_dn([7,Main.main],53)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],88)| Bool) +(declare-const |dn([9,Main.main],87)_scc(7)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],33)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],58)| Bool) +(declare-const |scc(6)_dn([3,7],29)| Bool) +(assert |dn([Main.main],113)|) +(assert (= |dn([7,Main.main],41)| (or |dn([7,Main.main],41)_dn([3,7],20)| |dn([7,Main.main],41)_dn([7,Main.main],42)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([7,Main.main],41)_dn([7,Main.main],42)|))) +(assert (not (and |dn([7,Main.main],41)_dn([7,Main.main],42)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (= |dn([3,7],24)| (or |dn([3,7],24)_dn([3,7],25)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([3,7],25)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([3,7],24)_dn([3,7],25)|))) +(assert (= |dn([7,Main.main],47)| (or |dn([7,Main.main],47)_dn([7,Main.main],41)| |dn([7,Main.main],47)_dn([7,Main.main],45)|))) +(assert (not (and |dn([7,Main.main],47)_dn([7,Main.main],41)| |dn([7,Main.main],47)_dn([7,Main.main],45)|))) +(assert (not (and |dn([7,Main.main],47)_dn([7,Main.main],45)| |dn([7,Main.main],47)_dn([7,Main.main],41)|))) +(assert (= |dn([9,Main.main],86)| (or |dn([9,Main.main],86)_dn([9,Main.main],87)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([9,Main.main],87)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([9,Main.main],86)_dn([9,Main.main],87)|))) +(assert (= |dn([7,Main.main],51)| (or |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (= |dn([3,7],20)| (or |dn([3,7],20)_dn([3,7],21)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([3,7],21)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([1,3],64)| |dn([3,7],20)_dn([3,7],21)|))) +(assert (= |dn([6,9],91)| (or |dn([6,9],91)_dn([7,Main.main],54)| |dn([6,9],91)_dn([6,9],92)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([6,9],91)_dn([6,9],92)|))) +(assert (not (and |dn([6,9],91)_dn([6,9],92)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (= |scc(3)| (or |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],31)|))) +(assert (= |dn([6,9],92)| (or |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (= |scc(4)| (or |scc(4)_dn([2,3],35)| |scc(4)_dn([4,1],70)|))) +(assert (not (and |scc(4)_dn([2,3],35)| |scc(4)_dn([4,1],70)|))) +(assert (not (and |scc(4)_dn([4,1],70)| |scc(4)_dn([2,3],35)|))) +(assert (= |dn([7,Main.main],54)| (or |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_scc(1)|))) +(assert (= |scc(0)| (or |scc(0)_dn([3,7],24)| |scc(0)_dn([2,3],34)|))) +(assert (not (and |scc(0)_dn([3,7],24)| |scc(0)_dn([2,3],34)|))) +(assert (not (and |scc(0)_dn([2,3],34)| |scc(0)_dn([3,7],24)|))) +(assert (= |dn([Main.main],109)| (or |dn([Main.main],109)_dn([Main.main],111)|))) +(assert (= |dn([7,Main.main],58)| (or |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_scc(1)|))) +(assert (= |dn([Main.main],104)| (or |dn([Main.main],104)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([Main.main],105)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([Main.main],105)|))) +(assert (not (and |dn([Main.main],104)_dn([Main.main],105)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not |dn([Main.main],102)|)) +(assert (= |dn([8,Main.main],101)| (or |dn([8,Main.main],101)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],96)|))) +(assert (= |dn([6,9],95)| (or |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (= |dn([8,Main.main],96)| (or |dn([8,Main.main],96)_dn([8,Main.main],97)|))) +(assert (= |dn([3,7],28)| (or |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (= |dn([Main.main],106)| (or |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (= |dn([2,3],36)| (or |dn([2,3],36)_dn([3,7],31)| |dn([2,3],36)_dn([2,3],37)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([2,3],36)_dn([2,3],37)|))) +(assert (not (and |dn([2,3],36)_dn([2,3],37)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (= |dn([4,1],78)| (or |dn([4,1],78)_dn([4,1],79)| |dn([4,1],78)_scc(4)|))) +(assert (not (and |dn([4,1],78)_dn([4,1],79)| |dn([4,1],78)_scc(4)|))) +(assert (not (and |dn([4,1],78)_scc(4)| |dn([4,1],78)_dn([4,1],79)|))) +(assert (= |dn([Main.main],114)| (or |dn([Main.main],114)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([Main.main],115)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([Main.main],115)|))) +(assert (not (and |dn([Main.main],114)_dn([Main.main],115)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (= |dn([2,3],35)| (or |dn([2,3],35)_dn([3,7],33)| |dn([2,3],35)_dn([2,3],36)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([2,3],35)_dn([2,3],36)|))) +(assert (not (and |dn([2,3],35)_dn([2,3],36)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (= |dn([2,3],38)| (or |dn([2,3],38)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],34)|))) +(assert (= |dn([5,1],63)| (or |dn([5,1],63)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (= |dn([7,Main.main],39)| (or |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (= |dn([3,7],33)| (or |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (= |dn([9,Main.main],88)| (or |dn([9,Main.main],88)_dn([9,Main.main],89)|))) +(assert (= |dn([4,1],80)| (or |dn([4,1],80)_dn([4,1],81)|))) +(assert (= |dn([Main.main],116)| (or |dn([Main.main],116)_dn([Main.main],113)|))) +(assert (= |dn([Main.main],111)| (or |dn([Main.main],111)_dn([Main.main],102)| |dn([Main.main],111)_dn([Main.main],103)|))) +(assert (not (and |dn([Main.main],111)_dn([Main.main],102)| |dn([Main.main],111)_dn([Main.main],103)|))) +(assert (not (and |dn([Main.main],111)_dn([Main.main],103)| |dn([Main.main],111)_dn([Main.main],102)|))) +(assert (= |dn([7,Main.main],42)| (or |dn([7,Main.main],42)_dn([3,7],22)| |dn([7,Main.main],42)_dn([7,Main.main],43)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([7,Main.main],42)_dn([7,Main.main],43)|))) +(assert (not (and |dn([7,Main.main],42)_dn([7,Main.main],43)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (= |dn([9,Main.main],85)| (or |dn([9,Main.main],85)_dn([9,Main.main],86)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([9,Main.main],86)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([9,Main.main],85)_dn([9,Main.main],86)|))) +(assert (= |dn([3,7],27)| (or |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (= |dn([1,3],64)| (or |dn([1,3],64)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (= |dn([9,Main.main],83)| (or |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (= |dn([1,3],67)| (or |dn([1,3],67)_dn([5,1],61)| |dn([1,3],67)_dn([1,3],68)|))) +(assert (not (and |dn([1,3],67)_dn([5,1],61)| |dn([1,3],67)_dn([1,3],68)|))) +(assert (not (and |dn([1,3],67)_dn([1,3],68)| |dn([1,3],67)_dn([5,1],61)|))) +(assert (= |dn([7,Main.main],40)| (or |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (= |dn([3,7],25)| (or |dn([3,7],25)_dn([1,3],67)|))) +(assert (= |dn([6,9],90)| (or |dn([6,9],90)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (= |dn([7,Main.main],60)| (or |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (= |dn([7,Main.main],50)| (or |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_scc(1)|))) +(assert (= |dn([5,1],62)| (or |dn([5,1],62)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],63)| |dn([5,1],62)_scc(2)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([5,1],62)_scc(2)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |dn([5,1],62)_scc(2)|))) +(assert (not (and |dn([5,1],62)_scc(2)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_scc(2)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (= |dn([3,7],22)| (or |dn([3,7],22)_dn([1,3],65)|))) +(assert (= |dn([7,Main.main],53)| (or |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (= |dn([6,9],93)| (or |dn([6,9],93)_dn([9,Main.main],88)| |dn([6,9],93)_dn([6,9],94)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([6,9],93)_dn([6,9],94)|))) +(assert (not (and |dn([6,9],93)_dn([6,9],94)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (= |dn([7,Main.main],57)| (or |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (= |dn([Main.main],108)| (or |dn([Main.main],108)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([Main.main],109)|))) +(assert (not (and |dn([Main.main],108)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([Main.main],109)|))) +(assert (not (and |dn([Main.main],108)_dn([Main.main],109)| |dn([Main.main],108)_dn([8,Main.main],97)|))) +(assert (= |dn([7,Main.main],55)| (or |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (= |scc(1)| (or |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([6,9],93)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([6,9],93)|))) +(assert (= |dn([Main.main],105)| (or |dn([Main.main],105)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([Main.main],106)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([Main.main],106)|))) +(assert (not (and |dn([Main.main],105)_dn([Main.main],106)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (= |scc(2)| (or |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],31)|))) +(assert (= |dn([8,Main.main],97)| (or |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (= |dn([Main.main],103)| (or |dn([Main.main],103)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([Main.main],104)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([Main.main],104)|))) +(assert (not (and |dn([Main.main],103)_dn([Main.main],104)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (= |scc(5)| (or |scc(5)_dn([5,1],63)| |scc(5)_dn([8,Main.main],100)|))) +(assert (not (and |scc(5)_dn([5,1],63)| |scc(5)_dn([8,Main.main],100)|))) +(assert (not (and |scc(5)_dn([8,Main.main],100)| |scc(5)_dn([5,1],63)|))) +(assert (not |dn([4,1],70)|)) +(assert (= |dn([6,9],94)| (or |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (= |dn([8,Main.main],100)| (or |dn([8,Main.main],100)_dn([4,1],78)| |dn([8,Main.main],100)_dn([8,Main.main],101)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([8,Main.main],100)_dn([8,Main.main],101)|))) +(assert (not (and |dn([8,Main.main],100)_dn([8,Main.main],101)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (= |dn([7,Main.main],59)| (or |dn([7,Main.main],59)_dn([7,Main.main],60)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([7,Main.main],60)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([7,Main.main],59)_dn([7,Main.main],60)|))) +(assert (= |dn([5,1],61)| (or |dn([5,1],61)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],62)|))) +(assert (= |dn([4,1],69)| (or |dn([4,1],69)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (= |dn([3,7],29)| (or |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (= |dn([3,7],31)| (or |dn([3,7],31)_dn([5,1],62)|))) +(assert (= |dn([Main.main],113)| (or |dn([Main.main],113)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([Main.main],114)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([Main.main],114)|))) +(assert (not (and |dn([Main.main],113)_dn([Main.main],114)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (= |dn([4,1],79)| (or |dn([4,1],79)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (= |dn([2,3],34)| (or |dn([2,3],34)_dn([2,3],35)|))) +(assert (= |dn([Main.main],115)| (or |dn([Main.main],115)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],116)|))) +(assert (not (and |dn([Main.main],115)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],116)|))) +(assert (not (and |dn([Main.main],115)_dn([Main.main],116)| |dn([Main.main],115)_dn([Main.main],111)|))) +(assert (= |dn([2,3],37)| (or |dn([2,3],37)_dn([2,3],38)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([2,3],38)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([2,3],37)_dn([2,3],38)|))) +(assert (= |dn([1,3],68)| (or |dn([1,3],68)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (= |dn([4,1],81)| (or |dn([4,1],81)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (= |scc(7)| (or |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],59)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],59)|))) +(assert (= |dn([9,Main.main],89)| (or |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (= |dn([1,3],66)| (or |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_scc(0)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_scc(0)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_scc(0)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (= |dn([9,Main.main],84)| (or |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (= |dn([1,3],65)| (or |dn([1,3],65)_dn([1,3],66)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([1,3],66)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([4,1],69)| |dn([1,3],65)_dn([1,3],66)|))) +(assert (= |dn([7,Main.main],43)| (or |dn([7,Main.main],43)_dn([7,Main.main],40)|))) +(assert (= |dn([9,Main.main],82)| (or |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (= |dn([7,Main.main],45)| (or |dn([7,Main.main],45)_dn([7,Main.main],40)|))) +(assert (= |dn([3,7],30)| (or |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (= |scc(8)| (or |scc(8)_dn([8,Main.main],96)| |scc(8)_dn([Main.main],108)|))) +(assert (not (and |scc(8)_dn([8,Main.main],96)| |scc(8)_dn([Main.main],108)|))) +(assert (not (and |scc(8)_dn([Main.main],108)| |scc(8)_dn([8,Main.main],96)|))) +(assert (= |dn([9,Main.main],87)| (or |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (= |dn([7,Main.main],49)| (or |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (= |scc(6)| (or |scc(6)_dn([3,7],29)|))) +(assert (= |dn([7,Main.main],41)| (or |dn([7,Main.main],47)_dn([7,Main.main],41)|))) +(assert (= |dn([3,7],24)| (or |scc(0)_dn([3,7],24)|))) +(assert (= |dn([7,Main.main],47)| (or |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (= |dn([9,Main.main],86)| (or |dn([9,Main.main],85)_dn([9,Main.main],86)|))) +(assert (= |dn([7,Main.main],51)| (or |dn([7,Main.main],50)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (= |dn([3,7],20)| (or |dn([7,Main.main],41)_dn([3,7],20)| |scc(2)_dn([3,7],20)| |scc(3)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (= |dn([6,9],91)| (or |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not |scc(3)|)) +(assert (= |dn([6,9],92)| (or |dn([6,9],91)_dn([6,9],92)|))) +(assert (= |scc(4)| (or |dn([4,1],78)_scc(4)|))) +(assert (= |dn([7,Main.main],54)| (or |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (= |scc(0)| (or |dn([1,3],66)_scc(0)|))) +(assert (= |dn([Main.main],109)| (or |dn([Main.main],108)_dn([Main.main],109)|))) +(assert (= |dn([7,Main.main],58)| (or |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (= |dn([Main.main],104)| (or |dn([Main.main],103)_dn([Main.main],104)|))) +(assert (= |dn([Main.main],102)| (or |dn([Main.main],111)_dn([Main.main],102)|))) +(assert (= |dn([8,Main.main],101)| (or |dn([8,Main.main],100)_dn([8,Main.main],101)|))) +(assert (= |dn([6,9],95)| (or |dn([7,Main.main],55)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (= |dn([8,Main.main],96)| (or |scc(8)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],96)|))) +(assert (not (and |scc(8)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],96)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],96)| |scc(8)_dn([8,Main.main],96)|))) +(assert (= |dn([3,7],28)| (or |dn([3,7],27)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (= |dn([Main.main],106)| (or |dn([Main.main],105)_dn([Main.main],106)|))) +(assert (= |dn([2,3],36)| (or |dn([2,3],35)_dn([2,3],36)|))) +(assert (= |dn([4,1],78)| (or |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (= |dn([Main.main],114)| (or |dn([Main.main],113)_dn([Main.main],114)|))) +(assert (= |dn([2,3],35)| (or |scc(4)_dn([2,3],35)| |dn([2,3],34)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |scc(4)_dn([2,3],35)| |dn([2,3],34)_dn([2,3],35)|))) +(assert (not (and |scc(4)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],34)_dn([2,3],35)| |scc(4)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],34)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],35)| |scc(4)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],35)| |dn([2,3],34)_dn([2,3],35)|))) +(assert (= |dn([2,3],38)| (or |dn([2,3],37)_dn([2,3],38)|))) +(assert (= |dn([5,1],63)| (or |scc(5)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |scc(5)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (not (and |scc(5)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],63)| |scc(5)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |scc(5)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (= |dn([7,Main.main],39)| (or |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (= |dn([3,7],33)| (or |dn([2,3],35)_dn([3,7],33)| |scc(2)_dn([3,7],33)| |scc(3)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (= |dn([9,Main.main],88)| (or |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (= |dn([4,1],80)| (or |dn([3,7],24)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (= |dn([Main.main],116)| (or |dn([Main.main],115)_dn([Main.main],116)|))) +(assert (= |dn([Main.main],111)| (or |dn([Main.main],109)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],111)|))) +(assert (not (and |dn([Main.main],109)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],111)|))) +(assert (not (and |dn([Main.main],115)_dn([Main.main],111)| |dn([Main.main],109)_dn([Main.main],111)|))) +(assert (= |dn([7,Main.main],42)| (or |dn([7,Main.main],41)_dn([7,Main.main],42)|))) +(assert (= |dn([9,Main.main],85)| (or |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (= |dn([3,7],27)| (or |dn([8,Main.main],97)_dn([3,7],27)| |scc(2)_dn([3,7],27)| |scc(3)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (= |dn([1,3],64)| (or |dn([3,7],20)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (= |dn([9,Main.main],83)| (or |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (= |dn([1,3],67)| (or |dn([3,7],25)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([3,7],25)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([3,7],25)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([3,7],25)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([3,7],25)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([3,7],25)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([3,7],25)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (= |dn([7,Main.main],40)| (or |dn([7,Main.main],43)_dn([7,Main.main],40)| |dn([7,Main.main],45)_dn([7,Main.main],40)|))) +(assert (not (and |dn([7,Main.main],43)_dn([7,Main.main],40)| |dn([7,Main.main],45)_dn([7,Main.main],40)|))) +(assert (not (and |dn([7,Main.main],45)_dn([7,Main.main],40)| |dn([7,Main.main],43)_dn([7,Main.main],40)|))) +(assert (= |dn([3,7],25)| (or |dn([3,7],24)_dn([3,7],25)|))) +(assert (= |dn([6,9],90)| (or |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (= |dn([7,Main.main],60)| (or |dn([7,Main.main],59)_dn([7,Main.main],60)|))) +(assert (= |dn([7,Main.main],50)| (or |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (= |dn([5,1],62)| (or |dn([3,7],31)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([3,7],31)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],62)|))) +(assert (not (and |dn([3,7],31)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],62)| |dn([3,7],31)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],62)| |dn([3,7],31)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],62)|))) +(assert (= |dn([3,7],22)| (or |dn([7,Main.main],42)_dn([3,7],22)| |scc(2)_dn([3,7],22)| |scc(3)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (= |dn([7,Main.main],53)| (or |dn([9,Main.main],87)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (= |dn([6,9],93)| (or |scc(1)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (= |dn([7,Main.main],57)| (or |scc(1)_dn([7,Main.main],57)|))) +(assert (= |dn([Main.main],108)| (or |scc(8)_dn([Main.main],108)|))) +(assert (= |dn([7,Main.main],55)| (or |dn([7,Main.main],54)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (= |scc(1)| (or |dn([6,9],95)_scc(1)| |scc(7)_scc(1)| |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (= |dn([Main.main],105)| (or |dn([Main.main],104)_dn([Main.main],105)|))) +(assert (= |scc(2)| (or |dn([5,1],62)_scc(2)|))) +(assert (= |dn([8,Main.main],97)| (or |dn([Main.main],108)_dn([8,Main.main],97)| |dn([8,Main.main],96)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([Main.main],108)_dn([8,Main.main],97)| |dn([8,Main.main],96)_dn([8,Main.main],97)|))) +(assert (not (and |dn([Main.main],108)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],96)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],96)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],97)| |dn([8,Main.main],96)_dn([8,Main.main],97)|))) +(assert (= |dn([Main.main],103)| (or |dn([Main.main],111)_dn([Main.main],103)|))) +(assert (= |scc(5)| (or |dn([3,7],30)_scc(5)|))) +(assert (= |dn([4,1],70)| (or |scc(4)_dn([4,1],70)|))) +(assert (= |dn([6,9],94)| (or |dn([6,9],93)_dn([6,9],94)|))) +(assert (= |dn([8,Main.main],100)| (or |scc(5)_dn([8,Main.main],100)|))) +(assert (= |dn([7,Main.main],59)| (or |dn([7,Main.main],58)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (= |dn([5,1],61)| (or |dn([1,3],67)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (not (and |dn([1,3],67)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (not (and |dn([1,3],67)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([1,3],67)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],61)| |dn([1,3],67)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (= |dn([4,1],69)| (or |dn([1,3],65)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (= |dn([3,7],29)| (or |scc(6)_dn([3,7],29)| |scc(2)_dn([3,7],29)| |scc(3)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (= |dn([3,7],31)| (or |dn([2,3],36)_dn([3,7],31)| |scc(2)_dn([3,7],31)| |scc(3)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (= |dn([4,1],79)| (or |dn([4,1],78)_dn([4,1],79)|))) +(assert (= |dn([2,3],34)| (or |scc(0)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],34)|))) +(assert (not (and |scc(0)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],34)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],34)| |scc(0)_dn([2,3],34)|))) +(assert (= |dn([Main.main],115)| (or |dn([Main.main],114)_dn([Main.main],115)|))) +(assert (= |dn([2,3],37)| (or |dn([2,3],36)_dn([2,3],37)|))) +(assert (= |dn([1,3],68)| (or |dn([1,3],67)_dn([1,3],68)|))) +(assert (= |dn([4,1],81)| (or |dn([4,1],80)_dn([4,1],81)|))) +(assert (= |scc(7)| (or |dn([9,Main.main],87)_scc(7)| |scc(1)_scc(7)| |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (= |dn([9,Main.main],89)| (or |dn([9,Main.main],88)_dn([9,Main.main],89)|))) +(assert (= |dn([1,3],66)| (or |dn([1,3],65)_dn([1,3],66)|))) +(assert (= |dn([9,Main.main],84)| (or |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (= |dn([1,3],65)| (or |dn([3,7],22)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([3,7],22)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (not (and |dn([3,7],22)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([3,7],22)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([3,7],22)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([3,7],22)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([3,7],22)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (= |dn([7,Main.main],43)| (or |dn([7,Main.main],42)_dn([7,Main.main],43)|))) +(assert (= |dn([9,Main.main],82)| (or |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (= |dn([7,Main.main],45)| (or |dn([7,Main.main],47)_dn([7,Main.main],45)|))) +(assert (= |dn([3,7],30)| (or |dn([3,7],29)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not |scc(8)|)) +(assert (= |dn([9,Main.main],87)| (or |dn([9,Main.main],86)_dn([9,Main.main],87)|))) +(assert (= |dn([3,7],21)| (or |dn([3,7],20)_dn([3,7],21)|))) +(assert (= |dn([7,Main.main],49)| (or |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (= |scc(6)| (or |dn([3,7],28)_scc(6)|))) +(assert-soft |dn([7,Main.main],41)_dn([3,7],20)| :weight 1) +(assert-soft |scc(2)_dn([3,7],20)| :weight 1) +(assert-soft |scc(3)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],33)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],20)_dn([3,7],21)| :weight 1) +(assert-soft |dn([7,Main.main],42)_dn([3,7],22)| :weight 1) +(assert-soft |scc(2)_dn([3,7],22)| :weight 1) +(assert-soft |scc(3)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],33)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],22)| :weight 1) +(assert-soft |scc(0)_dn([3,7],24)| :weight 1) +(assert-soft |dn([3,7],24)_dn([3,7],25)| :weight 1) +(assert-soft |dn([8,Main.main],97)_dn([3,7],27)| :weight 2) +(assert-soft |scc(2)_dn([3,7],27)| :weight 2) +(assert-soft |scc(3)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],21)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],28)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],30)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],33)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],29)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],27)_dn([3,7],28)| :weight 6) +(assert-soft |dn([3,7],29)_dn([3,7],28)| :weight 6) +(assert-soft |scc(6)_dn([3,7],29)| :weight 2) +(assert-soft |scc(2)_dn([3,7],29)| :weight 2) +(assert-soft |scc(3)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],21)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],28)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],30)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],33)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],27)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],29)_dn([3,7],30)| :weight 6) +(assert-soft |dn([3,7],27)_dn([3,7],30)| :weight 6) +(assert-soft |dn([2,3],36)_dn([3,7],31)| :weight 1) +(assert-soft |scc(2)_dn([3,7],31)| :weight 1) +(assert-soft |scc(3)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],33)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],31)| :weight 1) +(assert-soft |dn([2,3],35)_dn([3,7],33)| :weight 1) +(assert-soft |scc(2)_dn([3,7],33)| :weight 1) +(assert-soft |scc(3)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],33)| :weight 1) +(assert-soft |scc(0)_dn([2,3],34)| :weight 1) +(assert-soft |dn([2,3],38)_dn([2,3],34)| :weight 1) +(assert-soft |scc(4)_dn([2,3],35)| :weight 1) +(assert-soft |dn([2,3],34)_dn([2,3],35)| :weight 1) +(assert-soft |dn([2,3],38)_dn([2,3],35)| :weight 1) +(assert-soft |dn([2,3],35)_dn([2,3],36)| :weight 1) +(assert-soft |dn([2,3],36)_dn([2,3],37)| :weight 1) +(assert-soft |dn([2,3],37)_dn([2,3],38)| :weight 1) +(assert-soft |dn([Main.main],103)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],39)| :weight 6) +(assert-soft |scc(1)_dn([7,Main.main],39)| :weight 6) +(assert-soft |scc(7)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],43)_dn([7,Main.main],40)| :weight 4) +(assert-soft |dn([7,Main.main],45)_dn([7,Main.main],40)| :weight 4) +(assert-soft |dn([7,Main.main],47)_dn([7,Main.main],41)| :weight 1) +(assert-soft |dn([7,Main.main],41)_dn([7,Main.main],42)| :weight 1) +(assert-soft |dn([7,Main.main],42)_dn([7,Main.main],43)| :weight 1) +(assert-soft |dn([7,Main.main],47)_dn([7,Main.main],45)| :weight 4) +(assert-soft |dn([Main.main],106)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],47)| :weight 8) +(assert-soft |scc(1)_dn([7,Main.main],47)| :weight 8) +(assert-soft |scc(7)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([Main.main],104)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],49)| :weight 8) +(assert-soft |scc(1)_dn([7,Main.main],49)| :weight 8) +(assert-soft |scc(7)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([Main.main],105)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],50)| :weight 2) +(assert-soft |scc(1)_dn([7,Main.main],50)| :weight 2) +(assert-soft |scc(7)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],51)| :weight 6) +(assert-soft |scc(1)_dn([7,Main.main],51)| :weight 6) +(assert-soft |scc(7)_dn([7,Main.main],51)| :weight 6) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],51)| :weight 6) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],51)| :weight 6) +(assert-soft |dn([9,Main.main],87)_dn([7,Main.main],53)| :weight 6) +(assert-soft |scc(7)_dn([7,Main.main],53)| :weight 6) +(assert-soft |dn([6,9],91)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],54)| :weight 2) +(assert-soft |scc(1)_dn([7,Main.main],54)| :weight 2) +(assert-soft |scc(7)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],55)| :weight 18) +(assert-soft |scc(1)_dn([7,Main.main],55)| :weight 18) +(assert-soft |scc(7)_dn([7,Main.main],55)| :weight 18) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],55)| :weight 18) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],55)| :weight 18) +(assert-soft |scc(1)_dn([7,Main.main],57)| :weight 4) +(assert-soft |dn([2,3],37)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],58)| :weight 1) +(assert-soft |scc(1)_dn([7,Main.main],58)| :weight 1) +(assert-soft |scc(7)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],59)| :weight 1) +(assert-soft |scc(1)_dn([7,Main.main],59)| :weight 1) +(assert-soft |scc(7)_dn([7,Main.main],59)| :weight 1) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],59)| :weight 1) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],59)| :weight 1) +(assert-soft |dn([7,Main.main],59)_dn([7,Main.main],60)| :weight 1) +(assert-soft |dn([1,3],67)_dn([5,1],61)| :weight 1) +(assert-soft |dn([5,1],62)_dn([5,1],61)| :weight 1) +(assert-soft |dn([5,1],63)_dn([5,1],61)| :weight 1) +(assert-soft |dn([3,7],31)_dn([5,1],62)| :weight 1) +(assert-soft |dn([5,1],61)_dn([5,1],62)| :weight 1) +(assert-soft |dn([5,1],63)_dn([5,1],62)| :weight 1) +(assert-soft |scc(5)_dn([5,1],63)| :weight 8) +(assert-soft |dn([5,1],61)_dn([5,1],63)| :weight 8) +(assert-soft |dn([5,1],62)_dn([5,1],63)| :weight 8) +(assert-soft |dn([3,7],20)_dn([1,3],64)| :weight 1) +(assert-soft |dn([1,3],66)_dn([1,3],64)| :weight 1) +(assert-soft |dn([1,3],68)_dn([1,3],64)| :weight 1) +(assert-soft |dn([3,7],22)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],64)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],66)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],68)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],65)_dn([1,3],66)| :weight 1) +(assert-soft |dn([3,7],25)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],64)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],66)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],68)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],67)_dn([1,3],68)| :weight 1) +(assert-soft |dn([1,3],65)_dn([4,1],69)| :weight 1) +(assert-soft |dn([4,1],79)_dn([4,1],69)| :weight 1) +(assert-soft |dn([4,1],81)_dn([4,1],69)| :weight 1) +(assert-soft |scc(4)_dn([4,1],70)| :weight 2) +(assert-soft |dn([8,Main.main],100)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],69)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],79)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],81)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],78)_dn([4,1],79)| :weight 4) +(assert-soft |dn([3,7],24)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],69)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],79)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],81)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],80)_dn([4,1],81)| :weight 1) +(assert-soft |dn([Main.main],113)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],83)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([Main.main],114)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],82)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([7,Main.main],51)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],82)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],83)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],85)| :weight 6) +(assert-soft |dn([9,Main.main],85)_dn([9,Main.main],86)| :weight 6) +(assert-soft |dn([9,Main.main],86)_dn([9,Main.main],87)| :weight 2) +(assert-soft |dn([6,9],93)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],82)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],83)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],88)_dn([9,Main.main],89)| :weight 6) +(assert-soft |dn([9,Main.main],85)_dn([6,9],90)| :weight 8) +(assert-soft |dn([6,9],92)_dn([6,9],90)| :weight 8) +(assert-soft |dn([6,9],94)_dn([6,9],90)| :weight 8) +(assert-soft |dn([6,9],95)_dn([6,9],90)| :weight 8) +(assert-soft |dn([9,Main.main],86)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],90)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],92)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],94)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],95)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],91)_dn([6,9],92)| :weight 4) +(assert-soft |scc(1)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],90)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],92)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],94)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],95)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],93)_dn([6,9],94)| :weight 4) +(assert-soft |dn([7,Main.main],55)_dn([6,9],95)| :weight 6) +(assert-soft |dn([7,Main.main],59)_dn([6,9],95)| :weight 6) +(assert-soft |dn([6,9],90)_dn([6,9],95)| :weight 6) +(assert-soft |dn([6,9],92)_dn([6,9],95)| :weight 6) +(assert-soft |dn([6,9],94)_dn([6,9],95)| :weight 6) +(assert-soft |scc(8)_dn([8,Main.main],96)| :weight 4) +(assert-soft |dn([8,Main.main],101)_dn([8,Main.main],96)| :weight 4) +(assert-soft |dn([Main.main],108)_dn([8,Main.main],97)| :weight 8) +(assert-soft |dn([8,Main.main],96)_dn([8,Main.main],97)| :weight 8) +(assert-soft |dn([8,Main.main],101)_dn([8,Main.main],97)| :weight 8) +(assert-soft |scc(5)_dn([8,Main.main],100)| :weight 4) +(assert-soft |dn([8,Main.main],100)_dn([8,Main.main],101)| :weight 4) +(assert-soft |dn([Main.main],111)_dn([Main.main],102)| :weight 1) +(assert-soft |dn([Main.main],111)_dn([Main.main],103)| :weight 6) +(assert-soft |dn([Main.main],103)_dn([Main.main],104)| :weight 2) +(assert-soft |dn([Main.main],104)_dn([Main.main],105)| :weight 2) +(assert-soft |dn([Main.main],105)_dn([Main.main],106)| :weight 2) +(assert-soft |scc(8)_dn([Main.main],108)| :weight 2) +(assert-soft |dn([Main.main],108)_dn([Main.main],109)| :weight 6) +(assert-soft |dn([Main.main],109)_dn([Main.main],111)| :weight 6) +(assert-soft |dn([Main.main],115)_dn([Main.main],111)| :weight 6) +(assert-soft |dn([Main.main],116)_dn([Main.main],113)| :weight 3) +(assert-soft |dn([Main.main],113)_dn([Main.main],114)| :weight 1) +(assert-soft |dn([Main.main],114)_dn([Main.main],115)| :weight 1) +(assert-soft |dn([Main.main],115)_dn([Main.main],116)| :weight 2) +(assert-soft |dn([1,3],66)_scc(0)| :weight 1) +(assert-soft |dn([6,9],95)_scc(1)| :weight 6) +(assert-soft |scc(7)_scc(1)| :weight 6) +(assert-soft |dn([7,Main.main],50)_scc(1)| :weight 6) +(assert-soft |dn([7,Main.main],54)_scc(1)| :weight 6) +(assert-soft |dn([7,Main.main],58)_scc(1)| :weight 6) +(assert-soft |dn([5,1],62)_scc(2)| :weight 1) +(assert-soft |dn([4,1],78)_scc(4)| :weight 4) +(assert-soft |dn([3,7],30)_scc(5)| :weight 8) +(assert-soft |dn([3,7],28)_scc(6)| :weight 6) +(assert-soft |dn([9,Main.main],87)_scc(7)| :weight 2) +(assert-soft |scc(1)_scc(7)| :weight 2) +(assert-soft |dn([7,Main.main],50)_scc(7)| :weight 2) +(assert-soft |dn([7,Main.main],54)_scc(7)| :weight 2) +(assert-soft |dn([7,Main.main],58)_scc(7)| :weight 2) +(set-option :smt.pb.conflict_frequency 100) + +(optimize +; :wmaxsat_engine wpm2 + :wmaxsat_engine pwmax +; :wmaxsat_engine bvmax + :print_statistics true + :timeout 1200000 +) diff --git a/tests/chat_sls.smt2 b/tests/chat_sls.smt2 new file mode 100644 index 000000000..33a6d9b5e --- /dev/null +++ b/tests/chat_sls.smt2 @@ -0,0 +1,3380 @@ +(declare-const |dn([7,Main.main],41)| Bool) +(declare-const |dn([3,7],24)| Bool) +(declare-const |dn([7,Main.main],47)| Bool) +(declare-const |dn([9,Main.main],86)| Bool) +(declare-const |dn([7,Main.main],51)| Bool) +(declare-const |dn([3,7],20)| Bool) +(declare-const |dn([6,9],91)| Bool) +(declare-const |scc(3)| Bool) +(declare-const |dn([6,9],92)| Bool) +(declare-const |scc(4)| Bool) +(declare-const |dn([7,Main.main],54)| Bool) +(declare-const |scc(0)| Bool) +(declare-const |dn([Main.main],109)| Bool) +(declare-const |dn([7,Main.main],58)| Bool) +(declare-const |dn([Main.main],104)| Bool) +(declare-const |dn([Main.main],102)| Bool) +(declare-const |dn([8,Main.main],101)| Bool) +(declare-const |dn([6,9],95)| Bool) +(declare-const |dn([8,Main.main],96)| Bool) +(declare-const |dn([3,7],28)| Bool) +(declare-const |dn([Main.main],106)| Bool) +(declare-const |dn([2,3],36)| Bool) +(declare-const |dn([4,1],78)| Bool) +(declare-const |dn([Main.main],114)| Bool) +(declare-const |dn([2,3],35)| Bool) +(declare-const |dn([2,3],38)| Bool) +(declare-const |dn([5,1],63)| Bool) +(declare-const |dn([7,Main.main],39)| Bool) +(declare-const |dn([3,7],33)| Bool) +(declare-const |dn([9,Main.main],88)| Bool) +(declare-const |dn([4,1],80)| Bool) +(declare-const |dn([Main.main],116)| Bool) +(declare-const |dn([Main.main],111)| Bool) +(declare-const |dn([7,Main.main],42)| Bool) +(declare-const |dn([9,Main.main],85)| Bool) +(declare-const |dn([3,7],27)| Bool) +(declare-const |dn([1,3],64)| Bool) +(declare-const |dn([9,Main.main],83)| Bool) +(declare-const |dn([1,3],67)| Bool) +(declare-const |dn([7,Main.main],40)| Bool) +(declare-const |dn([3,7],25)| Bool) +(declare-const |dn([6,9],90)| Bool) +(declare-const |dn([7,Main.main],60)| Bool) +(declare-const |dn([7,Main.main],50)| Bool) +(declare-const |dn([5,1],62)| Bool) +(declare-const |dn([3,7],22)| Bool) +(declare-const |dn([7,Main.main],53)| Bool) +(declare-const |dn([6,9],93)| Bool) +(declare-const |dn([7,Main.main],57)| Bool) +(declare-const |dn([Main.main],108)| Bool) +(declare-const |dn([7,Main.main],55)| Bool) +(declare-const |scc(1)| Bool) +(declare-const |dn([Main.main],105)| Bool) +(declare-const |scc(2)| Bool) +(declare-const |dn([8,Main.main],97)| Bool) +(declare-const |dn([Main.main],103)| Bool) +(declare-const |scc(5)| Bool) +(declare-const |dn([4,1],70)| Bool) +(declare-const |dn([6,9],94)| Bool) +(declare-const |dn([8,Main.main],100)| Bool) +(declare-const |dn([7,Main.main],59)| Bool) +(declare-const |dn([5,1],61)| Bool) +(declare-const |dn([4,1],69)| Bool) +(declare-const |dn([3,7],29)| Bool) +(declare-const |dn([3,7],31)| Bool) +(declare-const |dn([Main.main],113)| Bool) +(declare-const |dn([4,1],79)| Bool) +(declare-const |dn([2,3],34)| Bool) +(declare-const |dn([Main.main],115)| Bool) +(declare-const |dn([2,3],37)| Bool) +(declare-const |dn([1,3],68)| Bool) +(declare-const |dn([4,1],81)| Bool) +(declare-const |scc(7)| Bool) +(declare-const |dn([9,Main.main],89)| Bool) +(declare-const |dn([1,3],66)| Bool) +(declare-const |dn([9,Main.main],84)| Bool) +(declare-const |dn([1,3],65)| Bool) +(declare-const |dn([7,Main.main],43)| Bool) +(declare-const |dn([9,Main.main],82)| Bool) +(declare-const |dn([7,Main.main],45)| Bool) +(declare-const |dn([3,7],30)| Bool) +(declare-const |scc(8)| Bool) +(declare-const |dn([9,Main.main],87)| Bool) +(declare-const |dn([3,7],21)| Bool) +(declare-const |dn([7,Main.main],49)| Bool) +(declare-const |scc(6)| Bool) +(declare-const |dn([7,Main.main],41)_dn([3,7],20)| Bool) +(declare-const |dn([7,Main.main],41)_dn([7,Main.main],42)| Bool) +(declare-const |dn([3,7],24)_dn([3,7],25)| Bool) +(declare-const |dn([3,7],24)_dn([4,1],80)| Bool) +(declare-const |dn([7,Main.main],47)_dn([7,Main.main],41)| Bool) +(declare-const |dn([7,Main.main],47)_dn([7,Main.main],45)| Bool) +(declare-const |dn([9,Main.main],86)_dn([9,Main.main],87)| Bool) +(declare-const |dn([9,Main.main],86)_dn([6,9],91)| Bool) +(declare-const |dn([7,Main.main],51)_dn([9,Main.main],84)| Bool) +(declare-const |dn([3,7],20)_dn([3,7],21)| Bool) +(declare-const |dn([3,7],20)_dn([1,3],64)| Bool) +(declare-const |dn([6,9],91)_dn([7,Main.main],54)| Bool) +(declare-const |dn([6,9],91)_dn([6,9],92)| Bool) +(declare-const |scc(3)_dn([3,7],20)| Bool) +(declare-const |scc(3)_dn([3,7],22)| Bool) +(declare-const |scc(3)_dn([3,7],27)| Bool) +(declare-const |scc(3)_dn([3,7],29)| Bool) +(declare-const |scc(3)_dn([3,7],31)| Bool) +(declare-const |scc(3)_dn([3,7],33)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],90)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],92)_dn([6,9],95)| Bool) +(declare-const |scc(4)_dn([2,3],35)| Bool) +(declare-const |scc(4)_dn([4,1],70)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],51)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],55)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],58)| Bool) +(declare-const |dn([7,Main.main],54)_dn([7,Main.main],59)| Bool) +(declare-const |dn([7,Main.main],54)_scc(1)| Bool) +(declare-const |dn([7,Main.main],54)_scc(7)| Bool) +(declare-const |scc(0)_dn([3,7],24)| Bool) +(declare-const |scc(0)_dn([2,3],34)| Bool) +(declare-const |dn([Main.main],109)_dn([Main.main],111)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],51)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],55)| Bool) +(declare-const |dn([7,Main.main],58)_dn([7,Main.main],59)| Bool) +(declare-const |dn([7,Main.main],58)_scc(1)| Bool) +(declare-const |dn([7,Main.main],58)_scc(7)| Bool) +(declare-const |dn([Main.main],104)_dn([7,Main.main],49)| Bool) +(declare-const |dn([Main.main],104)_dn([Main.main],105)| Bool) +(declare-const |dn([8,Main.main],101)_dn([8,Main.main],96)| Bool) +(declare-const |dn([8,Main.main],101)_dn([8,Main.main],97)| Bool) +(declare-const |dn([6,9],95)_dn([6,9],90)| Bool) +(declare-const |dn([6,9],95)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],95)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],95)_scc(1)| Bool) +(declare-const |dn([8,Main.main],96)_dn([8,Main.main],97)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],28)_dn([3,7],33)| Bool) +(declare-const |dn([3,7],28)_scc(6)| Bool) +(declare-const |dn([Main.main],106)_dn([7,Main.main],47)| Bool) +(declare-const |dn([2,3],36)_dn([3,7],31)| Bool) +(declare-const |dn([2,3],36)_dn([2,3],37)| Bool) +(declare-const |dn([4,1],78)_dn([4,1],79)| Bool) +(declare-const |dn([4,1],78)_scc(4)| Bool) +(declare-const |dn([Main.main],114)_dn([9,Main.main],83)| Bool) +(declare-const |dn([Main.main],114)_dn([Main.main],115)| Bool) +(declare-const |dn([2,3],35)_dn([3,7],33)| Bool) +(declare-const |dn([2,3],35)_dn([2,3],36)| Bool) +(declare-const |dn([2,3],38)_dn([2,3],34)| Bool) +(declare-const |dn([2,3],38)_dn([2,3],35)| Bool) +(declare-const |dn([5,1],63)_dn([5,1],61)| Bool) +(declare-const |dn([5,1],63)_dn([5,1],62)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],39)_dn([7,Main.main],58)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],33)_dn([3,7],31)| Bool) +(declare-const |dn([9,Main.main],88)_dn([9,Main.main],89)| Bool) +(declare-const |dn([4,1],80)_dn([4,1],81)| Bool) +(declare-const |dn([Main.main],116)_dn([Main.main],113)| Bool) +(declare-const |dn([Main.main],111)_dn([Main.main],102)| Bool) +(declare-const |dn([Main.main],111)_dn([Main.main],103)| Bool) +(declare-const |dn([7,Main.main],42)_dn([3,7],22)| Bool) +(declare-const |dn([7,Main.main],42)_dn([7,Main.main],43)| Bool) +(declare-const |dn([9,Main.main],85)_dn([9,Main.main],86)| Bool) +(declare-const |dn([9,Main.main],85)_dn([6,9],90)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],28)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],30)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],27)_dn([3,7],33)| Bool) +(declare-const |dn([1,3],64)_dn([1,3],65)| Bool) +(declare-const |dn([1,3],64)_dn([1,3],67)| Bool) +(declare-const |dn([9,Main.main],83)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],83)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],83)_dn([9,Main.main],88)| Bool) +(declare-const |dn([1,3],67)_dn([5,1],61)| Bool) +(declare-const |dn([1,3],67)_dn([1,3],68)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],40)_dn([7,Main.main],58)| Bool) +(declare-const |dn([3,7],25)_dn([1,3],67)| Bool) +(declare-const |dn([6,9],90)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],90)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],90)_dn([6,9],95)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],60)_dn([7,Main.main],58)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],51)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],55)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],58)| Bool) +(declare-const |dn([7,Main.main],50)_dn([7,Main.main],59)| Bool) +(declare-const |dn([7,Main.main],50)_scc(1)| Bool) +(declare-const |dn([7,Main.main],50)_scc(7)| Bool) +(declare-const |dn([5,1],62)_dn([5,1],61)| Bool) +(declare-const |dn([5,1],62)_dn([5,1],63)| Bool) +(declare-const |dn([5,1],62)_scc(2)| Bool) +(declare-const |dn([3,7],22)_dn([1,3],65)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],53)_dn([7,Main.main],58)| Bool) +(declare-const |dn([6,9],93)_dn([9,Main.main],88)| Bool) +(declare-const |dn([6,9],93)_dn([6,9],94)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],49)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],57)_dn([7,Main.main],58)| Bool) +(declare-const |dn([Main.main],108)_dn([8,Main.main],97)| Bool) +(declare-const |dn([Main.main],108)_dn([Main.main],109)| Bool) +(declare-const |dn([7,Main.main],55)_dn([6,9],95)| Bool) +(declare-const |scc(1)_dn([7,Main.main],39)| Bool) +(declare-const |scc(1)_dn([7,Main.main],47)| Bool) +(declare-const |scc(1)_dn([7,Main.main],49)| Bool) +(declare-const |scc(1)_dn([7,Main.main],50)| Bool) +(declare-const |scc(1)_dn([7,Main.main],51)| Bool) +(declare-const |scc(1)_dn([7,Main.main],54)| Bool) +(declare-const |scc(1)_dn([7,Main.main],55)| Bool) +(declare-const |scc(1)_dn([7,Main.main],57)| Bool) +(declare-const |scc(1)_dn([7,Main.main],58)| Bool) +(declare-const |scc(1)_dn([7,Main.main],59)| Bool) +(declare-const |scc(1)_dn([6,9],93)| Bool) +(declare-const |scc(1)_scc(7)| Bool) +(declare-const |dn([Main.main],105)_dn([7,Main.main],50)| Bool) +(declare-const |dn([Main.main],105)_dn([Main.main],106)| Bool) +(declare-const |scc(2)_dn([3,7],20)| Bool) +(declare-const |scc(2)_dn([3,7],22)| Bool) +(declare-const |scc(2)_dn([3,7],27)| Bool) +(declare-const |scc(2)_dn([3,7],29)| Bool) +(declare-const |scc(2)_dn([3,7],31)| Bool) +(declare-const |scc(2)_dn([3,7],33)| Bool) +(declare-const |dn([8,Main.main],97)_dn([3,7],27)| Bool) +(declare-const |dn([Main.main],103)_dn([7,Main.main],39)| Bool) +(declare-const |dn([Main.main],103)_dn([Main.main],104)| Bool) +(declare-const |scc(5)_dn([5,1],63)| Bool) +(declare-const |scc(5)_dn([8,Main.main],100)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],90)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],91)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],93)| Bool) +(declare-const |dn([6,9],94)_dn([6,9],95)| Bool) +(declare-const |dn([8,Main.main],100)_dn([4,1],78)| Bool) +(declare-const |dn([8,Main.main],100)_dn([8,Main.main],101)| Bool) +(declare-const |dn([7,Main.main],59)_dn([7,Main.main],60)| Bool) +(declare-const |dn([7,Main.main],59)_dn([6,9],95)| Bool) +(declare-const |dn([5,1],61)_dn([5,1],62)| Bool) +(declare-const |dn([5,1],61)_dn([5,1],63)| Bool) +(declare-const |dn([4,1],69)_dn([4,1],78)| Bool) +(declare-const |dn([4,1],69)_dn([4,1],80)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],28)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],30)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],29)_dn([3,7],33)| Bool) +(declare-const |dn([3,7],31)_dn([5,1],62)| Bool) +(declare-const |dn([Main.main],113)_dn([9,Main.main],82)| Bool) +(declare-const |dn([Main.main],113)_dn([Main.main],114)| Bool) +(declare-const |dn([4,1],79)_dn([4,1],69)| Bool) +(declare-const |dn([4,1],79)_dn([4,1],78)| Bool) +(declare-const |dn([4,1],79)_dn([4,1],80)| Bool) +(declare-const |dn([2,3],34)_dn([2,3],35)| Bool) +(declare-const |dn([Main.main],115)_dn([Main.main],111)| Bool) +(declare-const |dn([Main.main],115)_dn([Main.main],116)| Bool) +(declare-const |dn([2,3],37)_dn([2,3],38)| Bool) +(declare-const |dn([2,3],37)_dn([7,Main.main],58)| Bool) +(declare-const |dn([1,3],68)_dn([1,3],64)| Bool) +(declare-const |dn([1,3],68)_dn([1,3],65)| Bool) +(declare-const |dn([1,3],68)_dn([1,3],67)| Bool) +(declare-const |dn([4,1],81)_dn([4,1],69)| Bool) +(declare-const |dn([4,1],81)_dn([4,1],78)| Bool) +(declare-const |dn([4,1],81)_dn([4,1],80)| Bool) +(declare-const |scc(7)_dn([7,Main.main],39)| Bool) +(declare-const |scc(7)_dn([7,Main.main],47)| Bool) +(declare-const |scc(7)_dn([7,Main.main],49)| Bool) +(declare-const |scc(7)_dn([7,Main.main],50)| Bool) +(declare-const |scc(7)_dn([7,Main.main],51)| Bool) +(declare-const |scc(7)_dn([7,Main.main],53)| Bool) +(declare-const |scc(7)_dn([7,Main.main],54)| Bool) +(declare-const |scc(7)_dn([7,Main.main],55)| Bool) +(declare-const |scc(7)_dn([7,Main.main],58)| Bool) +(declare-const |scc(7)_dn([7,Main.main],59)| Bool) +(declare-const |scc(7)_scc(1)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],89)_dn([9,Main.main],88)| Bool) +(declare-const |dn([1,3],66)_dn([1,3],64)| Bool) +(declare-const |dn([1,3],66)_dn([1,3],65)| Bool) +(declare-const |dn([1,3],66)_dn([1,3],67)| Bool) +(declare-const |dn([1,3],66)_scc(0)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],85)| Bool) +(declare-const |dn([9,Main.main],84)_dn([9,Main.main],88)| Bool) +(declare-const |dn([1,3],65)_dn([1,3],66)| Bool) +(declare-const |dn([1,3],65)_dn([4,1],69)| Bool) +(declare-const |dn([7,Main.main],43)_dn([7,Main.main],40)| Bool) +(declare-const |dn([9,Main.main],82)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],82)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],82)_dn([9,Main.main],88)| Bool) +(declare-const |dn([7,Main.main],45)_dn([7,Main.main],40)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],30)_dn([3,7],33)| Bool) +(declare-const |dn([3,7],30)_scc(5)| Bool) +(declare-const |scc(8)_dn([8,Main.main],96)| Bool) +(declare-const |scc(8)_dn([Main.main],108)| Bool) +(declare-const |dn([9,Main.main],87)_dn([7,Main.main],53)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],82)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],83)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],84)| Bool) +(declare-const |dn([9,Main.main],87)_dn([9,Main.main],88)| Bool) +(declare-const |dn([9,Main.main],87)_scc(7)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],20)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],22)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],27)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],29)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],31)| Bool) +(declare-const |dn([3,7],21)_dn([3,7],33)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],39)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],47)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],50)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],54)| Bool) +(declare-const |dn([7,Main.main],49)_dn([7,Main.main],58)| Bool) +(declare-const |scc(6)_dn([3,7],29)| Bool) +(assert |dn([Main.main],113)|) +(assert (= |dn([7,Main.main],41)| (or |dn([7,Main.main],41)_dn([3,7],20)| |dn([7,Main.main],41)_dn([7,Main.main],42)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([7,Main.main],41)_dn([7,Main.main],42)|))) +(assert (not (and |dn([7,Main.main],41)_dn([7,Main.main],42)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (= |dn([3,7],24)| (or |dn([3,7],24)_dn([3,7],25)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([3,7],25)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([3,7],24)_dn([3,7],25)|))) +(assert (= |dn([7,Main.main],47)| (or |dn([7,Main.main],47)_dn([7,Main.main],41)| |dn([7,Main.main],47)_dn([7,Main.main],45)|))) +(assert (not (and |dn([7,Main.main],47)_dn([7,Main.main],41)| |dn([7,Main.main],47)_dn([7,Main.main],45)|))) +(assert (not (and |dn([7,Main.main],47)_dn([7,Main.main],45)| |dn([7,Main.main],47)_dn([7,Main.main],41)|))) +(assert (= |dn([9,Main.main],86)| (or |dn([9,Main.main],86)_dn([9,Main.main],87)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([9,Main.main],87)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([9,Main.main],86)_dn([9,Main.main],87)|))) +(assert (= |dn([7,Main.main],51)| (or |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (= |dn([3,7],20)| (or |dn([3,7],20)_dn([3,7],21)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([3,7],21)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([1,3],64)| |dn([3,7],20)_dn([3,7],21)|))) +(assert (= |dn([6,9],91)| (or |dn([6,9],91)_dn([7,Main.main],54)| |dn([6,9],91)_dn([6,9],92)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([6,9],91)_dn([6,9],92)|))) +(assert (not (and |dn([6,9],91)_dn([6,9],92)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (= |scc(3)| (or |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(3)_dn([3,7],31)|))) +(assert (= |dn([6,9],92)| (or |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (= |scc(4)| (or |scc(4)_dn([2,3],35)| |scc(4)_dn([4,1],70)|))) +(assert (not (and |scc(4)_dn([2,3],35)| |scc(4)_dn([4,1],70)|))) +(assert (not (and |scc(4)_dn([4,1],70)| |scc(4)_dn([2,3],35)|))) +(assert (= |dn([7,Main.main],54)| (or |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],54)_scc(1)|))) +(assert (= |scc(0)| (or |scc(0)_dn([3,7],24)| |scc(0)_dn([2,3],34)|))) +(assert (not (and |scc(0)_dn([3,7],24)| |scc(0)_dn([2,3],34)|))) +(assert (not (and |scc(0)_dn([2,3],34)| |scc(0)_dn([3,7],24)|))) +(assert (= |dn([Main.main],109)| (or |dn([Main.main],109)_dn([Main.main],111)|))) +(assert (= |dn([7,Main.main],58)| (or |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],58)_scc(1)|))) +(assert (= |dn([Main.main],104)| (or |dn([Main.main],104)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([Main.main],105)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([Main.main],105)|))) +(assert (not (and |dn([Main.main],104)_dn([Main.main],105)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not |dn([Main.main],102)|)) +(assert (= |dn([8,Main.main],101)| (or |dn([8,Main.main],101)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],96)|))) +(assert (= |dn([6,9],95)| (or |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (= |dn([8,Main.main],96)| (or |dn([8,Main.main],96)_dn([8,Main.main],97)|))) +(assert (= |dn([3,7],28)| (or |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],28)_scc(6)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_scc(6)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (= |dn([Main.main],106)| (or |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (= |dn([2,3],36)| (or |dn([2,3],36)_dn([3,7],31)| |dn([2,3],36)_dn([2,3],37)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([2,3],36)_dn([2,3],37)|))) +(assert (not (and |dn([2,3],36)_dn([2,3],37)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (= |dn([4,1],78)| (or |dn([4,1],78)_dn([4,1],79)| |dn([4,1],78)_scc(4)|))) +(assert (not (and |dn([4,1],78)_dn([4,1],79)| |dn([4,1],78)_scc(4)|))) +(assert (not (and |dn([4,1],78)_scc(4)| |dn([4,1],78)_dn([4,1],79)|))) +(assert (= |dn([Main.main],114)| (or |dn([Main.main],114)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([Main.main],115)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([Main.main],115)|))) +(assert (not (and |dn([Main.main],114)_dn([Main.main],115)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (= |dn([2,3],35)| (or |dn([2,3],35)_dn([3,7],33)| |dn([2,3],35)_dn([2,3],36)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([2,3],35)_dn([2,3],36)|))) +(assert (not (and |dn([2,3],35)_dn([2,3],36)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (= |dn([2,3],38)| (or |dn([2,3],38)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],34)|))) +(assert (= |dn([5,1],63)| (or |dn([5,1],63)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (= |dn([7,Main.main],39)| (or |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (= |dn([3,7],33)| (or |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (= |dn([9,Main.main],88)| (or |dn([9,Main.main],88)_dn([9,Main.main],89)|))) +(assert (= |dn([4,1],80)| (or |dn([4,1],80)_dn([4,1],81)|))) +(assert (= |dn([Main.main],116)| (or |dn([Main.main],116)_dn([Main.main],113)|))) +(assert (= |dn([Main.main],111)| (or |dn([Main.main],111)_dn([Main.main],102)| |dn([Main.main],111)_dn([Main.main],103)|))) +(assert (not (and |dn([Main.main],111)_dn([Main.main],102)| |dn([Main.main],111)_dn([Main.main],103)|))) +(assert (not (and |dn([Main.main],111)_dn([Main.main],103)| |dn([Main.main],111)_dn([Main.main],102)|))) +(assert (= |dn([7,Main.main],42)| (or |dn([7,Main.main],42)_dn([3,7],22)| |dn([7,Main.main],42)_dn([7,Main.main],43)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([7,Main.main],42)_dn([7,Main.main],43)|))) +(assert (not (and |dn([7,Main.main],42)_dn([7,Main.main],43)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (= |dn([9,Main.main],85)| (or |dn([9,Main.main],85)_dn([9,Main.main],86)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([9,Main.main],86)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([9,Main.main],85)_dn([9,Main.main],86)|))) +(assert (= |dn([3,7],27)| (or |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (= |dn([1,3],64)| (or |dn([1,3],64)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (= |dn([9,Main.main],83)| (or |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (= |dn([1,3],67)| (or |dn([1,3],67)_dn([5,1],61)| |dn([1,3],67)_dn([1,3],68)|))) +(assert (not (and |dn([1,3],67)_dn([5,1],61)| |dn([1,3],67)_dn([1,3],68)|))) +(assert (not (and |dn([1,3],67)_dn([1,3],68)| |dn([1,3],67)_dn([5,1],61)|))) +(assert (= |dn([7,Main.main],40)| (or |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (= |dn([3,7],25)| (or |dn([3,7],25)_dn([1,3],67)|))) +(assert (= |dn([6,9],90)| (or |dn([6,9],90)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (= |dn([7,Main.main],60)| (or |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (= |dn([7,Main.main],50)| (or |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],50)_scc(1)|))) +(assert (= |dn([5,1],62)| (or |dn([5,1],62)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],63)| |dn([5,1],62)_scc(2)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([5,1],62)_scc(2)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |dn([5,1],62)_scc(2)|))) +(assert (not (and |dn([5,1],62)_scc(2)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_scc(2)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (= |dn([3,7],22)| (or |dn([3,7],22)_dn([1,3],65)|))) +(assert (= |dn([7,Main.main],53)| (or |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (= |dn([6,9],93)| (or |dn([6,9],93)_dn([9,Main.main],88)| |dn([6,9],93)_dn([6,9],94)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([6,9],93)_dn([6,9],94)|))) +(assert (not (and |dn([6,9],93)_dn([6,9],94)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (= |dn([7,Main.main],57)| (or |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (= |dn([Main.main],108)| (or |dn([Main.main],108)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([Main.main],109)|))) +(assert (not (and |dn([Main.main],108)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([Main.main],109)|))) +(assert (not (and |dn([Main.main],108)_dn([Main.main],109)| |dn([Main.main],108)_dn([8,Main.main],97)|))) +(assert (= |dn([7,Main.main],55)| (or |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (= |scc(1)| (or |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([6,9],93)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],57)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |scc(1)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],57)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_scc(7)| |scc(1)_dn([6,9],93)|))) +(assert (= |dn([Main.main],105)| (or |dn([Main.main],105)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([Main.main],106)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([Main.main],106)|))) +(assert (not (and |dn([Main.main],105)_dn([Main.main],106)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (= |scc(2)| (or |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(2)_dn([3,7],31)|))) +(assert (= |dn([8,Main.main],97)| (or |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (= |dn([Main.main],103)| (or |dn([Main.main],103)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([Main.main],104)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([Main.main],104)|))) +(assert (not (and |dn([Main.main],103)_dn([Main.main],104)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (= |scc(5)| (or |scc(5)_dn([5,1],63)| |scc(5)_dn([8,Main.main],100)|))) +(assert (not (and |scc(5)_dn([5,1],63)| |scc(5)_dn([8,Main.main],100)|))) +(assert (not (and |scc(5)_dn([8,Main.main],100)| |scc(5)_dn([5,1],63)|))) +(assert (not |dn([4,1],70)|)) +(assert (= |dn([6,9],94)| (or |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (= |dn([8,Main.main],100)| (or |dn([8,Main.main],100)_dn([4,1],78)| |dn([8,Main.main],100)_dn([8,Main.main],101)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([8,Main.main],100)_dn([8,Main.main],101)|))) +(assert (not (and |dn([8,Main.main],100)_dn([8,Main.main],101)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (= |dn([7,Main.main],59)| (or |dn([7,Main.main],59)_dn([7,Main.main],60)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([7,Main.main],60)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([7,Main.main],59)_dn([7,Main.main],60)|))) +(assert (= |dn([5,1],61)| (or |dn([5,1],61)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],62)|))) +(assert (= |dn([4,1],69)| (or |dn([4,1],69)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (= |dn([3,7],29)| (or |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (= |dn([3,7],31)| (or |dn([3,7],31)_dn([5,1],62)|))) +(assert (= |dn([Main.main],113)| (or |dn([Main.main],113)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([Main.main],114)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([Main.main],114)|))) +(assert (not (and |dn([Main.main],113)_dn([Main.main],114)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (= |dn([4,1],79)| (or |dn([4,1],79)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (= |dn([2,3],34)| (or |dn([2,3],34)_dn([2,3],35)|))) +(assert (= |dn([Main.main],115)| (or |dn([Main.main],115)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],116)|))) +(assert (not (and |dn([Main.main],115)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],116)|))) +(assert (not (and |dn([Main.main],115)_dn([Main.main],116)| |dn([Main.main],115)_dn([Main.main],111)|))) +(assert (= |dn([2,3],37)| (or |dn([2,3],37)_dn([2,3],38)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([2,3],38)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([2,3],37)_dn([2,3],38)|))) +(assert (= |dn([1,3],68)| (or |dn([1,3],68)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (= |dn([4,1],81)| (or |dn([4,1],81)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (= |scc(7)| (or |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],59)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(7)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_scc(1)| |scc(7)_dn([7,Main.main],59)|))) +(assert (= |dn([9,Main.main],89)| (or |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (= |dn([1,3],66)| (or |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],66)_scc(0)|))) +(assert (not (and |dn([1,3],66)_scc(0)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_scc(0)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_scc(0)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (= |dn([9,Main.main],84)| (or |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],85)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (= |dn([1,3],65)| (or |dn([1,3],65)_dn([1,3],66)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([1,3],66)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([4,1],69)| |dn([1,3],65)_dn([1,3],66)|))) +(assert (= |dn([7,Main.main],43)| (or |dn([7,Main.main],43)_dn([7,Main.main],40)|))) +(assert (= |dn([9,Main.main],82)| (or |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (= |dn([7,Main.main],45)| (or |dn([7,Main.main],45)_dn([7,Main.main],40)|))) +(assert (= |dn([3,7],30)| (or |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],30)_scc(5)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_scc(5)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (= |scc(8)| (or |scc(8)_dn([8,Main.main],96)| |scc(8)_dn([Main.main],108)|))) +(assert (not (and |scc(8)_dn([8,Main.main],96)| |scc(8)_dn([Main.main],108)|))) +(assert (not (and |scc(8)_dn([Main.main],108)| |scc(8)_dn([8,Main.main],96)|))) +(assert (= |dn([9,Main.main],87)| (or |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (= |dn([7,Main.main],49)| (or |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (= |scc(6)| (or |scc(6)_dn([3,7],29)|))) +(assert (= |dn([7,Main.main],41)| (or |dn([7,Main.main],47)_dn([7,Main.main],41)|))) +(assert (= |dn([3,7],24)| (or |scc(0)_dn([3,7],24)|))) +(assert (= |dn([7,Main.main],47)| (or |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([Main.main],106)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |scc(1)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |scc(7)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],47)| |dn([7,Main.main],58)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([Main.main],106)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],39)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],40)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],49)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],53)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],57)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],60)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |scc(1)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |scc(7)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],50)_dn([7,Main.main],47)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],47)| |dn([7,Main.main],54)_dn([7,Main.main],47)|))) +(assert (= |dn([9,Main.main],86)| (or |dn([9,Main.main],85)_dn([9,Main.main],86)|))) +(assert (= |dn([7,Main.main],51)| (or |dn([7,Main.main],50)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |scc(1)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (not (and |scc(7)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],51)| |dn([7,Main.main],58)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],50)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |scc(1)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |scc(7)_dn([7,Main.main],51)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],51)| |dn([7,Main.main],54)_dn([7,Main.main],51)|))) +(assert (= |dn([3,7],20)| (or |dn([7,Main.main],41)_dn([3,7],20)| |scc(2)_dn([3,7],20)| |scc(3)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([7,Main.main],41)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |scc(2)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |scc(3)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],20)| |dn([3,7],29)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([7,Main.main],41)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |scc(2)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |scc(3)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],21)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],28)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],30)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],33)_dn([3,7],20)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],20)| |dn([3,7],27)_dn([3,7],20)|))) +(assert (= |dn([6,9],91)| (or |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([9,Main.main],86)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],91)| |dn([6,9],95)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([9,Main.main],86)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],90)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],92)_dn([6,9],91)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],91)| |dn([6,9],94)_dn([6,9],91)|))) +(assert (not |scc(3)|)) +(assert (= |dn([6,9],92)| (or |dn([6,9],91)_dn([6,9],92)|))) +(assert (= |scc(4)| (or |dn([4,1],78)_scc(4)|))) +(assert (= |dn([7,Main.main],54)| (or |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([6,9],91)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |scc(1)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (not (and |scc(7)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],54)| |dn([7,Main.main],58)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([6,9],91)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],39)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],40)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],49)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],53)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],57)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],60)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |scc(1)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |scc(7)_dn([7,Main.main],54)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],54)| |dn([7,Main.main],50)_dn([7,Main.main],54)|))) +(assert (= |scc(0)| (or |dn([1,3],66)_scc(0)|))) +(assert (= |dn([Main.main],109)| (or |dn([Main.main],108)_dn([Main.main],109)|))) +(assert (= |dn([7,Main.main],58)| (or |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([2,3],37)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |scc(1)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (not (and |scc(7)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],58)| |dn([7,Main.main],54)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([2,3],37)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],39)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],40)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],49)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],53)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],57)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],60)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |scc(1)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |scc(7)_dn([7,Main.main],58)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],58)| |dn([7,Main.main],50)_dn([7,Main.main],58)|))) +(assert (= |dn([Main.main],104)| (or |dn([Main.main],103)_dn([Main.main],104)|))) +(assert (= |dn([Main.main],102)| (or |dn([Main.main],111)_dn([Main.main],102)|))) +(assert (= |dn([8,Main.main],101)| (or |dn([8,Main.main],100)_dn([8,Main.main],101)|))) +(assert (= |dn([6,9],95)| (or |dn([7,Main.main],55)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],55)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([7,Main.main],59)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],95)| |dn([6,9],94)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([7,Main.main],55)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([7,Main.main],59)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],90)_dn([6,9],95)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],95)| |dn([6,9],92)_dn([6,9],95)|))) +(assert (= |dn([8,Main.main],96)| (or |scc(8)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],96)|))) +(assert (not (and |scc(8)_dn([8,Main.main],96)| |dn([8,Main.main],101)_dn([8,Main.main],96)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],96)| |scc(8)_dn([8,Main.main],96)|))) +(assert (= |dn([3,7],28)| (or |dn([3,7],27)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],28)| |dn([3,7],29)_dn([3,7],28)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],28)| |dn([3,7],27)_dn([3,7],28)|))) +(assert (= |dn([Main.main],106)| (or |dn([Main.main],105)_dn([Main.main],106)|))) +(assert (= |dn([2,3],36)| (or |dn([2,3],35)_dn([2,3],36)|))) +(assert (= |dn([4,1],78)| (or |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (not (and |dn([8,Main.main],100)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],78)| |dn([4,1],81)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([8,Main.main],100)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],69)_dn([4,1],78)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],78)| |dn([4,1],79)_dn([4,1],78)|))) +(assert (= |dn([Main.main],114)| (or |dn([Main.main],113)_dn([Main.main],114)|))) +(assert (= |dn([2,3],35)| (or |scc(4)_dn([2,3],35)| |dn([2,3],34)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |scc(4)_dn([2,3],35)| |dn([2,3],34)_dn([2,3],35)|))) +(assert (not (and |scc(4)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],34)_dn([2,3],35)| |scc(4)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],34)_dn([2,3],35)| |dn([2,3],38)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],35)| |scc(4)_dn([2,3],35)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],35)| |dn([2,3],34)_dn([2,3],35)|))) +(assert (= |dn([2,3],38)| (or |dn([2,3],37)_dn([2,3],38)|))) +(assert (= |dn([5,1],63)| (or |scc(5)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |scc(5)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (not (and |scc(5)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],63)| |scc(5)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],63)| |dn([5,1],62)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |scc(5)_dn([5,1],63)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],63)| |dn([5,1],61)_dn([5,1],63)|))) +(assert (= |dn([7,Main.main],39)| (or |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([Main.main],103)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |scc(1)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |scc(7)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],39)| |dn([7,Main.main],58)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([Main.main],103)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],40)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],49)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],53)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],57)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],60)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |scc(1)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |scc(7)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],50)_dn([7,Main.main],39)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],39)| |dn([7,Main.main],54)_dn([7,Main.main],39)|))) +(assert (= |dn([3,7],33)| (or |dn([2,3],35)_dn([3,7],33)| |scc(2)_dn([3,7],33)| |scc(3)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([2,3],35)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |scc(2)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |scc(3)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],33)| |dn([3,7],29)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([2,3],35)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |scc(2)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |scc(3)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],21)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],28)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],30)_dn([3,7],33)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],33)| |dn([3,7],27)_dn([3,7],33)|))) +(assert (= |dn([9,Main.main],88)| (or |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([6,9],93)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],88)| |dn([9,Main.main],84)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([6,9],93)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],82)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],83)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],87)_dn([9,Main.main],88)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],88)| |dn([9,Main.main],89)_dn([9,Main.main],88)|))) +(assert (= |dn([4,1],80)| (or |dn([3,7],24)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([3,7],24)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],69)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],80)| |dn([4,1],81)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([3,7],24)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],69)_dn([4,1],80)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],80)| |dn([4,1],79)_dn([4,1],80)|))) +(assert (= |dn([Main.main],116)| (or |dn([Main.main],115)_dn([Main.main],116)|))) +(assert (= |dn([Main.main],111)| (or |dn([Main.main],109)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],111)|))) +(assert (not (and |dn([Main.main],109)_dn([Main.main],111)| |dn([Main.main],115)_dn([Main.main],111)|))) +(assert (not (and |dn([Main.main],115)_dn([Main.main],111)| |dn([Main.main],109)_dn([Main.main],111)|))) +(assert (= |dn([7,Main.main],42)| (or |dn([7,Main.main],41)_dn([7,Main.main],42)|))) +(assert (= |dn([9,Main.main],85)| (or |dn([9,Main.main],84)_dn([9,Main.main],85)|))) +(assert (= |dn([3,7],27)| (or |dn([8,Main.main],97)_dn([3,7],27)| |scc(2)_dn([3,7],27)| |scc(3)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([8,Main.main],97)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |scc(2)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |scc(3)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],27)| |dn([3,7],29)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([8,Main.main],97)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |scc(2)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |scc(3)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],21)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],28)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],30)_dn([3,7],27)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],27)| |dn([3,7],33)_dn([3,7],27)|))) +(assert (= |dn([1,3],64)| (or |dn([3,7],20)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (not (and |dn([3,7],20)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],64)| |dn([1,3],68)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([3,7],20)_dn([1,3],64)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],64)| |dn([1,3],66)_dn([1,3],64)|))) +(assert (= |dn([9,Main.main],83)| (or |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([Main.main],114)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],83)| |dn([9,Main.main],84)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([Main.main],114)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],82)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],87)_dn([9,Main.main],83)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],83)| |dn([9,Main.main],89)_dn([9,Main.main],83)|))) +(assert (= |dn([1,3],67)| (or |dn([3,7],25)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([3,7],25)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([3,7],25)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([3,7],25)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([3,7],25)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([3,7],25)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],67)| |dn([1,3],68)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([3,7],25)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],64)_dn([1,3],67)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],67)| |dn([1,3],66)_dn([1,3],67)|))) +(assert (= |dn([7,Main.main],40)| (or |dn([7,Main.main],43)_dn([7,Main.main],40)| |dn([7,Main.main],45)_dn([7,Main.main],40)|))) +(assert (not (and |dn([7,Main.main],43)_dn([7,Main.main],40)| |dn([7,Main.main],45)_dn([7,Main.main],40)|))) +(assert (not (and |dn([7,Main.main],45)_dn([7,Main.main],40)| |dn([7,Main.main],43)_dn([7,Main.main],40)|))) +(assert (= |dn([3,7],25)| (or |dn([3,7],24)_dn([3,7],25)|))) +(assert (= |dn([6,9],90)| (or |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([9,Main.main],85)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],90)| |dn([6,9],95)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([9,Main.main],85)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],92)_dn([6,9],90)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],90)| |dn([6,9],94)_dn([6,9],90)|))) +(assert (= |dn([7,Main.main],60)| (or |dn([7,Main.main],59)_dn([7,Main.main],60)|))) +(assert (= |dn([7,Main.main],50)| (or |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([Main.main],105)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],49)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |scc(1)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (not (and |scc(7)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],50)| |dn([7,Main.main],58)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([Main.main],105)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],39)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],40)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],49)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],53)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],57)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],60)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |scc(1)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |scc(7)_dn([7,Main.main],50)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],50)| |dn([7,Main.main],54)_dn([7,Main.main],50)|))) +(assert (= |dn([5,1],62)| (or |dn([3,7],31)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([3,7],31)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],62)|))) +(assert (not (and |dn([3,7],31)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],62)| |dn([3,7],31)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],61)_dn([5,1],62)| |dn([5,1],63)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],62)| |dn([3,7],31)_dn([5,1],62)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],62)| |dn([5,1],61)_dn([5,1],62)|))) +(assert (= |dn([3,7],22)| (or |dn([7,Main.main],42)_dn([3,7],22)| |scc(2)_dn([3,7],22)| |scc(3)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([7,Main.main],42)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |scc(2)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |scc(3)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],22)| |dn([3,7],29)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([7,Main.main],42)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |scc(2)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |scc(3)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],21)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],28)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],30)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],33)_dn([3,7],22)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],22)| |dn([3,7],27)_dn([3,7],22)|))) +(assert (= |dn([7,Main.main],53)| (or |dn([9,Main.main],87)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |dn([9,Main.main],87)_dn([7,Main.main],53)| |scc(7)_dn([7,Main.main],53)|))) +(assert (not (and |scc(7)_dn([7,Main.main],53)| |dn([9,Main.main],87)_dn([7,Main.main],53)|))) +(assert (= |dn([6,9],93)| (or |scc(1)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |scc(1)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],90)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],92)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],94)_dn([6,9],93)| |dn([6,9],95)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |scc(1)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],90)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],92)_dn([6,9],93)|))) +(assert (not (and |dn([6,9],95)_dn([6,9],93)| |dn([6,9],94)_dn([6,9],93)|))) +(assert (= |dn([7,Main.main],57)| (or |scc(1)_dn([7,Main.main],57)|))) +(assert (= |dn([Main.main],108)| (or |scc(8)_dn([Main.main],108)|))) +(assert (= |dn([7,Main.main],55)| (or |dn([7,Main.main],54)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |scc(1)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (not (and |scc(7)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],55)| |dn([7,Main.main],58)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],54)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |scc(1)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |scc(7)_dn([7,Main.main],55)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],55)| |dn([7,Main.main],50)_dn([7,Main.main],55)|))) +(assert (= |scc(1)| (or |dn([6,9],95)_scc(1)| |scc(7)_scc(1)| |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([6,9],95)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |scc(7)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (not (and |dn([7,Main.main],50)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],54)_scc(1)| |dn([7,Main.main],58)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([6,9],95)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |scc(7)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],50)_scc(1)|))) +(assert (not (and |dn([7,Main.main],58)_scc(1)| |dn([7,Main.main],54)_scc(1)|))) +(assert (= |dn([Main.main],105)| (or |dn([Main.main],104)_dn([Main.main],105)|))) +(assert (= |scc(2)| (or |dn([5,1],62)_scc(2)|))) +(assert (= |dn([8,Main.main],97)| (or |dn([Main.main],108)_dn([8,Main.main],97)| |dn([8,Main.main],96)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([Main.main],108)_dn([8,Main.main],97)| |dn([8,Main.main],96)_dn([8,Main.main],97)|))) +(assert (not (and |dn([Main.main],108)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],96)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],96)_dn([8,Main.main],97)| |dn([8,Main.main],101)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],97)| |dn([Main.main],108)_dn([8,Main.main],97)|))) +(assert (not (and |dn([8,Main.main],101)_dn([8,Main.main],97)| |dn([8,Main.main],96)_dn([8,Main.main],97)|))) +(assert (= |dn([Main.main],103)| (or |dn([Main.main],111)_dn([Main.main],103)|))) +(assert (= |scc(5)| (or |dn([3,7],30)_scc(5)|))) +(assert (= |dn([4,1],70)| (or |scc(4)_dn([4,1],70)|))) +(assert (= |dn([6,9],94)| (or |dn([6,9],93)_dn([6,9],94)|))) +(assert (= |dn([8,Main.main],100)| (or |scc(5)_dn([8,Main.main],100)|))) +(assert (= |dn([7,Main.main],59)| (or |dn([7,Main.main],58)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |scc(1)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (not (and |scc(7)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],59)| |dn([7,Main.main],54)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],58)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |scc(1)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |scc(7)_dn([7,Main.main],59)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],59)| |dn([7,Main.main],50)_dn([7,Main.main],59)|))) +(assert (= |dn([5,1],61)| (or |dn([1,3],67)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (not (and |dn([1,3],67)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (not (and |dn([1,3],67)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([1,3],67)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],62)_dn([5,1],61)| |dn([5,1],63)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],61)| |dn([1,3],67)_dn([5,1],61)|))) +(assert (not (and |dn([5,1],63)_dn([5,1],61)| |dn([5,1],62)_dn([5,1],61)|))) +(assert (= |dn([4,1],69)| (or |dn([1,3],65)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (not (and |dn([1,3],65)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],79)_dn([4,1],69)| |dn([4,1],81)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([1,3],65)_dn([4,1],69)|))) +(assert (not (and |dn([4,1],81)_dn([4,1],69)| |dn([4,1],79)_dn([4,1],69)|))) +(assert (= |dn([3,7],29)| (or |scc(6)_dn([3,7],29)| |scc(2)_dn([3,7],29)| |scc(3)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |scc(6)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |scc(2)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |scc(3)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],29)| |dn([3,7],27)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |scc(6)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |scc(2)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |scc(3)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],21)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],28)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],30)_dn([3,7],29)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],29)| |dn([3,7],33)_dn([3,7],29)|))) +(assert (= |dn([3,7],31)| (or |dn([2,3],36)_dn([3,7],31)| |scc(2)_dn([3,7],31)| |scc(3)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([2,3],36)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |scc(2)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |scc(3)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],21)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],28)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],30)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],33)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],31)| |dn([3,7],29)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([2,3],36)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |scc(2)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |scc(3)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],21)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],28)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],30)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],33)_dn([3,7],31)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],31)| |dn([3,7],27)_dn([3,7],31)|))) +(assert (= |dn([4,1],79)| (or |dn([4,1],78)_dn([4,1],79)|))) +(assert (= |dn([2,3],34)| (or |scc(0)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],34)|))) +(assert (not (and |scc(0)_dn([2,3],34)| |dn([2,3],38)_dn([2,3],34)|))) +(assert (not (and |dn([2,3],38)_dn([2,3],34)| |scc(0)_dn([2,3],34)|))) +(assert (= |dn([Main.main],115)| (or |dn([Main.main],114)_dn([Main.main],115)|))) +(assert (= |dn([2,3],37)| (or |dn([2,3],36)_dn([2,3],37)|))) +(assert (= |dn([1,3],68)| (or |dn([1,3],67)_dn([1,3],68)|))) +(assert (= |dn([4,1],81)| (or |dn([4,1],80)_dn([4,1],81)|))) +(assert (= |scc(7)| (or |dn([9,Main.main],87)_scc(7)| |scc(1)_scc(7)| |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([9,Main.main],87)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |scc(1)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (not (and |dn([7,Main.main],50)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],54)_scc(7)| |dn([7,Main.main],58)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([9,Main.main],87)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |scc(1)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],50)_scc(7)|))) +(assert (not (and |dn([7,Main.main],58)_scc(7)| |dn([7,Main.main],54)_scc(7)|))) +(assert (= |dn([9,Main.main],89)| (or |dn([9,Main.main],88)_dn([9,Main.main],89)|))) +(assert (= |dn([1,3],66)| (or |dn([1,3],65)_dn([1,3],66)|))) +(assert (= |dn([9,Main.main],84)| (or |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([7,Main.main],51)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],82)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],84)| |dn([9,Main.main],89)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([7,Main.main],51)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],82)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],83)_dn([9,Main.main],84)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],84)| |dn([9,Main.main],87)_dn([9,Main.main],84)|))) +(assert (= |dn([1,3],65)| (or |dn([3,7],22)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([3,7],22)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (not (and |dn([3,7],22)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([3,7],22)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([3,7],22)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],64)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([3,7],22)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],66)_dn([1,3],65)| |dn([1,3],68)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([3,7],22)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],64)_dn([1,3],65)|))) +(assert (not (and |dn([1,3],68)_dn([1,3],65)| |dn([1,3],66)_dn([1,3],65)|))) +(assert (= |dn([7,Main.main],43)| (or |dn([7,Main.main],42)_dn([7,Main.main],43)|))) +(assert (= |dn([9,Main.main],82)| (or |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([Main.main],113)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],83)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],87)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],89)_dn([9,Main.main],82)| |dn([9,Main.main],84)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([Main.main],113)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],83)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],87)_dn([9,Main.main],82)|))) +(assert (not (and |dn([9,Main.main],84)_dn([9,Main.main],82)| |dn([9,Main.main],89)_dn([9,Main.main],82)|))) +(assert (= |dn([7,Main.main],45)| (or |dn([7,Main.main],47)_dn([7,Main.main],45)|))) +(assert (= |dn([3,7],30)| (or |dn([3,7],29)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],29)_dn([3,7],30)| |dn([3,7],27)_dn([3,7],30)|))) +(assert (not (and |dn([3,7],27)_dn([3,7],30)| |dn([3,7],29)_dn([3,7],30)|))) +(assert (not |scc(8)|)) +(assert (= |dn([9,Main.main],87)| (or |dn([9,Main.main],86)_dn([9,Main.main],87)|))) +(assert (= |dn([3,7],21)| (or |dn([3,7],20)_dn([3,7],21)|))) +(assert (= |dn([7,Main.main],49)| (or |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([Main.main],104)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],39)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],40)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],53)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],57)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],60)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |scc(1)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |scc(7)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],50)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],54)_dn([7,Main.main],49)| |dn([7,Main.main],58)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([Main.main],104)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],39)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],40)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],53)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],57)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],60)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |scc(1)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |scc(7)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],50)_dn([7,Main.main],49)|))) +(assert (not (and |dn([7,Main.main],58)_dn([7,Main.main],49)| |dn([7,Main.main],54)_dn([7,Main.main],49)|))) +(assert (= |scc(6)| (or |dn([3,7],28)_scc(6)|))) +(assert-soft |dn([7,Main.main],41)_dn([3,7],20)| :weight 1) +(assert-soft |scc(2)_dn([3,7],20)| :weight 1) +(assert-soft |scc(3)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],33)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],20)| :weight 1) +(assert-soft |dn([3,7],20)_dn([3,7],21)| :weight 1) +(assert-soft |dn([7,Main.main],42)_dn([3,7],22)| :weight 1) +(assert-soft |scc(2)_dn([3,7],22)| :weight 1) +(assert-soft |scc(3)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],33)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],22)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],22)| :weight 1) +(assert-soft |scc(0)_dn([3,7],24)| :weight 1) +(assert-soft |dn([3,7],24)_dn([3,7],25)| :weight 1) +(assert-soft |dn([8,Main.main],97)_dn([3,7],27)| :weight 2) +(assert-soft |scc(2)_dn([3,7],27)| :weight 2) +(assert-soft |scc(3)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],21)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],28)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],30)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],33)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],29)_dn([3,7],27)| :weight 2) +(assert-soft |dn([3,7],27)_dn([3,7],28)| :weight 6) +(assert-soft |dn([3,7],29)_dn([3,7],28)| :weight 6) +(assert-soft |scc(6)_dn([3,7],29)| :weight 2) +(assert-soft |scc(2)_dn([3,7],29)| :weight 2) +(assert-soft |scc(3)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],21)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],28)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],30)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],33)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],27)_dn([3,7],29)| :weight 2) +(assert-soft |dn([3,7],29)_dn([3,7],30)| :weight 6) +(assert-soft |dn([3,7],27)_dn([3,7],30)| :weight 6) +(assert-soft |dn([2,3],36)_dn([3,7],31)| :weight 1) +(assert-soft |scc(2)_dn([3,7],31)| :weight 1) +(assert-soft |scc(3)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],33)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],31)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],31)| :weight 1) +(assert-soft |dn([2,3],35)_dn([3,7],33)| :weight 1) +(assert-soft |scc(2)_dn([3,7],33)| :weight 1) +(assert-soft |scc(3)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],21)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],28)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],30)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],27)_dn([3,7],33)| :weight 1) +(assert-soft |dn([3,7],29)_dn([3,7],33)| :weight 1) +(assert-soft |scc(0)_dn([2,3],34)| :weight 1) +(assert-soft |dn([2,3],38)_dn([2,3],34)| :weight 1) +(assert-soft |scc(4)_dn([2,3],35)| :weight 1) +(assert-soft |dn([2,3],34)_dn([2,3],35)| :weight 1) +(assert-soft |dn([2,3],38)_dn([2,3],35)| :weight 1) +(assert-soft |dn([2,3],35)_dn([2,3],36)| :weight 1) +(assert-soft |dn([2,3],36)_dn([2,3],37)| :weight 1) +(assert-soft |dn([2,3],37)_dn([2,3],38)| :weight 1) +(assert-soft |dn([Main.main],103)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],39)| :weight 6) +(assert-soft |scc(1)_dn([7,Main.main],39)| :weight 6) +(assert-soft |scc(7)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],39)| :weight 6) +(assert-soft |dn([7,Main.main],43)_dn([7,Main.main],40)| :weight 4) +(assert-soft |dn([7,Main.main],45)_dn([7,Main.main],40)| :weight 4) +(assert-soft |dn([7,Main.main],47)_dn([7,Main.main],41)| :weight 1) +(assert-soft |dn([7,Main.main],41)_dn([7,Main.main],42)| :weight 1) +(assert-soft |dn([7,Main.main],42)_dn([7,Main.main],43)| :weight 1) +(assert-soft |dn([7,Main.main],47)_dn([7,Main.main],45)| :weight 4) +(assert-soft |dn([Main.main],106)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],47)| :weight 8) +(assert-soft |scc(1)_dn([7,Main.main],47)| :weight 8) +(assert-soft |scc(7)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],47)| :weight 8) +(assert-soft |dn([Main.main],104)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],49)| :weight 8) +(assert-soft |scc(1)_dn([7,Main.main],49)| :weight 8) +(assert-soft |scc(7)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],49)| :weight 8) +(assert-soft |dn([Main.main],105)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],50)| :weight 2) +(assert-soft |scc(1)_dn([7,Main.main],50)| :weight 2) +(assert-soft |scc(7)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],50)| :weight 2) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],51)| :weight 6) +(assert-soft |scc(1)_dn([7,Main.main],51)| :weight 6) +(assert-soft |scc(7)_dn([7,Main.main],51)| :weight 6) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],51)| :weight 6) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],51)| :weight 6) +(assert-soft |dn([9,Main.main],87)_dn([7,Main.main],53)| :weight 6) +(assert-soft |scc(7)_dn([7,Main.main],53)| :weight 6) +(assert-soft |dn([6,9],91)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],54)| :weight 2) +(assert-soft |scc(1)_dn([7,Main.main],54)| :weight 2) +(assert-soft |scc(7)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],54)| :weight 2) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],55)| :weight 18) +(assert-soft |scc(1)_dn([7,Main.main],55)| :weight 18) +(assert-soft |scc(7)_dn([7,Main.main],55)| :weight 18) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],55)| :weight 18) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],55)| :weight 18) +(assert-soft |scc(1)_dn([7,Main.main],57)| :weight 4) +(assert-soft |dn([2,3],37)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],39)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],40)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],49)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],53)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],57)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],60)_dn([7,Main.main],58)| :weight 1) +(assert-soft |scc(1)_dn([7,Main.main],58)| :weight 1) +(assert-soft |scc(7)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],58)| :weight 1) +(assert-soft |dn([7,Main.main],58)_dn([7,Main.main],59)| :weight 1) +(assert-soft |scc(1)_dn([7,Main.main],59)| :weight 1) +(assert-soft |scc(7)_dn([7,Main.main],59)| :weight 1) +(assert-soft |dn([7,Main.main],50)_dn([7,Main.main],59)| :weight 1) +(assert-soft |dn([7,Main.main],54)_dn([7,Main.main],59)| :weight 1) +(assert-soft |dn([7,Main.main],59)_dn([7,Main.main],60)| :weight 1) +(assert-soft |dn([1,3],67)_dn([5,1],61)| :weight 1) +(assert-soft |dn([5,1],62)_dn([5,1],61)| :weight 1) +(assert-soft |dn([5,1],63)_dn([5,1],61)| :weight 1) +(assert-soft |dn([3,7],31)_dn([5,1],62)| :weight 1) +(assert-soft |dn([5,1],61)_dn([5,1],62)| :weight 1) +(assert-soft |dn([5,1],63)_dn([5,1],62)| :weight 1) +(assert-soft |scc(5)_dn([5,1],63)| :weight 8) +(assert-soft |dn([5,1],61)_dn([5,1],63)| :weight 8) +(assert-soft |dn([5,1],62)_dn([5,1],63)| :weight 8) +(assert-soft |dn([3,7],20)_dn([1,3],64)| :weight 1) +(assert-soft |dn([1,3],66)_dn([1,3],64)| :weight 1) +(assert-soft |dn([1,3],68)_dn([1,3],64)| :weight 1) +(assert-soft |dn([3,7],22)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],64)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],66)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],68)_dn([1,3],65)| :weight 1) +(assert-soft |dn([1,3],65)_dn([1,3],66)| :weight 1) +(assert-soft |dn([3,7],25)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],64)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],66)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],68)_dn([1,3],67)| :weight 1) +(assert-soft |dn([1,3],67)_dn([1,3],68)| :weight 1) +(assert-soft |dn([1,3],65)_dn([4,1],69)| :weight 1) +(assert-soft |dn([4,1],79)_dn([4,1],69)| :weight 1) +(assert-soft |dn([4,1],81)_dn([4,1],69)| :weight 1) +(assert-soft |scc(4)_dn([4,1],70)| :weight 2) +(assert-soft |dn([8,Main.main],100)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],69)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],79)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],81)_dn([4,1],78)| :weight 6) +(assert-soft |dn([4,1],78)_dn([4,1],79)| :weight 4) +(assert-soft |dn([3,7],24)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],69)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],79)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],81)_dn([4,1],80)| :weight 1) +(assert-soft |dn([4,1],80)_dn([4,1],81)| :weight 1) +(assert-soft |dn([Main.main],113)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],83)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],82)| :weight 4) +(assert-soft |dn([Main.main],114)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],82)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],83)| :weight 4) +(assert-soft |dn([7,Main.main],51)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],82)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],83)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],84)| :weight 2) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],85)| :weight 6) +(assert-soft |dn([9,Main.main],85)_dn([9,Main.main],86)| :weight 6) +(assert-soft |dn([9,Main.main],86)_dn([9,Main.main],87)| :weight 2) +(assert-soft |dn([6,9],93)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],82)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],83)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],87)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],89)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],84)_dn([9,Main.main],88)| :weight 6) +(assert-soft |dn([9,Main.main],88)_dn([9,Main.main],89)| :weight 6) +(assert-soft |dn([9,Main.main],85)_dn([6,9],90)| :weight 8) +(assert-soft |dn([6,9],92)_dn([6,9],90)| :weight 8) +(assert-soft |dn([6,9],94)_dn([6,9],90)| :weight 8) +(assert-soft |dn([6,9],95)_dn([6,9],90)| :weight 8) +(assert-soft |dn([9,Main.main],86)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],90)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],92)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],94)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],95)_dn([6,9],91)| :weight 8) +(assert-soft |dn([6,9],91)_dn([6,9],92)| :weight 4) +(assert-soft |scc(1)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],90)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],92)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],94)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],95)_dn([6,9],93)| :weight 6) +(assert-soft |dn([6,9],93)_dn([6,9],94)| :weight 4) +(assert-soft |dn([7,Main.main],55)_dn([6,9],95)| :weight 6) +(assert-soft |dn([7,Main.main],59)_dn([6,9],95)| :weight 6) +(assert-soft |dn([6,9],90)_dn([6,9],95)| :weight 6) +(assert-soft |dn([6,9],92)_dn([6,9],95)| :weight 6) +(assert-soft |dn([6,9],94)_dn([6,9],95)| :weight 6) +(assert-soft |scc(8)_dn([8,Main.main],96)| :weight 4) +(assert-soft |dn([8,Main.main],101)_dn([8,Main.main],96)| :weight 4) +(assert-soft |dn([Main.main],108)_dn([8,Main.main],97)| :weight 8) +(assert-soft |dn([8,Main.main],96)_dn([8,Main.main],97)| :weight 8) +(assert-soft |dn([8,Main.main],101)_dn([8,Main.main],97)| :weight 8) +(assert-soft |scc(5)_dn([8,Main.main],100)| :weight 4) +(assert-soft |dn([8,Main.main],100)_dn([8,Main.main],101)| :weight 4) +(assert-soft |dn([Main.main],111)_dn([Main.main],102)| :weight 1) +(assert-soft |dn([Main.main],111)_dn([Main.main],103)| :weight 6) +(assert-soft |dn([Main.main],103)_dn([Main.main],104)| :weight 2) +(assert-soft |dn([Main.main],104)_dn([Main.main],105)| :weight 2) +(assert-soft |dn([Main.main],105)_dn([Main.main],106)| :weight 2) +(assert-soft |scc(8)_dn([Main.main],108)| :weight 2) +(assert-soft |dn([Main.main],108)_dn([Main.main],109)| :weight 6) +(assert-soft |dn([Main.main],109)_dn([Main.main],111)| :weight 6) +(assert-soft |dn([Main.main],115)_dn([Main.main],111)| :weight 6) +(assert-soft |dn([Main.main],116)_dn([Main.main],113)| :weight 3) +(assert-soft |dn([Main.main],113)_dn([Main.main],114)| :weight 1) +(assert-soft |dn([Main.main],114)_dn([Main.main],115)| :weight 1) +(assert-soft |dn([Main.main],115)_dn([Main.main],116)| :weight 2) +(assert-soft |dn([1,3],66)_scc(0)| :weight 1) +(assert-soft |dn([6,9],95)_scc(1)| :weight 6) +(assert-soft |scc(7)_scc(1)| :weight 6) +(assert-soft |dn([7,Main.main],50)_scc(1)| :weight 6) +(assert-soft |dn([7,Main.main],54)_scc(1)| :weight 6) +(assert-soft |dn([7,Main.main],58)_scc(1)| :weight 6) +(assert-soft |dn([5,1],62)_scc(2)| :weight 1) +(assert-soft |dn([4,1],78)_scc(4)| :weight 4) +(assert-soft |dn([3,7],30)_scc(5)| :weight 8) +(assert-soft |dn([3,7],28)_scc(6)| :weight 6) +(assert-soft |dn([9,Main.main],87)_scc(7)| :weight 2) +(assert-soft |scc(1)_scc(7)| :weight 2) +(assert-soft |dn([7,Main.main],50)_scc(7)| :weight 2) +(assert-soft |dn([7,Main.main],54)_scc(7)| :weight 2) +(assert-soft |dn([7,Main.main],58)_scc(7)| :weight 2) +(set-option :smt.pb.conflict_frequency 100) + +(optimize + :wmaxsat_engine bvsls + :print_statistics true + :timeout 1200000 +) diff --git a/tests/ravi_sls.smt2 b/tests/ravi_sls.smt2 new file mode 100644 index 000000000..7db65dc40 --- /dev/null +++ b/tests/ravi_sls.smt2 @@ -0,0 +1,443 @@ +(set-option :smt.relevancy 0) +(set-option :smt.pb.conflict_frequency 10000) +(set-option :opt.pb.compile_equality true) +(set-option :smt.pb.enable_simplex true) +; declare an integer variable for each mini-pathlet's multiplicity +(declare-const A0_2_3_10 Int) +(declare-const A0_2_3_5_4_7_9 Int) +(declare-const A0_2_3_5_4_8_9 Int) +(declare-const A0_1_3_10 Int) +(declare-const A0_1_3_5_4_7_9 Int) +(declare-const A0_1_3_5_4_8_9 Int) +(declare-const A1_3_10 Int) +(declare-const A1_3_5_4_7_9 Int) +(declare-const A1_3_5_4_8_9 Int) +(declare-const A2_3_10 Int) +(declare-const A2_3_5_4_7_9 Int) +(declare-const A2_3_5_4_8_9 Int) +(declare-const A3_10 Int) +(declare-const A3_5_4_7_9_12_13 Int) +(declare-const A3_5_4_7_9_11_13 Int) +(declare-const A3_5_4_8_9_12_13 Int) +(declare-const A3_5_4_8_9_11_13 Int) +(declare-const A4_7_9_12_13 Int) +(declare-const A4_7_9_11_13 Int) +(declare-const A4_8_9_12_13 Int) +(declare-const A4_8_9_11_13 Int) +(declare-const A5_4_7_9_12_13 Int) +(declare-const A5_4_7_9_11_13 Int) +(declare-const A5_4_8_9_12_13 Int) +(declare-const A5_4_8_9_11_13 Int) +(declare-const A6_21_10 Int) +(declare-const A6_4_7_9_12_13 Int) +(declare-const A6_4_7_9_11_13 Int) +(declare-const A6_4_8_9_12_13 Int) +(declare-const A6_4_8_9_11_13 Int) +(declare-const A7_9_12_13 Int) +(declare-const A7_9_11_13 Int) +(declare-const A8_9_12_13 Int) +(declare-const A8_9_11_13 Int) +(declare-const A9_12_13_15_17_18 Int) +(declare-const A9_12_13_15_17_16_19 Int) +(declare-const A9_12_13_14_17_18 Int) +(declare-const A9_12_13_14_17_16_19 Int) +(declare-const A9_11_13_15_17_18 Int) +(declare-const A9_11_13_15_17_16_19 Int) +(declare-const A9_11_13_14_17_18 Int) +(declare-const A9_11_13_14_17_16_19 Int) +(declare-const A11_13_15_17_18_19 Int) +(declare-const A11_13_15_17_16_19 Int) +(declare-const A11_13_14_17_18_19 Int) +(declare-const A11_13_14_17_16_19 Int) +(declare-const A12_13_15_17_18_19 Int) +(declare-const A12_13_15_17_16_19 Int) +(declare-const A12_13_14_17_18_19 Int) +(declare-const A12_13_14_17_16_19 Int) +(declare-const A13_15_17_18_19 Int) +(declare-const A13_15_17_16_19 Int) +(declare-const A13_14_17_18_19 Int) +(declare-const A13_14_17_16_19 Int) +(declare-const A20_6_21_10 Int) +(declare-const A20_6_4_7_9_12 Int) +(declare-const A20_6_4_7_9_11 Int) +(declare-const A20_6_4_8_9_12 Int) +(declare-const A20_6_4_8_9_11 Int) +(declare-const A21_10 Int) +; positive mult for each minipathlet +(assert (<= 0 A0_2_3_10)) +(assert (<= A0_2_3_10 4)) +(assert (<= 0 A0_2_3_5_4_7_9)) +(assert (<= A0_2_3_5_4_7_9 4)) +(assert (<= 0 A0_2_3_5_4_8_9)) +(assert (<= A0_2_3_5_4_8_9 4)) +(assert (<= 0 A0_1_3_10)) +(assert (<= A0_1_3_10 4)) +(assert (<= 0 A0_1_3_5_4_7_9)) +(assert (<= A0_1_3_5_4_7_9 4)) +(assert (<= 0 A0_1_3_5_4_8_9)) +(assert (<= A0_1_3_5_4_8_9 4)) +(assert (<= 0 A1_3_10)) +(assert (<= A1_3_10 4)) +(assert (<= 0 A1_3_5_4_7_9)) +(assert (<= A1_3_5_4_7_9 4)) +(assert (<= 0 A1_3_5_4_8_9)) +(assert (<= A1_3_5_4_8_9 4)) +(assert (<= 0 A2_3_10)) +(assert (<= A2_3_10 4)) +(assert (<= 0 A2_3_5_4_7_9)) +(assert (<= A2_3_5_4_7_9 4)) +(assert (<= 0 A2_3_5_4_8_9)) +(assert (<= A2_3_5_4_8_9 4)) +(assert (<= 0 A3_10)) +(assert (<= A3_10 4)) +(assert (<= 0 A3_5_4_7_9_12_13)) +(assert (<= A3_5_4_7_9_12_13 4)) +(assert (<= 0 A3_5_4_7_9_11_13)) +(assert (<= A3_5_4_7_9_11_13 4)) +(assert (<= 0 A3_5_4_8_9_12_13)) +(assert (<= A3_5_4_8_9_12_13 4)) +(assert (<= 0 A3_5_4_8_9_11_13)) +(assert (<= A3_5_4_8_9_11_13 4)) +(assert (<= 0 A4_7_9_12_13)) +(assert (<= A4_7_9_12_13 4)) +(assert (<= 0 A4_7_9_11_13)) +(assert (<= A4_7_9_11_13 4)) +(assert (<= 0 A4_8_9_12_13)) +(assert (<= A4_8_9_12_13 4)) +(assert (<= 0 A4_8_9_11_13)) +(assert (<= A4_8_9_11_13 4)) +(assert (<= 0 A5_4_7_9_12_13)) +(assert (<= A5_4_7_9_12_13 4)) +(assert (<= 0 A5_4_7_9_11_13)) +(assert (<= A5_4_7_9_11_13 4)) +(assert (<= 0 A5_4_8_9_12_13)) +(assert (<= A5_4_8_9_12_13 4)) +(assert (<= 0 A5_4_8_9_11_13)) +(assert (<= A5_4_8_9_11_13 4)) +(assert (<= 0 A6_21_10)) +(assert (<= A6_21_10 4)) +(assert (<= 0 A6_4_7_9_12_13)) +(assert (<= A6_4_7_9_12_13 4)) +(assert (<= 0 A6_4_7_9_11_13)) +(assert (<= A6_4_7_9_11_13 4)) +(assert (<= 0 A6_4_8_9_12_13)) +(assert (<= A6_4_8_9_12_13 4)) +(assert (<= 0 A6_4_8_9_11_13)) +(assert (<= A6_4_8_9_11_13 4)) +(assert (<= 0 A7_9_12_13)) +(assert (<= A7_9_12_13 4)) +(assert (<= 0 A7_9_11_13)) +(assert (<= A7_9_11_13 4)) +(assert (<= 0 A8_9_12_13)) +(assert (<= A8_9_12_13 4)) +(assert (<= 0 A8_9_11_13)) +(assert (<= A8_9_11_13 4)) +(assert (<= 0 A9_12_13_15_17_18)) +(assert (<= A9_12_13_15_17_18 4)) +(assert (<= 0 A9_12_13_15_17_16_19)) +(assert (<= A9_12_13_15_17_16_19 4)) +(assert (<= 0 A9_12_13_14_17_18)) +(assert (<= A9_12_13_14_17_18 4)) +(assert (<= 0 A9_12_13_14_17_16_19)) +(assert (<= A9_12_13_14_17_16_19 4)) +(assert (<= 0 A9_11_13_15_17_18)) +(assert (<= A9_11_13_15_17_18 4)) +(assert (<= 0 A9_11_13_15_17_16_19)) +(assert (<= A9_11_13_15_17_16_19 4)) +(assert (<= 0 A9_11_13_14_17_18)) +(assert (<= A9_11_13_14_17_18 4)) +(assert (<= 0 A9_11_13_14_17_16_19)) +(assert (<= A9_11_13_14_17_16_19 4)) +(assert (<= 0 A11_13_15_17_18_19)) +(assert (<= A11_13_15_17_18_19 4)) +(assert (<= 0 A11_13_15_17_16_19)) +(assert (<= A11_13_15_17_16_19 4)) +(assert (<= 0 A11_13_14_17_18_19)) +(assert (<= A11_13_14_17_18_19 4)) +(assert (<= 0 A11_13_14_17_16_19)) +(assert (<= A11_13_14_17_16_19 4)) +(assert (<= 0 A12_13_15_17_18_19)) +(assert (<= A12_13_15_17_18_19 4)) +(assert (<= 0 A12_13_15_17_16_19)) +(assert (<= A12_13_15_17_16_19 4)) +(assert (<= 0 A12_13_14_17_18_19)) +(assert (<= A12_13_14_17_18_19 4)) +(assert (<= 0 A12_13_14_17_16_19)) +(assert (<= A12_13_14_17_16_19 4)) +(assert (<= 0 A13_15_17_18_19)) +(assert (<= A13_15_17_18_19 4)) +(assert (<= 0 A13_15_17_16_19)) +(assert (<= A13_15_17_16_19 4)) +(assert (<= 0 A13_14_17_18_19)) +(assert (<= A13_14_17_18_19 4)) +(assert (<= 0 A13_14_17_16_19)) +(assert (<= A13_14_17_16_19 4)) +(assert (<= 0 A20_6_21_10)) +(assert (<= A20_6_21_10 4)) +(assert (<= 0 A20_6_4_7_9_12)) +(assert (<= A20_6_4_7_9_12 4)) +(assert (<= 0 A20_6_4_7_9_11)) +(assert (<= A20_6_4_7_9_11 4)) +(assert (<= 0 A20_6_4_8_9_12)) +(assert (<= A20_6_4_8_9_12 4)) +(assert (<= 0 A20_6_4_8_9_11)) +(assert (<= A20_6_4_8_9_11 4)) +(assert (<= 0 A21_10)) +(assert (<= A21_10 4)) +; range of multiplicities for each contig-pair +; contigs 0 1, #pairs 7, dist 8.36 +(assert (and (<= 0 (+ A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) (<= (+ A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9) 4))) +(assert-soft (= 0 (+ A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) :dweight 2.852312) ; p=0001405 +(assert-soft (= 1 (+ A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) :dweight 0.852312) ; p=0140504 +(assert-soft (= 2 (+ A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) :dweight 1.408176) ; p=0039068 +(assert-soft (= 3 (+ A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) :dweight 2.838611) ; p=0001450 +(assert-soft (= 4 (+ A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) :dweight 4.627113) ; p=0000024 +; contigs 1 3, #pairs 5, dist 1.07 +(assert (and (<= 0 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) (<= (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9) 4))) +(assert-soft (= 0 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) :dweight 4.168291) ; p=0000068 +(assert-soft (= 1 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) :dweight 2.168291) ; p=0006787 +(assert-soft (= 2 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) :dweight 1.195873) ; p=0063698 +(assert-soft (= 3 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) :dweight 0.848149) ; p=0141857 +(assert-soft (= 4 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) :dweight 0.756187) ; p=0175313 +; contigs 2 3, #pairs 4, dist 1.07 +(assert (and (<= 0 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) (<= (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9) 4))) +(assert-soft (= 0 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) :dweight 3.535379) ; p=0000291 +(assert-soft (= 1 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) :dweight 1.535379) ; p=0029149 +(assert-soft (= 2 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) :dweight 0.874154) ; p=0133612 +(assert-soft (= 3 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) :dweight 0.712685) ; p=0193783 +(assert-soft (= 4 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) :dweight 0.755826) ; p=0175458 +; contigs 3 4, #pairs 3, dist 2.77 +(assert (and (<= 0 (+ A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) (<= (+ A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13) 4))) +(assert-soft (= 0 (+ A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) :dweight 5.564238) ; p=0000003 +(assert-soft (= 1 (+ A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) :dweight 3.564238) ; p=0000273 +(assert-soft (= 2 (+ A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) :dweight 2.714464) ; p=0001930 +(assert-soft (= 3 (+ A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) :dweight 2.239507) ; p=0005761 +(assert-soft (= 4 (+ A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) :dweight 1.918007) ; p=0012078 +; contigs 4 9, #pairs 2, dist 1.24 +(assert (and (<= 0 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) (<= (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13) 4))) +(assert-soft (= 0 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) :dweight 4.280499) ; p=0000052 +(assert-soft (= 1 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) :dweight 2.280499) ; p=0005242 +(assert-soft (= 2 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) :dweight 1.725376) ; p=0018820 +(assert-soft (= 3 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) :dweight 1.420131) ; p=0038007 +(assert-soft (= 4 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) :dweight 1.217191) ; p=0060647 +; contigs 5 9, #pairs 1, dist 1.46 +(assert (and (<= 0 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) (<= (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13) 4))) +(assert-soft (= 0 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) :dweight 6.000000) ; p=0000001 +(assert-soft (= 1 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) :dweight 4.000000) ; p=0000100 +(assert-soft (= 2 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) :dweight 6.000000) ; p=0000001 +(assert-soft (= 3 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) :dweight 8.000000) ; p=0000000 +(assert-soft (= 4 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) :dweight 1.0000000) ; p=0000000 +; contigs 6 9, #pairs 0, dist 2.79 +(assert (and (<= 0 (+ A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) (<= (+ A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13) 4))) +(assert-soft (= 0 (+ A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) :dweight 1.100798) ; p=0079287 +(assert-soft (= 1 (+ A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) :dweight 1.100798) ; p=0079287 +(assert-soft (= 2 (+ A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) :dweight 1.100798) ; p=0079287 +(assert-soft (= 3 (+ A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) :dweight 1.100798) ; p=0079287 +(assert-soft (= 4 (+ A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) :dweight 1.100798) ; p=0079287 +; contigs 7 9, #pairs 4, dist 1.08 +(assert (and (<= 0 (+ A7_9_12_13 A7_9_11_13)) (<= (+ A7_9_12_13 A7_9_11_13) 4))) +(assert-soft (= 0 (+ A7_9_12_13 A7_9_11_13)) :dweight 4.830293) ; p=0000015 +(assert-soft (= 1 (+ A7_9_12_13 A7_9_11_13)) :dweight 2.830293) ; p=0001478 +(assert-soft (= 2 (+ A7_9_12_13 A7_9_11_13)) :dweight 1.839248) ; p=0014479 +(assert-soft (= 3 (+ A7_9_12_13 A7_9_11_13)) :dweight 1.347958) ; p=0044879 +(assert-soft (= 4 (+ A7_9_12_13 A7_9_11_13)) :dweight 1.061278) ; p=0086840 +; contigs 8 9, #pairs 2, dist 1.10 +(assert (and (<= 0 (+ A8_9_12_13 A8_9_11_13)) (<= (+ A8_9_12_13 A8_9_11_13) 4))) +(assert-soft (= 0 (+ A8_9_12_13 A8_9_11_13)) :dweight 3.085052) ; p=0000822 +(assert-soft (= 1 (+ A8_9_12_13 A8_9_11_13)) :dweight 1.085052) ; p=0082214 +(assert-soft (= 2 (+ A8_9_12_13 A8_9_11_13)) :dweight 0.712306) ; p=0193952 +(assert-soft (= 3 (+ A8_9_12_13 A8_9_11_13)) :dweight 0.589437) ; p=0257373 +(assert-soft (= 4 (+ A8_9_12_13 A8_9_11_13)) :dweight 0.568873) ; p=0269853 +; contigs 9 12, #pairs 1, dist 1.77 +(assert (and (<= 0 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19)) (<= (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19) 4))) +(assert-soft (= 0 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19)) :dweight 2.518279) ; p=0003032 +(assert-soft (= 1 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19)) :dweight 0.518279) ; p=0303195 +(assert-soft (= 2 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19)) :dweight 0.434295) ; p=0367879 +(assert-soft (= 3 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19)) :dweight 0.475249) ; p=0334773 +(assert-soft (= 4 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19)) :dweight 0.567356) ; p=0270797 +; contigs 11 13, #pairs 2, dist 1.00 +(assert (and (<= 0 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) (<= (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19) 4))) +(assert-soft (= 0 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) :dweight 2.755831) ; p=0001755 +(assert-soft (= 1 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) :dweight 0.755831) ; p=0175456 +(assert-soft (= 2 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) :dweight 0.568471) ; p=0270103 +(assert-soft (= 3 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) :dweight 0.630988) ; p=0233890 +(assert-soft (= 4 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) :dweight 0.795810) ; p=0160026 +; contigs 12 13, #pairs 2, dist 1.01 +(assert (and (<= 0 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) (<= (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19) 4))) +(assert-soft (= 0 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) :dweight 2.662349) ; p=0002176 +(assert-soft (= 1 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) :dweight 0.662349) ; p=0217596 +(assert-soft (= 2 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) :dweight 0.583662) ; p=0260818 +(assert-soft (= 3 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) :dweight 0.754853) ; p=0175852 +(assert-soft (= 4 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) :dweight 1.028349) ; p=0093681 +; contigs 13 15, #pairs 1, dist 2.58 +(assert (and (<= 0 (+ A13_15_17_18_19 A13_15_17_16_19)) (<= (+ A13_15_17_18_19 A13_15_17_16_19) 4))) +(assert-soft (= 0 (+ A13_15_17_18_19 A13_15_17_16_19)) :dweight 2.434616) ; p=0003676 +(assert-soft (= 1 (+ A13_15_17_18_19 A13_15_17_16_19)) :dweight 0.434616) ; p=0367607 +(assert-soft (= 2 (+ A13_15_17_18_19 A13_15_17_16_19)) :dweight 0.584809) ; p=0260130 +(assert-soft (= 3 (+ A13_15_17_18_19 A13_15_17_16_19)) :dweight 0.859941) ; p=0138057 +(assert-soft (= 4 (+ A13_15_17_18_19 A13_15_17_16_19)) :dweight 1.186226) ; p=0065129 +; contigs 20 6, #pairs 7, dist 1.085 +(assert (and (<= 0 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) (<= (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11) 4))) +(assert-soft (= 0 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) :dweight 2.850723) ; p=0001410 +(assert-soft (= 1 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) :dweight 0.850723) ; p=0141019 +(assert-soft (= 2 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) :dweight 2.181023) ; p=0006591 +(assert-soft (= 3 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) :dweight 4.385894) ; p=0000041 +(assert-soft (= 4 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) :dweight 6.948833) ; p=0000000 +; contigs 21 10, #pairs 1, dist 1.2 +(assert (and (<= 0 (+ A21_10)) (<= (+ A21_10) 4))) +(assert-soft (= 0 (+ A21_10)) :dweight 2.629839) ; p=0002345 +(assert-soft (= 1 (+ A21_10)) :dweight 0.629839) ; p=0234510 +(assert-soft (= 2 (+ A21_10)) :dweight 0.469677) ; p=0339096 +(assert-soft (= 3 (+ A21_10)) :dweight 0.434455) ; p=0367744 +(assert-soft (= 4 (+ A21_10)) :dweight 0.450384) ; p=0354499 +; range of multiplicities for each contig +; contig 0, length 931, #reads 41, min 0, max 4 +(assert (and (<= 0 (+ A0_2_3_10 A0_2_3_5_4_7_9 A0_2_3_5_4_8_9 A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) (<= (+ A0_2_3_10 A0_2_3_5_4_7_9 A0_2_3_5_4_8_9 A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9) 4))) +(assert-soft (= 0 (+ A0_2_3_10 A0_2_3_5_4_7_9 A0_2_3_5_4_8_9 A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) :dweight 4.060041) ; p=0000087 +(assert-soft (= 1 (+ A0_2_3_10 A0_2_3_5_4_7_9 A0_2_3_5_4_8_9 A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) :dweight 2.060041) ; p=0008709 +(assert-soft (= 2 (+ A0_2_3_10 A0_2_3_5_4_7_9 A0_2_3_5_4_8_9 A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) :dweight 1.3620829) ; p=0000000 +(assert-soft (= 3 (+ A0_2_3_10 A0_2_3_5_4_7_9 A0_2_3_5_4_8_9 A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) :dweight 3.0304105) ; p=0000000 +(assert-soft (= 4 (+ A0_2_3_10 A0_2_3_5_4_7_9 A0_2_3_5_4_8_9 A0_1_3_10 A0_1_3_5_4_7_9 A0_1_3_5_4_8_9)) :dweight 4.9084634) ; p=0000000 +; contig 1, length 195, #reads 16, min 0, max 4 +(assert (and (<= 0 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) (<= (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9) 4))) +(assert-soft (= 0 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) :dweight 5.312217) ; p=0000005 +(assert-soft (= 1 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) :dweight 3.312217) ; p=0000487 +(assert-soft (= 2 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) :dweight 1.202826) ; p=0062686 +(assert-soft (= 3 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) :dweight 1.092455) ; p=0080825 +(assert-soft (= 4 (+ A1_3_10 A1_3_5_4_7_9 A1_3_5_4_8_9)) :dweight 1.800524) ; p=0015830 +; contig 2, length 198, #reads 21, min 0, max 4 +(assert (and (<= 0 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) (<= (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9) 4))) +(assert-soft (= 0 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) :dweight 7.526226) ; p=0000000 +(assert-soft (= 1 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) :dweight 5.526226) ; p=0000003 +(assert-soft (= 2 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) :dweight 1.998081) ; p=0010044 +(assert-soft (= 3 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) :dweight 1.093650) ; p=0080603 +(assert-soft (= 4 (+ A2_3_10 A2_3_5_4_7_9 A2_3_5_4_8_9)) :dweight 1.263422) ; p=0054523 +; contig 3, length 347, #reads 56, min 0, max 4 +(assert (and (<= 0 (+ A3_10 A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) (<= (+ A3_10 A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13) 4))) +(assert-soft (= 0 (+ A3_10 A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) :dweight 1.6034953) ; p=0000000 +(assert-soft (= 1 (+ A3_10 A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) :dweight 1.4034953) ; p=0000000 +(assert-soft (= 2 (+ A3_10 A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) :dweight 4.261782) ; p=0000055 +(assert-soft (= 3 (+ A3_10 A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) :dweight 1.485181) ; p=0032720 +(assert-soft (= 4 (+ A3_10 A3_5_4_7_9_12_13 A3_5_4_7_9_11_13 A3_5_4_8_9_12_13 A3_5_4_8_9_11_13)) :dweight 1.573120) ; p=0026723 +; contig 4, length 113, #reads 8, min 0, max 4 +(assert (and (<= 0 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) (<= (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13) 4))) +(assert-soft (= 0 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) :dweight 7.744934) ; p=0000000 +(assert-soft (= 1 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) :dweight 5.744934) ; p=0000002 +(assert-soft (= 2 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) :dweight 3.682280) ; p=0000208 +(assert-soft (= 3 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) :dweight 2.619135) ; p=0002404 +(assert-soft (= 4 (+ A4_7_9_12_13 A4_7_9_11_13 A4_8_9_12_13 A4_8_9_11_13)) :dweight 1.965211) ; p=0010834 +; contig 5, length 101, #reads 2, min 0, max 4 +(assert (and (<= 0 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) (<= (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13) 4))) +(assert-soft (= 0 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) :dweight 4.686648) ; p=0000021 +(assert-soft (= 1 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) :dweight 2.686648) ; p=0002058 +(assert-soft (= 2 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) :dweight 2.113387) ; p=0007702 +(assert-soft (= 3 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) :dweight 1.790003) ; p=0016218 +(assert-soft (= 4 (+ A5_4_7_9_12_13 A5_4_7_9_11_13 A5_4_8_9_12_13 A5_4_8_9_11_13)) :dweight 1.568925) ; p=0026982 +; contig 6, length 223, #reads 24, min 0, max 4 +(assert (and (<= 0 (+ A6_21_10 A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) (<= (+ A6_21_10 A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13) 4))) +(assert-soft (= 0 (+ A6_21_10 A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) :dweight 7.515357) ; p=0000000 +(assert-soft (= 1 (+ A6_21_10 A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) :dweight 5.515357) ; p=0000003 +(assert-soft (= 2 (+ A6_21_10 A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) :dweight 1.804093) ; p=0015700 +(assert-soft (= 3 (+ A6_21_10 A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) :dweight 1.091359) ; p=0081029 +(assert-soft (= 4 (+ A6_21_10 A6_4_7_9_12_13 A6_4_7_9_11_13 A6_4_8_9_12_13 A6_4_8_9_11_13)) :dweight 1.606284) ; p=0024758 +; contig 7, length 191, #reads 9, min 0, max 4 +(assert (and (<= 0 (+ A7_9_12_13 A7_9_11_13)) (<= (+ A7_9_12_13 A7_9_11_13) 4))) +(assert-soft (= 0 (+ A7_9_12_13 A7_9_11_13)) :dweight 3.169161) ; p=0000677 +(assert-soft (= 1 (+ A7_9_12_13 A7_9_11_13)) :dweight 1.169161) ; p=0067739 +(assert-soft (= 2 (+ A7_9_12_13 A7_9_11_13)) :dweight 1.051784) ; p=0088760 +(assert-soft (= 3 (+ A7_9_12_13 A7_9_11_13)) :dweight 2.058857) ; p=0008733 +(assert-soft (= 4 (+ A7_9_12_13 A7_9_11_13)) :dweight 3.526301) ; p=0000298 +; contig 8, length 200, #reads 12, min 0, max 4 +(assert (and (<= 0 (+ A8_9_12_13 A8_9_11_13)) (<= (+ A8_9_12_13 A8_9_11_13) 4))) +(assert-soft (= 0 (+ A8_9_12_13 A8_9_11_13)) :dweight 3.724714) ; p=0000188 +(assert-soft (= 1 (+ A8_9_12_13 A8_9_11_13)) :dweight 1.724714) ; p=0018849 +(assert-soft (= 2 (+ A8_9_12_13 A8_9_11_13)) :dweight 0.963436) ; p=0108784 +(assert-soft (= 3 (+ A8_9_12_13 A8_9_11_13)) :dweight 1.701424) ; p=0019887 +(assert-soft (= 4 (+ A8_9_12_13 A8_9_11_13)) :dweight 3.053242) ; p=0000885 +; contig 9, length 269, #reads 32, min 0, max 4 +(assert (and (<= 0 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19 A9_11_13_15_17_18 A9_11_13_15_17_16_19 A9_11_13_14_17_18 A9_11_13_14_17_16_19)) (<= (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19 A9_11_13_15_17_18 A9_11_13_15_17_16_19 A9_11_13_14_17_18 A9_11_13_14_17_16_19) 4))) +(assert-soft (= 0 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19 A9_11_13_15_17_18 A9_11_13_15_17_16_19 A9_11_13_14_17_18 A9_11_13_14_17_16_19)) :dweight 8.757585) ; p=0000000 +(assert-soft (= 1 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19 A9_11_13_15_17_18 A9_11_13_15_17_16_19 A9_11_13_14_17_18 A9_11_13_14_17_16_19)) :dweight 6.757585) ; p=0000000 +(assert-soft (= 2 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19 A9_11_13_15_17_18 A9_11_13_15_17_16_19 A9_11_13_14_17_18 A9_11_13_14_17_16_19)) :dweight 1.962827) ; p=0010894 +(assert-soft (= 3 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19 A9_11_13_15_17_18 A9_11_13_15_17_16_19 A9_11_13_14_17_18 A9_11_13_14_17_16_19)) :dweight 1.166108) ; p=0068217 +(assert-soft (= 4 (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19 A9_11_13_15_17_18 A9_11_13_15_17_16_19 A9_11_13_14_17_18 A9_11_13_14_17_16_19)) :dweight 2.006269) ; p=0009857 +; contig 11, length 170, #reads 7, min 0, max 4 +(assert (and (<= 0 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) (<= (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19) 4))) +(assert-soft (= 0 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) :dweight 3.066473) ; p=0000858 +(assert-soft (= 1 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) :dweight 1.066473) ; p=0085808 +(assert-soft (= 2 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) :dweight 0.946381) ; p=0113141 +(assert-soft (= 3 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) :dweight 1.700861) ; p=0019913 +(assert-soft (= 4 (+ A11_13_15_17_18_19 A11_13_15_17_16_19 A11_13_14_17_18_19 A11_13_14_17_16_19)) :dweight 2.813408) ; p=0001537 +; contig 12, length 198, #reads 15, min 0, max 4 +(assert (and (<= 0 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) (<= (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19) 4))) +(assert-soft (= 0 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) :dweight 4.784554) ; p=0000016 +(assert-soft (= 1 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) :dweight 2.784554) ; p=0001642 +(assert-soft (= 2 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) :dweight 1.062589) ; p=0086579 +(assert-soft (= 3 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) :dweight 1.214705) ; p=0060995 +(assert-soft (= 4 (+ A12_13_15_17_18_19 A12_13_15_17_16_19 A12_13_14_17_18_19 A12_13_14_17_16_19)) :dweight 2.134110) ; p=0007343 +; contig 13, length 349, #reads 28, min 0, max 4 +(assert (and (<= 0 (+ A13_15_17_18_19 A13_15_17_16_19 A13_14_17_18_19 A13_14_17_16_19)) (<= (+ A13_15_17_18_19 A13_15_17_16_19 A13_14_17_18_19 A13_14_17_16_19) 4))) +(assert-soft (= 0 (+ A13_15_17_18_19 A13_15_17_16_19 A13_14_17_18_19 A13_14_17_16_19)) :dweight 4.577071) ; p=0000026 +(assert-soft (= 1 (+ A13_15_17_18_19 A13_15_17_16_19 A13_14_17_18_19 A13_14_17_16_19)) :dweight 2.577071) ; p=0002648 +(assert-soft (= 2 (+ A13_15_17_18_19 A13_15_17_16_19 A13_14_17_18_19 A13_14_17_16_19)) :dweight 1.290338) ; p=0051246 +(assert-soft (= 3 (+ A13_15_17_18_19 A13_15_17_16_19 A13_14_17_18_19 A13_14_17_16_19)) :dweight 3.501889) ; p=0000315 +(assert-soft (= 4 (+ A13_15_17_18_19 A13_15_17_16_19 A13_14_17_18_19 A13_14_17_16_19)) :dweight 7.145711) ; p=0000000 +; contig 20, length 1151, #reads 32, min 0, max 4 +(assert (and (<= 0 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) (<= (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11) 4))) +(assert-soft (= 0 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) :dweight 8.689981) ; p=0000000 +(assert-soft (= 1 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) :dweight 6.689981) ; p=0000000 +(assert-soft (= 2 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) :dweight 2.7295778) ; p=0000000 +(assert-soft (= 3 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) :dweight 5.1899615) ; p=0000000 +(assert-soft (= 4 (+ A20_6_21_10 A20_6_4_7_9_12 A20_6_4_7_9_11 A20_6_4_8_9_12 A20_6_4_8_9_11)) :dweight 7.8140332) ; p=0000000 +; contig 21, length 107, #reads 4, min 0, max 4 +(assert (and (<= 0 (+ A21_10)) (<= (+ A21_10) 4))) +(assert-soft (= 0 (+ A21_10)) :dweight 5.154038) ; p=0000007 +(assert-soft (= 1 (+ A21_10)) :dweight 3.154038) ; p=0000701 +(assert-soft (= 2 (+ A21_10)) :dweight 2.122711) ; p=0007539 +(assert-soft (= 3 (+ A21_10)) :dweight 1.591139) ; p=0025637 +(assert-soft (= 4 (+ A21_10)) :dweight 1.264177) ; p=0054428 +; consistency of minipathlet multiplicities +(assert (= (+ A9_12_13_15_17_18) (+ A12_13_15_17_18_19))) +(assert (= (+ A5_4_7_9_11_13 A6_4_7_9_11_13) (+ A4_7_9_11_13))) +(assert (= (+ A0_2_3_5_4_8_9) (+ A2_3_5_4_8_9))) +(assert (= (+ A1_3_5_4_8_9 A2_3_5_4_8_9) (+ A3_5_4_8_9_12_13 A3_5_4_8_9_11_13))) +(assert (= (+ A9_11_13_14_17_16_19) (+ A11_13_14_17_16_19))) +(assert (= (+ A11_13_14_17_16_19 A12_13_14_17_16_19) (+ A13_14_17_16_19))) +(assert (= (+ A20_6_21_10) (+ A6_21_10))) +(assert (= (+ A11_13_14_17_18_19 A12_13_14_17_18_19) (+ A13_14_17_18_19))) +(assert (= (+ A0_1_3_5_4_7_9) (+ A1_3_5_4_7_9))) +(assert (= (+ A9_12_13_14_17_18) (+ A12_13_14_17_18_19))) +(assert (= (+ A1_3_10 A2_3_10) (+ A3_10))) +(assert (= (+ A11_13_15_17_18_19 A12_13_15_17_18_19) (+ A13_15_17_18_19))) +(assert (= (+ A11_13_15_17_16_19 A12_13_15_17_16_19) (+ A13_15_17_16_19))) +(assert (= (+ A9_12_13_14_17_16_19) (+ A12_13_14_17_16_19))) +(assert (= (+ A7_9_11_13 A8_9_11_13) (+ A9_11_13_15_17_18 A9_11_13_15_17_16_19 A9_11_13_14_17_18 A9_11_13_14_17_16_19))) +(assert (= (+ A0_2_3_5_4_7_9) (+ A2_3_5_4_7_9))) +(assert (= (+ A4_8_9_11_13) (+ A8_9_11_13))) +(assert (= (+ A0_1_3_10) (+ A1_3_10))) +(assert (= (+ A20_6_4_8_9_12) (+ A6_4_8_9_12_13))) +(assert (= (+ A3_5_4_8_9_11_13) (+ A5_4_8_9_11_13))) +(assert (= (+ A0_1_3_5_4_8_9) (+ A1_3_5_4_8_9))) +(assert (= (+ A5_4_8_9_11_13 A6_4_8_9_11_13) (+ A4_8_9_11_13))) +(assert (= (+ A20_6_4_7_9_12) (+ A6_4_7_9_12_13))) +(assert (= (+ A20_6_4_7_9_11) (+ A6_4_7_9_11_13))) +(assert (= (+ A3_5_4_8_9_12_13) (+ A5_4_8_9_12_13))) +(assert (= (+ A4_7_9_12_13) (+ A7_9_12_13))) +(assert (= (+ A9_12_13_15_17_16_19) (+ A12_13_15_17_16_19))) +(assert (= (+ A9_11_13_15_17_16_19) (+ A11_13_15_17_16_19))) +(assert (= (+ A1_3_5_4_7_9 A2_3_5_4_7_9) (+ A3_5_4_7_9_12_13 A3_5_4_7_9_11_13))) +(assert (= (+ A3_5_4_7_9_12_13) (+ A5_4_7_9_12_13))) +(assert (= (+ A7_9_12_13 A8_9_12_13) (+ A9_12_13_15_17_18 A9_12_13_15_17_16_19 A9_12_13_14_17_18 A9_12_13_14_17_16_19))) +(assert (= (+ A0_2_3_10) (+ A2_3_10))) +(assert (= (+ A9_11_13_14_17_18) (+ A11_13_14_17_18_19))) +(assert (= (+ A4_8_9_12_13) (+ A8_9_12_13))) +(assert (= (+ A5_4_7_9_12_13 A6_4_7_9_12_13) (+ A4_7_9_12_13))) +(assert (= (+ A9_11_13_15_17_18) (+ A11_13_15_17_18_19))) +(assert (= (+ A6_21_10) (+ A21_10))) +(assert (= (+ A20_6_4_8_9_11) (+ A6_4_8_9_11_13))) +(assert (= (+ A3_5_4_7_9_11_13) (+ A5_4_7_9_11_13))) +(assert (= (+ A5_4_8_9_12_13 A6_4_8_9_12_13) (+ A4_8_9_12_13))) +(assert (= (+ A4_7_9_11_13) (+ A7_9_11_13))) +(optimize :print_statistics true + :wmaxsat_engine sls + :maxsat_engine weighted_maxsat) diff --git a/tests/sls1.smt2 b/tests/sls1.smt2 new file mode 100644 index 000000000..5f38a9418 --- /dev/null +++ b/tests/sls1.smt2 @@ -0,0 +1,5844 @@ +(set-option :smt.relevancy 0) +(set-option :smt.pb.conflict_frequency 10000) +(declare-fun x_354 () Int) +(declare-fun x_522 () Int) +(declare-fun x_464 () Int) +(declare-fun x_644 () Int) +(declare-fun x_174 () Int) +(declare-fun x_397 () Int) +(declare-fun x_432 () Int) +(declare-fun x_557 () Int) +(declare-fun x_926 () Int) +(declare-fun x_582 () Int) +(declare-fun x_779 () Int) +(declare-fun x_759 () Int) +(declare-fun x_912 () Int) +(declare-fun x_868 () Int) +(declare-fun x_384 () Int) +(declare-fun x_963 () Int) +(declare-fun x_658 () Int) +(declare-fun x_362 () Int) +(declare-fun x_984 () Int) +(declare-fun x_308 () Int) +(declare-fun x_456 () Int) +(declare-fun x_17 () Int) +(declare-fun x_816 () Int) +(declare-fun x_833 () Int) +(declare-fun x_463 () Int) +(declare-fun x_211 () Int) +(declare-fun x_607 () Int) +(declare-fun x_139 () Int) +(declare-fun x_124 () Int) +(declare-fun x_291 () Int) +(declare-fun x_859 () Int) +(declare-fun x_888 () Int) +(declare-fun x_31 () Int) +(declare-fun x_472 () Int) +(declare-fun x_434 () Int) +(declare-fun x_154 () Int) +(declare-fun x_347 () Int) +(declare-fun x_88 () Int) +(declare-fun x_769 () Int) +(declare-fun x_986 () Int) +(declare-fun x_8 () Int) +(declare-fun x_196 () Int) +(declare-fun x_882 () Int) +(declare-fun x_711 () Int) +(declare-fun x_167 () Int) +(declare-fun x_119 () Int) +(declare-fun x_4 () Int) +(declare-fun x_33 () Int) +(declare-fun x_178 () Int) +(declare-fun x_893 () Int) +(declare-fun x_429 () Int) +(declare-fun x_527 () Int) +(declare-fun x_194 () Int) +(declare-fun x_498 () Int) +(declare-fun x_346 () Int) +(declare-fun x_712 () Int) +(declare-fun x_691 () Int) +(declare-fun x_294 () Int) +(declare-fun x_402 () Int) +(declare-fun x_213 () Int) +(declare-fun x_239 () Int) +(declare-fun x_297 () Int) +(declare-fun x_427 () Int) +(declare-fun x_489 () Int) +(declare-fun x_841 () Int) +(declare-fun x_186 () Int) +(declare-fun x_149 () Int) +(declare-fun x_586 () Int) +(declare-fun x_932 () Int) +(declare-fun x_367 () Int) +(declare-fun x_77 () Int) +(declare-fun x_123 () Int) +(declare-fun x_884 () Int) +(declare-fun x_989 () Int) +(declare-fun x_242 () Int) +(declare-fun x_614 () Int) +(declare-fun x_381 () Int) +(declare-fun x_388 () Int) +(declare-fun x_306 () Int) +(declare-fun x_737 () Int) +(declare-fun x_277 () Int) +(declare-fun x_966 () Int) +(declare-fun x_67 () Int) +(declare-fun x_678 () Int) +(declare-fun x_87 () Int) +(declare-fun x_496 () Int) +(declare-fun x_919 () Int) +(declare-fun x_439 () Int) +(declare-fun x_854 () Int) +(declare-fun x_961 () Int) +(declare-fun x_697 () Int) +(declare-fun x_19 () Int) +(declare-fun x_818 () Int) +(declare-fun x_158 () Int) +(declare-fun x_26 () Int) +(declare-fun x_436 () Int) +(declare-fun x_798 () Int) +(declare-fun x_457 () Int) +(declare-fun x_838 () Int) +(declare-fun x_953 () Int) +(declare-fun x_524 () Int) +(declare-fun x_574 () Int) +(declare-fun x_212 () Int) +(declare-fun x_486 () Int) +(declare-fun x_3 () Int) +(declare-fun x_256 () Int) +(declare-fun x_22 () Int) +(declare-fun x_676 () Int) +(declare-fun x_789 () Int) +(declare-fun x_892 () Int) +(declare-fun x_682 () Int) +(declare-fun x_84 () Int) +(declare-fun x_819 () Int) +(declare-fun x_454 () Int) +(declare-fun x_59 () Int) +(declare-fun x_227 () Int) +(declare-fun x_572 () Int) +(declare-fun x_914 () Int) +(declare-fun x_39 () Int) +(declare-fun x_679 () Int) +(declare-fun x_824 () Int) +(declare-fun x_684 () Int) +(declare-fun x_221 () Int) +(declare-fun x_274 () Int) +(declare-fun x_32 () Int) +(declare-fun x_348 () Int) +(declare-fun x_877 () Int) +(declare-fun x_701 () Int) +(declare-fun x_231 () Int) +(declare-fun x_549 () Int) +(declare-fun x_889 () Int) +(declare-fun x_879 () Int) +(declare-fun x_662 () Int) +(declare-fun x_302 () Int) +(declare-fun x_979 () Int) +(declare-fun x_861 () Int) +(declare-fun x_973 () Int) +(declare-fun x_401 () Int) +(declare-fun x_537 () Int) +(declare-fun x_972 () Int) +(declare-fun x_269 () Int) +(declare-fun x_957 () Int) +(declare-fun x_271 () Int) +(declare-fun x_363 () Int) +(declare-fun x_181 () Int) +(declare-fun x_357 () Int) +(declare-fun x_591 () Int) +(declare-fun x_559 () Int) +(declare-fun x_51 () Int) +(declare-fun x_916 () Int) +(declare-fun x_389 () Int) +(declare-fun x_512 () Int) +(declare-fun x_988 () Int) +(declare-fun x_667 () Int) +(declare-fun x_511 () Int) +(declare-fun x_733 () Int) +(declare-fun x_821 () Int) +(declare-fun x_671 () Int) +(declare-fun x_707 () Int) +(declare-fun x_826 () Int) +(declare-fun x_319 () Int) +(declare-fun x_399 () Int) +(declare-fun x_852 () Int) +(declare-fun x_442 () Int) +(declare-fun x_108 () Int) +(declare-fun x_392 () Int) +(declare-fun x_776 () Int) +(declare-fun x_993 () Int) +(declare-fun x_459 () Int) +(declare-fun x_913 () Int) +(declare-fun x_107 () Int) +(declare-fun x_994 () Int) +(declare-fun x_61 () Int) +(declare-fun x_802 () Int) +(declare-fun x_677 () Int) +(declare-fun x_857 () Int) +(declare-fun x_706 () Int) +(declare-fun x_278 () Int) +(declare-fun x_443 () Int) +(declare-fun x_813 () Int) +(declare-fun x_971 () Int) +(declare-fun x_173 () Int) +(declare-fun x_91 () Int) +(declare-fun x_396 () Int) +(declare-fun x_551 () Int) +(declare-fun x_846 () Int) +(declare-fun x_417 () Int) +(declare-fun x_54 () Int) +(declare-fun x_721 () Int) +(declare-fun x_331 () Int) +(declare-fun x_467 () Int) +(declare-fun x_553 () Int) +(declare-fun x_959 () Int) +(declare-fun x_871 () Int) +(declare-fun x_692 () Int) +(declare-fun x_792 () Int) +(declare-fun x_593 () Int) +(declare-fun x_412 () Int) +(declare-fun x_531 () Int) +(declare-fun x_352 () Int) +(declare-fun x_333 () Int) +(declare-fun x_596 () Int) +(declare-fun x_229 () Int) +(declare-fun x_447 () Int) +(declare-fun x_53 () Int) +(declare-fun x_548 () Int) +(declare-fun x_43 () Int) +(declare-fun x_13 () Int) +(declare-fun x_198 () Int) +(declare-fun x_47 () Int) +(declare-fun x_626 () Int) +(declare-fun x_648 () Int) +(declare-fun x_902 () Int) +(declare-fun x_594 () Int) +(declare-fun x_113 () Int) +(declare-fun x_286 () Int) +(declare-fun x_163 () Int) +(declare-fun x_157 () Int) +(declare-fun x_659 () Int) +(declare-fun x_24 () Int) +(declare-fun x_631 () Int) +(declare-fun x_699 () Int) +(declare-fun x_366 () Int) +(declare-fun x_6 () Int) +(declare-fun x_156 () Int) +(declare-fun x_876 () Int) +(declare-fun x_598 () Int) +(declare-fun x_974 () Int) +(declare-fun x_372 () Int) +(declare-fun x_538 () Int) +(declare-fun x_287 () Int) +(declare-fun x_71 () Int) +(declare-fun x_371 () Int) +(declare-fun x_646 () Int) +(declare-fun x_519 () Int) +(declare-fun x_121 () Int) +(declare-fun x_268 () Int) +(declare-fun x_746 () Int) +(declare-fun x_562 () Int) +(declare-fun x_799 () Int) +(declare-fun x_423 () Int) +(declare-fun x_808 () Int) +(declare-fun x_303 () Int) +(declare-fun x_536 () Int) +(declare-fun x_344 () Int) +(declare-fun x_322 () Int) +(declare-fun x_299 () Int) +(declare-fun x_976 () Int) +(declare-fun x_279 () Int) +(declare-fun x_482 () Int) +(declare-fun x_246 () Int) +(declare-fun x_763 () Int) +(declare-fun x_111 () Int) +(declare-fun x_226 () Int) +(declare-fun x_741 () Int) +(declare-fun x_188 () Int) +(declare-fun x_873 () Int) +(declare-fun x_767 () Int) +(declare-fun x_766 () Int) +(declare-fun x_7 () Int) +(declare-fun x_377 () Int) +(declare-fun x_719 () Int) +(declare-fun x_704 () Int) +(declare-fun x_72 () Int) +(declare-fun x_27 () Int) +(declare-fun x_284 () Int) +(declare-fun x_943 () Int) +(declare-fun x_42 () Int) +(declare-fun x_881 () Int) +(declare-fun x_693 () Int) +(declare-fun x_422 () Int) +(declare-fun x_218 () Int) +(declare-fun x_736 () Int) +(declare-fun x_817 () Int) +(declare-fun x_168 () Int) +(declare-fun x_359 () Int) +(declare-fun x_16 () Int) +(declare-fun x_469 () Int) +(declare-fun x_814 () Int) +(declare-fun x_62 () Int) +(declare-fun x_461 () Int) +(declare-fun x_483 () Int) +(declare-fun x_68 () Int) +(declare-fun x_786 () Int) +(declare-fun x_938 () Int) +(declare-fun x_204 () Int) +(declare-fun x_718 () Int) +(declare-fun x_197 () Int) +(declare-fun x_603 () Int) +(declare-fun x_616 () Int) +(declare-fun x_117 () Int) +(declare-fun x_567 () Int) +(declare-fun x_729 () Int) +(declare-fun x_942 () Int) +(declare-fun x_748 () Int) +(declare-fun x_992 () Int) +(declare-fun x_713 () Int) +(declare-fun x_326 () Int) +(declare-fun x_689 () Int) +(declare-fun x_948 () Int) +(declare-fun x_717 () Int) +(declare-fun x_403 () Int) +(declare-fun x_872 () Int) +(declare-fun x_73 () Int) +(declare-fun x_639 () Int) +(declare-fun x_137 () Int) +(declare-fun x_373 () Int) +(declare-fun x_364 () Int) +(declare-fun x_576 () Int) +(declare-fun x_358 () Int) +(declare-fun x_466 () Int) +(declare-fun x_122 () Int) +(declare-fun x_637 () Int) +(declare-fun x_202 () Int) +(declare-fun x_476 () Int) +(declare-fun x_44 () Int) +(declare-fun x_151 () Int) +(declare-fun x_253 () Int) +(declare-fun x_696 () Int) +(declare-fun x_822 () Int) +(declare-fun x_641 () Int) +(declare-fun x_924 () Int) +(declare-fun x_233 () Int) +(declare-fun x_136 () Int) +(declare-fun x_222 () Int) +(declare-fun x_318 () Int) +(declare-fun x_694 () Int) +(declare-fun x_543 () Int) +(declare-fun x_141 () Int) +(declare-fun x_418 () Int) +(declare-fun x_409 () Int) +(declare-fun x_601 () Int) +(declare-fun x_339 () Int) +(declare-fun x_958 () Int) +(declare-fun x_773 () Int) +(declare-fun x_448 () Int) +(declare-fun x_508 () Int) +(declare-fun x_104 () Int) +(declare-fun x_674 () Int) +(declare-fun x_991 () Int) +(declare-fun x_406 () Int) +(declare-fun x_283 () Int) +(declare-fun x_552 () Int) +(declare-fun x_907 () Int) +(declare-fun x_408 () Int) +(declare-fun x_451 () Int) +(declare-fun x_897 () Int) +(declare-fun x_503 () Int) +(declare-fun x_672 () Int) +(declare-fun x_264 () Int) +(declare-fun x_382 () Int) +(declare-fun x_554 () Int) +(declare-fun x_561 () Int) +(declare-fun x_11 () Int) +(declare-fun x_329 () Int) +(declare-fun x_727 () Int) +(declare-fun x_97 () Int) +(declare-fun x_343 () Int) +(declare-fun x_918 () Int) +(declare-fun x_289 () Int) +(declare-fun x_803 () Int) +(declare-fun x_812 () Int) +(declare-fun x_547 () Int) +(declare-fun x_806 () Int) +(declare-fun x_252 () Int) +(declare-fun x_273 () Int) +(declare-fun x_618 () Int) +(declare-fun x_301 () Int) +(declare-fun x_688 () Int) +(declare-fun x_224 () Int) +(declare-fun x_449 () Int) +(declare-fun x_327 () Int) +(declare-fun x_387 () Int) +(declare-fun x_86 () Int) +(declare-fun x_89 () Int) +(declare-fun x_404 () Int) +(declare-fun x_507 () Int) +(declare-fun x_312 () Int) +(declare-fun x_578 () Int) +(declare-fun x_722 () Int) +(declare-fun x_762 () Int) +(declare-fun x_169 () Int) +(declare-fun x_206 () Int) +(declare-fun x_383 () Int) +(declare-fun x_867 () Int) +(declare-fun x_627 () Int) +(declare-fun x_638 () Int) +(declare-fun x_184 () Int) +(declare-fun x_479 () Int) +(declare-fun x_292 () Int) +(declare-fun x_844 () Int) +(declare-fun x_421 () Int) +(declare-fun x_911 () Int) +(declare-fun x_419 () Int) +(declare-fun x_612 () Int) +(declare-fun x_192 () Int) +(declare-fun x_656 () Int) +(declare-fun x_702 () Int) +(declare-fun x_778 () Int) +(declare-fun x_281 () Int) +(declare-fun x_834 () Int) +(declare-fun x_63 () Int) +(declare-fun x_836 () Int) +(declare-fun x_793 () Int) +(declare-fun x_622 () Int) +(declare-fun x_899 () Int) +(declare-fun x_944 () Int) +(declare-fun x_369 () Int) +(declare-fun x_336 () Int) +(declare-fun x_869 () Int) +(declare-fun x_257 () Int) +(declare-fun x_1001 () Int) +(declare-fun x_904 () Int) +(declare-fun x_528 () Int) +(declare-fun x_997 () Int) +(declare-fun x_414 () Int) +(declare-fun x_223 () Int) +(declare-fun x_642 () Int) +(declare-fun x_76 () Int) +(declare-fun x_29 () Int) +(declare-fun x_533 () Int) +(declare-fun x_41 () Int) +(declare-fun x_581 () Int) +(declare-fun x_791 () Int) +(declare-fun x_809 () Int) +(declare-fun x_321 () Int) +(declare-fun x_939 () Int) +(declare-fun x_541 () Int) +(declare-fun x_652 () Int) +(declare-fun x_569 () Int) +(declare-fun x_934 () Int) +(declare-fun x_207 () Int) +(declare-fun x_376 () Int) +(declare-fun x_109 () Int) +(declare-fun x_761 () Int) +(declare-fun x_446 () Int) +(declare-fun x_657 () Int) +(declare-fun x_171 () Int) +(declare-fun x_558 () Int) +(declare-fun x_276 () Int) +(declare-fun x_46 () Int) +(declare-fun x_668 () Int) +(declare-fun x_57 () Int) +(declare-fun x_374 () Int) +(declare-fun x_209 () Int) +(declare-fun x_739 () Int) +(declare-fun x_909 () Int) +(declare-fun x_468 () Int) +(declare-fun x_14 () Int) +(declare-fun x_832 () Int) +(declare-fun x_391 () Int) +(declare-fun x_517 () Int) +(declare-fun x_12 () Int) +(declare-fun x_244 () Int) +(declare-fun x_628 () Int) +(declare-fun x_334 () Int) +(declare-fun x_502 () Int) +(declare-fun x_883 () Int) +(declare-fun x_379 () Int) +(declare-fun x_307 () Int) +(declare-fun x_182 () Int) +(declare-fun x_293 () Int) +(declare-fun x_288 () Int) +(declare-fun x_633 () Int) +(declare-fun x_866 () Int) +(declare-fun x_571 () Int) +(declare-fun x_842 () Int) +(declare-fun x_921 () Int) +(declare-fun x_797 () Int) +(declare-fun x_153 () Int) +(declare-fun x_398 () Int) +(declare-fun x_583 () Int) +(declare-fun x_683 () Int) +(declare-fun x_189 () Int) +(declare-fun x_964 () Int) +(declare-fun x_164 () Int) +(declare-fun x_474 () Int) +(declare-fun x_521 () Int) +(declare-fun x_21 () Int) +(declare-fun x_518 () Int) +(declare-fun x_473 () Int) +(declare-fun x_896 () Int) +(declare-fun x_796 () Int) +(declare-fun x_477 () Int) +(declare-fun x_74 () Int) +(declare-fun x_116 () Int) +(declare-fun x_837 () Int) +(declare-fun x_673 () Int) +(declare-fun x_309 () Int) +(declare-fun x_58 () Int) +(declare-fun x_428 () Int) +(declare-fun x_589 () Int) +(declare-fun x_747 () Int) +(declare-fun x_929 () Int) +(declare-fun x_529 () Int) +(declare-fun x_413 () Int) +(declare-fun x_847 () Int) +(declare-fun x_262 () Int) +(declare-fun x_801 () Int) +(declare-fun x_952 () Int) +(declare-fun x_632 () Int) +(declare-fun x_142 () Int) +(declare-fun x_491 () Int) +(declare-fun x_546 () Int) +(declare-fun x_839 () Int) +(declare-fun x_588 () Int) +(declare-fun x_393 () Int) +(declare-fun x_118 () Int) +(declare-fun x_901 () Int) +(declare-fun x_962 () Int) +(declare-fun x_968 () Int) +(declare-fun x_886 () Int) +(declare-fun x_774 () Int) +(declare-fun x_487 () Int) +(declare-fun x_127 () Int) +(declare-fun x_237 () Int) +(declare-fun x_723 () Int) +(declare-fun x_542 () Int) +(declare-fun x_753 () Int) +(declare-fun x_129 () Int) +(declare-fun x_864 () Int) +(declare-fun x_611 () Int) +(declare-fun x_416 () Int) +(declare-fun x_947 () Int) +(declare-fun x_1202 () Int) +(declare-fun x_563 () Int) +(declare-fun x_337 () Int) +(declare-fun x_544 () Int) +(declare-fun x_654 () Int) +(declare-fun x_756 () Int) +(declare-fun x_744 () Int) +(declare-fun x_891 () Int) +(declare-fun x_378 () Int) +(declare-fun x_134 () Int) +(declare-fun x_208 () Int) +(declare-fun x_758 () Int) +(declare-fun x_848 () Int) +(declare-fun x_927 () Int) +(declare-fun x_937 () Int) +(declare-fun x_602 () Int) +(declare-fun x_349 () Int) +(declare-fun x_96 () Int) +(declare-fun x_162 () Int) +(declare-fun x_37 () Int) +(declare-fun x_941 () Int) +(declare-fun x_906 () Int) +(declare-fun x_811 () Int) +(declare-fun x_138 () Int) +(declare-fun x_621 () Int) +(declare-fun x_492 () Int) +(declare-fun x_764 () Int) +(declare-fun x_452 () Int) +(declare-fun x_851 () Int) +(declare-fun x_98 () Int) +(declare-fun x_236 () Int) +(declare-fun x_453 () Int) +(declare-fun x_978 () Int) +(declare-fun x_499 () Int) +(declare-fun x_494 () Int) +(declare-fun x_316 () Int) +(declare-fun x_587 () Int) +(declare-fun x_103 () Int) +(declare-fun x_734 () Int) +(declare-fun x_923 () Int) +(declare-fun x_228 () Int) +(declare-fun x_504 () Int) +(declare-fun x_564 () Int) +(declare-fun x_592 () Int) +(declare-fun x_2 () Int) +(declare-fun x_539 () Int) +(declare-fun x_247 () Int) +(declare-fun x_931 () Int) +(declare-fun x_903 () Int) +(declare-fun x_64 () Int) +(declare-fun x_232 () Int) +(declare-fun x_298 () Int) +(declare-fun x_126 () Int) +(declare-fun x_787 () Int) +(declare-fun x_243 () Int) +(declare-fun x_356 () Int) +(declare-fun x_709 () Int) +(declare-fun x_823 () Int) +(declare-fun x_338 () Int) +(declare-fun x_201 () Int) +(declare-fun x_304 () Int) +(declare-fun x_101 () Int) +(declare-fun x_568 () Int) +(declare-fun x_573 () Int) +(declare-fun x_28 () Int) +(declare-fun x_516 () Int) +(declare-fun x_619 () Int) +(declare-fun x_102 () Int) +(declare-fun x_92 () Int) +(declare-fun x_604 () Int) +(declare-fun x_597 () Int) +(declare-fun x_663 () Int) +(declare-fun x_731 () Int) +(declare-fun x_328 () Int) +(declare-fun x_143 () Int) +(declare-fun x_849 () Int) +(declare-fun x_128 () Int) +(declare-fun x_266 () Int) +(declare-fun x_203 () Int) +(declare-fun x_661 () Int) +(declare-fun x_996 () Int) +(declare-fun x_462 () Int) +(declare-fun x_977 () Int) +(declare-fun x_458 () Int) +(declare-fun x_933 () Int) +(declare-fun x_94 () Int) +(declare-fun x_332 () Int) +(declare-fun x_514 () Int) +(declare-fun x_969 () Int) +(declare-fun x_987 () Int) +(declare-fun x_497 () Int) +(declare-fun x_666 () Int) +(declare-fun x_858 () Int) +(declare-fun x_643 () Int) +(declare-fun x_523 () Int) +(declare-fun x_609 () Int) +(declare-fun x_263 () Int) +(declare-fun x_878 () Int) +(declare-fun x_981 () Int) +(declare-fun x_863 () Int) +(declare-fun x_324 () Int) +(declare-fun x_783 () Int) +(declare-fun x_241 () Int) +(declare-fun x_407 () Int) +(declare-fun x_708 () Int) +(declare-fun x_862 () Int) +(declare-fun x_757 () Int) +(declare-fun x_251 () Int) +(declare-fun x_771 () Int) +(declare-fun x_478 () Int) +(declare-fun x_437 () Int) +(declare-fun x_267 () Int) +(declare-fun x_599 () Int) +(declare-fun x_234 () Int) +(declare-fun x_177 () Int) +(declare-fun x_726 () Int) +(declare-fun x_261 () Int) +(declare-fun x_353 () Int) +(declare-fun x_732 () Int) +(declare-fun x_908 () Int) +(declare-fun x_361 () Int) +(declare-fun x_887 () Int) +(declare-fun x_488 () Int) +(declare-fun x_917 () Int) +(declare-fun x_716 () Int) +(declare-fun x_166 () Int) +(declare-fun x_112 () Int) +(declare-fun x_629 () Int) +(declare-fun x_52 () Int) +(declare-fun x_34 () Int) +(declare-fun x_183 () Int) +(declare-fun x_999 () Int) +(declare-fun x_99 () Int) +(declare-fun x_444 () Int) +(declare-fun x_424 () Int) +(declare-fun x_317 () Int) +(declare-fun x_784 () Int) +(declare-fun x_584 () Int) +(declare-fun x_282 () Int) +(declare-fun x_743 () Int) +(declare-fun x_56 () Int) +(declare-fun x_749 () Int) +(declare-fun x_411 () Int) +(declare-fun x_647 () Int) +(declare-fun x_219 () Int) +(declare-fun x_946 () Int) +(declare-fun x_433 () Int) +(declare-fun x_106 () Int) +(declare-fun x_38 () Int) +(declare-fun x_314 () Int) +(declare-fun x_481 () Int) +(declare-fun x_768 () Int) +(declare-fun x_579 () Int) +(declare-fun x_114 () Int) +(declare-fun x_894 () Int) +(declare-fun x_146 () Int) +(declare-fun x_577 () Int) +(declare-fun x_394 () Int) +(declare-fun x_566 () Int) +(declare-fun x_738 () Int) +(declare-fun x_506 () Int) +(declare-fun x_351 () Int) +(declare-fun x_493 () Int) +(declare-fun x_624 () Int) +(declare-fun x_653 () Int) +(declare-fun x_386 () Int) +(declare-fun x_526 () Int) +(declare-fun x_148 () Int) +(declare-fun x_131 () Int) +(declare-fun x_669 () Int) +(declare-fun x_982 () Int) +(declare-fun x_664 () Int) +(declare-fun x_501 () Int) +(declare-fun x_856 () Int) +(declare-fun x_828 () Int) +(declare-fun x_161 () Int) +(declare-fun x_772 () Int) +(declare-fun x_147 () Int) +(declare-fun x_967 () Int) +(declare-fun x_313 () Int) +(declare-fun x_681 () Int) +(declare-fun x_724 () Int) +(declare-fun x_636 () Int) +(declare-fun x_83 () Int) +(declare-fun x_754 () Int) +(declare-fun x_484 () Int) +(declare-fun x_49 () Int) +(declare-fun x_703 () Int) +(declare-fun x_36 () Int) +(declare-fun x_152 () Int) +(declare-fun x_187 () Int) +(declare-fun x_752 () Int) +(declare-fun x_191 () Int) +(declare-fun x_634 () Int) +(declare-fun x_788 () Int) +(declare-fun x_259 () Int) +(declare-fun x_431 () Int) +(declare-fun x_509 () Int) +(declare-fun x_93 () Int) +(declare-fun x_9 () Int) +(declare-fun x_513 () Int) +(declare-fun x_248 () Int) +(declare-fun x_272 () Int) +(declare-fun x_751 () Int) +(declare-fun x_686 () Int) +(declare-fun x_714 () Int) +(declare-fun x_807 () Int) +(declare-fun x_922 () Int) +(declare-fun x_81 () Int) +(declare-fun x_613 () Int) +(declare-fun x_928 () Int) +(declare-fun x_1604 () Int) +(declare-fun x_78 () Int) +(declare-fun x_249 () Int) +(declare-fun x_79 () Int) +(declare-fun x_649 () Int) +(declare-fun x_781 () Int) +(declare-fun x_687 () Int) +(declare-fun x_82 () Int) +(declare-fun x_804 () Int) +(declare-fun x_441 () Int) +(declare-fun x_651 () Int) +(declare-fun x_936 () Int) +(declare-fun x_1 () Int) +(declare-fun x_179 () Int) +(declare-fun x_199 () Int) +(declare-fun x_623 () Int) +(declare-fun x_794 () Int) +(declare-fun x_777 () Int) +(declare-fun x_214 () Int) +(declare-fun x_296 () Int) +(declare-fun x_949 () Int) +(declare-fun x_133 () Int) +(declare-fun x_829 () Int) +(declare-fun x_556 () Int) +(declare-fun x_617 () Int) +(declare-fun x_18 () Int) +(declare-fun x_728 () Int) +(declare-fun x_426 () Int) +(declare-fun x_898 () Int) +(declare-fun x_23 () Int) +(declare-fun x_843 () Int) +(declare-fun x_827 () Int) +(declare-fun x_831 () Int) +(declare-fun x_954 () Int) +(declare-fun x_341 () Int) +(declare-fun x_956 () Int) +(declare-fun x_983 () Int) +(declare-fun x_606 () Int) +(declare-fun x_874 () Int) +(declare-fun x_698 () Int) +(declare-fun x_782 () Int) +(declare-fun x_48 () Int) +(declare-fun x_172 () Int) +(declare-fun x_342 () Int) +(declare-fun x_238 () Int) +(declare-fun x_323 () Int) +(declare-fun x_608 () Int) +(declare-fun x_471 () Int) +(declare-fun x_216 () Int) +(declare-fun x_69 () Int) +(declare-fun x_438 () Int) +(declare-fun x_534 () Int) +(declare-fun x_368 () Int) +(declare-fun x_193 () Int) +(declare-fun x_532 () Int) +(declare-fun x_951 () Int) +(declare-fun x_258 () Int) +(declare-fun x_853 () Int) +(declare-fun x_132 () Int) +(declare-fun x_159 () Int) +(declare-fun x_217 () Int) +(declare-fun x_742 () Int) +(declare-fun x_311 () Int) +(declare-fun x_1403 () Int) +(declare-fun x_176 () Int) +(declare-fun x_254 () Int) +(declare-fun x_66 () Int) +(declare-fun x_144 () Int) +(declare-fun x_998 () Int) +(assert (<= 0 x_1)) +(assert (>= 1 x_1)) +(assert (<= 0 x_2)) +(assert (>= 1 x_2)) +(assert (<= 0 x_3)) +(assert (>= 1 x_3)) +(assert (<= 0 x_4)) +(assert (>= 1 x_4)) +(assert (<= 0 x_6)) +(assert (>= 1 x_6)) +(assert (<= 0 x_7)) +(assert (>= 1 x_7)) +(assert (<= 0 x_8)) +(assert (>= 1 x_8)) +(assert (<= 0 x_9)) +(assert (>= 1 x_9)) +(assert (<= 0 x_11)) +(assert (>= 1 x_11)) +(assert (<= 0 x_12)) +(assert (>= 1 x_12)) +(assert (<= 0 x_13)) +(assert (>= 1 x_13)) +(assert (<= 0 x_14)) +(assert (>= 1 x_14)) +(assert (<= 0 x_16)) +(assert (>= 1 x_16)) +(assert (<= 0 x_17)) +(assert (>= 1 x_17)) +(assert (<= 0 x_18)) +(assert (>= 1 x_18)) +(assert (<= 0 x_19)) +(assert (>= 1 x_19)) +(assert (<= 0 x_21)) +(assert (>= 1 x_21)) +(assert (<= 0 x_22)) +(assert (>= 1 x_22)) +(assert (<= 0 x_23)) +(assert (>= 1 x_23)) +(assert (<= 0 x_24)) +(assert (>= 1 x_24)) +(assert (<= 0 x_26)) +(assert (>= 1 x_26)) +(assert (<= 0 x_27)) +(assert (>= 1 x_27)) +(assert (<= 0 x_28)) +(assert (>= 1 x_28)) +(assert (<= 0 x_29)) +(assert (>= 1 x_29)) +(assert (<= 0 x_31)) +(assert (>= 1 x_31)) +(assert (<= 0 x_32)) +(assert (>= 1 x_32)) +(assert (<= 0 x_33)) +(assert (>= 1 x_33)) +(assert (<= 0 x_34)) +(assert (>= 1 x_34)) +(assert (<= 0 x_36)) +(assert (>= 1 x_36)) +(assert (<= 0 x_37)) +(assert (>= 1 x_37)) +(assert (<= 0 x_38)) +(assert (>= 1 x_38)) +(assert (<= 0 x_39)) +(assert (>= 1 x_39)) +(assert (<= 0 x_41)) +(assert (>= 1 x_41)) +(assert (<= 0 x_42)) +(assert (>= 1 x_42)) +(assert (<= 0 x_43)) +(assert (>= 1 x_43)) +(assert (<= 0 x_44)) +(assert (>= 1 x_44)) +(assert (<= 0 x_46)) +(assert (>= 1 x_46)) +(assert (<= 0 x_47)) +(assert (>= 1 x_47)) +(assert (<= 0 x_48)) +(assert (>= 1 x_48)) +(assert (<= 0 x_49)) +(assert (>= 1 x_49)) +(assert (<= 0 x_51)) +(assert (>= 1 x_51)) +(assert (<= 0 x_52)) +(assert (>= 1 x_52)) +(assert (<= 0 x_53)) +(assert (>= 1 x_53)) +(assert (<= 0 x_54)) +(assert (>= 1 x_54)) +(assert (<= 0 x_56)) +(assert (>= 1 x_56)) +(assert (<= 0 x_57)) +(assert (>= 1 x_57)) +(assert (<= 0 x_58)) +(assert (>= 1 x_58)) +(assert (<= 0 x_59)) +(assert (>= 1 x_59)) +(assert (<= 0 x_61)) +(assert (>= 1 x_61)) +(assert (<= 0 x_62)) +(assert (>= 1 x_62)) +(assert (<= 0 x_63)) +(assert (>= 1 x_63)) +(assert (<= 0 x_64)) +(assert (>= 1 x_64)) +(assert (<= 0 x_66)) +(assert (>= 1 x_66)) +(assert (<= 0 x_67)) +(assert (>= 1 x_67)) +(assert (<= 0 x_68)) +(assert (>= 1 x_68)) +(assert (<= 0 x_69)) +(assert (>= 1 x_69)) +(assert (<= 0 x_71)) +(assert (>= 1 x_71)) +(assert (<= 0 x_72)) +(assert (>= 1 x_72)) +(assert (<= 0 x_73)) +(assert (>= 1 x_73)) +(assert (<= 0 x_74)) +(assert (>= 1 x_74)) +(assert (<= 0 x_76)) +(assert (>= 1 x_76)) +(assert (<= 0 x_77)) +(assert (>= 1 x_77)) +(assert (<= 0 x_78)) +(assert (>= 1 x_78)) +(assert (<= 0 x_79)) +(assert (>= 1 x_79)) +(assert (<= 0 x_81)) +(assert (>= 1 x_81)) +(assert (<= 0 x_82)) +(assert (>= 1 x_82)) +(assert (<= 0 x_83)) +(assert (>= 1 x_83)) +(assert (<= 0 x_84)) +(assert (>= 1 x_84)) +(assert (<= 0 x_86)) +(assert (>= 1 x_86)) +(assert (<= 0 x_87)) +(assert (>= 1 x_87)) +(assert (<= 0 x_88)) +(assert (>= 1 x_88)) +(assert (<= 0 x_89)) +(assert (>= 1 x_89)) +(assert (<= 0 x_91)) +(assert (>= 1 x_91)) +(assert (<= 0 x_92)) +(assert (>= 1 x_92)) +(assert (<= 0 x_93)) +(assert (>= 1 x_93)) +(assert (<= 0 x_94)) +(assert (>= 1 x_94)) +(assert (<= 0 x_96)) +(assert (>= 1 x_96)) +(assert (<= 0 x_97)) +(assert (>= 1 x_97)) +(assert (<= 0 x_98)) +(assert (>= 1 x_98)) +(assert (<= 0 x_99)) +(assert (>= 1 x_99)) +(assert (<= 0 x_101)) +(assert (>= 1 x_101)) +(assert (<= 0 x_102)) +(assert (>= 1 x_102)) +(assert (<= 0 x_103)) +(assert (>= 1 x_103)) +(assert (<= 0 x_104)) +(assert (>= 1 x_104)) +(assert (<= 0 x_106)) +(assert (>= 1 x_106)) +(assert (<= 0 x_107)) +(assert (>= 1 x_107)) +(assert (<= 0 x_108)) +(assert (>= 1 x_108)) +(assert (<= 0 x_109)) +(assert (>= 1 x_109)) +(assert (<= 0 x_111)) +(assert (>= 1 x_111)) +(assert (<= 0 x_112)) +(assert (>= 1 x_112)) +(assert (<= 0 x_113)) +(assert (>= 1 x_113)) +(assert (<= 0 x_114)) +(assert (>= 1 x_114)) +(assert (<= 0 x_116)) +(assert (>= 1 x_116)) +(assert (<= 0 x_117)) +(assert (>= 1 x_117)) +(assert (<= 0 x_118)) +(assert (>= 1 x_118)) +(assert (<= 0 x_119)) +(assert (>= 1 x_119)) +(assert (<= 0 x_121)) +(assert (>= 1 x_121)) +(assert (<= 0 x_122)) +(assert (>= 1 x_122)) +(assert (<= 0 x_123)) +(assert (>= 1 x_123)) +(assert (<= 0 x_124)) +(assert (>= 1 x_124)) +(assert (<= 0 x_126)) +(assert (>= 1 x_126)) +(assert (<= 0 x_127)) +(assert (>= 1 x_127)) +(assert (<= 0 x_128)) +(assert (>= 1 x_128)) +(assert (<= 0 x_129)) +(assert (>= 1 x_129)) +(assert (<= 0 x_131)) +(assert (>= 1 x_131)) +(assert (<= 0 x_132)) +(assert (>= 1 x_132)) +(assert (<= 0 x_133)) +(assert (>= 1 x_133)) +(assert (<= 0 x_134)) +(assert (>= 1 x_134)) +(assert (<= 0 x_136)) +(assert (>= 1 x_136)) +(assert (<= 0 x_137)) +(assert (>= 1 x_137)) +(assert (<= 0 x_138)) +(assert (>= 1 x_138)) +(assert (<= 0 x_139)) +(assert (>= 1 x_139)) +(assert (<= 0 x_141)) +(assert (>= 1 x_141)) +(assert (<= 0 x_142)) +(assert (>= 1 x_142)) +(assert (<= 0 x_143)) +(assert (>= 1 x_143)) +(assert (<= 0 x_144)) +(assert (>= 1 x_144)) +(assert (<= 0 x_146)) +(assert (>= 1 x_146)) +(assert (<= 0 x_147)) +(assert (>= 1 x_147)) +(assert (<= 0 x_148)) +(assert (>= 1 x_148)) +(assert (<= 0 x_149)) +(assert (>= 1 x_149)) +(assert (<= 0 x_151)) +(assert (>= 1 x_151)) +(assert (<= 0 x_152)) +(assert (>= 1 x_152)) +(assert (<= 0 x_153)) +(assert (>= 1 x_153)) +(assert (<= 0 x_154)) +(assert (>= 1 x_154)) +(assert (<= 0 x_156)) +(assert (>= 1 x_156)) +(assert (<= 0 x_157)) +(assert (>= 1 x_157)) +(assert (<= 0 x_158)) +(assert (>= 1 x_158)) +(assert (<= 0 x_159)) +(assert (>= 1 x_159)) +(assert (<= 0 x_161)) +(assert (>= 1 x_161)) +(assert (<= 0 x_162)) +(assert (>= 1 x_162)) +(assert (<= 0 x_163)) +(assert (>= 1 x_163)) +(assert (<= 0 x_164)) +(assert (>= 1 x_164)) +(assert (<= 0 x_166)) +(assert (>= 1 x_166)) +(assert (<= 0 x_167)) +(assert (>= 1 x_167)) +(assert (<= 0 x_168)) +(assert (>= 1 x_168)) +(assert (<= 0 x_169)) +(assert (>= 1 x_169)) +(assert (<= 0 x_171)) +(assert (>= 1 x_171)) +(assert (<= 0 x_172)) +(assert (>= 1 x_172)) +(assert (<= 0 x_173)) +(assert (>= 1 x_173)) +(assert (<= 0 x_174)) +(assert (>= 1 x_174)) +(assert (<= 0 x_176)) +(assert (>= 1 x_176)) +(assert (<= 0 x_177)) +(assert (>= 1 x_177)) +(assert (<= 0 x_178)) +(assert (>= 1 x_178)) +(assert (<= 0 x_179)) +(assert (>= 1 x_179)) +(assert (<= 0 x_181)) +(assert (>= 1 x_181)) +(assert (<= 0 x_182)) +(assert (>= 1 x_182)) +(assert (<= 0 x_183)) +(assert (>= 1 x_183)) +(assert (<= 0 x_184)) +(assert (>= 1 x_184)) +(assert (<= 0 x_186)) +(assert (>= 1 x_186)) +(assert (<= 0 x_187)) +(assert (>= 1 x_187)) +(assert (<= 0 x_188)) +(assert (>= 1 x_188)) +(assert (<= 0 x_189)) +(assert (>= 1 x_189)) +(assert (<= 0 x_191)) +(assert (>= 1 x_191)) +(assert (<= 0 x_192)) +(assert (>= 1 x_192)) +(assert (<= 0 x_193)) +(assert (>= 1 x_193)) +(assert (<= 0 x_194)) +(assert (>= 1 x_194)) +(assert (<= 0 x_196)) +(assert (>= 1 x_196)) +(assert (<= 0 x_197)) +(assert (>= 1 x_197)) +(assert (<= 0 x_198)) +(assert (>= 1 x_198)) +(assert (<= 0 x_199)) +(assert (>= 1 x_199)) +(assert (<= 0 x_201)) +(assert (>= 1 x_201)) +(assert (<= 0 x_202)) +(assert (>= 1 x_202)) +(assert (<= 0 x_203)) +(assert (>= 1 x_203)) +(assert (<= 0 x_204)) +(assert (>= 1 x_204)) +(assert (<= 0 x_206)) +(assert (>= 1 x_206)) +(assert (<= 0 x_207)) +(assert (>= 1 x_207)) +(assert (<= 0 x_208)) +(assert (>= 1 x_208)) +(assert (<= 0 x_209)) +(assert (>= 1 x_209)) +(assert (<= 0 x_211)) +(assert (>= 1 x_211)) +(assert (<= 0 x_212)) +(assert (>= 1 x_212)) +(assert (<= 0 x_213)) +(assert (>= 1 x_213)) +(assert (<= 0 x_214)) +(assert (>= 1 x_214)) +(assert (<= 0 x_216)) +(assert (>= 1 x_216)) +(assert (<= 0 x_217)) +(assert (>= 1 x_217)) +(assert (<= 0 x_218)) +(assert (>= 1 x_218)) +(assert (<= 0 x_219)) +(assert (>= 1 x_219)) +(assert (<= 0 x_221)) +(assert (>= 1 x_221)) +(assert (<= 0 x_222)) +(assert (>= 1 x_222)) +(assert (<= 0 x_223)) +(assert (>= 1 x_223)) +(assert (<= 0 x_224)) +(assert (>= 1 x_224)) +(assert (<= 0 x_226)) +(assert (>= 1 x_226)) +(assert (<= 0 x_227)) +(assert (>= 1 x_227)) +(assert (<= 0 x_228)) +(assert (>= 1 x_228)) +(assert (<= 0 x_229)) +(assert (>= 1 x_229)) +(assert (<= 0 x_231)) +(assert (>= 1 x_231)) +(assert (<= 0 x_232)) +(assert (>= 1 x_232)) +(assert (<= 0 x_233)) +(assert (>= 1 x_233)) +(assert (<= 0 x_234)) +(assert (>= 1 x_234)) +(assert (<= 0 x_236)) +(assert (>= 1 x_236)) +(assert (<= 0 x_237)) +(assert (>= 1 x_237)) +(assert (<= 0 x_238)) +(assert (>= 1 x_238)) +(assert (<= 0 x_239)) +(assert (>= 1 x_239)) +(assert (<= 0 x_241)) +(assert (>= 1 x_241)) +(assert (<= 0 x_242)) +(assert (>= 1 x_242)) +(assert (<= 0 x_243)) +(assert (>= 1 x_243)) +(assert (<= 0 x_244)) +(assert (>= 1 x_244)) +(assert (<= 0 x_246)) +(assert (>= 1 x_246)) +(assert (<= 0 x_247)) +(assert (>= 1 x_247)) +(assert (<= 0 x_248)) +(assert (>= 1 x_248)) +(assert (<= 0 x_249)) +(assert (>= 1 x_249)) +(assert (<= 0 x_251)) +(assert (>= 1 x_251)) +(assert (<= 0 x_252)) +(assert (>= 1 x_252)) +(assert (<= 0 x_253)) +(assert (>= 1 x_253)) +(assert (<= 0 x_254)) +(assert (>= 1 x_254)) +(assert (<= 0 x_256)) +(assert (>= 1 x_256)) +(assert (<= 0 x_257)) +(assert (>= 1 x_257)) +(assert (<= 0 x_258)) +(assert (>= 1 x_258)) +(assert (<= 0 x_259)) +(assert (>= 1 x_259)) +(assert (<= 0 x_261)) +(assert (>= 1 x_261)) +(assert (<= 0 x_262)) +(assert (>= 1 x_262)) +(assert (<= 0 x_263)) +(assert (>= 1 x_263)) +(assert (<= 0 x_264)) +(assert (>= 1 x_264)) +(assert (<= 0 x_266)) +(assert (>= 1 x_266)) +(assert (<= 0 x_267)) +(assert (>= 1 x_267)) +(assert (<= 0 x_268)) +(assert (>= 1 x_268)) +(assert (<= 0 x_269)) +(assert (>= 1 x_269)) +(assert (<= 0 x_271)) +(assert (>= 1 x_271)) +(assert (<= 0 x_272)) +(assert (>= 1 x_272)) +(assert (<= 0 x_273)) +(assert (>= 1 x_273)) +(assert (<= 0 x_274)) +(assert (>= 1 x_274)) +(assert (<= 0 x_276)) +(assert (>= 1 x_276)) +(assert (<= 0 x_277)) +(assert (>= 1 x_277)) +(assert (<= 0 x_278)) +(assert (>= 1 x_278)) +(assert (<= 0 x_279)) +(assert (>= 1 x_279)) +(assert (<= 0 x_281)) +(assert (>= 1 x_281)) +(assert (<= 0 x_282)) +(assert (>= 1 x_282)) +(assert (<= 0 x_283)) +(assert (>= 1 x_283)) +(assert (<= 0 x_284)) +(assert (>= 1 x_284)) +(assert (<= 0 x_286)) +(assert (>= 1 x_286)) +(assert (<= 0 x_287)) +(assert (>= 1 x_287)) +(assert (<= 0 x_288)) +(assert (>= 1 x_288)) +(assert (<= 0 x_289)) +(assert (>= 1 x_289)) +(assert (<= 0 x_291)) +(assert (>= 1 x_291)) +(assert (<= 0 x_292)) +(assert (>= 1 x_292)) +(assert (<= 0 x_293)) +(assert (>= 1 x_293)) +(assert (<= 0 x_294)) +(assert (>= 1 x_294)) +(assert (<= 0 x_296)) +(assert (>= 1 x_296)) +(assert (<= 0 x_297)) +(assert (>= 1 x_297)) +(assert (<= 0 x_298)) +(assert (>= 1 x_298)) +(assert (<= 0 x_299)) +(assert (>= 1 x_299)) +(assert (<= 0 x_301)) +(assert (>= 1 x_301)) +(assert (<= 0 x_302)) +(assert (>= 1 x_302)) +(assert (<= 0 x_303)) +(assert (>= 1 x_303)) +(assert (<= 0 x_304)) +(assert (>= 1 x_304)) +(assert (<= 0 x_306)) +(assert (>= 1 x_306)) +(assert (<= 0 x_307)) +(assert (>= 1 x_307)) +(assert (<= 0 x_308)) +(assert (>= 1 x_308)) +(assert (<= 0 x_309)) +(assert (>= 1 x_309)) +(assert (<= 0 x_311)) +(assert (>= 1 x_311)) +(assert (<= 0 x_312)) +(assert (>= 1 x_312)) +(assert (<= 0 x_313)) +(assert (>= 1 x_313)) +(assert (<= 0 x_314)) +(assert (>= 1 x_314)) +(assert (<= 0 x_316)) +(assert (>= 1 x_316)) +(assert (<= 0 x_317)) +(assert (>= 1 x_317)) +(assert (<= 0 x_318)) +(assert (>= 1 x_318)) +(assert (<= 0 x_319)) +(assert (>= 1 x_319)) +(assert (<= 0 x_321)) +(assert (>= 1 x_321)) +(assert (<= 0 x_322)) +(assert (>= 1 x_322)) +(assert (<= 0 x_323)) +(assert (>= 1 x_323)) +(assert (<= 0 x_324)) +(assert (>= 1 x_324)) +(assert (<= 0 x_326)) +(assert (>= 1 x_326)) +(assert (<= 0 x_327)) +(assert (>= 1 x_327)) +(assert (<= 0 x_328)) +(assert (>= 1 x_328)) +(assert (<= 0 x_329)) +(assert (>= 1 x_329)) +(assert (<= 0 x_331)) +(assert (>= 1 x_331)) +(assert (<= 0 x_332)) +(assert (>= 1 x_332)) +(assert (<= 0 x_333)) +(assert (>= 1 x_333)) +(assert (<= 0 x_334)) +(assert (>= 1 x_334)) +(assert (<= 0 x_336)) +(assert (>= 1 x_336)) +(assert (<= 0 x_337)) +(assert (>= 1 x_337)) +(assert (<= 0 x_338)) +(assert (>= 1 x_338)) +(assert (<= 0 x_339)) +(assert (>= 1 x_339)) +(assert (<= 0 x_341)) +(assert (>= 1 x_341)) +(assert (<= 0 x_342)) +(assert (>= 1 x_342)) +(assert (<= 0 x_343)) +(assert (>= 1 x_343)) +(assert (<= 0 x_344)) +(assert (>= 1 x_344)) +(assert (<= 0 x_346)) +(assert (>= 1 x_346)) +(assert (<= 0 x_347)) +(assert (>= 1 x_347)) +(assert (<= 0 x_348)) +(assert (>= 1 x_348)) +(assert (<= 0 x_349)) +(assert (>= 1 x_349)) +(assert (<= 0 x_351)) +(assert (>= 1 x_351)) +(assert (<= 0 x_352)) +(assert (>= 1 x_352)) +(assert (<= 0 x_353)) +(assert (>= 1 x_353)) +(assert (<= 0 x_354)) +(assert (>= 1 x_354)) +(assert (<= 0 x_356)) +(assert (>= 1 x_356)) +(assert (<= 0 x_357)) +(assert (>= 1 x_357)) +(assert (<= 0 x_358)) +(assert (>= 1 x_358)) +(assert (<= 0 x_359)) +(assert (>= 1 x_359)) +(assert (<= 0 x_361)) +(assert (>= 1 x_361)) +(assert (<= 0 x_362)) +(assert (>= 1 x_362)) +(assert (<= 0 x_363)) +(assert (>= 1 x_363)) +(assert (<= 0 x_364)) +(assert (>= 1 x_364)) +(assert (<= 0 x_366)) +(assert (>= 1 x_366)) +(assert (<= 0 x_367)) +(assert (>= 1 x_367)) +(assert (<= 0 x_368)) +(assert (>= 1 x_368)) +(assert (<= 0 x_369)) +(assert (>= 1 x_369)) +(assert (<= 0 x_371)) +(assert (>= 1 x_371)) +(assert (<= 0 x_372)) +(assert (>= 1 x_372)) +(assert (<= 0 x_373)) +(assert (>= 1 x_373)) +(assert (<= 0 x_374)) +(assert (>= 1 x_374)) +(assert (<= 0 x_376)) +(assert (>= 1 x_376)) +(assert (<= 0 x_377)) +(assert (>= 1 x_377)) +(assert (<= 0 x_378)) +(assert (>= 1 x_378)) +(assert (<= 0 x_379)) +(assert (>= 1 x_379)) +(assert (<= 0 x_381)) +(assert (>= 1 x_381)) +(assert (<= 0 x_382)) +(assert (>= 1 x_382)) +(assert (<= 0 x_383)) +(assert (>= 1 x_383)) +(assert (<= 0 x_384)) +(assert (>= 1 x_384)) +(assert (<= 0 x_386)) +(assert (>= 1 x_386)) +(assert (<= 0 x_387)) +(assert (>= 1 x_387)) +(assert (<= 0 x_388)) +(assert (>= 1 x_388)) +(assert (<= 0 x_389)) +(assert (>= 1 x_389)) +(assert (<= 0 x_391)) +(assert (>= 1 x_391)) +(assert (<= 0 x_392)) +(assert (>= 1 x_392)) +(assert (<= 0 x_393)) +(assert (>= 1 x_393)) +(assert (<= 0 x_394)) +(assert (>= 1 x_394)) +(assert (<= 0 x_396)) +(assert (>= 1 x_396)) +(assert (<= 0 x_397)) +(assert (>= 1 x_397)) +(assert (<= 0 x_398)) +(assert (>= 1 x_398)) +(assert (<= 0 x_399)) +(assert (>= 1 x_399)) +(assert (<= 0 x_401)) +(assert (>= 1 x_401)) +(assert (<= 0 x_402)) +(assert (>= 1 x_402)) +(assert (<= 0 x_403)) +(assert (>= 1 x_403)) +(assert (<= 0 x_404)) +(assert (>= 1 x_404)) +(assert (<= 0 x_406)) +(assert (>= 1 x_406)) +(assert (<= 0 x_407)) +(assert (>= 1 x_407)) +(assert (<= 0 x_408)) +(assert (>= 1 x_408)) +(assert (<= 0 x_409)) +(assert (>= 1 x_409)) +(assert (<= 0 x_411)) +(assert (>= 1 x_411)) +(assert (<= 0 x_412)) +(assert (>= 1 x_412)) +(assert (<= 0 x_413)) +(assert (>= 1 x_413)) +(assert (<= 0 x_414)) +(assert (>= 1 x_414)) +(assert (<= 0 x_416)) +(assert (>= 1 x_416)) +(assert (<= 0 x_417)) +(assert (>= 1 x_417)) +(assert (<= 0 x_418)) +(assert (>= 1 x_418)) +(assert (<= 0 x_419)) +(assert (>= 1 x_419)) +(assert (<= 0 x_421)) +(assert (>= 1 x_421)) +(assert (<= 0 x_422)) +(assert (>= 1 x_422)) +(assert (<= 0 x_423)) +(assert (>= 1 x_423)) +(assert (<= 0 x_424)) +(assert (>= 1 x_424)) +(assert (<= 0 x_426)) +(assert (>= 1 x_426)) +(assert (<= 0 x_427)) +(assert (>= 1 x_427)) +(assert (<= 0 x_428)) +(assert (>= 1 x_428)) +(assert (<= 0 x_429)) +(assert (>= 1 x_429)) +(assert (<= 0 x_431)) +(assert (>= 1 x_431)) +(assert (<= 0 x_432)) +(assert (>= 1 x_432)) +(assert (<= 0 x_433)) +(assert (>= 1 x_433)) +(assert (<= 0 x_434)) +(assert (>= 1 x_434)) +(assert (<= 0 x_436)) +(assert (>= 1 x_436)) +(assert (<= 0 x_437)) +(assert (>= 1 x_437)) +(assert (<= 0 x_438)) +(assert (>= 1 x_438)) +(assert (<= 0 x_439)) +(assert (>= 1 x_439)) +(assert (<= 0 x_441)) +(assert (>= 1 x_441)) +(assert (<= 0 x_442)) +(assert (>= 1 x_442)) +(assert (<= 0 x_443)) +(assert (>= 1 x_443)) +(assert (<= 0 x_444)) +(assert (>= 1 x_444)) +(assert (<= 0 x_446)) +(assert (>= 1 x_446)) +(assert (<= 0 x_447)) +(assert (>= 1 x_447)) +(assert (<= 0 x_448)) +(assert (>= 1 x_448)) +(assert (<= 0 x_449)) +(assert (>= 1 x_449)) +(assert (<= 0 x_451)) +(assert (>= 1 x_451)) +(assert (<= 0 x_452)) +(assert (>= 1 x_452)) +(assert (<= 0 x_453)) +(assert (>= 1 x_453)) +(assert (<= 0 x_454)) +(assert (>= 1 x_454)) +(assert (<= 0 x_456)) +(assert (>= 1 x_456)) +(assert (<= 0 x_457)) +(assert (>= 1 x_457)) +(assert (<= 0 x_458)) +(assert (>= 1 x_458)) +(assert (<= 0 x_459)) +(assert (>= 1 x_459)) +(assert (<= 0 x_461)) +(assert (>= 1 x_461)) +(assert (<= 0 x_462)) +(assert (>= 1 x_462)) +(assert (<= 0 x_463)) +(assert (>= 1 x_463)) +(assert (<= 0 x_464)) +(assert (>= 1 x_464)) +(assert (<= 0 x_466)) +(assert (>= 1 x_466)) +(assert (<= 0 x_467)) +(assert (>= 1 x_467)) +(assert (<= 0 x_468)) +(assert (>= 1 x_468)) +(assert (<= 0 x_469)) +(assert (>= 1 x_469)) +(assert (<= 0 x_471)) +(assert (>= 1 x_471)) +(assert (<= 0 x_472)) +(assert (>= 1 x_472)) +(assert (<= 0 x_473)) +(assert (>= 1 x_473)) +(assert (<= 0 x_474)) +(assert (>= 1 x_474)) +(assert (<= 0 x_476)) +(assert (>= 1 x_476)) +(assert (<= 0 x_477)) +(assert (>= 1 x_477)) +(assert (<= 0 x_478)) +(assert (>= 1 x_478)) +(assert (<= 0 x_479)) +(assert (>= 1 x_479)) +(assert (<= 0 x_481)) +(assert (>= 1 x_481)) +(assert (<= 0 x_482)) +(assert (>= 1 x_482)) +(assert (<= 0 x_483)) +(assert (>= 1 x_483)) +(assert (<= 0 x_484)) +(assert (>= 1 x_484)) +(assert (<= 0 x_486)) +(assert (>= 1 x_486)) +(assert (<= 0 x_487)) +(assert (>= 1 x_487)) +(assert (<= 0 x_488)) +(assert (>= 1 x_488)) +(assert (<= 0 x_489)) +(assert (>= 1 x_489)) +(assert (<= 0 x_491)) +(assert (>= 1 x_491)) +(assert (<= 0 x_492)) +(assert (>= 1 x_492)) +(assert (<= 0 x_493)) +(assert (>= 1 x_493)) +(assert (<= 0 x_494)) +(assert (>= 1 x_494)) +(assert (<= 0 x_496)) +(assert (>= 1 x_496)) +(assert (<= 0 x_497)) +(assert (>= 1 x_497)) +(assert (<= 0 x_498)) +(assert (>= 1 x_498)) +(assert (<= 0 x_499)) +(assert (>= 1 x_499)) +(assert (<= 0 x_501)) +(assert (>= 1 x_501)) +(assert (<= 0 x_502)) +(assert (>= 1 x_502)) +(assert (<= 0 x_503)) +(assert (>= 1 x_503)) +(assert (<= 0 x_504)) +(assert (>= 1 x_504)) +(assert (<= 0 x_506)) +(assert (>= 1 x_506)) +(assert (<= 0 x_507)) +(assert (>= 1 x_507)) +(assert (<= 0 x_508)) +(assert (>= 1 x_508)) +(assert (<= 0 x_509)) +(assert (>= 1 x_509)) +(assert (<= 0 x_511)) +(assert (>= 1 x_511)) +(assert (<= 0 x_512)) +(assert (>= 1 x_512)) +(assert (<= 0 x_513)) +(assert (>= 1 x_513)) +(assert (<= 0 x_514)) +(assert (>= 1 x_514)) +(assert (<= 0 x_516)) +(assert (>= 1 x_516)) +(assert (<= 0 x_517)) +(assert (>= 1 x_517)) +(assert (<= 0 x_518)) +(assert (>= 1 x_518)) +(assert (<= 0 x_519)) +(assert (>= 1 x_519)) +(assert (<= 0 x_521)) +(assert (>= 1 x_521)) +(assert (<= 0 x_522)) +(assert (>= 1 x_522)) +(assert (<= 0 x_523)) +(assert (>= 1 x_523)) +(assert (<= 0 x_524)) +(assert (>= 1 x_524)) +(assert (<= 0 x_526)) +(assert (>= 1 x_526)) +(assert (<= 0 x_527)) +(assert (>= 1 x_527)) +(assert (<= 0 x_528)) +(assert (>= 1 x_528)) +(assert (<= 0 x_529)) +(assert (>= 1 x_529)) +(assert (<= 0 x_531)) +(assert (>= 1 x_531)) +(assert (<= 0 x_532)) +(assert (>= 1 x_532)) +(assert (<= 0 x_533)) +(assert (>= 1 x_533)) +(assert (<= 0 x_534)) +(assert (>= 1 x_534)) +(assert (<= 0 x_536)) +(assert (>= 1 x_536)) +(assert (<= 0 x_537)) +(assert (>= 1 x_537)) +(assert (<= 0 x_538)) +(assert (>= 1 x_538)) +(assert (<= 0 x_539)) +(assert (>= 1 x_539)) +(assert (<= 0 x_541)) +(assert (>= 1 x_541)) +(assert (<= 0 x_542)) +(assert (>= 1 x_542)) +(assert (<= 0 x_543)) +(assert (>= 1 x_543)) +(assert (<= 0 x_544)) +(assert (>= 1 x_544)) +(assert (<= 0 x_546)) +(assert (>= 1 x_546)) +(assert (<= 0 x_547)) +(assert (>= 1 x_547)) +(assert (<= 0 x_548)) +(assert (>= 1 x_548)) +(assert (<= 0 x_549)) +(assert (>= 1 x_549)) +(assert (<= 0 x_551)) +(assert (>= 1 x_551)) +(assert (<= 0 x_552)) +(assert (>= 1 x_552)) +(assert (<= 0 x_553)) +(assert (>= 1 x_553)) +(assert (<= 0 x_554)) +(assert (>= 1 x_554)) +(assert (<= 0 x_556)) +(assert (>= 1 x_556)) +(assert (<= 0 x_557)) +(assert (>= 1 x_557)) +(assert (<= 0 x_558)) +(assert (>= 1 x_558)) +(assert (<= 0 x_559)) +(assert (>= 1 x_559)) +(assert (<= 0 x_561)) +(assert (>= 1 x_561)) +(assert (<= 0 x_562)) +(assert (>= 1 x_562)) +(assert (<= 0 x_563)) +(assert (>= 1 x_563)) +(assert (<= 0 x_564)) +(assert (>= 1 x_564)) +(assert (<= 0 x_566)) +(assert (>= 1 x_566)) +(assert (<= 0 x_567)) +(assert (>= 1 x_567)) +(assert (<= 0 x_568)) +(assert (>= 1 x_568)) +(assert (<= 0 x_569)) +(assert (>= 1 x_569)) +(assert (<= 0 x_571)) +(assert (>= 1 x_571)) +(assert (<= 0 x_572)) +(assert (>= 1 x_572)) +(assert (<= 0 x_573)) +(assert (>= 1 x_573)) +(assert (<= 0 x_574)) +(assert (>= 1 x_574)) +(assert (<= 0 x_576)) +(assert (>= 1 x_576)) +(assert (<= 0 x_577)) +(assert (>= 1 x_577)) +(assert (<= 0 x_578)) +(assert (>= 1 x_578)) +(assert (<= 0 x_579)) +(assert (>= 1 x_579)) +(assert (<= 0 x_581)) +(assert (>= 1 x_581)) +(assert (<= 0 x_582)) +(assert (>= 1 x_582)) +(assert (<= 0 x_583)) +(assert (>= 1 x_583)) +(assert (<= 0 x_584)) +(assert (>= 1 x_584)) +(assert (<= 0 x_586)) +(assert (>= 1 x_586)) +(assert (<= 0 x_587)) +(assert (>= 1 x_587)) +(assert (<= 0 x_588)) +(assert (>= 1 x_588)) +(assert (<= 0 x_589)) +(assert (>= 1 x_589)) +(assert (<= 0 x_591)) +(assert (>= 1 x_591)) +(assert (<= 0 x_592)) +(assert (>= 1 x_592)) +(assert (<= 0 x_593)) +(assert (>= 1 x_593)) +(assert (<= 0 x_594)) +(assert (>= 1 x_594)) +(assert (<= 0 x_596)) +(assert (>= 1 x_596)) +(assert (<= 0 x_597)) +(assert (>= 1 x_597)) +(assert (<= 0 x_598)) +(assert (>= 1 x_598)) +(assert (<= 0 x_599)) +(assert (>= 1 x_599)) +(assert (<= 0 x_601)) +(assert (>= 1 x_601)) +(assert (<= 0 x_602)) +(assert (>= 1 x_602)) +(assert (<= 0 x_603)) +(assert (>= 1 x_603)) +(assert (<= 0 x_604)) +(assert (>= 1 x_604)) +(assert (<= 0 x_606)) +(assert (>= 1 x_606)) +(assert (<= 0 x_607)) +(assert (>= 1 x_607)) +(assert (<= 0 x_608)) +(assert (>= 1 x_608)) +(assert (<= 0 x_609)) +(assert (>= 1 x_609)) +(assert (<= 0 x_611)) +(assert (>= 1 x_611)) +(assert (<= 0 x_612)) +(assert (>= 1 x_612)) +(assert (<= 0 x_613)) +(assert (>= 1 x_613)) +(assert (<= 0 x_614)) +(assert (>= 1 x_614)) +(assert (<= 0 x_616)) +(assert (>= 1 x_616)) +(assert (<= 0 x_617)) +(assert (>= 1 x_617)) +(assert (<= 0 x_618)) +(assert (>= 1 x_618)) +(assert (<= 0 x_619)) +(assert (>= 1 x_619)) +(assert (<= 0 x_621)) +(assert (>= 1 x_621)) +(assert (<= 0 x_622)) +(assert (>= 1 x_622)) +(assert (<= 0 x_623)) +(assert (>= 1 x_623)) +(assert (<= 0 x_624)) +(assert (>= 1 x_624)) +(assert (<= 0 x_626)) +(assert (>= 1 x_626)) +(assert (<= 0 x_627)) +(assert (>= 1 x_627)) +(assert (<= 0 x_628)) +(assert (>= 1 x_628)) +(assert (<= 0 x_629)) +(assert (>= 1 x_629)) +(assert (<= 0 x_631)) +(assert (>= 1 x_631)) +(assert (<= 0 x_632)) +(assert (>= 1 x_632)) +(assert (<= 0 x_633)) +(assert (>= 1 x_633)) +(assert (<= 0 x_634)) +(assert (>= 1 x_634)) +(assert (<= 0 x_636)) +(assert (>= 1 x_636)) +(assert (<= 0 x_637)) +(assert (>= 1 x_637)) +(assert (<= 0 x_638)) +(assert (>= 1 x_638)) +(assert (<= 0 x_639)) +(assert (>= 1 x_639)) +(assert (<= 0 x_641)) +(assert (>= 1 x_641)) +(assert (<= 0 x_642)) +(assert (>= 1 x_642)) +(assert (<= 0 x_643)) +(assert (>= 1 x_643)) +(assert (<= 0 x_644)) +(assert (>= 1 x_644)) +(assert (<= 0 x_646)) +(assert (>= 1 x_646)) +(assert (<= 0 x_647)) +(assert (>= 1 x_647)) +(assert (<= 0 x_648)) +(assert (>= 1 x_648)) +(assert (<= 0 x_649)) +(assert (>= 1 x_649)) +(assert (<= 0 x_651)) +(assert (>= 1 x_651)) +(assert (<= 0 x_652)) +(assert (>= 1 x_652)) +(assert (<= 0 x_653)) +(assert (>= 1 x_653)) +(assert (<= 0 x_654)) +(assert (>= 1 x_654)) +(assert (<= 0 x_656)) +(assert (>= 1 x_656)) +(assert (<= 0 x_657)) +(assert (>= 1 x_657)) +(assert (<= 0 x_658)) +(assert (>= 1 x_658)) +(assert (<= 0 x_659)) +(assert (>= 1 x_659)) +(assert (<= 0 x_661)) +(assert (>= 1 x_661)) +(assert (<= 0 x_662)) +(assert (>= 1 x_662)) +(assert (<= 0 x_663)) +(assert (>= 1 x_663)) +(assert (<= 0 x_664)) +(assert (>= 1 x_664)) +(assert (<= 0 x_666)) +(assert (>= 1 x_666)) +(assert (<= 0 x_667)) +(assert (>= 1 x_667)) +(assert (<= 0 x_668)) +(assert (>= 1 x_668)) +(assert (<= 0 x_669)) +(assert (>= 1 x_669)) +(assert (<= 0 x_671)) +(assert (>= 1 x_671)) +(assert (<= 0 x_672)) +(assert (>= 1 x_672)) +(assert (<= 0 x_673)) +(assert (>= 1 x_673)) +(assert (<= 0 x_674)) +(assert (>= 1 x_674)) +(assert (<= 0 x_676)) +(assert (>= 1 x_676)) +(assert (<= 0 x_677)) +(assert (>= 1 x_677)) +(assert (<= 0 x_678)) +(assert (>= 1 x_678)) +(assert (<= 0 x_679)) +(assert (>= 1 x_679)) +(assert (<= 0 x_681)) +(assert (>= 1 x_681)) +(assert (<= 0 x_682)) +(assert (>= 1 x_682)) +(assert (<= 0 x_683)) +(assert (>= 1 x_683)) +(assert (<= 0 x_684)) +(assert (>= 1 x_684)) +(assert (<= 0 x_686)) +(assert (>= 1 x_686)) +(assert (<= 0 x_687)) +(assert (>= 1 x_687)) +(assert (<= 0 x_688)) +(assert (>= 1 x_688)) +(assert (<= 0 x_689)) +(assert (>= 1 x_689)) +(assert (<= 0 x_691)) +(assert (>= 1 x_691)) +(assert (<= 0 x_692)) +(assert (>= 1 x_692)) +(assert (<= 0 x_693)) +(assert (>= 1 x_693)) +(assert (<= 0 x_694)) +(assert (>= 1 x_694)) +(assert (<= 0 x_696)) +(assert (>= 1 x_696)) +(assert (<= 0 x_697)) +(assert (>= 1 x_697)) +(assert (<= 0 x_698)) +(assert (>= 1 x_698)) +(assert (<= 0 x_699)) +(assert (>= 1 x_699)) +(assert (<= 0 x_701)) +(assert (>= 1 x_701)) +(assert (<= 0 x_702)) +(assert (>= 1 x_702)) +(assert (<= 0 x_703)) +(assert (>= 1 x_703)) +(assert (<= 0 x_704)) +(assert (>= 1 x_704)) +(assert (<= 0 x_706)) +(assert (>= 1 x_706)) +(assert (<= 0 x_707)) +(assert (>= 1 x_707)) +(assert (<= 0 x_708)) +(assert (>= 1 x_708)) +(assert (<= 0 x_709)) +(assert (>= 1 x_709)) +(assert (<= 0 x_711)) +(assert (>= 1 x_711)) +(assert (<= 0 x_712)) +(assert (>= 1 x_712)) +(assert (<= 0 x_713)) +(assert (>= 1 x_713)) +(assert (<= 0 x_714)) +(assert (>= 1 x_714)) +(assert (<= 0 x_716)) +(assert (>= 1 x_716)) +(assert (<= 0 x_717)) +(assert (>= 1 x_717)) +(assert (<= 0 x_718)) +(assert (>= 1 x_718)) +(assert (<= 0 x_719)) +(assert (>= 1 x_719)) +(assert (<= 0 x_721)) +(assert (>= 1 x_721)) +(assert (<= 0 x_722)) +(assert (>= 1 x_722)) +(assert (<= 0 x_723)) +(assert (>= 1 x_723)) +(assert (<= 0 x_724)) +(assert (>= 1 x_724)) +(assert (<= 0 x_726)) +(assert (>= 1 x_726)) +(assert (<= 0 x_727)) +(assert (>= 1 x_727)) +(assert (<= 0 x_728)) +(assert (>= 1 x_728)) +(assert (<= 0 x_729)) +(assert (>= 1 x_729)) +(assert (<= 0 x_731)) +(assert (>= 1 x_731)) +(assert (<= 0 x_732)) +(assert (>= 1 x_732)) +(assert (<= 0 x_733)) +(assert (>= 1 x_733)) +(assert (<= 0 x_734)) +(assert (>= 1 x_734)) +(assert (<= 0 x_736)) +(assert (>= 1 x_736)) +(assert (<= 0 x_737)) +(assert (>= 1 x_737)) +(assert (<= 0 x_738)) +(assert (>= 1 x_738)) +(assert (<= 0 x_739)) +(assert (>= 1 x_739)) +(assert (<= 0 x_741)) +(assert (>= 1 x_741)) +(assert (<= 0 x_742)) +(assert (>= 1 x_742)) +(assert (<= 0 x_743)) +(assert (>= 1 x_743)) +(assert (<= 0 x_744)) +(assert (>= 1 x_744)) +(assert (<= 0 x_746)) +(assert (>= 1 x_746)) +(assert (<= 0 x_747)) +(assert (>= 1 x_747)) +(assert (<= 0 x_748)) +(assert (>= 1 x_748)) +(assert (<= 0 x_749)) +(assert (>= 1 x_749)) +(assert (<= 0 x_751)) +(assert (>= 1 x_751)) +(assert (<= 0 x_752)) +(assert (>= 1 x_752)) +(assert (<= 0 x_753)) +(assert (>= 1 x_753)) +(assert (<= 0 x_754)) +(assert (>= 1 x_754)) +(assert (<= 0 x_756)) +(assert (>= 1 x_756)) +(assert (<= 0 x_757)) +(assert (>= 1 x_757)) +(assert (<= 0 x_758)) +(assert (>= 1 x_758)) +(assert (<= 0 x_759)) +(assert (>= 1 x_759)) +(assert (<= 0 x_761)) +(assert (>= 1 x_761)) +(assert (<= 0 x_762)) +(assert (>= 1 x_762)) +(assert (<= 0 x_763)) +(assert (>= 1 x_763)) +(assert (<= 0 x_764)) +(assert (>= 1 x_764)) +(assert (<= 0 x_766)) +(assert (>= 1 x_766)) +(assert (<= 0 x_767)) +(assert (>= 1 x_767)) +(assert (<= 0 x_768)) +(assert (>= 1 x_768)) +(assert (<= 0 x_769)) +(assert (>= 1 x_769)) +(assert (<= 0 x_771)) +(assert (>= 1 x_771)) +(assert (<= 0 x_772)) +(assert (>= 1 x_772)) +(assert (<= 0 x_773)) +(assert (>= 1 x_773)) +(assert (<= 0 x_774)) +(assert (>= 1 x_774)) +(assert (<= 0 x_776)) +(assert (>= 1 x_776)) +(assert (<= 0 x_777)) +(assert (>= 1 x_777)) +(assert (<= 0 x_778)) +(assert (>= 1 x_778)) +(assert (<= 0 x_779)) +(assert (>= 1 x_779)) +(assert (<= 0 x_781)) +(assert (>= 1 x_781)) +(assert (<= 0 x_782)) +(assert (>= 1 x_782)) +(assert (<= 0 x_783)) +(assert (>= 1 x_783)) +(assert (<= 0 x_784)) +(assert (>= 1 x_784)) +(assert (<= 0 x_786)) +(assert (>= 1 x_786)) +(assert (<= 0 x_787)) +(assert (>= 1 x_787)) +(assert (<= 0 x_788)) +(assert (>= 1 x_788)) +(assert (<= 0 x_789)) +(assert (>= 1 x_789)) +(assert (<= 0 x_791)) +(assert (>= 1 x_791)) +(assert (<= 0 x_792)) +(assert (>= 1 x_792)) +(assert (<= 0 x_793)) +(assert (>= 1 x_793)) +(assert (<= 0 x_794)) +(assert (>= 1 x_794)) +(assert (<= 0 x_796)) +(assert (>= 1 x_796)) +(assert (<= 0 x_797)) +(assert (>= 1 x_797)) +(assert (<= 0 x_798)) +(assert (>= 1 x_798)) +(assert (<= 0 x_799)) +(assert (>= 1 x_799)) +(assert (<= 0 x_801)) +(assert (>= 1 x_801)) +(assert (<= 0 x_802)) +(assert (>= 1 x_802)) +(assert (<= 0 x_803)) +(assert (>= 1 x_803)) +(assert (<= 0 x_804)) +(assert (>= 1 x_804)) +(assert (<= 0 x_806)) +(assert (>= 1 x_806)) +(assert (<= 0 x_807)) +(assert (>= 1 x_807)) +(assert (<= 0 x_808)) +(assert (>= 1 x_808)) +(assert (<= 0 x_809)) +(assert (>= 1 x_809)) +(assert (<= 0 x_811)) +(assert (>= 1 x_811)) +(assert (<= 0 x_812)) +(assert (>= 1 x_812)) +(assert (<= 0 x_813)) +(assert (>= 1 x_813)) +(assert (<= 0 x_814)) +(assert (>= 1 x_814)) +(assert (<= 0 x_816)) +(assert (>= 1 x_816)) +(assert (<= 0 x_817)) +(assert (>= 1 x_817)) +(assert (<= 0 x_818)) +(assert (>= 1 x_818)) +(assert (<= 0 x_819)) +(assert (>= 1 x_819)) +(assert (<= 0 x_821)) +(assert (>= 1 x_821)) +(assert (<= 0 x_822)) +(assert (>= 1 x_822)) +(assert (<= 0 x_823)) +(assert (>= 1 x_823)) +(assert (<= 0 x_824)) +(assert (>= 1 x_824)) +(assert (<= 0 x_826)) +(assert (>= 1 x_826)) +(assert (<= 0 x_827)) +(assert (>= 1 x_827)) +(assert (<= 0 x_828)) +(assert (>= 1 x_828)) +(assert (<= 0 x_829)) +(assert (>= 1 x_829)) +(assert (<= 0 x_831)) +(assert (>= 1 x_831)) +(assert (<= 0 x_832)) +(assert (>= 1 x_832)) +(assert (<= 0 x_833)) +(assert (>= 1 x_833)) +(assert (<= 0 x_834)) +(assert (>= 1 x_834)) +(assert (<= 0 x_836)) +(assert (>= 1 x_836)) +(assert (<= 0 x_837)) +(assert (>= 1 x_837)) +(assert (<= 0 x_838)) +(assert (>= 1 x_838)) +(assert (<= 0 x_839)) +(assert (>= 1 x_839)) +(assert (<= 0 x_841)) +(assert (>= 1 x_841)) +(assert (<= 0 x_842)) +(assert (>= 1 x_842)) +(assert (<= 0 x_843)) +(assert (>= 1 x_843)) +(assert (<= 0 x_844)) +(assert (>= 1 x_844)) +(assert (<= 0 x_846)) +(assert (>= 1 x_846)) +(assert (<= 0 x_847)) +(assert (>= 1 x_847)) +(assert (<= 0 x_848)) +(assert (>= 1 x_848)) +(assert (<= 0 x_849)) +(assert (>= 1 x_849)) +(assert (<= 0 x_851)) +(assert (>= 1 x_851)) +(assert (<= 0 x_852)) +(assert (>= 1 x_852)) +(assert (<= 0 x_853)) +(assert (>= 1 x_853)) +(assert (<= 0 x_854)) +(assert (>= 1 x_854)) +(assert (<= 0 x_856)) +(assert (>= 1 x_856)) +(assert (<= 0 x_857)) +(assert (>= 1 x_857)) +(assert (<= 0 x_858)) +(assert (>= 1 x_858)) +(assert (<= 0 x_859)) +(assert (>= 1 x_859)) +(assert (<= 0 x_861)) +(assert (>= 1 x_861)) +(assert (<= 0 x_862)) +(assert (>= 1 x_862)) +(assert (<= 0 x_863)) +(assert (>= 1 x_863)) +(assert (<= 0 x_864)) +(assert (>= 1 x_864)) +(assert (<= 0 x_866)) +(assert (>= 1 x_866)) +(assert (<= 0 x_867)) +(assert (>= 1 x_867)) +(assert (<= 0 x_868)) +(assert (>= 1 x_868)) +(assert (<= 0 x_869)) +(assert (>= 1 x_869)) +(assert (<= 0 x_871)) +(assert (>= 1 x_871)) +(assert (<= 0 x_872)) +(assert (>= 1 x_872)) +(assert (<= 0 x_873)) +(assert (>= 1 x_873)) +(assert (<= 0 x_874)) +(assert (>= 1 x_874)) +(assert (<= 0 x_876)) +(assert (>= 1 x_876)) +(assert (<= 0 x_877)) +(assert (>= 1 x_877)) +(assert (<= 0 x_878)) +(assert (>= 1 x_878)) +(assert (<= 0 x_879)) +(assert (>= 1 x_879)) +(assert (<= 0 x_881)) +(assert (>= 1 x_881)) +(assert (<= 0 x_882)) +(assert (>= 1 x_882)) +(assert (<= 0 x_883)) +(assert (>= 1 x_883)) +(assert (<= 0 x_884)) +(assert (>= 1 x_884)) +(assert (<= 0 x_886)) +(assert (>= 1 x_886)) +(assert (<= 0 x_887)) +(assert (>= 1 x_887)) +(assert (<= 0 x_888)) +(assert (>= 1 x_888)) +(assert (<= 0 x_889)) +(assert (>= 1 x_889)) +(assert (<= 0 x_891)) +(assert (>= 1 x_891)) +(assert (<= 0 x_892)) +(assert (>= 1 x_892)) +(assert (<= 0 x_893)) +(assert (>= 1 x_893)) +(assert (<= 0 x_894)) +(assert (>= 1 x_894)) +(assert (<= 0 x_896)) +(assert (>= 1 x_896)) +(assert (<= 0 x_897)) +(assert (>= 1 x_897)) +(assert (<= 0 x_898)) +(assert (>= 1 x_898)) +(assert (<= 0 x_899)) +(assert (>= 1 x_899)) +(assert (<= 0 x_901)) +(assert (>= 1 x_901)) +(assert (<= 0 x_902)) +(assert (>= 1 x_902)) +(assert (<= 0 x_903)) +(assert (>= 1 x_903)) +(assert (<= 0 x_904)) +(assert (>= 1 x_904)) +(assert (<= 0 x_906)) +(assert (>= 1 x_906)) +(assert (<= 0 x_907)) +(assert (>= 1 x_907)) +(assert (<= 0 x_908)) +(assert (>= 1 x_908)) +(assert (<= 0 x_909)) +(assert (>= 1 x_909)) +(assert (<= 0 x_911)) +(assert (>= 1 x_911)) +(assert (<= 0 x_912)) +(assert (>= 1 x_912)) +(assert (<= 0 x_913)) +(assert (>= 1 x_913)) +(assert (<= 0 x_914)) +(assert (>= 1 x_914)) +(assert (<= 0 x_916)) +(assert (>= 1 x_916)) +(assert (<= 0 x_917)) +(assert (>= 1 x_917)) +(assert (<= 0 x_918)) +(assert (>= 1 x_918)) +(assert (<= 0 x_919)) +(assert (>= 1 x_919)) +(assert (<= 0 x_921)) +(assert (>= 1 x_921)) +(assert (<= 0 x_922)) +(assert (>= 1 x_922)) +(assert (<= 0 x_923)) +(assert (>= 1 x_923)) +(assert (<= 0 x_924)) +(assert (>= 1 x_924)) +(assert (<= 0 x_926)) +(assert (>= 1 x_926)) +(assert (<= 0 x_927)) +(assert (>= 1 x_927)) +(assert (<= 0 x_928)) +(assert (>= 1 x_928)) +(assert (<= 0 x_929)) +(assert (>= 1 x_929)) +(assert (<= 0 x_931)) +(assert (>= 1 x_931)) +(assert (<= 0 x_932)) +(assert (>= 1 x_932)) +(assert (<= 0 x_933)) +(assert (>= 1 x_933)) +(assert (<= 0 x_934)) +(assert (>= 1 x_934)) +(assert (<= 0 x_936)) +(assert (>= 1 x_936)) +(assert (<= 0 x_937)) +(assert (>= 1 x_937)) +(assert (<= 0 x_938)) +(assert (>= 1 x_938)) +(assert (<= 0 x_939)) +(assert (>= 1 x_939)) +(assert (<= 0 x_941)) +(assert (>= 1 x_941)) +(assert (<= 0 x_942)) +(assert (>= 1 x_942)) +(assert (<= 0 x_943)) +(assert (>= 1 x_943)) +(assert (<= 0 x_944)) +(assert (>= 1 x_944)) +(assert (<= 0 x_946)) +(assert (>= 1 x_946)) +(assert (<= 0 x_947)) +(assert (>= 1 x_947)) +(assert (<= 0 x_948)) +(assert (>= 1 x_948)) +(assert (<= 0 x_949)) +(assert (>= 1 x_949)) +(assert (<= 0 x_951)) +(assert (>= 1 x_951)) +(assert (<= 0 x_952)) +(assert (>= 1 x_952)) +(assert (<= 0 x_953)) +(assert (>= 1 x_953)) +(assert (<= 0 x_954)) +(assert (>= 1 x_954)) +(assert (<= 0 x_956)) +(assert (>= 1 x_956)) +(assert (<= 0 x_957)) +(assert (>= 1 x_957)) +(assert (<= 0 x_958)) +(assert (>= 1 x_958)) +(assert (<= 0 x_959)) +(assert (>= 1 x_959)) +(assert (<= 0 x_961)) +(assert (>= 1 x_961)) +(assert (<= 0 x_962)) +(assert (>= 1 x_962)) +(assert (<= 0 x_963)) +(assert (>= 1 x_963)) +(assert (<= 0 x_964)) +(assert (>= 1 x_964)) +(assert (<= 0 x_966)) +(assert (>= 1 x_966)) +(assert (<= 0 x_967)) +(assert (>= 1 x_967)) +(assert (<= 0 x_968)) +(assert (>= 1 x_968)) +(assert (<= 0 x_969)) +(assert (>= 1 x_969)) +(assert (<= 0 x_971)) +(assert (>= 1 x_971)) +(assert (<= 0 x_972)) +(assert (>= 1 x_972)) +(assert (<= 0 x_973)) +(assert (>= 1 x_973)) +(assert (<= 0 x_974)) +(assert (>= 1 x_974)) +(assert (<= 0 x_976)) +(assert (>= 1 x_976)) +(assert (<= 0 x_977)) +(assert (>= 1 x_977)) +(assert (<= 0 x_978)) +(assert (>= 1 x_978)) +(assert (<= 0 x_979)) +(assert (>= 1 x_979)) +(assert (<= 0 x_981)) +(assert (>= 1 x_981)) +(assert (<= 0 x_982)) +(assert (>= 1 x_982)) +(assert (<= 0 x_983)) +(assert (>= 1 x_983)) +(assert (<= 0 x_984)) +(assert (>= 1 x_984)) +(assert (<= 0 x_986)) +(assert (>= 1 x_986)) +(assert (<= 0 x_987)) +(assert (>= 1 x_987)) +(assert (<= 0 x_988)) +(assert (>= 1 x_988)) +(assert (<= 0 x_989)) +(assert (>= 1 x_989)) +(assert (<= 0 x_991)) +(assert (>= 1 x_991)) +(assert (<= 0 x_992)) +(assert (>= 1 x_992)) +(assert (<= 0 x_993)) +(assert (>= 1 x_993)) +(assert (<= 0 x_994)) +(assert (>= 1 x_994)) +(assert (<= 0 x_996)) +(assert (>= 1 x_996)) +(assert (<= 0 x_997)) +(assert (>= 1 x_997)) +(assert (<= 0 x_998)) +(assert (>= 1 x_998)) +(assert (<= 0 x_999)) +(assert (>= 1 x_999)) +(assert (<= 0 x_1001)) +(assert (>= 1 x_1001)) +(assert (<= 0 x_1202)) +(assert (>= 1 x_1202)) +(assert (<= 0 x_1403)) +(assert (>= 1 x_1403)) +(assert (<= 0 x_1604)) +(assert (>= 1 x_1604)) +(assert (= 1 (+ x_1 x_2 x_3 x_4))) +(assert (= 1 (+ x_6 x_7 x_8 x_9))) +(assert (= 1 (+ x_11 x_12 x_13 x_14))) +(assert (= 1 (+ x_16 x_17 x_18 x_19))) +(assert (= 1 (+ x_21 x_22 x_23 x_24))) +(assert (= 1 (+ x_26 x_27 x_28 x_29))) +(assert (= 1 (+ x_31 x_32 x_33 x_34))) +(assert (= 1 (+ x_36 x_37 x_38 x_39))) +(assert (= 1 (+ x_41 x_42 x_43 x_44))) +(assert (= 1 (+ x_46 x_47 x_48 x_49))) +(assert (= 1 (+ x_51 x_52 x_53 x_54))) +(assert (= 1 (+ x_56 x_57 x_58 x_59))) +(assert (= 1 (+ x_61 x_62 x_63 x_64))) +(assert (= 1 (+ x_66 x_67 x_68 x_69))) +(assert (= 1 (+ x_71 x_72 x_73 x_74))) +(assert (= 1 (+ x_76 x_77 x_78 x_79))) +(assert (= 1 (+ x_81 x_82 x_83 x_84))) +(assert (= 1 (+ x_86 x_87 x_88 x_89))) +(assert (= 1 (+ x_91 x_92 x_93 x_94))) +(assert (= 1 (+ x_96 x_97 x_98 x_99))) +(assert (= 1 (+ x_101 x_102 x_103 x_104))) +(assert (= 1 (+ x_106 x_107 x_108 x_109))) +(assert (= 1 (+ x_111 x_112 x_113 x_114))) +(assert (= 1 (+ x_116 x_117 x_118 x_119))) +(assert (= 1 (+ x_121 x_122 x_123 x_124))) +(assert (= 1 (+ x_126 x_127 x_128 x_129))) +(assert (= 1 (+ x_131 x_132 x_133 x_134))) +(assert (= 1 (+ x_136 x_137 x_138 x_139))) +(assert (= 1 (+ x_141 x_142 x_143 x_144))) +(assert (= 1 (+ x_146 x_147 x_148 x_149))) +(assert (= 1 (+ x_151 x_152 x_153 x_154))) +(assert (= 1 (+ x_156 x_157 x_158 x_159))) +(assert (= 1 (+ x_161 x_162 x_163 x_164))) +(assert (= 1 (+ x_166 x_167 x_168 x_169))) +(assert (= 1 (+ x_171 x_172 x_173 x_174))) +(assert (= 1 (+ x_176 x_177 x_178 x_179))) +(assert (= 1 (+ x_181 x_182 x_183 x_184))) +(assert (= 1 (+ x_186 x_187 x_188 x_189))) +(assert (= 1 (+ x_191 x_192 x_193 x_194))) +(assert (= 1 (+ x_196 x_197 x_198 x_199))) +(assert (= 1 (+ x_201 x_202 x_203 x_204))) +(assert (= 1 (+ x_206 x_207 x_208 x_209))) +(assert (= 1 (+ x_211 x_212 x_213 x_214))) +(assert (= 1 (+ x_216 x_217 x_218 x_219))) +(assert (= 1 (+ x_221 x_222 x_223 x_224))) +(assert (= 1 (+ x_226 x_227 x_228 x_229))) +(assert (= 1 (+ x_231 x_232 x_233 x_234))) +(assert (= 1 (+ x_236 x_237 x_238 x_239))) +(assert (= 1 (+ x_241 x_242 x_243 x_244))) +(assert (= 1 (+ x_246 x_247 x_248 x_249))) +(assert (= 1 (+ x_251 x_252 x_253 x_254))) +(assert (= 1 (+ x_256 x_257 x_258 x_259))) +(assert (= 1 (+ x_261 x_262 x_263 x_264))) +(assert (= 1 (+ x_266 x_267 x_268 x_269))) +(assert (= 1 (+ x_271 x_272 x_273 x_274))) +(assert (= 1 (+ x_276 x_277 x_278 x_279))) +(assert (= 1 (+ x_281 x_282 x_283 x_284))) +(assert (= 1 (+ x_286 x_287 x_288 x_289))) +(assert (= 1 (+ x_291 x_292 x_293 x_294))) +(assert (= 1 (+ x_296 x_297 x_298 x_299))) +(assert (= 1 (+ x_301 x_302 x_303 x_304))) +(assert (= 1 (+ x_306 x_307 x_308 x_309))) +(assert (= 1 (+ x_311 x_312 x_313 x_314))) +(assert (= 1 (+ x_316 x_317 x_318 x_319))) +(assert (= 1 (+ x_321 x_322 x_323 x_324))) +(assert (= 1 (+ x_326 x_327 x_328 x_329))) +(assert (= 1 (+ x_331 x_332 x_333 x_334))) +(assert (= 1 (+ x_336 x_337 x_338 x_339))) +(assert (= 1 (+ x_341 x_342 x_343 x_344))) +(assert (= 1 (+ x_346 x_347 x_348 x_349))) +(assert (= 1 (+ x_351 x_352 x_353 x_354))) +(assert (= 1 (+ x_356 x_357 x_358 x_359))) +(assert (= 1 (+ x_361 x_362 x_363 x_364))) +(assert (= 1 (+ x_366 x_367 x_368 x_369))) +(assert (= 1 (+ x_371 x_372 x_373 x_374))) +(assert (= 1 (+ x_376 x_377 x_378 x_379))) +(assert (= 1 (+ x_381 x_382 x_383 x_384))) +(assert (= 1 (+ x_386 x_387 x_388 x_389))) +(assert (= 1 (+ x_391 x_392 x_393 x_394))) +(assert (= 1 (+ x_396 x_397 x_398 x_399))) +(assert (= 1 (+ x_401 x_402 x_403 x_404))) +(assert (= 1 (+ x_406 x_407 x_408 x_409))) +(assert (= 1 (+ x_411 x_412 x_413 x_414))) +(assert (= 1 (+ x_416 x_417 x_418 x_419))) +(assert (= 1 (+ x_421 x_422 x_423 x_424))) +(assert (= 1 (+ x_426 x_427 x_428 x_429))) +(assert (= 1 (+ x_431 x_432 x_433 x_434))) +(assert (= 1 (+ x_436 x_437 x_438 x_439))) +(assert (= 1 (+ x_441 x_442 x_443 x_444))) +(assert (= 1 (+ x_446 x_447 x_448 x_449))) +(assert (= 1 (+ x_451 x_452 x_453 x_454))) +(assert (= 1 (+ x_456 x_457 x_458 x_459))) +(assert (= 1 (+ x_461 x_462 x_463 x_464))) +(assert (= 1 (+ x_466 x_467 x_468 x_469))) +(assert (= 1 (+ x_471 x_472 x_473 x_474))) +(assert (= 1 (+ x_476 x_477 x_478 x_479))) +(assert (= 1 (+ x_481 x_482 x_483 x_484))) +(assert (= 1 (+ x_486 x_487 x_488 x_489))) +(assert (= 1 (+ x_491 x_492 x_493 x_494))) +(assert (= 1 (+ x_496 x_497 x_498 x_499))) +(assert (= 1 (+ x_501 x_502 x_503 x_504))) +(assert (= 1 (+ x_506 x_507 x_508 x_509))) +(assert (= 1 (+ x_511 x_512 x_513 x_514))) +(assert (= 1 (+ x_516 x_517 x_518 x_519))) +(assert (= 1 (+ x_521 x_522 x_523 x_524))) +(assert (= 1 (+ x_526 x_527 x_528 x_529))) +(assert (= 1 (+ x_531 x_532 x_533 x_534))) +(assert (= 1 (+ x_536 x_537 x_538 x_539))) +(assert (= 1 (+ x_541 x_542 x_543 x_544))) +(assert (= 1 (+ x_546 x_547 x_548 x_549))) +(assert (= 1 (+ x_551 x_552 x_553 x_554))) +(assert (= 1 (+ x_556 x_557 x_558 x_559))) +(assert (= 1 (+ x_561 x_562 x_563 x_564))) +(assert (= 1 (+ x_566 x_567 x_568 x_569))) +(assert (= 1 (+ x_571 x_572 x_573 x_574))) +(assert (= 1 (+ x_576 x_577 x_578 x_579))) +(assert (= 1 (+ x_581 x_582 x_583 x_584))) +(assert (= 1 (+ x_586 x_587 x_588 x_589))) +(assert (= 1 (+ x_591 x_592 x_593 x_594))) +(assert (= 1 (+ x_596 x_597 x_598 x_599))) +(assert (= 1 (+ x_601 x_602 x_603 x_604))) +(assert (= 1 (+ x_606 x_607 x_608 x_609))) +(assert (= 1 (+ x_611 x_612 x_613 x_614))) +(assert (= 1 (+ x_616 x_617 x_618 x_619))) +(assert (= 1 (+ x_621 x_622 x_623 x_624))) +(assert (= 1 (+ x_626 x_627 x_628 x_629))) +(assert (= 1 (+ x_631 x_632 x_633 x_634))) +(assert (= 1 (+ x_636 x_637 x_638 x_639))) +(assert (= 1 (+ x_641 x_642 x_643 x_644))) +(assert (= 1 (+ x_646 x_647 x_648 x_649))) +(assert (= 1 (+ x_651 x_652 x_653 x_654))) +(assert (= 1 (+ x_656 x_657 x_658 x_659))) +(assert (= 1 (+ x_661 x_662 x_663 x_664))) +(assert (= 1 (+ x_666 x_667 x_668 x_669))) +(assert (= 1 (+ x_671 x_672 x_673 x_674))) +(assert (= 1 (+ x_676 x_677 x_678 x_679))) +(assert (= 1 (+ x_681 x_682 x_683 x_684))) +(assert (= 1 (+ x_686 x_687 x_688 x_689))) +(assert (= 1 (+ x_691 x_692 x_693 x_694))) +(assert (= 1 (+ x_696 x_697 x_698 x_699))) +(assert (= 1 (+ x_701 x_702 x_703 x_704))) +(assert (= 1 (+ x_706 x_707 x_708 x_709))) +(assert (= 1 (+ x_711 x_712 x_713 x_714))) +(assert (= 1 (+ x_716 x_717 x_718 x_719))) +(assert (= 1 (+ x_721 x_722 x_723 x_724))) +(assert (= 1 (+ x_726 x_727 x_728 x_729))) +(assert (= 1 (+ x_731 x_732 x_733 x_734))) +(assert (= 1 (+ x_736 x_737 x_738 x_739))) +(assert (= 1 (+ x_741 x_742 x_743 x_744))) +(assert (= 1 (+ x_746 x_747 x_748 x_749))) +(assert (= 1 (+ x_751 x_752 x_753 x_754))) +(assert (= 1 (+ x_756 x_757 x_758 x_759))) +(assert (= 1 (+ x_761 x_762 x_763 x_764))) +(assert (= 1 (+ x_766 x_767 x_768 x_769))) +(assert (= 1 (+ x_771 x_772 x_773 x_774))) +(assert (= 1 (+ x_776 x_777 x_778 x_779))) +(assert (= 1 (+ x_781 x_782 x_783 x_784))) +(assert (= 1 (+ x_786 x_787 x_788 x_789))) +(assert (= 1 (+ x_791 x_792 x_793 x_794))) +(assert (= 1 (+ x_796 x_797 x_798 x_799))) +(assert (= 1 (+ x_801 x_802 x_803 x_804))) +(assert (= 1 (+ x_806 x_807 x_808 x_809))) +(assert (= 1 (+ x_811 x_812 x_813 x_814))) +(assert (= 1 (+ x_816 x_817 x_818 x_819))) +(assert (= 1 (+ x_821 x_822 x_823 x_824))) +(assert (= 1 (+ x_826 x_827 x_828 x_829))) +(assert (= 1 (+ x_831 x_832 x_833 x_834))) +(assert (= 1 (+ x_836 x_837 x_838 x_839))) +(assert (= 1 (+ x_841 x_842 x_843 x_844))) +(assert (= 1 (+ x_846 x_847 x_848 x_849))) +(assert (= 1 (+ x_851 x_852 x_853 x_854))) +(assert (= 1 (+ x_856 x_857 x_858 x_859))) +(assert (= 1 (+ x_861 x_862 x_863 x_864))) +(assert (= 1 (+ x_866 x_867 x_868 x_869))) +(assert (= 1 (+ x_871 x_872 x_873 x_874))) +(assert (= 1 (+ x_876 x_877 x_878 x_879))) +(assert (= 1 (+ x_881 x_882 x_883 x_884))) +(assert (= 1 (+ x_886 x_887 x_888 x_889))) +(assert (= 1 (+ x_891 x_892 x_893 x_894))) +(assert (= 1 (+ x_896 x_897 x_898 x_899))) +(assert (= 1 (+ x_901 x_902 x_903 x_904))) +(assert (= 1 (+ x_906 x_907 x_908 x_909))) +(assert (= 1 (+ x_911 x_912 x_913 x_914))) +(assert (= 1 (+ x_916 x_917 x_918 x_919))) +(assert (= 1 (+ x_921 x_922 x_923 x_924))) +(assert (= 1 (+ x_926 x_927 x_928 x_929))) +(assert (= 1 (+ x_931 x_932 x_933 x_934))) +(assert (= 1 (+ x_936 x_937 x_938 x_939))) +(assert (= 1 (+ x_941 x_942 x_943 x_944))) +(assert (= 1 (+ x_946 x_947 x_948 x_949))) +(assert (= 1 (+ x_951 x_952 x_953 x_954))) +(assert (= 1 (+ x_956 x_957 x_958 x_959))) +(assert (= 1 (+ x_961 x_962 x_963 x_964))) +(assert (= 1 (+ x_966 x_967 x_968 x_969))) +(assert (= 1 (+ x_971 x_972 x_973 x_974))) +(assert (= 1 (+ x_976 x_977 x_978 x_979))) +(assert (= 1 (+ x_981 x_982 x_983 x_984))) +(assert (= 1 (+ x_986 x_987 x_988 x_989))) +(assert (= 1 (+ x_991 x_992 x_993 x_994))) +(assert (= 1 (+ x_996 x_997 x_998 x_999))) +(assert (<= 0 (+ x_1001 (* (- 1) x_4)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_9)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_14)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_19)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_24)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_29)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_34)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_39)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_44)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_49)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_54)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_59)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_64)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_69)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_74)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_79)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_84)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_89)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_94)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_99)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_104)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_109)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_114)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_119)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_124)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_129)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_134)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_139)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_144)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_149)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_154)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_159)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_164)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_169)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_174)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_179)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_184)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_189)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_194)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_199)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_204)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_209)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_214)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_219)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_224)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_229)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_234)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_239)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_244)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_249)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_254)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_259)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_264)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_269)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_274)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_279)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_284)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_289)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_294)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_299)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_304)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_309)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_314)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_319)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_324)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_329)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_334)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_339)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_344)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_349)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_354)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_359)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_364)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_369)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_374)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_379)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_384)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_389)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_394)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_399)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_404)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_409)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_414)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_419)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_424)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_429)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_434)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_439)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_444)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_449)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_454)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_459)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_464)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_469)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_474)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_479)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_484)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_489)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_494)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_499)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_504)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_509)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_514)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_519)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_524)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_529)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_534)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_539)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_544)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_549)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_554)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_559)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_564)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_569)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_574)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_579)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_584)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_589)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_594)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_599)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_604)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_609)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_614)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_619)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_624)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_629)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_634)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_639)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_644)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_649)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_654)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_659)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_664)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_669)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_674)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_679)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_684)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_689)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_694)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_699)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_704)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_709)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_714)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_719)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_724)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_729)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_734)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_739)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_744)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_749)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_754)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_759)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_764)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_769)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_774)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_779)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_784)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_789)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_794)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_799)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_804)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_809)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_814)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_819)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_824)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_829)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_834)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_839)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_844)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_849)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_854)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_859)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_864)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_869)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_874)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_879)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_884)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_889)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_894)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_899)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_904)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_909)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_914)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_919)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_924)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_929)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_934)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_939)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_944)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_949)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_954)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_959)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_964)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_969)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_974)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_979)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_984)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_989)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_994)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_999)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_1)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_6)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_11)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_16)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_21)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_26)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_31)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_36)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_41)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_46)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_51)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_56)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_61)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_66)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_71)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_76)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_81)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_86)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_91)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_96)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_101)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_106)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_111)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_116)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_121)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_126)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_131)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_136)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_141)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_146)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_151)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_156)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_161)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_166)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_171)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_176)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_181)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_186)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_191)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_196)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_201)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_206)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_211)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_216)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_221)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_226)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_231)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_236)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_241)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_246)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_251)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_256)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_261)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_266)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_271)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_276)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_281)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_286)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_291)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_296)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_301)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_306)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_311)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_316)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_321)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_326)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_331)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_336)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_341)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_346)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_351)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_356)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_361)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_366)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_371)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_376)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_381)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_386)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_391)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_396)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_401)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_406)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_411)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_416)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_421)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_426)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_431)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_436)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_441)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_446)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_451)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_456)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_461)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_466)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_471)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_476)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_481)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_486)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_491)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_496)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_501)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_506)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_511)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_516)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_521)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_526)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_531)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_536)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_541)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_546)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_551)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_556)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_561)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_566)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_571)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_576)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_581)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_586)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_591)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_596)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_601)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_606)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_611)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_616)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_621)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_626)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_631)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_636)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_641)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_646)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_651)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_656)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_661)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_666)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_671)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_676)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_681)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_686)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_691)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_696)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_701)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_706)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_711)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_716)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_721)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_726)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_731)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_736)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_741)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_746)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_751)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_756)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_761)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_766)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_771)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_776)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_781)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_786)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_791)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_796)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_801)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_806)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_811)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_816)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_821)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_826)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_831)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_836)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_841)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_846)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_851)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_856)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_861)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_866)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_871)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_876)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_881)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_886)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_891)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_896)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_901)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_906)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_911)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_916)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_921)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_926)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_931)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_936)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_941)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_946)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_951)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_956)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_961)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_966)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_971)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_976)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_981)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_986)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_991)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_996)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_2)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_7)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_12)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_17)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_22)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_27)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_32)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_37)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_42)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_47)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_52)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_57)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_62)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_67)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_72)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_77)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_82)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_87)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_92)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_97)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_102)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_107)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_112)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_117)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_122)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_127)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_132)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_137)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_142)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_147)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_152)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_157)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_162)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_167)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_172)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_177)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_182)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_187)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_192)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_197)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_202)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_207)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_212)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_217)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_222)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_227)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_232)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_237)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_242)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_247)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_252)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_257)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_262)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_267)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_272)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_277)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_282)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_287)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_292)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_297)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_302)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_307)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_312)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_317)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_322)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_327)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_332)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_337)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_342)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_347)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_352)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_357)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_362)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_367)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_372)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_377)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_382)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_387)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_392)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_397)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_402)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_407)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_412)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_417)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_422)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_427)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_432)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_437)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_442)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_447)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_452)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_457)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_462)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_467)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_472)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_477)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_482)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_487)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_492)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_497)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_502)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_507)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_512)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_517)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_522)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_527)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_532)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_537)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_542)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_547)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_552)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_557)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_562)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_567)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_572)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_577)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_582)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_587)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_592)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_597)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_602)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_607)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_612)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_617)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_622)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_627)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_632)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_637)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_642)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_647)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_652)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_657)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_662)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_667)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_672)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_677)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_682)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_687)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_692)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_697)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_702)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_707)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_712)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_717)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_722)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_727)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_732)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_737)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_742)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_747)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_752)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_757)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_762)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_767)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_772)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_777)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_782)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_787)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_792)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_797)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_802)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_807)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_812)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_817)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_822)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_827)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_832)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_837)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_842)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_847)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_852)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_857)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_862)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_867)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_872)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_877)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_882)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_887)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_892)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_897)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_902)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_907)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_912)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_917)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_922)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_927)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_932)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_937)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_942)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_947)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_952)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_957)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_962)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_967)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_972)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_977)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_982)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_987)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_992)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_997)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_3)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_8)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_13)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_18)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_23)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_28)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_33)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_38)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_43)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_48)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_53)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_58)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_63)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_68)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_73)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_78)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_83)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_88)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_93)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_98)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_103)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_108)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_113)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_118)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_123)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_128)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_133)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_138)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_143)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_148)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_153)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_158)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_163)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_168)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_173)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_178)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_183)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_188)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_193)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_198)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_203)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_208)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_213)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_218)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_223)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_228)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_233)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_238)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_243)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_248)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_253)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_258)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_263)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_268)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_273)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_278)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_283)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_288)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_293)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_298)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_303)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_308)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_313)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_318)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_323)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_328)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_333)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_338)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_343)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_348)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_353)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_358)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_363)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_368)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_373)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_378)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_383)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_388)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_393)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_398)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_403)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_408)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_413)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_418)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_423)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_428)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_433)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_438)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_443)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_448)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_453)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_458)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_463)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_468)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_473)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_478)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_483)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_488)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_493)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_498)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_503)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_508)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_513)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_518)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_523)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_528)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_533)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_538)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_543)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_548)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_553)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_558)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_563)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_568)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_573)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_578)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_583)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_588)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_593)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_598)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_603)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_608)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_613)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_618)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_623)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_628)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_633)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_638)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_643)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_648)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_653)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_658)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_663)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_668)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_673)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_678)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_683)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_688)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_693)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_698)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_703)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_708)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_713)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_718)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_723)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_728)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_733)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_738)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_743)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_748)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_753)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_758)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_763)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_768)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_773)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_778)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_783)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_788)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_793)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_798)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_803)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_808)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_813)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_818)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_823)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_828)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_833)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_838)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_843)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_848)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_853)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_858)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_863)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_868)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_873)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_878)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_883)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_888)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_893)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_898)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_903)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_908)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_913)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_918)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_923)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_928)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_933)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_938)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_943)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_948)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_953)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_958)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_963)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_968)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_973)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_978)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_983)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_988)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_993)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_998)))) +(assert (<= 0 + (+ (* 21600 x_1001) + (* (- 50) x_9) + (* (- 40) x_14) + (* (- 50) x_19) + (* (- 60) x_24) + (* (- 40) x_29) + (* (- 40) x_34) + (* (- 50) x_39) + (* (- 40) x_44) + (* (- 40) x_49) + (* (- 40) x_54) + (* (- 50) x_59) + (* (- 40) x_64) + (* (- 40) x_69) + (* (- 50) x_74) + (* (- 60) x_79) + (* (- 70) x_84) + (* (- 80) x_89) + (* (- 90) x_94) + (* (- 100) x_99) + (* (- 40) x_104) + (* (- 50) x_109) + (* (- 60) x_114) + (* (- 70) x_119) + (* (- 40) x_124) + (* (- 50) x_129) + (* (- 60) x_134) + (* (- 70) x_139) + (* (- 80) x_144) + (* (- 90) x_149) + (* (- 100) x_154) + (* (- 110) x_159) + (* (- 120) x_164) + (* (- 40) x_169) + (* (- 50) x_174) + (* (- 60) x_179) + (* (- 70) x_184) + (* (- 40) x_189) + (* (- 50) x_194) + (* (- 60) x_199) + (* (- 40) x_204) + (* (- 50) x_209) + (* (- 40) x_214) + (* (- 50) x_219) + (* (- 60) x_224) + (* (- 70) x_229) + (* (- 80) x_234) + (* (- 90) x_239) + (* (- 100) x_244) + (* (- 110) x_249) + (* (- 40) x_254) + (* (- 50) x_259) + (* (- 60) x_264) + (* (- 70) x_269) + (* (- 80) x_274) + (* (- 90) x_279) + (* (- 100) x_284) + (* (- 40) x_289) + (* (- 50) x_294) + (* (- 60) x_299) + (* (- 70) x_304) + (* (- 80) x_309) + (* (- 90) x_314) + (* (- 100) x_319) + (* (- 110) x_324) + (* (- 40) x_329) + (* (- 50) x_334) + (* (- 60) x_339) + (* (- 70) x_344) + (* (- 80) x_349) + (* (- 90) x_354) + (* (- 100) x_359) + (* (- 40) x_364) + (* (- 50) x_369) + (* (- 60) x_374) + (* (- 70) x_379) + (* (- 80) x_384) + (* (- 90) x_389) + (* (- 100) x_394) + (* (- 40) x_399) + (* (- 50) x_404) + (* (- 60) x_409) + (* (- 40) x_414) + (* (- 50) x_419) + (* (- 60) x_424) + (* (- 70) x_429) + (* (- 80) x_434) + (* (- 90) x_439) + (* (- 100) x_444) + (* (- 110) x_449) + (* (- 120) x_454) + (* (- 130) x_459) + (* (- 40) x_464) + (* (- 50) x_469) + (* (- 60) x_474) + (* (- 70) x_479) + (* (- 80) x_484) + (* (- 90) x_489) + (* (- 40) x_494) + (* (- 40) x_499) + (* (- 50) x_504) + (* (- 60) x_509) + (* (- 70) x_514) + (* (- 80) x_519) + (* (- 90) x_524) + (* (- 40) x_529) + (* (- 50) x_534) + (* (- 60) x_539) + (* (- 40) x_544) + (* (- 50) x_549) + (* (- 60) x_554) + (* (- 70) x_559) + (* (- 40) x_564) + (* (- 50) x_569) + (* (- 60) x_574) + (* (- 70) x_579) + (* (- 80) x_584) + (* (- 90) x_589) + (* (- 40) x_594) + (* (- 40) x_599) + (* (- 50) x_604) + (* (- 60) x_609) + (* (- 70) x_614) + (* (- 80) x_619) + (* (- 40) x_624) + (* (- 50) x_629) + (* (- 60) x_634) + (* (- 70) x_639) + (* (- 80) x_644) + (* (- 90) x_649) + (* (- 100) x_654) + (* (- 110) x_659) + (* (- 40) x_664) + (* (- 50) x_669) + (* (- 60) x_674) + (* (- 70) x_679) + (* (- 40) x_684) + (* (- 50) x_689) + (* (- 60) x_694) + (* (- 70) x_699) + (* (- 80) x_704) + (* (- 90) x_709) + (* (- 100) x_714) + (* (- 110) x_719) + (* (- 120) x_724) + (* (- 40) x_729) + (* (- 50) x_734) + (* (- 60) x_739) + (* (- 70) x_744) + (* (- 80) x_749) + (* (- 90) x_754) + (* (- 100) x_759) + (* (- 110) x_764) + (* (- 40) x_769) + (* (- 50) x_774) + (* (- 40) x_779) + (* (- 50) x_784) + (* (- 40) x_789) + (* (- 50) x_794) + (* (- 60) x_799) + (* (- 70) x_804) + (* (- 80) x_809) + (* (- 90) x_814) + (* (- 100) x_819) + (* (- 40) x_824) + (* (- 50) x_829) + (* (- 60) x_834) + (* (- 70) x_839) + (* (- 80) x_844) + (* (- 90) x_849) + (* (- 100) x_854) + (* (- 110) x_859) + (* (- 40) x_864) + (* (- 50) x_869) + (* (- 60) x_874) + (* (- 70) x_879) + (* (- 80) x_884) + (* (- 90) x_889) + (* (- 40) x_894) + (* (- 50) x_899) + (* (- 60) x_904) + (* (- 70) x_909) + (* (- 80) x_914) + (* (- 90) x_919) + (* (- 100) x_924) + (* (- 52) x_929) + (* (- 52) x_934) + (* (- 65) x_939) + (* (- 52) x_944) + (* (- 52) x_949) + (* (- 65) x_954) + (* (- 52) x_959) + (* (- 65) x_964) + (* (- 52) x_969) + (* (- 65) x_974) + (* (- 78) x_979) + (* (- 91) x_984) + (* (- 104) x_989) + (* (- 117) x_994) + (* (- 130) x_999) + (* (- 40) x_4)))) +(assert (<= 0 + (+ (* 7400 x_1202) + (* (- 50) x_6) + (* (- 40) x_11) + (* (- 50) x_16) + (* (- 60) x_21) + (* (- 40) x_26) + (* (- 40) x_31) + (* (- 50) x_36) + (* (- 40) x_41) + (* (- 40) x_46) + (* (- 40) x_51) + (* (- 50) x_56) + (* (- 40) x_61) + (* (- 40) x_66) + (* (- 50) x_71) + (* (- 60) x_76) + (* (- 70) x_81) + (* (- 80) x_86) + (* (- 90) x_91) + (* (- 100) x_96) + (* (- 40) x_101) + (* (- 50) x_106) + (* (- 60) x_111) + (* (- 70) x_116) + (* (- 40) x_121) + (* (- 50) x_126) + (* (- 60) x_131) + (* (- 70) x_136) + (* (- 80) x_141) + (* (- 90) x_146) + (* (- 100) x_151) + (* (- 110) x_156) + (* (- 120) x_161) + (* (- 40) x_166) + (* (- 50) x_171) + (* (- 60) x_176) + (* (- 70) x_181) + (* (- 40) x_186) + (* (- 50) x_191) + (* (- 60) x_196) + (* (- 40) x_201) + (* (- 50) x_206) + (* (- 40) x_211) + (* (- 50) x_216) + (* (- 60) x_221) + (* (- 70) x_226) + (* (- 80) x_231) + (* (- 90) x_236) + (* (- 100) x_241) + (* (- 110) x_246) + (* (- 40) x_251) + (* (- 50) x_256) + (* (- 60) x_261) + (* (- 70) x_266) + (* (- 80) x_271) + (* (- 90) x_276) + (* (- 100) x_281) + (* (- 40) x_286) + (* (- 50) x_291) + (* (- 60) x_296) + (* (- 70) x_301) + (* (- 80) x_306) + (* (- 90) x_311) + (* (- 100) x_316) + (* (- 110) x_321) + (* (- 40) x_326) + (* (- 50) x_331) + (* (- 60) x_336) + (* (- 70) x_341) + (* (- 80) x_346) + (* (- 90) x_351) + (* (- 100) x_356) + (* (- 40) x_361) + (* (- 50) x_366) + (* (- 60) x_371) + (* (- 70) x_376) + (* (- 80) x_381) + (* (- 90) x_386) + (* (- 100) x_391) + (* (- 40) x_396) + (* (- 50) x_401) + (* (- 60) x_406) + (* (- 40) x_411) + (* (- 50) x_416) + (* (- 60) x_421) + (* (- 70) x_426) + (* (- 80) x_431) + (* (- 90) x_436) + (* (- 100) x_441) + (* (- 110) x_446) + (* (- 120) x_451) + (* (- 130) x_456) + (* (- 40) x_461) + (* (- 50) x_466) + (* (- 60) x_471) + (* (- 70) x_476) + (* (- 80) x_481) + (* (- 90) x_486) + (* (- 40) x_491) + (* (- 40) x_496) + (* (- 50) x_501) + (* (- 60) x_506) + (* (- 70) x_511) + (* (- 80) x_516) + (* (- 90) x_521) + (* (- 40) x_526) + (* (- 50) x_531) + (* (- 60) x_536) + (* (- 40) x_541) + (* (- 50) x_546) + (* (- 60) x_551) + (* (- 70) x_556) + (* (- 40) x_561) + (* (- 50) x_566) + (* (- 60) x_571) + (* (- 70) x_576) + (* (- 80) x_581) + (* (- 90) x_586) + (* (- 40) x_591) + (* (- 40) x_596) + (* (- 50) x_601) + (* (- 60) x_606) + (* (- 70) x_611) + (* (- 80) x_616) + (* (- 40) x_621) + (* (- 50) x_626) + (* (- 60) x_631) + (* (- 70) x_636) + (* (- 80) x_641) + (* (- 90) x_646) + (* (- 100) x_651) + (* (- 110) x_656) + (* (- 40) x_661) + (* (- 50) x_666) + (* (- 60) x_671) + (* (- 70) x_676) + (* (- 40) x_681) + (* (- 50) x_686) + (* (- 60) x_691) + (* (- 70) x_696) + (* (- 80) x_701) + (* (- 90) x_706) + (* (- 100) x_711) + (* (- 110) x_716) + (* (- 120) x_721) + (* (- 40) x_726) + (* (- 50) x_731) + (* (- 60) x_736) + (* (- 70) x_741) + (* (- 80) x_746) + (* (- 90) x_751) + (* (- 100) x_756) + (* (- 110) x_761) + (* (- 40) x_766) + (* (- 50) x_771) + (* (- 40) x_776) + (* (- 50) x_781) + (* (- 40) x_786) + (* (- 50) x_791) + (* (- 60) x_796) + (* (- 70) x_801) + (* (- 80) x_806) + (* (- 90) x_811) + (* (- 100) x_816) + (* (- 40) x_821) + (* (- 50) x_826) + (* (- 60) x_831) + (* (- 70) x_836) + (* (- 80) x_841) + (* (- 90) x_846) + (* (- 100) x_851) + (* (- 110) x_856) + (* (- 40) x_861) + (* (- 50) x_866) + (* (- 60) x_871) + (* (- 70) x_876) + (* (- 80) x_881) + (* (- 90) x_886) + (* (- 40) x_891) + (* (- 50) x_896) + (* (- 60) x_901) + (* (- 70) x_906) + (* (- 80) x_911) + (* (- 90) x_916) + (* (- 100) x_921) + (* (- 52) x_926) + (* (- 52) x_931) + (* (- 65) x_936) + (* (- 52) x_941) + (* (- 52) x_946) + (* (- 65) x_951) + (* (- 52) x_956) + (* (- 65) x_961) + (* (- 52) x_966) + (* (- 65) x_971) + (* (- 78) x_976) + (* (- 91) x_981) + (* (- 104) x_986) + (* (- 117) x_991) + (* (- 130) x_996) + (* (- 40) x_1)))) +(assert (<= 0 + (+ (* 26500 x_1403) + (* (- 50) x_7) + (* (- 40) x_12) + (* (- 50) x_17) + (* (- 60) x_22) + (* (- 40) x_27) + (* (- 40) x_32) + (* (- 50) x_37) + (* (- 40) x_42) + (* (- 40) x_47) + (* (- 40) x_52) + (* (- 50) x_57) + (* (- 40) x_62) + (* (- 40) x_67) + (* (- 50) x_72) + (* (- 60) x_77) + (* (- 70) x_82) + (* (- 80) x_87) + (* (- 90) x_92) + (* (- 100) x_97) + (* (- 40) x_102) + (* (- 50) x_107) + (* (- 60) x_112) + (* (- 70) x_117) + (* (- 40) x_122) + (* (- 50) x_127) + (* (- 60) x_132) + (* (- 70) x_137) + (* (- 80) x_142) + (* (- 90) x_147) + (* (- 100) x_152) + (* (- 110) x_157) + (* (- 120) x_162) + (* (- 40) x_167) + (* (- 50) x_172) + (* (- 60) x_177) + (* (- 70) x_182) + (* (- 40) x_187) + (* (- 50) x_192) + (* (- 60) x_197) + (* (- 40) x_202) + (* (- 50) x_207) + (* (- 40) x_212) + (* (- 50) x_217) + (* (- 60) x_222) + (* (- 70) x_227) + (* (- 80) x_232) + (* (- 90) x_237) + (* (- 100) x_242) + (* (- 110) x_247) + (* (- 40) x_252) + (* (- 50) x_257) + (* (- 60) x_262) + (* (- 70) x_267) + (* (- 80) x_272) + (* (- 90) x_277) + (* (- 100) x_282) + (* (- 40) x_287) + (* (- 50) x_292) + (* (- 60) x_297) + (* (- 70) x_302) + (* (- 80) x_307) + (* (- 90) x_312) + (* (- 100) x_317) + (* (- 110) x_322) + (* (- 40) x_327) + (* (- 50) x_332) + (* (- 60) x_337) + (* (- 70) x_342) + (* (- 80) x_347) + (* (- 90) x_352) + (* (- 100) x_357) + (* (- 40) x_362) + (* (- 50) x_367) + (* (- 60) x_372) + (* (- 70) x_377) + (* (- 80) x_382) + (* (- 90) x_387) + (* (- 100) x_392) + (* (- 40) x_397) + (* (- 50) x_402) + (* (- 60) x_407) + (* (- 40) x_412) + (* (- 50) x_417) + (* (- 60) x_422) + (* (- 70) x_427) + (* (- 80) x_432) + (* (- 90) x_437) + (* (- 100) x_442) + (* (- 110) x_447) + (* (- 120) x_452) + (* (- 130) x_457) + (* (- 40) x_462) + (* (- 50) x_467) + (* (- 60) x_472) + (* (- 70) x_477) + (* (- 80) x_482) + (* (- 90) x_487) + (* (- 40) x_492) + (* (- 40) x_497) + (* (- 50) x_502) + (* (- 60) x_507) + (* (- 70) x_512) + (* (- 80) x_517) + (* (- 90) x_522) + (* (- 40) x_527) + (* (- 50) x_532) + (* (- 60) x_537) + (* (- 40) x_542) + (* (- 50) x_547) + (* (- 60) x_552) + (* (- 70) x_557) + (* (- 40) x_562) + (* (- 50) x_567) + (* (- 60) x_572) + (* (- 70) x_577) + (* (- 80) x_582) + (* (- 90) x_587) + (* (- 40) x_592) + (* (- 40) x_597) + (* (- 50) x_602) + (* (- 60) x_607) + (* (- 70) x_612) + (* (- 80) x_617) + (* (- 40) x_622) + (* (- 50) x_627) + (* (- 60) x_632) + (* (- 70) x_637) + (* (- 80) x_642) + (* (- 90) x_647) + (* (- 100) x_652) + (* (- 110) x_657) + (* (- 40) x_662) + (* (- 50) x_667) + (* (- 60) x_672) + (* (- 70) x_677) + (* (- 40) x_682) + (* (- 50) x_687) + (* (- 60) x_692) + (* (- 70) x_697) + (* (- 80) x_702) + (* (- 90) x_707) + (* (- 100) x_712) + (* (- 110) x_717) + (* (- 120) x_722) + (* (- 40) x_727) + (* (- 50) x_732) + (* (- 60) x_737) + (* (- 70) x_742) + (* (- 80) x_747) + (* (- 90) x_752) + (* (- 100) x_757) + (* (- 110) x_762) + (* (- 40) x_767) + (* (- 50) x_772) + (* (- 40) x_777) + (* (- 50) x_782) + (* (- 40) x_787) + (* (- 50) x_792) + (* (- 60) x_797) + (* (- 70) x_802) + (* (- 80) x_807) + (* (- 90) x_812) + (* (- 100) x_817) + (* (- 40) x_822) + (* (- 50) x_827) + (* (- 60) x_832) + (* (- 70) x_837) + (* (- 80) x_842) + (* (- 90) x_847) + (* (- 100) x_852) + (* (- 110) x_857) + (* (- 40) x_862) + (* (- 50) x_867) + (* (- 60) x_872) + (* (- 70) x_877) + (* (- 80) x_882) + (* (- 90) x_887) + (* (- 40) x_892) + (* (- 50) x_897) + (* (- 60) x_902) + (* (- 70) x_907) + (* (- 80) x_912) + (* (- 90) x_917) + (* (- 100) x_922) + (* (- 52) x_927) + (* (- 52) x_932) + (* (- 65) x_937) + (* (- 52) x_942) + (* (- 52) x_947) + (* (- 65) x_952) + (* (- 52) x_957) + (* (- 65) x_962) + (* (- 52) x_967) + (* (- 65) x_972) + (* (- 78) x_977) + (* (- 91) x_982) + (* (- 104) x_987) + (* (- 117) x_992) + (* (- 130) x_997) + (* (- 40) x_2)))) +(assert (<= 0 + (+ (* 4500 x_1604) + (* (- 50) x_8) + (* (- 40) x_13) + (* (- 50) x_18) + (* (- 60) x_23) + (* (- 40) x_28) + (* (- 40) x_33) + (* (- 50) x_38) + (* (- 40) x_43) + (* (- 40) x_48) + (* (- 40) x_53) + (* (- 50) x_58) + (* (- 40) x_63) + (* (- 40) x_68) + (* (- 50) x_73) + (* (- 60) x_78) + (* (- 70) x_83) + (* (- 80) x_88) + (* (- 90) x_93) + (* (- 100) x_98) + (* (- 40) x_103) + (* (- 50) x_108) + (* (- 60) x_113) + (* (- 70) x_118) + (* (- 40) x_123) + (* (- 50) x_128) + (* (- 60) x_133) + (* (- 70) x_138) + (* (- 80) x_143) + (* (- 90) x_148) + (* (- 100) x_153) + (* (- 110) x_158) + (* (- 120) x_163) + (* (- 40) x_168) + (* (- 50) x_173) + (* (- 60) x_178) + (* (- 70) x_183) + (* (- 40) x_188) + (* (- 50) x_193) + (* (- 60) x_198) + (* (- 40) x_203) + (* (- 50) x_208) + (* (- 40) x_213) + (* (- 50) x_218) + (* (- 60) x_223) + (* (- 70) x_228) + (* (- 80) x_233) + (* (- 90) x_238) + (* (- 100) x_243) + (* (- 110) x_248) + (* (- 40) x_253) + (* (- 50) x_258) + (* (- 60) x_263) + (* (- 70) x_268) + (* (- 80) x_273) + (* (- 90) x_278) + (* (- 100) x_283) + (* (- 40) x_288) + (* (- 50) x_293) + (* (- 60) x_298) + (* (- 70) x_303) + (* (- 80) x_308) + (* (- 90) x_313) + (* (- 100) x_318) + (* (- 110) x_323) + (* (- 40) x_328) + (* (- 50) x_333) + (* (- 60) x_338) + (* (- 70) x_343) + (* (- 80) x_348) + (* (- 90) x_353) + (* (- 100) x_358) + (* (- 40) x_363) + (* (- 50) x_368) + (* (- 60) x_373) + (* (- 70) x_378) + (* (- 80) x_383) + (* (- 90) x_388) + (* (- 100) x_393) + (* (- 40) x_398) + (* (- 50) x_403) + (* (- 60) x_408) + (* (- 40) x_413) + (* (- 50) x_418) + (* (- 60) x_423) + (* (- 70) x_428) + (* (- 80) x_433) + (* (- 90) x_438) + (* (- 100) x_443) + (* (- 110) x_448) + (* (- 120) x_453) + (* (- 130) x_458) + (* (- 40) x_463) + (* (- 50) x_468) + (* (- 60) x_473) + (* (- 70) x_478) + (* (- 80) x_483) + (* (- 90) x_488) + (* (- 40) x_493) + (* (- 40) x_498) + (* (- 50) x_503) + (* (- 60) x_508) + (* (- 70) x_513) + (* (- 80) x_518) + (* (- 90) x_523) + (* (- 40) x_528) + (* (- 50) x_533) + (* (- 60) x_538) + (* (- 40) x_543) + (* (- 50) x_548) + (* (- 60) x_553) + (* (- 70) x_558) + (* (- 40) x_563) + (* (- 50) x_568) + (* (- 60) x_573) + (* (- 70) x_578) + (* (- 80) x_583) + (* (- 90) x_588) + (* (- 40) x_593) + (* (- 40) x_598) + (* (- 50) x_603) + (* (- 60) x_608) + (* (- 70) x_613) + (* (- 80) x_618) + (* (- 40) x_623) + (* (- 50) x_628) + (* (- 60) x_633) + (* (- 70) x_638) + (* (- 80) x_643) + (* (- 90) x_648) + (* (- 100) x_653) + (* (- 110) x_658) + (* (- 40) x_663) + (* (- 50) x_668) + (* (- 60) x_673) + (* (- 70) x_678) + (* (- 40) x_683) + (* (- 50) x_688) + (* (- 60) x_693) + (* (- 70) x_698) + (* (- 80) x_703) + (* (- 90) x_708) + (* (- 100) x_713) + (* (- 110) x_718) + (* (- 120) x_723) + (* (- 40) x_728) + (* (- 50) x_733) + (* (- 60) x_738) + (* (- 70) x_743) + (* (- 80) x_748) + (* (- 90) x_753) + (* (- 100) x_758) + (* (- 110) x_763) + (* (- 40) x_768) + (* (- 50) x_773) + (* (- 40) x_778) + (* (- 50) x_783) + (* (- 40) x_788) + (* (- 50) x_793) + (* (- 60) x_798) + (* (- 70) x_803) + (* (- 80) x_808) + (* (- 90) x_813) + (* (- 100) x_818) + (* (- 40) x_823) + (* (- 50) x_828) + (* (- 60) x_833) + (* (- 70) x_838) + (* (- 80) x_843) + (* (- 90) x_848) + (* (- 100) x_853) + (* (- 110) x_858) + (* (- 40) x_863) + (* (- 50) x_868) + (* (- 60) x_873) + (* (- 70) x_878) + (* (- 80) x_883) + (* (- 90) x_888) + (* (- 40) x_893) + (* (- 50) x_898) + (* (- 60) x_903) + (* (- 70) x_908) + (* (- 80) x_913) + (* (- 90) x_918) + (* (- 100) x_923) + (* (- 52) x_928) + (* (- 52) x_933) + (* (- 65) x_938) + (* (- 52) x_943) + (* (- 52) x_948) + (* (- 65) x_953) + (* (- 52) x_958) + (* (- 65) x_963) + (* (- 52) x_968) + (* (- 65) x_973) + (* (- 78) x_978) + (* (- 91) x_983) + (* (- 104) x_988) + (* (- 117) x_993) + (* (- 130) x_998) + (* (- 40) x_3)))) +(assert (<= 0 + (+ (* 3850 x_1001) + (* (- 30) x_9) + (* (- 24) x_14) + (* (- 30) x_19) + (* (- 36) x_24) + (* (- 24) x_29) + (* (- 24) x_34) + (* (- 30) x_39) + (* (- 24) x_44) + (* (- 24) x_49) + (* (- 24) x_54) + (* (- 30) x_59) + (* (- 24) x_64) + (* (- 24) x_69) + (* (- 30) x_74) + (* (- 36) x_79) + (* (- 42) x_84) + (* (- 48) x_89) + (* (- 54) x_94) + (* (- 60) x_99) + (* (- 24) x_104) + (* (- 30) x_109) + (* (- 36) x_114) + (* (- 42) x_119) + (* (- 24) x_124) + (* (- 30) x_129) + (* (- 36) x_134) + (* (- 42) x_139) + (* (- 48) x_144) + (* (- 54) x_149) + (* (- 60) x_154) + (* (- 66) x_159) + (* (- 72) x_164) + (* (- 24) x_169) + (* (- 30) x_174) + (* (- 36) x_179) + (* (- 42) x_184) + (* (- 24) x_189) + (* (- 30) x_194) + (* (- 36) x_199) + (* (- 24) x_204) + (* (- 30) x_209) + (* (- 24) x_214) + (* (- 30) x_219) + (* (- 36) x_224) + (* (- 42) x_229) + (* (- 48) x_234) + (* (- 54) x_239) + (* (- 60) x_244) + (* (- 66) x_249) + (* (- 24) x_254) + (* (- 30) x_259) + (* (- 36) x_264) + (* (- 42) x_269) + (* (- 48) x_274) + (* (- 54) x_279) + (* (- 60) x_284) + (* (- 24) x_289) + (* (- 30) x_294) + (* (- 36) x_299) + (* (- 42) x_304) + (* (- 48) x_309) + (* (- 54) x_314) + (* (- 60) x_319) + (* (- 66) x_324) + (* (- 24) x_329) + (* (- 30) x_334) + (* (- 36) x_339) + (* (- 42) x_344) + (* (- 48) x_349) + (* (- 54) x_354) + (* (- 60) x_359) + (* (- 24) x_364) + (* (- 30) x_369) + (* (- 36) x_374) + (* (- 42) x_379) + (* (- 48) x_384) + (* (- 54) x_389) + (* (- 60) x_394) + (* (- 24) x_399) + (* (- 30) x_404) + (* (- 36) x_409) + (* (- 24) x_414) + (* (- 30) x_419) + (* (- 36) x_424) + (* (- 42) x_429) + (* (- 48) x_434) + (* (- 54) x_439) + (* (- 60) x_444) + (* (- 66) x_449) + (* (- 72) x_454) + (* (- 78) x_459) + (* (- 24) x_464) + (* (- 30) x_469) + (* (- 36) x_474) + (* (- 42) x_479) + (* (- 48) x_484) + (* (- 54) x_489) + (* (- 24) x_494) + (* (- 24) x_499) + (* (- 30) x_504) + (* (- 36) x_509) + (* (- 42) x_514) + (* (- 48) x_519) + (* (- 54) x_524) + (* (- 24) x_529) + (* (- 30) x_534) + (* (- 36) x_539) + (* (- 24) x_544) + (* (- 30) x_549) + (* (- 36) x_554) + (* (- 42) x_559) + (* (- 24) x_564) + (* (- 30) x_569) + (* (- 36) x_574) + (* (- 42) x_579) + (* (- 48) x_584) + (* (- 54) x_589) + (* (- 24) x_594) + (* (- 24) x_599) + (* (- 30) x_604) + (* (- 36) x_609) + (* (- 42) x_614) + (* (- 48) x_619) + (* (- 24) x_624) + (* (- 30) x_629) + (* (- 36) x_634) + (* (- 42) x_639) + (* (- 48) x_644) + (* (- 54) x_649) + (* (- 60) x_654) + (* (- 66) x_659) + (* (- 24) x_664) + (* (- 30) x_669) + (* (- 36) x_674) + (* (- 42) x_679) + (* (- 24) x_684) + (* (- 30) x_689) + (* (- 36) x_694) + (* (- 42) x_699) + (* (- 48) x_704) + (* (- 54) x_709) + (* (- 60) x_714) + (* (- 66) x_719) + (* (- 72) x_724) + (* (- 24) x_729) + (* (- 30) x_734) + (* (- 36) x_739) + (* (- 42) x_744) + (* (- 48) x_749) + (* (- 54) x_754) + (* (- 60) x_759) + (* (- 66) x_764) + (* (- 24) x_769) + (* (- 30) x_774) + (* (- 24) x_779) + (* (- 30) x_784) + (* (- 24) x_789) + (* (- 30) x_794) + (* (- 36) x_799) + (* (- 42) x_804) + (* (- 48) x_809) + (* (- 54) x_814) + (* (- 60) x_819) + (* (- 24) x_824) + (* (- 30) x_829) + (* (- 36) x_834) + (* (- 42) x_839) + (* (- 48) x_844) + (* (- 54) x_849) + (* (- 60) x_854) + (* (- 66) x_859) + (* (- 24) x_864) + (* (- 30) x_869) + (* (- 36) x_874) + (* (- 42) x_879) + (* (- 48) x_884) + (* (- 54) x_889) + (* (- 24) x_894) + (* (- 30) x_899) + (* (- 36) x_904) + (* (- 42) x_909) + (* (- 48) x_914) + (* (- 54) x_919) + (* (- 60) x_924) + (* (- 36) x_929) + (* (- 36) x_934) + (* (- 45) x_939) + (* (- 36) x_944) + (* (- 36) x_949) + (* (- 45) x_954) + (* (- 36) x_959) + (* (- 45) x_964) + (* (- 36) x_969) + (* (- 45) x_974) + (* (- 54) x_979) + (* (- 63) x_984) + (* (- 72) x_989) + (* (- 81) x_994) + (* (- 90) x_999) + (* (- 24) x_4)))) +(assert (<= 0 + (+ (* 3000 x_1202) + (* (- 30) x_6) + (* (- 24) x_11) + (* (- 30) x_16) + (* (- 36) x_21) + (* (- 24) x_26) + (* (- 24) x_31) + (* (- 30) x_36) + (* (- 24) x_41) + (* (- 24) x_46) + (* (- 24) x_51) + (* (- 30) x_56) + (* (- 24) x_61) + (* (- 24) x_66) + (* (- 30) x_71) + (* (- 36) x_76) + (* (- 42) x_81) + (* (- 48) x_86) + (* (- 54) x_91) + (* (- 60) x_96) + (* (- 24) x_101) + (* (- 30) x_106) + (* (- 36) x_111) + (* (- 42) x_116) + (* (- 24) x_121) + (* (- 30) x_126) + (* (- 36) x_131) + (* (- 42) x_136) + (* (- 48) x_141) + (* (- 54) x_146) + (* (- 60) x_151) + (* (- 66) x_156) + (* (- 72) x_161) + (* (- 24) x_166) + (* (- 30) x_171) + (* (- 36) x_176) + (* (- 42) x_181) + (* (- 24) x_186) + (* (- 30) x_191) + (* (- 36) x_196) + (* (- 24) x_201) + (* (- 30) x_206) + (* (- 24) x_211) + (* (- 30) x_216) + (* (- 36) x_221) + (* (- 42) x_226) + (* (- 48) x_231) + (* (- 54) x_236) + (* (- 60) x_241) + (* (- 66) x_246) + (* (- 24) x_251) + (* (- 30) x_256) + (* (- 36) x_261) + (* (- 42) x_266) + (* (- 48) x_271) + (* (- 54) x_276) + (* (- 60) x_281) + (* (- 24) x_286) + (* (- 30) x_291) + (* (- 36) x_296) + (* (- 42) x_301) + (* (- 48) x_306) + (* (- 54) x_311) + (* (- 60) x_316) + (* (- 66) x_321) + (* (- 24) x_326) + (* (- 30) x_331) + (* (- 36) x_336) + (* (- 42) x_341) + (* (- 48) x_346) + (* (- 54) x_351) + (* (- 60) x_356) + (* (- 24) x_361) + (* (- 30) x_366) + (* (- 36) x_371) + (* (- 42) x_376) + (* (- 48) x_381) + (* (- 54) x_386) + (* (- 60) x_391) + (* (- 24) x_396) + (* (- 30) x_401) + (* (- 36) x_406) + (* (- 24) x_411) + (* (- 30) x_416) + (* (- 36) x_421) + (* (- 42) x_426) + (* (- 48) x_431) + (* (- 54) x_436) + (* (- 60) x_441) + (* (- 66) x_446) + (* (- 72) x_451) + (* (- 78) x_456) + (* (- 24) x_461) + (* (- 30) x_466) + (* (- 36) x_471) + (* (- 42) x_476) + (* (- 48) x_481) + (* (- 54) x_486) + (* (- 24) x_491) + (* (- 24) x_496) + (* (- 30) x_501) + (* (- 36) x_506) + (* (- 42) x_511) + (* (- 48) x_516) + (* (- 54) x_521) + (* (- 24) x_526) + (* (- 30) x_531) + (* (- 36) x_536) + (* (- 24) x_541) + (* (- 30) x_546) + (* (- 36) x_551) + (* (- 42) x_556) + (* (- 24) x_561) + (* (- 30) x_566) + (* (- 36) x_571) + (* (- 42) x_576) + (* (- 48) x_581) + (* (- 54) x_586) + (* (- 24) x_591) + (* (- 24) x_596) + (* (- 30) x_601) + (* (- 36) x_606) + (* (- 42) x_611) + (* (- 48) x_616) + (* (- 24) x_621) + (* (- 30) x_626) + (* (- 36) x_631) + (* (- 42) x_636) + (* (- 48) x_641) + (* (- 54) x_646) + (* (- 60) x_651) + (* (- 66) x_656) + (* (- 24) x_661) + (* (- 30) x_666) + (* (- 36) x_671) + (* (- 42) x_676) + (* (- 24) x_681) + (* (- 30) x_686) + (* (- 36) x_691) + (* (- 42) x_696) + (* (- 48) x_701) + (* (- 54) x_706) + (* (- 60) x_711) + (* (- 66) x_716) + (* (- 72) x_721) + (* (- 24) x_726) + (* (- 30) x_731) + (* (- 36) x_736) + (* (- 42) x_741) + (* (- 48) x_746) + (* (- 54) x_751) + (* (- 60) x_756) + (* (- 66) x_761) + (* (- 24) x_766) + (* (- 30) x_771) + (* (- 24) x_776) + (* (- 30) x_781) + (* (- 24) x_786) + (* (- 30) x_791) + (* (- 36) x_796) + (* (- 42) x_801) + (* (- 48) x_806) + (* (- 54) x_811) + (* (- 60) x_816) + (* (- 24) x_821) + (* (- 30) x_826) + (* (- 36) x_831) + (* (- 42) x_836) + (* (- 48) x_841) + (* (- 54) x_846) + (* (- 60) x_851) + (* (- 66) x_856) + (* (- 24) x_861) + (* (- 30) x_866) + (* (- 36) x_871) + (* (- 42) x_876) + (* (- 48) x_881) + (* (- 54) x_886) + (* (- 24) x_891) + (* (- 30) x_896) + (* (- 36) x_901) + (* (- 42) x_906) + (* (- 48) x_911) + (* (- 54) x_916) + (* (- 60) x_921) + (* (- 36) x_926) + (* (- 36) x_931) + (* (- 45) x_936) + (* (- 36) x_941) + (* (- 36) x_946) + (* (- 45) x_951) + (* (- 36) x_956) + (* (- 45) x_961) + (* (- 36) x_966) + (* (- 45) x_971) + (* (- 54) x_976) + (* (- 63) x_981) + (* (- 72) x_986) + (* (- 81) x_991) + (* (- 90) x_996) + (* (- 24) x_1)))) +(assert (<= 0 + (+ (* 7700 x_1403) + (* (- 30) x_7) + (* (- 24) x_12) + (* (- 30) x_17) + (* (- 36) x_22) + (* (- 24) x_27) + (* (- 24) x_32) + (* (- 30) x_37) + (* (- 24) x_42) + (* (- 24) x_47) + (* (- 24) x_52) + (* (- 30) x_57) + (* (- 24) x_62) + (* (- 24) x_67) + (* (- 30) x_72) + (* (- 36) x_77) + (* (- 42) x_82) + (* (- 48) x_87) + (* (- 54) x_92) + (* (- 60) x_97) + (* (- 24) x_102) + (* (- 30) x_107) + (* (- 36) x_112) + (* (- 42) x_117) + (* (- 24) x_122) + (* (- 30) x_127) + (* (- 36) x_132) + (* (- 42) x_137) + (* (- 48) x_142) + (* (- 54) x_147) + (* (- 60) x_152) + (* (- 66) x_157) + (* (- 72) x_162) + (* (- 24) x_167) + (* (- 30) x_172) + (* (- 36) x_177) + (* (- 42) x_182) + (* (- 24) x_187) + (* (- 30) x_192) + (* (- 36) x_197) + (* (- 24) x_202) + (* (- 30) x_207) + (* (- 24) x_212) + (* (- 30) x_217) + (* (- 36) x_222) + (* (- 42) x_227) + (* (- 48) x_232) + (* (- 54) x_237) + (* (- 60) x_242) + (* (- 66) x_247) + (* (- 24) x_252) + (* (- 30) x_257) + (* (- 36) x_262) + (* (- 42) x_267) + (* (- 48) x_272) + (* (- 54) x_277) + (* (- 60) x_282) + (* (- 24) x_287) + (* (- 30) x_292) + (* (- 36) x_297) + (* (- 42) x_302) + (* (- 48) x_307) + (* (- 54) x_312) + (* (- 60) x_317) + (* (- 66) x_322) + (* (- 24) x_327) + (* (- 30) x_332) + (* (- 36) x_337) + (* (- 42) x_342) + (* (- 48) x_347) + (* (- 54) x_352) + (* (- 60) x_357) + (* (- 24) x_362) + (* (- 30) x_367) + (* (- 36) x_372) + (* (- 42) x_377) + (* (- 48) x_382) + (* (- 54) x_387) + (* (- 60) x_392) + (* (- 24) x_397) + (* (- 30) x_402) + (* (- 36) x_407) + (* (- 24) x_412) + (* (- 30) x_417) + (* (- 36) x_422) + (* (- 42) x_427) + (* (- 48) x_432) + (* (- 54) x_437) + (* (- 60) x_442) + (* (- 66) x_447) + (* (- 72) x_452) + (* (- 78) x_457) + (* (- 24) x_462) + (* (- 30) x_467) + (* (- 36) x_472) + (* (- 42) x_477) + (* (- 48) x_482) + (* (- 54) x_487) + (* (- 24) x_492) + (* (- 24) x_497) + (* (- 30) x_502) + (* (- 36) x_507) + (* (- 42) x_512) + (* (- 48) x_517) + (* (- 54) x_522) + (* (- 24) x_527) + (* (- 30) x_532) + (* (- 36) x_537) + (* (- 24) x_542) + (* (- 30) x_547) + (* (- 36) x_552) + (* (- 42) x_557) + (* (- 24) x_562) + (* (- 30) x_567) + (* (- 36) x_572) + (* (- 42) x_577) + (* (- 48) x_582) + (* (- 54) x_587) + (* (- 24) x_592) + (* (- 24) x_597) + (* (- 30) x_602) + (* (- 36) x_607) + (* (- 42) x_612) + (* (- 48) x_617) + (* (- 24) x_622) + (* (- 30) x_627) + (* (- 36) x_632) + (* (- 42) x_637) + (* (- 48) x_642) + (* (- 54) x_647) + (* (- 60) x_652) + (* (- 66) x_657) + (* (- 24) x_662) + (* (- 30) x_667) + (* (- 36) x_672) + (* (- 42) x_677) + (* (- 24) x_682) + (* (- 30) x_687) + (* (- 36) x_692) + (* (- 42) x_697) + (* (- 48) x_702) + (* (- 54) x_707) + (* (- 60) x_712) + (* (- 66) x_717) + (* (- 72) x_722) + (* (- 24) x_727) + (* (- 30) x_732) + (* (- 36) x_737) + (* (- 42) x_742) + (* (- 48) x_747) + (* (- 54) x_752) + (* (- 60) x_757) + (* (- 66) x_762) + (* (- 24) x_767) + (* (- 30) x_772) + (* (- 24) x_777) + (* (- 30) x_782) + (* (- 24) x_787) + (* (- 30) x_792) + (* (- 36) x_797) + (* (- 42) x_802) + (* (- 48) x_807) + (* (- 54) x_812) + (* (- 60) x_817) + (* (- 24) x_822) + (* (- 30) x_827) + (* (- 36) x_832) + (* (- 42) x_837) + (* (- 48) x_842) + (* (- 54) x_847) + (* (- 60) x_852) + (* (- 66) x_857) + (* (- 24) x_862) + (* (- 30) x_867) + (* (- 36) x_872) + (* (- 42) x_877) + (* (- 48) x_882) + (* (- 54) x_887) + (* (- 24) x_892) + (* (- 30) x_897) + (* (- 36) x_902) + (* (- 42) x_907) + (* (- 48) x_912) + (* (- 54) x_917) + (* (- 60) x_922) + (* (- 36) x_927) + (* (- 36) x_932) + (* (- 45) x_937) + (* (- 36) x_942) + (* (- 36) x_947) + (* (- 45) x_952) + (* (- 36) x_957) + (* (- 45) x_962) + (* (- 36) x_967) + (* (- 45) x_972) + (* (- 54) x_977) + (* (- 63) x_982) + (* (- 72) x_987) + (* (- 81) x_992) + (* (- 90) x_997) + (* (- 24) x_2)))) +(assert (<= 0 + (+ (* 3960 x_1604) + (* (- 30) x_8) + (* (- 24) x_13) + (* (- 30) x_18) + (* (- 36) x_23) + (* (- 24) x_28) + (* (- 24) x_33) + (* (- 30) x_38) + (* (- 24) x_43) + (* (- 24) x_48) + (* (- 24) x_53) + (* (- 30) x_58) + (* (- 24) x_63) + (* (- 24) x_68) + (* (- 30) x_73) + (* (- 36) x_78) + (* (- 42) x_83) + (* (- 48) x_88) + (* (- 54) x_93) + (* (- 60) x_98) + (* (- 24) x_103) + (* (- 30) x_108) + (* (- 36) x_113) + (* (- 42) x_118) + (* (- 24) x_123) + (* (- 30) x_128) + (* (- 36) x_133) + (* (- 42) x_138) + (* (- 48) x_143) + (* (- 54) x_148) + (* (- 60) x_153) + (* (- 66) x_158) + (* (- 72) x_163) + (* (- 24) x_168) + (* (- 30) x_173) + (* (- 36) x_178) + (* (- 42) x_183) + (* (- 24) x_188) + (* (- 30) x_193) + (* (- 36) x_198) + (* (- 24) x_203) + (* (- 30) x_208) + (* (- 24) x_213) + (* (- 30) x_218) + (* (- 36) x_223) + (* (- 42) x_228) + (* (- 48) x_233) + (* (- 54) x_238) + (* (- 60) x_243) + (* (- 66) x_248) + (* (- 24) x_253) + (* (- 30) x_258) + (* (- 36) x_263) + (* (- 42) x_268) + (* (- 48) x_273) + (* (- 54) x_278) + (* (- 60) x_283) + (* (- 24) x_288) + (* (- 30) x_293) + (* (- 36) x_298) + (* (- 42) x_303) + (* (- 48) x_308) + (* (- 54) x_313) + (* (- 60) x_318) + (* (- 66) x_323) + (* (- 24) x_328) + (* (- 30) x_333) + (* (- 36) x_338) + (* (- 42) x_343) + (* (- 48) x_348) + (* (- 54) x_353) + (* (- 60) x_358) + (* (- 24) x_363) + (* (- 30) x_368) + (* (- 36) x_373) + (* (- 42) x_378) + (* (- 48) x_383) + (* (- 54) x_388) + (* (- 60) x_393) + (* (- 24) x_398) + (* (- 30) x_403) + (* (- 36) x_408) + (* (- 24) x_413) + (* (- 30) x_418) + (* (- 36) x_423) + (* (- 42) x_428) + (* (- 48) x_433) + (* (- 54) x_438) + (* (- 60) x_443) + (* (- 66) x_448) + (* (- 72) x_453) + (* (- 78) x_458) + (* (- 24) x_463) + (* (- 30) x_468) + (* (- 36) x_473) + (* (- 42) x_478) + (* (- 48) x_483) + (* (- 54) x_488) + (* (- 24) x_493) + (* (- 24) x_498) + (* (- 30) x_503) + (* (- 36) x_508) + (* (- 42) x_513) + (* (- 48) x_518) + (* (- 54) x_523) + (* (- 24) x_528) + (* (- 30) x_533) + (* (- 36) x_538) + (* (- 24) x_543) + (* (- 30) x_548) + (* (- 36) x_553) + (* (- 42) x_558) + (* (- 24) x_563) + (* (- 30) x_568) + (* (- 36) x_573) + (* (- 42) x_578) + (* (- 48) x_583) + (* (- 54) x_588) + (* (- 24) x_593) + (* (- 24) x_598) + (* (- 30) x_603) + (* (- 36) x_608) + (* (- 42) x_613) + (* (- 48) x_618) + (* (- 24) x_623) + (* (- 30) x_628) + (* (- 36) x_633) + (* (- 42) x_638) + (* (- 48) x_643) + (* (- 54) x_648) + (* (- 60) x_653) + (* (- 66) x_658) + (* (- 24) x_663) + (* (- 30) x_668) + (* (- 36) x_673) + (* (- 42) x_678) + (* (- 24) x_683) + (* (- 30) x_688) + (* (- 36) x_693) + (* (- 42) x_698) + (* (- 48) x_703) + (* (- 54) x_708) + (* (- 60) x_713) + (* (- 66) x_718) + (* (- 72) x_723) + (* (- 24) x_728) + (* (- 30) x_733) + (* (- 36) x_738) + (* (- 42) x_743) + (* (- 48) x_748) + (* (- 54) x_753) + (* (- 60) x_758) + (* (- 66) x_763) + (* (- 24) x_768) + (* (- 30) x_773) + (* (- 24) x_778) + (* (- 30) x_783) + (* (- 24) x_788) + (* (- 30) x_793) + (* (- 36) x_798) + (* (- 42) x_803) + (* (- 48) x_808) + (* (- 54) x_813) + (* (- 60) x_818) + (* (- 24) x_823) + (* (- 30) x_828) + (* (- 36) x_833) + (* (- 42) x_838) + (* (- 48) x_843) + (* (- 54) x_848) + (* (- 60) x_853) + (* (- 66) x_858) + (* (- 24) x_863) + (* (- 30) x_868) + (* (- 36) x_873) + (* (- 42) x_878) + (* (- 48) x_883) + (* (- 54) x_888) + (* (- 24) x_893) + (* (- 30) x_898) + (* (- 36) x_903) + (* (- 42) x_908) + (* (- 48) x_913) + (* (- 54) x_918) + (* (- 60) x_923) + (* (- 36) x_928) + (* (- 36) x_933) + (* (- 45) x_938) + (* (- 36) x_943) + (* (- 36) x_948) + (* (- 45) x_953) + (* (- 36) x_958) + (* (- 45) x_963) + (* (- 36) x_968) + (* (- 45) x_973) + (* (- 54) x_978) + (* (- 63) x_983) + (* (- 72) x_988) + (* (- 81) x_993) + (* (- 90) x_998) + (* (- 24) x_3)))) + +(assert (= x_1202 1)) +(assert (= x_1403 1)) +(assert (= x_1604 0)) +(assert (= x_1001 0)) + +;(minimize (+ x_1202 x_1403 x_1604 x_1001)) +(minimize (+ (* 2 x_1) + (* 3 x_2) + (* 4 x_3) + x_9 + (* 2 x_6) + (* 3 x_7) + (* 4 x_8) + x_14 + (* 2 x_11) + (* 3 x_12) + (* 4 x_13) + x_19 + (* 2 x_16) + (* 3 x_17) + (* 4 x_18) + x_24 + (* 2 x_21) + (* 3 x_22) + (* 4 x_23) + x_29 + (* 2 x_26) + (* 3 x_27) + (* 4 x_28) + x_34 + (* 2 x_31) + (* 3 x_32) + (* 4 x_33) + x_39 + (* 2 x_36) + (* 3 x_37) + (* 4 x_38) + x_44 + (* 2 x_41) + (* 3 x_42) + (* 4 x_43) + x_49 + (* 2 x_46) + (* 3 x_47) + (* 4 x_48) + x_54 + (* 2 x_51) + (* 3 x_52) + (* 4 x_53) + x_59 + (* 2 x_56) + (* 3 x_57) + (* 4 x_58) + x_64 + (* 2 x_61) + (* 3 x_62) + (* 4 x_63) + x_69 + (* 2 x_66) + (* 3 x_67) + (* 4 x_68) + x_74 + (* 2 x_71) + (* 3 x_72) + (* 4 x_73) + x_79 + (* 2 x_76) + (* 3 x_77) + (* 4 x_78) + x_84 + (* 2 x_81) + (* 3 x_82) + (* 4 x_83) + x_89 + (* 2 x_86) + (* 3 x_87) + (* 4 x_88) + x_94 + (* 2 x_91) + (* 3 x_92) + (* 4 x_93) + x_99 + (* 2 x_96) + (* 3 x_97) + (* 4 x_98) + x_104 + (* 2 x_101) + (* 3 x_102) + (* 4 x_103) + x_109 + (* 2 x_106) + (* 3 x_107) + (* 4 x_108) + x_114 + (* 2 x_111) + (* 3 x_112) + (* 4 x_113) + x_119 + (* 2 x_116) + (* 3 x_117) + (* 4 x_118) + x_124 + (* 2 x_121) + (* 3 x_122) + (* 4 x_123) + x_129 + (* 2 x_126) + (* 3 x_127) + (* 4 x_128) + x_134 + (* 2 x_131) + (* 3 x_132) + (* 4 x_133) + x_139 + (* 2 x_136) + (* 3 x_137) + (* 4 x_138) + x_144 + (* 2 x_141) + (* 3 x_142) + (* 4 x_143) + x_149 + (* 2 x_146) + (* 3 x_147) + (* 4 x_148) + x_154 + (* 2 x_151) + (* 3 x_152) + (* 4 x_153) + x_159 + (* 2 x_156) + (* 3 x_157) + (* 4 x_158) + x_164 + (* 2 x_161) + (* 3 x_162) + (* 4 x_163) + x_169 + (* 2 x_166) + (* 3 x_167) + (* 4 x_168) + x_174 + (* 2 x_171) + (* 3 x_172) + (* 4 x_173) + x_179 + (* 2 x_176) + (* 3 x_177) + (* 4 x_178) + x_184 + (* 2 x_181) + (* 3 x_182) + (* 4 x_183) + x_189 + (* 2 x_186) + (* 3 x_187) + (* 4 x_188) + x_194 + (* 2 x_191) + (* 3 x_192) + (* 4 x_193) + x_199 + (* 2 x_196) + (* 3 x_197) + (* 4 x_198) + x_204 + (* 2 x_201) + (* 3 x_202) + (* 4 x_203) + x_209 + (* 2 x_206) + (* 3 x_207) + (* 4 x_208) + x_214 + (* 2 x_211) + (* 3 x_212) + (* 4 x_213) + x_219 + (* 2 x_216) + (* 3 x_217) + (* 4 x_218) + x_224 + (* 2 x_221) + (* 3 x_222) + (* 4 x_223) + x_229 + (* 2 x_226) + (* 3 x_227) + (* 4 x_228) + x_234 + (* 2 x_231) + (* 3 x_232) + (* 4 x_233) + x_239 + (* 2 x_236) + (* 3 x_237) + (* 4 x_238) + x_244 + (* 2 x_241) + (* 3 x_242) + (* 4 x_243) + x_249 + (* 2 x_246) + (* 3 x_247) + (* 4 x_248) + x_254 + (* 2 x_251) + (* 3 x_252) + (* 4 x_253) + x_259 + (* 2 x_256) + (* 3 x_257) + (* 4 x_258) + x_264 + (* 2 x_261) + (* 3 x_262) + (* 4 x_263) + x_269 + (* 2 x_266) + (* 3 x_267) + (* 4 x_268) + x_274 + (* 2 x_271) + (* 3 x_272) + (* 4 x_273) + x_279 + (* 2 x_276) + (* 3 x_277) + (* 4 x_278) + x_284 + (* 2 x_281) + (* 3 x_282) + (* 4 x_283) + x_289 + (* 2 x_286) + (* 3 x_287) + (* 4 x_288) + x_294 + (* 2 x_291) + (* 3 x_292) + (* 4 x_293) + x_299 + (* 2 x_296) + (* 3 x_297) + (* 4 x_298) + x_304 + (* 2 x_301) + (* 3 x_302) + (* 4 x_303) + x_309 + (* 2 x_306) + (* 3 x_307) + (* 4 x_308) + x_314 + (* 2 x_311) + (* 3 x_312) + (* 4 x_313) + x_319 + (* 2 x_316) + (* 3 x_317) + (* 4 x_318) + x_324 + (* 2 x_321) + (* 3 x_322) + (* 4 x_323) + x_329 + (* 2 x_326) + (* 3 x_327) + (* 4 x_328) + x_334 + (* 2 x_331) + (* 3 x_332) + (* 4 x_333) + x_339 + (* 2 x_336) + (* 3 x_337) + (* 4 x_338) + x_344 + (* 2 x_341) + (* 3 x_342) + (* 4 x_343) + x_349 + (* 2 x_346) + (* 3 x_347) + (* 4 x_348) + x_354 + (* 2 x_351) + (* 3 x_352) + (* 4 x_353) + x_359 + (* 2 x_356) + (* 3 x_357) + (* 4 x_358) + x_364 + (* 2 x_361) + (* 3 x_362) + (* 4 x_363) + x_369 + (* 2 x_366) + (* 3 x_367) + (* 4 x_368) + x_374 + (* 2 x_371) + (* 3 x_372) + (* 4 x_373) + x_379 + (* 2 x_376) + (* 3 x_377) + (* 4 x_378) + x_384 + (* 2 x_381) + (* 3 x_382) + (* 4 x_383) + x_389 + (* 2 x_386) + (* 3 x_387) + (* 4 x_388) + x_394 + (* 2 x_391) + (* 3 x_392) + (* 4 x_393) + x_399 + (* 2 x_396) + (* 3 x_397) + (* 4 x_398) + x_404 + (* 2 x_401) + (* 3 x_402) + (* 4 x_403) + x_409 + (* 2 x_406) + (* 3 x_407) + (* 4 x_408) + x_414 + (* 2 x_411) + (* 3 x_412) + (* 4 x_413) + x_419 + (* 2 x_416) + (* 3 x_417) + (* 4 x_418) + x_424 + (* 2 x_421) + (* 3 x_422) + (* 4 x_423) + x_429 + (* 2 x_426) + (* 3 x_427) + (* 4 x_428) + x_434 + (* 2 x_431) + (* 3 x_432) + (* 4 x_433) + x_439 + (* 2 x_436) + (* 3 x_437) + (* 4 x_438) + x_444 + (* 2 x_441) + (* 3 x_442) + (* 4 x_443) + x_449 + (* 2 x_446) + (* 3 x_447) + (* 4 x_448) + x_454 + (* 2 x_451) + (* 3 x_452) + (* 4 x_453) + x_459 + (* 2 x_456) + (* 3 x_457) + (* 4 x_458) + x_464 + (* 2 x_461) + (* 3 x_462) + (* 4 x_463) + x_469 + (* 2 x_466) + (* 3 x_467) + (* 4 x_468) + x_474 + (* 2 x_471) + (* 3 x_472) + (* 4 x_473) + x_479 + (* 2 x_476) + (* 3 x_477) + (* 4 x_478) + x_484 + (* 2 x_481) + (* 3 x_482) + (* 4 x_483) + x_489 + (* 2 x_486) + (* 3 x_487) + (* 4 x_488) + x_494 + (* 2 x_491) + (* 3 x_492) + (* 4 x_493) + x_499 + (* 2 x_496) + (* 3 x_497) + (* 4 x_498) + x_504 + (* 2 x_501) + (* 3 x_502) + (* 4 x_503) + x_509 + (* 2 x_506) + (* 3 x_507) + (* 4 x_508) + x_514 + (* 2 x_511) + (* 3 x_512) + (* 4 x_513) + x_519 + (* 2 x_516) + (* 3 x_517) + (* 4 x_518) + x_524 + (* 2 x_521) + (* 3 x_522) + (* 4 x_523) + x_529 + (* 2 x_526) + (* 3 x_527) + (* 4 x_528) + x_534 + (* 2 x_531) + (* 3 x_532) + (* 4 x_533) + x_539 + (* 2 x_536) + (* 3 x_537) + (* 4 x_538) + x_544 + (* 2 x_541) + (* 3 x_542) + (* 4 x_543) + x_549 + (* 2 x_546) + (* 3 x_547) + (* 4 x_548) + x_554 + (* 2 x_551) + (* 3 x_552) + (* 4 x_553) + x_559 + (* 2 x_556) + (* 3 x_557) + (* 4 x_558) + x_564 + (* 2 x_561) + (* 3 x_562) + (* 4 x_563) + x_569 + (* 2 x_566) + (* 3 x_567) + (* 4 x_568) + x_574 + (* 2 x_571) + (* 3 x_572) + (* 4 x_573) + x_579 + (* 2 x_576) + (* 3 x_577) + (* 4 x_578) + x_584 + (* 2 x_581) + (* 3 x_582) + (* 4 x_583) + x_589 + (* 2 x_586) + (* 3 x_587) + (* 4 x_588) + x_594 + (* 2 x_591) + (* 3 x_592) + (* 4 x_593) + x_599 + (* 2 x_596) + (* 3 x_597) + (* 4 x_598) + x_604 + (* 2 x_601) + (* 3 x_602) + (* 4 x_603) + x_609 + (* 2 x_606) + (* 3 x_607) + (* 4 x_608) + x_614 + (* 2 x_611) + (* 3 x_612) + (* 4 x_613) + x_619 + (* 2 x_616) + (* 3 x_617) + (* 4 x_618) + x_624 + (* 2 x_621) + (* 3 x_622) + (* 4 x_623) + x_629 + (* 2 x_626) + (* 3 x_627) + (* 4 x_628) + x_634 + (* 2 x_631) + (* 3 x_632) + (* 4 x_633) + x_639 + (* 2 x_636) + (* 3 x_637) + (* 4 x_638) + x_644 + (* 2 x_641) + (* 3 x_642) + (* 4 x_643) + x_649 + (* 2 x_646) + (* 3 x_647) + (* 4 x_648) + x_654 + (* 2 x_651) + (* 3 x_652) + (* 4 x_653) + x_659 + (* 2 x_656) + (* 3 x_657) + (* 4 x_658) + x_664 + (* 2 x_661) + (* 3 x_662) + (* 4 x_663) + x_669 + (* 2 x_666) + (* 3 x_667) + (* 4 x_668) + x_674 + (* 2 x_671) + (* 3 x_672) + (* 4 x_673) + x_679 + (* 2 x_676) + (* 3 x_677) + (* 4 x_678) + x_684 + (* 2 x_681) + (* 3 x_682) + (* 4 x_683) + x_689 + (* 2 x_686) + (* 3 x_687) + (* 4 x_688) + x_694 + (* 2 x_691) + (* 3 x_692) + (* 4 x_693) + x_699 + (* 2 x_696) + (* 3 x_697) + (* 4 x_698) + x_704 + (* 2 x_701) + (* 3 x_702) + (* 4 x_703) + x_709 + (* 2 x_706) + (* 3 x_707) + (* 4 x_708) + x_714 + (* 2 x_711) + (* 3 x_712) + (* 4 x_713) + x_719 + (* 2 x_716) + (* 3 x_717) + (* 4 x_718) + x_724 + (* 2 x_721) + (* 3 x_722) + (* 4 x_723) + x_729 + (* 2 x_726) + (* 3 x_727) + (* 4 x_728) + x_734 + (* 2 x_731) + (* 3 x_732) + (* 4 x_733) + x_739 + (* 2 x_736) + (* 3 x_737) + (* 4 x_738) + x_744 + (* 2 x_741) + (* 3 x_742) + (* 4 x_743) + x_749 + (* 2 x_746) + (* 3 x_747) + (* 4 x_748) + x_754 + (* 2 x_751) + (* 3 x_752) + (* 4 x_753) + x_759 + (* 2 x_756) + (* 3 x_757) + (* 4 x_758) + x_764 + (* 2 x_761) + (* 3 x_762) + (* 4 x_763) + x_769 + (* 2 x_766) + (* 3 x_767) + (* 4 x_768) + x_774 + (* 2 x_771) + (* 3 x_772) + (* 4 x_773) + x_779 + (* 2 x_776) + (* 3 x_777) + (* 4 x_778) + x_784 + (* 2 x_781) + (* 3 x_782) + (* 4 x_783) + x_789 + (* 2 x_786) + (* 3 x_787) + (* 4 x_788) + x_794 + (* 2 x_791) + (* 3 x_792) + (* 4 x_793) + x_799 + (* 2 x_796) + (* 3 x_797) + (* 4 x_798) + x_804 + (* 2 x_801) + (* 3 x_802) + (* 4 x_803) + x_809 + (* 2 x_806) + (* 3 x_807) + (* 4 x_808) + x_814 + (* 2 x_811) + (* 3 x_812) + (* 4 x_813) + x_819 + (* 2 x_816) + (* 3 x_817) + (* 4 x_818) + x_824 + (* 2 x_821) + (* 3 x_822) + (* 4 x_823) + x_829 + (* 2 x_826) + (* 3 x_827) + (* 4 x_828) + x_834 + (* 2 x_831) + (* 3 x_832) + (* 4 x_833) + x_839 + (* 2 x_836) + (* 3 x_837) + (* 4 x_838) + x_844 + (* 2 x_841) + (* 3 x_842) + (* 4 x_843) + x_849 + (* 2 x_846) + (* 3 x_847) + (* 4 x_848) + x_854 + (* 2 x_851) + (* 3 x_852) + (* 4 x_853) + x_859 + (* 2 x_856) + (* 3 x_857) + (* 4 x_858) + x_864 + (* 2 x_861) + (* 3 x_862) + (* 4 x_863) + x_869 + (* 2 x_866) + (* 3 x_867) + (* 4 x_868) + x_874 + (* 2 x_871) + (* 3 x_872) + (* 4 x_873) + x_879 + (* 2 x_876) + (* 3 x_877) + (* 4 x_878) + x_884 + (* 2 x_881) + (* 3 x_882) + (* 4 x_883) + x_889 + (* 2 x_886) + (* 3 x_887) + (* 4 x_888) + x_894 + (* 2 x_891) + (* 3 x_892) + (* 4 x_893) + x_899 + (* 2 x_896) + (* 3 x_897) + (* 4 x_898) + x_904 + (* 2 x_901) + (* 3 x_902) + (* 4 x_903) + x_909 + (* 2 x_906) + (* 3 x_907) + (* 4 x_908) + x_914 + (* 2 x_911) + (* 3 x_912) + (* 4 x_913) + x_919 + (* 2 x_916) + (* 3 x_917) + (* 4 x_918) + x_924 + (* 2 x_921) + (* 3 x_922) + (* 4 x_923) + x_929 + (* 2 x_926) + (* 3 x_927) + (* 4 x_928) + x_934 + (* 2 x_931) + (* 3 x_932) + (* 4 x_933) + x_939 + (* 2 x_936) + (* 3 x_937) + (* 4 x_938) + x_944 + (* 2 x_941) + (* 3 x_942) + (* 4 x_943) + x_949 + (* 2 x_946) + (* 3 x_947) + (* 4 x_948) + x_954 + (* 2 x_951) + (* 3 x_952) + (* 4 x_953) + x_959 + (* 2 x_956) + (* 3 x_957) + (* 4 x_958) + x_964 + (* 2 x_961) + (* 3 x_962) + (* 4 x_963) + x_969 + (* 2 x_966) + (* 3 x_967) + (* 4 x_968) + x_974 + (* 2 x_971) + (* 3 x_972) + (* 4 x_973) + x_979 + (* 2 x_976) + (* 3 x_977) + (* 4 x_978) + x_984 + (* 2 x_981) + (* 3 x_982) + (* 4 x_983) + x_989 + (* 2 x_986) + (* 3 x_987) + (* 4 x_988) + x_994 + (* 2 x_991) + (* 3 x_992) + (* 4 x_993) + x_999 + (* 2 x_996) + (* 3 x_997) + (* 4 x_998) + x_4 + (* 100 x_1202) + (* 100 x_1403) + (* 100 x_1604) + (* 100 x_1001))) +(optimize :print_statistics true + :wmaxsat_engine bvsls + :maxsat_engine weighted_maxsat) diff --git a/tests/wmax1.smt2 b/tests/wmax1.smt2 new file mode 100644 index 000000000..602309e95 --- /dev/null +++ b/tests/wmax1.smt2 @@ -0,0 +1,5842 @@ +(declare-fun x_354 () Int) +(declare-fun x_522 () Int) +(declare-fun x_464 () Int) +(declare-fun x_644 () Int) +(declare-fun x_174 () Int) +(declare-fun x_397 () Int) +(declare-fun x_432 () Int) +(declare-fun x_557 () Int) +(declare-fun x_926 () Int) +(declare-fun x_582 () Int) +(declare-fun x_779 () Int) +(declare-fun x_759 () Int) +(declare-fun x_912 () Int) +(declare-fun x_868 () Int) +(declare-fun x_384 () Int) +(declare-fun x_963 () Int) +(declare-fun x_658 () Int) +(declare-fun x_362 () Int) +(declare-fun x_984 () Int) +(declare-fun x_308 () Int) +(declare-fun x_456 () Int) +(declare-fun x_17 () Int) +(declare-fun x_816 () Int) +(declare-fun x_833 () Int) +(declare-fun x_463 () Int) +(declare-fun x_211 () Int) +(declare-fun x_607 () Int) +(declare-fun x_139 () Int) +(declare-fun x_124 () Int) +(declare-fun x_291 () Int) +(declare-fun x_859 () Int) +(declare-fun x_888 () Int) +(declare-fun x_31 () Int) +(declare-fun x_472 () Int) +(declare-fun x_434 () Int) +(declare-fun x_154 () Int) +(declare-fun x_347 () Int) +(declare-fun x_88 () Int) +(declare-fun x_769 () Int) +(declare-fun x_986 () Int) +(declare-fun x_8 () Int) +(declare-fun x_196 () Int) +(declare-fun x_882 () Int) +(declare-fun x_711 () Int) +(declare-fun x_167 () Int) +(declare-fun x_119 () Int) +(declare-fun x_4 () Int) +(declare-fun x_33 () Int) +(declare-fun x_178 () Int) +(declare-fun x_893 () Int) +(declare-fun x_429 () Int) +(declare-fun x_527 () Int) +(declare-fun x_194 () Int) +(declare-fun x_498 () Int) +(declare-fun x_346 () Int) +(declare-fun x_712 () Int) +(declare-fun x_691 () Int) +(declare-fun x_294 () Int) +(declare-fun x_402 () Int) +(declare-fun x_213 () Int) +(declare-fun x_239 () Int) +(declare-fun x_297 () Int) +(declare-fun x_427 () Int) +(declare-fun x_489 () Int) +(declare-fun x_841 () Int) +(declare-fun x_186 () Int) +(declare-fun x_149 () Int) +(declare-fun x_586 () Int) +(declare-fun x_932 () Int) +(declare-fun x_367 () Int) +(declare-fun x_77 () Int) +(declare-fun x_123 () Int) +(declare-fun x_884 () Int) +(declare-fun x_989 () Int) +(declare-fun x_242 () Int) +(declare-fun x_614 () Int) +(declare-fun x_381 () Int) +(declare-fun x_388 () Int) +(declare-fun x_306 () Int) +(declare-fun x_737 () Int) +(declare-fun x_277 () Int) +(declare-fun x_966 () Int) +(declare-fun x_67 () Int) +(declare-fun x_678 () Int) +(declare-fun x_87 () Int) +(declare-fun x_496 () Int) +(declare-fun x_919 () Int) +(declare-fun x_439 () Int) +(declare-fun x_854 () Int) +(declare-fun x_961 () Int) +(declare-fun x_697 () Int) +(declare-fun x_19 () Int) +(declare-fun x_818 () Int) +(declare-fun x_158 () Int) +(declare-fun x_26 () Int) +(declare-fun x_436 () Int) +(declare-fun x_798 () Int) +(declare-fun x_457 () Int) +(declare-fun x_838 () Int) +(declare-fun x_953 () Int) +(declare-fun x_524 () Int) +(declare-fun x_574 () Int) +(declare-fun x_212 () Int) +(declare-fun x_486 () Int) +(declare-fun x_3 () Int) +(declare-fun x_256 () Int) +(declare-fun x_22 () Int) +(declare-fun x_676 () Int) +(declare-fun x_789 () Int) +(declare-fun x_892 () Int) +(declare-fun x_682 () Int) +(declare-fun x_84 () Int) +(declare-fun x_819 () Int) +(declare-fun x_454 () Int) +(declare-fun x_59 () Int) +(declare-fun x_227 () Int) +(declare-fun x_572 () Int) +(declare-fun x_914 () Int) +(declare-fun x_39 () Int) +(declare-fun x_679 () Int) +(declare-fun x_824 () Int) +(declare-fun x_684 () Int) +(declare-fun x_221 () Int) +(declare-fun x_274 () Int) +(declare-fun x_32 () Int) +(declare-fun x_348 () Int) +(declare-fun x_877 () Int) +(declare-fun x_701 () Int) +(declare-fun x_231 () Int) +(declare-fun x_549 () Int) +(declare-fun x_889 () Int) +(declare-fun x_879 () Int) +(declare-fun x_662 () Int) +(declare-fun x_302 () Int) +(declare-fun x_979 () Int) +(declare-fun x_861 () Int) +(declare-fun x_973 () Int) +(declare-fun x_401 () Int) +(declare-fun x_537 () Int) +(declare-fun x_972 () Int) +(declare-fun x_269 () Int) +(declare-fun x_957 () Int) +(declare-fun x_271 () Int) +(declare-fun x_363 () Int) +(declare-fun x_181 () Int) +(declare-fun x_357 () Int) +(declare-fun x_591 () Int) +(declare-fun x_559 () Int) +(declare-fun x_51 () Int) +(declare-fun x_916 () Int) +(declare-fun x_389 () Int) +(declare-fun x_512 () Int) +(declare-fun x_988 () Int) +(declare-fun x_667 () Int) +(declare-fun x_511 () Int) +(declare-fun x_733 () Int) +(declare-fun x_821 () Int) +(declare-fun x_671 () Int) +(declare-fun x_707 () Int) +(declare-fun x_826 () Int) +(declare-fun x_319 () Int) +(declare-fun x_399 () Int) +(declare-fun x_852 () Int) +(declare-fun x_442 () Int) +(declare-fun x_108 () Int) +(declare-fun x_392 () Int) +(declare-fun x_776 () Int) +(declare-fun x_993 () Int) +(declare-fun x_459 () Int) +(declare-fun x_913 () Int) +(declare-fun x_107 () Int) +(declare-fun x_994 () Int) +(declare-fun x_61 () Int) +(declare-fun x_802 () Int) +(declare-fun x_677 () Int) +(declare-fun x_857 () Int) +(declare-fun x_706 () Int) +(declare-fun x_278 () Int) +(declare-fun x_443 () Int) +(declare-fun x_813 () Int) +(declare-fun x_971 () Int) +(declare-fun x_173 () Int) +(declare-fun x_91 () Int) +(declare-fun x_396 () Int) +(declare-fun x_551 () Int) +(declare-fun x_846 () Int) +(declare-fun x_417 () Int) +(declare-fun x_54 () Int) +(declare-fun x_721 () Int) +(declare-fun x_331 () Int) +(declare-fun x_467 () Int) +(declare-fun x_553 () Int) +(declare-fun x_959 () Int) +(declare-fun x_871 () Int) +(declare-fun x_692 () Int) +(declare-fun x_792 () Int) +(declare-fun x_593 () Int) +(declare-fun x_412 () Int) +(declare-fun x_531 () Int) +(declare-fun x_352 () Int) +(declare-fun x_333 () Int) +(declare-fun x_596 () Int) +(declare-fun x_229 () Int) +(declare-fun x_447 () Int) +(declare-fun x_53 () Int) +(declare-fun x_548 () Int) +(declare-fun x_43 () Int) +(declare-fun x_13 () Int) +(declare-fun x_198 () Int) +(declare-fun x_47 () Int) +(declare-fun x_626 () Int) +(declare-fun x_648 () Int) +(declare-fun x_902 () Int) +(declare-fun x_594 () Int) +(declare-fun x_113 () Int) +(declare-fun x_286 () Int) +(declare-fun x_163 () Int) +(declare-fun x_157 () Int) +(declare-fun x_659 () Int) +(declare-fun x_24 () Int) +(declare-fun x_631 () Int) +(declare-fun x_699 () Int) +(declare-fun x_366 () Int) +(declare-fun x_6 () Int) +(declare-fun x_156 () Int) +(declare-fun x_876 () Int) +(declare-fun x_598 () Int) +(declare-fun x_974 () Int) +(declare-fun x_372 () Int) +(declare-fun x_538 () Int) +(declare-fun x_287 () Int) +(declare-fun x_71 () Int) +(declare-fun x_371 () Int) +(declare-fun x_646 () Int) +(declare-fun x_519 () Int) +(declare-fun x_121 () Int) +(declare-fun x_268 () Int) +(declare-fun x_746 () Int) +(declare-fun x_562 () Int) +(declare-fun x_799 () Int) +(declare-fun x_423 () Int) +(declare-fun x_808 () Int) +(declare-fun x_303 () Int) +(declare-fun x_536 () Int) +(declare-fun x_344 () Int) +(declare-fun x_322 () Int) +(declare-fun x_299 () Int) +(declare-fun x_976 () Int) +(declare-fun x_279 () Int) +(declare-fun x_482 () Int) +(declare-fun x_246 () Int) +(declare-fun x_763 () Int) +(declare-fun x_111 () Int) +(declare-fun x_226 () Int) +(declare-fun x_741 () Int) +(declare-fun x_188 () Int) +(declare-fun x_873 () Int) +(declare-fun x_767 () Int) +(declare-fun x_766 () Int) +(declare-fun x_7 () Int) +(declare-fun x_377 () Int) +(declare-fun x_719 () Int) +(declare-fun x_704 () Int) +(declare-fun x_72 () Int) +(declare-fun x_27 () Int) +(declare-fun x_284 () Int) +(declare-fun x_943 () Int) +(declare-fun x_42 () Int) +(declare-fun x_881 () Int) +(declare-fun x_693 () Int) +(declare-fun x_422 () Int) +(declare-fun x_218 () Int) +(declare-fun x_736 () Int) +(declare-fun x_817 () Int) +(declare-fun x_168 () Int) +(declare-fun x_359 () Int) +(declare-fun x_16 () Int) +(declare-fun x_469 () Int) +(declare-fun x_814 () Int) +(declare-fun x_62 () Int) +(declare-fun x_461 () Int) +(declare-fun x_483 () Int) +(declare-fun x_68 () Int) +(declare-fun x_786 () Int) +(declare-fun x_938 () Int) +(declare-fun x_204 () Int) +(declare-fun x_718 () Int) +(declare-fun x_197 () Int) +(declare-fun x_603 () Int) +(declare-fun x_616 () Int) +(declare-fun x_117 () Int) +(declare-fun x_567 () Int) +(declare-fun x_729 () Int) +(declare-fun x_942 () Int) +(declare-fun x_748 () Int) +(declare-fun x_992 () Int) +(declare-fun x_713 () Int) +(declare-fun x_326 () Int) +(declare-fun x_689 () Int) +(declare-fun x_948 () Int) +(declare-fun x_717 () Int) +(declare-fun x_403 () Int) +(declare-fun x_872 () Int) +(declare-fun x_73 () Int) +(declare-fun x_639 () Int) +(declare-fun x_137 () Int) +(declare-fun x_373 () Int) +(declare-fun x_364 () Int) +(declare-fun x_576 () Int) +(declare-fun x_358 () Int) +(declare-fun x_466 () Int) +(declare-fun x_122 () Int) +(declare-fun x_637 () Int) +(declare-fun x_202 () Int) +(declare-fun x_476 () Int) +(declare-fun x_44 () Int) +(declare-fun x_151 () Int) +(declare-fun x_253 () Int) +(declare-fun x_696 () Int) +(declare-fun x_822 () Int) +(declare-fun x_641 () Int) +(declare-fun x_924 () Int) +(declare-fun x_233 () Int) +(declare-fun x_136 () Int) +(declare-fun x_222 () Int) +(declare-fun x_318 () Int) +(declare-fun x_694 () Int) +(declare-fun x_543 () Int) +(declare-fun x_141 () Int) +(declare-fun x_418 () Int) +(declare-fun x_409 () Int) +(declare-fun x_601 () Int) +(declare-fun x_339 () Int) +(declare-fun x_958 () Int) +(declare-fun x_773 () Int) +(declare-fun x_448 () Int) +(declare-fun x_508 () Int) +(declare-fun x_104 () Int) +(declare-fun x_674 () Int) +(declare-fun x_991 () Int) +(declare-fun x_406 () Int) +(declare-fun x_283 () Int) +(declare-fun x_552 () Int) +(declare-fun x_907 () Int) +(declare-fun x_408 () Int) +(declare-fun x_451 () Int) +(declare-fun x_897 () Int) +(declare-fun x_503 () Int) +(declare-fun x_672 () Int) +(declare-fun x_264 () Int) +(declare-fun x_382 () Int) +(declare-fun x_554 () Int) +(declare-fun x_561 () Int) +(declare-fun x_11 () Int) +(declare-fun x_329 () Int) +(declare-fun x_727 () Int) +(declare-fun x_97 () Int) +(declare-fun x_343 () Int) +(declare-fun x_918 () Int) +(declare-fun x_289 () Int) +(declare-fun x_803 () Int) +(declare-fun x_812 () Int) +(declare-fun x_547 () Int) +(declare-fun x_806 () Int) +(declare-fun x_252 () Int) +(declare-fun x_273 () Int) +(declare-fun x_618 () Int) +(declare-fun x_301 () Int) +(declare-fun x_688 () Int) +(declare-fun x_224 () Int) +(declare-fun x_449 () Int) +(declare-fun x_327 () Int) +(declare-fun x_387 () Int) +(declare-fun x_86 () Int) +(declare-fun x_89 () Int) +(declare-fun x_404 () Int) +(declare-fun x_507 () Int) +(declare-fun x_312 () Int) +(declare-fun x_578 () Int) +(declare-fun x_722 () Int) +(declare-fun x_762 () Int) +(declare-fun x_169 () Int) +(declare-fun x_206 () Int) +(declare-fun x_383 () Int) +(declare-fun x_867 () Int) +(declare-fun x_627 () Int) +(declare-fun x_638 () Int) +(declare-fun x_184 () Int) +(declare-fun x_479 () Int) +(declare-fun x_292 () Int) +(declare-fun x_844 () Int) +(declare-fun x_421 () Int) +(declare-fun x_911 () Int) +(declare-fun x_419 () Int) +(declare-fun x_612 () Int) +(declare-fun x_192 () Int) +(declare-fun x_656 () Int) +(declare-fun x_702 () Int) +(declare-fun x_778 () Int) +(declare-fun x_281 () Int) +(declare-fun x_834 () Int) +(declare-fun x_63 () Int) +(declare-fun x_836 () Int) +(declare-fun x_793 () Int) +(declare-fun x_622 () Int) +(declare-fun x_899 () Int) +(declare-fun x_944 () Int) +(declare-fun x_369 () Int) +(declare-fun x_336 () Int) +(declare-fun x_869 () Int) +(declare-fun x_257 () Int) +(declare-fun x_1001 () Int) +(declare-fun x_904 () Int) +(declare-fun x_528 () Int) +(declare-fun x_997 () Int) +(declare-fun x_414 () Int) +(declare-fun x_223 () Int) +(declare-fun x_642 () Int) +(declare-fun x_76 () Int) +(declare-fun x_29 () Int) +(declare-fun x_533 () Int) +(declare-fun x_41 () Int) +(declare-fun x_581 () Int) +(declare-fun x_791 () Int) +(declare-fun x_809 () Int) +(declare-fun x_321 () Int) +(declare-fun x_939 () Int) +(declare-fun x_541 () Int) +(declare-fun x_652 () Int) +(declare-fun x_569 () Int) +(declare-fun x_934 () Int) +(declare-fun x_207 () Int) +(declare-fun x_376 () Int) +(declare-fun x_109 () Int) +(declare-fun x_761 () Int) +(declare-fun x_446 () Int) +(declare-fun x_657 () Int) +(declare-fun x_171 () Int) +(declare-fun x_558 () Int) +(declare-fun x_276 () Int) +(declare-fun x_46 () Int) +(declare-fun x_668 () Int) +(declare-fun x_57 () Int) +(declare-fun x_374 () Int) +(declare-fun x_209 () Int) +(declare-fun x_739 () Int) +(declare-fun x_909 () Int) +(declare-fun x_468 () Int) +(declare-fun x_14 () Int) +(declare-fun x_832 () Int) +(declare-fun x_391 () Int) +(declare-fun x_517 () Int) +(declare-fun x_12 () Int) +(declare-fun x_244 () Int) +(declare-fun x_628 () Int) +(declare-fun x_334 () Int) +(declare-fun x_502 () Int) +(declare-fun x_883 () Int) +(declare-fun x_379 () Int) +(declare-fun x_307 () Int) +(declare-fun x_182 () Int) +(declare-fun x_293 () Int) +(declare-fun x_288 () Int) +(declare-fun x_633 () Int) +(declare-fun x_866 () Int) +(declare-fun x_571 () Int) +(declare-fun x_842 () Int) +(declare-fun x_921 () Int) +(declare-fun x_797 () Int) +(declare-fun x_153 () Int) +(declare-fun x_398 () Int) +(declare-fun x_583 () Int) +(declare-fun x_683 () Int) +(declare-fun x_189 () Int) +(declare-fun x_964 () Int) +(declare-fun x_164 () Int) +(declare-fun x_474 () Int) +(declare-fun x_521 () Int) +(declare-fun x_21 () Int) +(declare-fun x_518 () Int) +(declare-fun x_473 () Int) +(declare-fun x_896 () Int) +(declare-fun x_796 () Int) +(declare-fun x_477 () Int) +(declare-fun x_74 () Int) +(declare-fun x_116 () Int) +(declare-fun x_837 () Int) +(declare-fun x_673 () Int) +(declare-fun x_309 () Int) +(declare-fun x_58 () Int) +(declare-fun x_428 () Int) +(declare-fun x_589 () Int) +(declare-fun x_747 () Int) +(declare-fun x_929 () Int) +(declare-fun x_529 () Int) +(declare-fun x_413 () Int) +(declare-fun x_847 () Int) +(declare-fun x_262 () Int) +(declare-fun x_801 () Int) +(declare-fun x_952 () Int) +(declare-fun x_632 () Int) +(declare-fun x_142 () Int) +(declare-fun x_491 () Int) +(declare-fun x_546 () Int) +(declare-fun x_839 () Int) +(declare-fun x_588 () Int) +(declare-fun x_393 () Int) +(declare-fun x_118 () Int) +(declare-fun x_901 () Int) +(declare-fun x_962 () Int) +(declare-fun x_968 () Int) +(declare-fun x_886 () Int) +(declare-fun x_774 () Int) +(declare-fun x_487 () Int) +(declare-fun x_127 () Int) +(declare-fun x_237 () Int) +(declare-fun x_723 () Int) +(declare-fun x_542 () Int) +(declare-fun x_753 () Int) +(declare-fun x_129 () Int) +(declare-fun x_864 () Int) +(declare-fun x_611 () Int) +(declare-fun x_416 () Int) +(declare-fun x_947 () Int) +(declare-fun x_1202 () Int) +(declare-fun x_563 () Int) +(declare-fun x_337 () Int) +(declare-fun x_544 () Int) +(declare-fun x_654 () Int) +(declare-fun x_756 () Int) +(declare-fun x_744 () Int) +(declare-fun x_891 () Int) +(declare-fun x_378 () Int) +(declare-fun x_134 () Int) +(declare-fun x_208 () Int) +(declare-fun x_758 () Int) +(declare-fun x_848 () Int) +(declare-fun x_927 () Int) +(declare-fun x_937 () Int) +(declare-fun x_602 () Int) +(declare-fun x_349 () Int) +(declare-fun x_96 () Int) +(declare-fun x_162 () Int) +(declare-fun x_37 () Int) +(declare-fun x_941 () Int) +(declare-fun x_906 () Int) +(declare-fun x_811 () Int) +(declare-fun x_138 () Int) +(declare-fun x_621 () Int) +(declare-fun x_492 () Int) +(declare-fun x_764 () Int) +(declare-fun x_452 () Int) +(declare-fun x_851 () Int) +(declare-fun x_98 () Int) +(declare-fun x_236 () Int) +(declare-fun x_453 () Int) +(declare-fun x_978 () Int) +(declare-fun x_499 () Int) +(declare-fun x_494 () Int) +(declare-fun x_316 () Int) +(declare-fun x_587 () Int) +(declare-fun x_103 () Int) +(declare-fun x_734 () Int) +(declare-fun x_923 () Int) +(declare-fun x_228 () Int) +(declare-fun x_504 () Int) +(declare-fun x_564 () Int) +(declare-fun x_592 () Int) +(declare-fun x_2 () Int) +(declare-fun x_539 () Int) +(declare-fun x_247 () Int) +(declare-fun x_931 () Int) +(declare-fun x_903 () Int) +(declare-fun x_64 () Int) +(declare-fun x_232 () Int) +(declare-fun x_298 () Int) +(declare-fun x_126 () Int) +(declare-fun x_787 () Int) +(declare-fun x_243 () Int) +(declare-fun x_356 () Int) +(declare-fun x_709 () Int) +(declare-fun x_823 () Int) +(declare-fun x_338 () Int) +(declare-fun x_201 () Int) +(declare-fun x_304 () Int) +(declare-fun x_101 () Int) +(declare-fun x_568 () Int) +(declare-fun x_573 () Int) +(declare-fun x_28 () Int) +(declare-fun x_516 () Int) +(declare-fun x_619 () Int) +(declare-fun x_102 () Int) +(declare-fun x_92 () Int) +(declare-fun x_604 () Int) +(declare-fun x_597 () Int) +(declare-fun x_663 () Int) +(declare-fun x_731 () Int) +(declare-fun x_328 () Int) +(declare-fun x_143 () Int) +(declare-fun x_849 () Int) +(declare-fun x_128 () Int) +(declare-fun x_266 () Int) +(declare-fun x_203 () Int) +(declare-fun x_661 () Int) +(declare-fun x_996 () Int) +(declare-fun x_462 () Int) +(declare-fun x_977 () Int) +(declare-fun x_458 () Int) +(declare-fun x_933 () Int) +(declare-fun x_94 () Int) +(declare-fun x_332 () Int) +(declare-fun x_514 () Int) +(declare-fun x_969 () Int) +(declare-fun x_987 () Int) +(declare-fun x_497 () Int) +(declare-fun x_666 () Int) +(declare-fun x_858 () Int) +(declare-fun x_643 () Int) +(declare-fun x_523 () Int) +(declare-fun x_609 () Int) +(declare-fun x_263 () Int) +(declare-fun x_878 () Int) +(declare-fun x_981 () Int) +(declare-fun x_863 () Int) +(declare-fun x_324 () Int) +(declare-fun x_783 () Int) +(declare-fun x_241 () Int) +(declare-fun x_407 () Int) +(declare-fun x_708 () Int) +(declare-fun x_862 () Int) +(declare-fun x_757 () Int) +(declare-fun x_251 () Int) +(declare-fun x_771 () Int) +(declare-fun x_478 () Int) +(declare-fun x_437 () Int) +(declare-fun x_267 () Int) +(declare-fun x_599 () Int) +(declare-fun x_234 () Int) +(declare-fun x_177 () Int) +(declare-fun x_726 () Int) +(declare-fun x_261 () Int) +(declare-fun x_353 () Int) +(declare-fun x_732 () Int) +(declare-fun x_908 () Int) +(declare-fun x_361 () Int) +(declare-fun x_887 () Int) +(declare-fun x_488 () Int) +(declare-fun x_917 () Int) +(declare-fun x_716 () Int) +(declare-fun x_166 () Int) +(declare-fun x_112 () Int) +(declare-fun x_629 () Int) +(declare-fun x_52 () Int) +(declare-fun x_34 () Int) +(declare-fun x_183 () Int) +(declare-fun x_999 () Int) +(declare-fun x_99 () Int) +(declare-fun x_444 () Int) +(declare-fun x_424 () Int) +(declare-fun x_317 () Int) +(declare-fun x_784 () Int) +(declare-fun x_584 () Int) +(declare-fun x_282 () Int) +(declare-fun x_743 () Int) +(declare-fun x_56 () Int) +(declare-fun x_749 () Int) +(declare-fun x_411 () Int) +(declare-fun x_647 () Int) +(declare-fun x_219 () Int) +(declare-fun x_946 () Int) +(declare-fun x_433 () Int) +(declare-fun x_106 () Int) +(declare-fun x_38 () Int) +(declare-fun x_314 () Int) +(declare-fun x_481 () Int) +(declare-fun x_768 () Int) +(declare-fun x_579 () Int) +(declare-fun x_114 () Int) +(declare-fun x_894 () Int) +(declare-fun x_146 () Int) +(declare-fun x_577 () Int) +(declare-fun x_394 () Int) +(declare-fun x_566 () Int) +(declare-fun x_738 () Int) +(declare-fun x_506 () Int) +(declare-fun x_351 () Int) +(declare-fun x_493 () Int) +(declare-fun x_624 () Int) +(declare-fun x_653 () Int) +(declare-fun x_386 () Int) +(declare-fun x_526 () Int) +(declare-fun x_148 () Int) +(declare-fun x_131 () Int) +(declare-fun x_669 () Int) +(declare-fun x_982 () Int) +(declare-fun x_664 () Int) +(declare-fun x_501 () Int) +(declare-fun x_856 () Int) +(declare-fun x_828 () Int) +(declare-fun x_161 () Int) +(declare-fun x_772 () Int) +(declare-fun x_147 () Int) +(declare-fun x_967 () Int) +(declare-fun x_313 () Int) +(declare-fun x_681 () Int) +(declare-fun x_724 () Int) +(declare-fun x_636 () Int) +(declare-fun x_83 () Int) +(declare-fun x_754 () Int) +(declare-fun x_484 () Int) +(declare-fun x_49 () Int) +(declare-fun x_703 () Int) +(declare-fun x_36 () Int) +(declare-fun x_152 () Int) +(declare-fun x_187 () Int) +(declare-fun x_752 () Int) +(declare-fun x_191 () Int) +(declare-fun x_634 () Int) +(declare-fun x_788 () Int) +(declare-fun x_259 () Int) +(declare-fun x_431 () Int) +(declare-fun x_509 () Int) +(declare-fun x_93 () Int) +(declare-fun x_9 () Int) +(declare-fun x_513 () Int) +(declare-fun x_248 () Int) +(declare-fun x_272 () Int) +(declare-fun x_751 () Int) +(declare-fun x_686 () Int) +(declare-fun x_714 () Int) +(declare-fun x_807 () Int) +(declare-fun x_922 () Int) +(declare-fun x_81 () Int) +(declare-fun x_613 () Int) +(declare-fun x_928 () Int) +(declare-fun x_1604 () Int) +(declare-fun x_78 () Int) +(declare-fun x_249 () Int) +(declare-fun x_79 () Int) +(declare-fun x_649 () Int) +(declare-fun x_781 () Int) +(declare-fun x_687 () Int) +(declare-fun x_82 () Int) +(declare-fun x_804 () Int) +(declare-fun x_441 () Int) +(declare-fun x_651 () Int) +(declare-fun x_936 () Int) +(declare-fun x_1 () Int) +(declare-fun x_179 () Int) +(declare-fun x_199 () Int) +(declare-fun x_623 () Int) +(declare-fun x_794 () Int) +(declare-fun x_777 () Int) +(declare-fun x_214 () Int) +(declare-fun x_296 () Int) +(declare-fun x_949 () Int) +(declare-fun x_133 () Int) +(declare-fun x_829 () Int) +(declare-fun x_556 () Int) +(declare-fun x_617 () Int) +(declare-fun x_18 () Int) +(declare-fun x_728 () Int) +(declare-fun x_426 () Int) +(declare-fun x_898 () Int) +(declare-fun x_23 () Int) +(declare-fun x_843 () Int) +(declare-fun x_827 () Int) +(declare-fun x_831 () Int) +(declare-fun x_954 () Int) +(declare-fun x_341 () Int) +(declare-fun x_956 () Int) +(declare-fun x_983 () Int) +(declare-fun x_606 () Int) +(declare-fun x_874 () Int) +(declare-fun x_698 () Int) +(declare-fun x_782 () Int) +(declare-fun x_48 () Int) +(declare-fun x_172 () Int) +(declare-fun x_342 () Int) +(declare-fun x_238 () Int) +(declare-fun x_323 () Int) +(declare-fun x_608 () Int) +(declare-fun x_471 () Int) +(declare-fun x_216 () Int) +(declare-fun x_69 () Int) +(declare-fun x_438 () Int) +(declare-fun x_534 () Int) +(declare-fun x_368 () Int) +(declare-fun x_193 () Int) +(declare-fun x_532 () Int) +(declare-fun x_951 () Int) +(declare-fun x_258 () Int) +(declare-fun x_853 () Int) +(declare-fun x_132 () Int) +(declare-fun x_159 () Int) +(declare-fun x_217 () Int) +(declare-fun x_742 () Int) +(declare-fun x_311 () Int) +(declare-fun x_1403 () Int) +(declare-fun x_176 () Int) +(declare-fun x_254 () Int) +(declare-fun x_66 () Int) +(declare-fun x_144 () Int) +(declare-fun x_998 () Int) +(assert (<= 0 x_1)) +(assert (>= 1 x_1)) +(assert (<= 0 x_2)) +(assert (>= 1 x_2)) +(assert (<= 0 x_3)) +(assert (>= 1 x_3)) +(assert (<= 0 x_4)) +(assert (>= 1 x_4)) +(assert (<= 0 x_6)) +(assert (>= 1 x_6)) +(assert (<= 0 x_7)) +(assert (>= 1 x_7)) +(assert (<= 0 x_8)) +(assert (>= 1 x_8)) +(assert (<= 0 x_9)) +(assert (>= 1 x_9)) +(assert (<= 0 x_11)) +(assert (>= 1 x_11)) +(assert (<= 0 x_12)) +(assert (>= 1 x_12)) +(assert (<= 0 x_13)) +(assert (>= 1 x_13)) +(assert (<= 0 x_14)) +(assert (>= 1 x_14)) +(assert (<= 0 x_16)) +(assert (>= 1 x_16)) +(assert (<= 0 x_17)) +(assert (>= 1 x_17)) +(assert (<= 0 x_18)) +(assert (>= 1 x_18)) +(assert (<= 0 x_19)) +(assert (>= 1 x_19)) +(assert (<= 0 x_21)) +(assert (>= 1 x_21)) +(assert (<= 0 x_22)) +(assert (>= 1 x_22)) +(assert (<= 0 x_23)) +(assert (>= 1 x_23)) +(assert (<= 0 x_24)) +(assert (>= 1 x_24)) +(assert (<= 0 x_26)) +(assert (>= 1 x_26)) +(assert (<= 0 x_27)) +(assert (>= 1 x_27)) +(assert (<= 0 x_28)) +(assert (>= 1 x_28)) +(assert (<= 0 x_29)) +(assert (>= 1 x_29)) +(assert (<= 0 x_31)) +(assert (>= 1 x_31)) +(assert (<= 0 x_32)) +(assert (>= 1 x_32)) +(assert (<= 0 x_33)) +(assert (>= 1 x_33)) +(assert (<= 0 x_34)) +(assert (>= 1 x_34)) +(assert (<= 0 x_36)) +(assert (>= 1 x_36)) +(assert (<= 0 x_37)) +(assert (>= 1 x_37)) +(assert (<= 0 x_38)) +(assert (>= 1 x_38)) +(assert (<= 0 x_39)) +(assert (>= 1 x_39)) +(assert (<= 0 x_41)) +(assert (>= 1 x_41)) +(assert (<= 0 x_42)) +(assert (>= 1 x_42)) +(assert (<= 0 x_43)) +(assert (>= 1 x_43)) +(assert (<= 0 x_44)) +(assert (>= 1 x_44)) +(assert (<= 0 x_46)) +(assert (>= 1 x_46)) +(assert (<= 0 x_47)) +(assert (>= 1 x_47)) +(assert (<= 0 x_48)) +(assert (>= 1 x_48)) +(assert (<= 0 x_49)) +(assert (>= 1 x_49)) +(assert (<= 0 x_51)) +(assert (>= 1 x_51)) +(assert (<= 0 x_52)) +(assert (>= 1 x_52)) +(assert (<= 0 x_53)) +(assert (>= 1 x_53)) +(assert (<= 0 x_54)) +(assert (>= 1 x_54)) +(assert (<= 0 x_56)) +(assert (>= 1 x_56)) +(assert (<= 0 x_57)) +(assert (>= 1 x_57)) +(assert (<= 0 x_58)) +(assert (>= 1 x_58)) +(assert (<= 0 x_59)) +(assert (>= 1 x_59)) +(assert (<= 0 x_61)) +(assert (>= 1 x_61)) +(assert (<= 0 x_62)) +(assert (>= 1 x_62)) +(assert (<= 0 x_63)) +(assert (>= 1 x_63)) +(assert (<= 0 x_64)) +(assert (>= 1 x_64)) +(assert (<= 0 x_66)) +(assert (>= 1 x_66)) +(assert (<= 0 x_67)) +(assert (>= 1 x_67)) +(assert (<= 0 x_68)) +(assert (>= 1 x_68)) +(assert (<= 0 x_69)) +(assert (>= 1 x_69)) +(assert (<= 0 x_71)) +(assert (>= 1 x_71)) +(assert (<= 0 x_72)) +(assert (>= 1 x_72)) +(assert (<= 0 x_73)) +(assert (>= 1 x_73)) +(assert (<= 0 x_74)) +(assert (>= 1 x_74)) +(assert (<= 0 x_76)) +(assert (>= 1 x_76)) +(assert (<= 0 x_77)) +(assert (>= 1 x_77)) +(assert (<= 0 x_78)) +(assert (>= 1 x_78)) +(assert (<= 0 x_79)) +(assert (>= 1 x_79)) +(assert (<= 0 x_81)) +(assert (>= 1 x_81)) +(assert (<= 0 x_82)) +(assert (>= 1 x_82)) +(assert (<= 0 x_83)) +(assert (>= 1 x_83)) +(assert (<= 0 x_84)) +(assert (>= 1 x_84)) +(assert (<= 0 x_86)) +(assert (>= 1 x_86)) +(assert (<= 0 x_87)) +(assert (>= 1 x_87)) +(assert (<= 0 x_88)) +(assert (>= 1 x_88)) +(assert (<= 0 x_89)) +(assert (>= 1 x_89)) +(assert (<= 0 x_91)) +(assert (>= 1 x_91)) +(assert (<= 0 x_92)) +(assert (>= 1 x_92)) +(assert (<= 0 x_93)) +(assert (>= 1 x_93)) +(assert (<= 0 x_94)) +(assert (>= 1 x_94)) +(assert (<= 0 x_96)) +(assert (>= 1 x_96)) +(assert (<= 0 x_97)) +(assert (>= 1 x_97)) +(assert (<= 0 x_98)) +(assert (>= 1 x_98)) +(assert (<= 0 x_99)) +(assert (>= 1 x_99)) +(assert (<= 0 x_101)) +(assert (>= 1 x_101)) +(assert (<= 0 x_102)) +(assert (>= 1 x_102)) +(assert (<= 0 x_103)) +(assert (>= 1 x_103)) +(assert (<= 0 x_104)) +(assert (>= 1 x_104)) +(assert (<= 0 x_106)) +(assert (>= 1 x_106)) +(assert (<= 0 x_107)) +(assert (>= 1 x_107)) +(assert (<= 0 x_108)) +(assert (>= 1 x_108)) +(assert (<= 0 x_109)) +(assert (>= 1 x_109)) +(assert (<= 0 x_111)) +(assert (>= 1 x_111)) +(assert (<= 0 x_112)) +(assert (>= 1 x_112)) +(assert (<= 0 x_113)) +(assert (>= 1 x_113)) +(assert (<= 0 x_114)) +(assert (>= 1 x_114)) +(assert (<= 0 x_116)) +(assert (>= 1 x_116)) +(assert (<= 0 x_117)) +(assert (>= 1 x_117)) +(assert (<= 0 x_118)) +(assert (>= 1 x_118)) +(assert (<= 0 x_119)) +(assert (>= 1 x_119)) +(assert (<= 0 x_121)) +(assert (>= 1 x_121)) +(assert (<= 0 x_122)) +(assert (>= 1 x_122)) +(assert (<= 0 x_123)) +(assert (>= 1 x_123)) +(assert (<= 0 x_124)) +(assert (>= 1 x_124)) +(assert (<= 0 x_126)) +(assert (>= 1 x_126)) +(assert (<= 0 x_127)) +(assert (>= 1 x_127)) +(assert (<= 0 x_128)) +(assert (>= 1 x_128)) +(assert (<= 0 x_129)) +(assert (>= 1 x_129)) +(assert (<= 0 x_131)) +(assert (>= 1 x_131)) +(assert (<= 0 x_132)) +(assert (>= 1 x_132)) +(assert (<= 0 x_133)) +(assert (>= 1 x_133)) +(assert (<= 0 x_134)) +(assert (>= 1 x_134)) +(assert (<= 0 x_136)) +(assert (>= 1 x_136)) +(assert (<= 0 x_137)) +(assert (>= 1 x_137)) +(assert (<= 0 x_138)) +(assert (>= 1 x_138)) +(assert (<= 0 x_139)) +(assert (>= 1 x_139)) +(assert (<= 0 x_141)) +(assert (>= 1 x_141)) +(assert (<= 0 x_142)) +(assert (>= 1 x_142)) +(assert (<= 0 x_143)) +(assert (>= 1 x_143)) +(assert (<= 0 x_144)) +(assert (>= 1 x_144)) +(assert (<= 0 x_146)) +(assert (>= 1 x_146)) +(assert (<= 0 x_147)) +(assert (>= 1 x_147)) +(assert (<= 0 x_148)) +(assert (>= 1 x_148)) +(assert (<= 0 x_149)) +(assert (>= 1 x_149)) +(assert (<= 0 x_151)) +(assert (>= 1 x_151)) +(assert (<= 0 x_152)) +(assert (>= 1 x_152)) +(assert (<= 0 x_153)) +(assert (>= 1 x_153)) +(assert (<= 0 x_154)) +(assert (>= 1 x_154)) +(assert (<= 0 x_156)) +(assert (>= 1 x_156)) +(assert (<= 0 x_157)) +(assert (>= 1 x_157)) +(assert (<= 0 x_158)) +(assert (>= 1 x_158)) +(assert (<= 0 x_159)) +(assert (>= 1 x_159)) +(assert (<= 0 x_161)) +(assert (>= 1 x_161)) +(assert (<= 0 x_162)) +(assert (>= 1 x_162)) +(assert (<= 0 x_163)) +(assert (>= 1 x_163)) +(assert (<= 0 x_164)) +(assert (>= 1 x_164)) +(assert (<= 0 x_166)) +(assert (>= 1 x_166)) +(assert (<= 0 x_167)) +(assert (>= 1 x_167)) +(assert (<= 0 x_168)) +(assert (>= 1 x_168)) +(assert (<= 0 x_169)) +(assert (>= 1 x_169)) +(assert (<= 0 x_171)) +(assert (>= 1 x_171)) +(assert (<= 0 x_172)) +(assert (>= 1 x_172)) +(assert (<= 0 x_173)) +(assert (>= 1 x_173)) +(assert (<= 0 x_174)) +(assert (>= 1 x_174)) +(assert (<= 0 x_176)) +(assert (>= 1 x_176)) +(assert (<= 0 x_177)) +(assert (>= 1 x_177)) +(assert (<= 0 x_178)) +(assert (>= 1 x_178)) +(assert (<= 0 x_179)) +(assert (>= 1 x_179)) +(assert (<= 0 x_181)) +(assert (>= 1 x_181)) +(assert (<= 0 x_182)) +(assert (>= 1 x_182)) +(assert (<= 0 x_183)) +(assert (>= 1 x_183)) +(assert (<= 0 x_184)) +(assert (>= 1 x_184)) +(assert (<= 0 x_186)) +(assert (>= 1 x_186)) +(assert (<= 0 x_187)) +(assert (>= 1 x_187)) +(assert (<= 0 x_188)) +(assert (>= 1 x_188)) +(assert (<= 0 x_189)) +(assert (>= 1 x_189)) +(assert (<= 0 x_191)) +(assert (>= 1 x_191)) +(assert (<= 0 x_192)) +(assert (>= 1 x_192)) +(assert (<= 0 x_193)) +(assert (>= 1 x_193)) +(assert (<= 0 x_194)) +(assert (>= 1 x_194)) +(assert (<= 0 x_196)) +(assert (>= 1 x_196)) +(assert (<= 0 x_197)) +(assert (>= 1 x_197)) +(assert (<= 0 x_198)) +(assert (>= 1 x_198)) +(assert (<= 0 x_199)) +(assert (>= 1 x_199)) +(assert (<= 0 x_201)) +(assert (>= 1 x_201)) +(assert (<= 0 x_202)) +(assert (>= 1 x_202)) +(assert (<= 0 x_203)) +(assert (>= 1 x_203)) +(assert (<= 0 x_204)) +(assert (>= 1 x_204)) +(assert (<= 0 x_206)) +(assert (>= 1 x_206)) +(assert (<= 0 x_207)) +(assert (>= 1 x_207)) +(assert (<= 0 x_208)) +(assert (>= 1 x_208)) +(assert (<= 0 x_209)) +(assert (>= 1 x_209)) +(assert (<= 0 x_211)) +(assert (>= 1 x_211)) +(assert (<= 0 x_212)) +(assert (>= 1 x_212)) +(assert (<= 0 x_213)) +(assert (>= 1 x_213)) +(assert (<= 0 x_214)) +(assert (>= 1 x_214)) +(assert (<= 0 x_216)) +(assert (>= 1 x_216)) +(assert (<= 0 x_217)) +(assert (>= 1 x_217)) +(assert (<= 0 x_218)) +(assert (>= 1 x_218)) +(assert (<= 0 x_219)) +(assert (>= 1 x_219)) +(assert (<= 0 x_221)) +(assert (>= 1 x_221)) +(assert (<= 0 x_222)) +(assert (>= 1 x_222)) +(assert (<= 0 x_223)) +(assert (>= 1 x_223)) +(assert (<= 0 x_224)) +(assert (>= 1 x_224)) +(assert (<= 0 x_226)) +(assert (>= 1 x_226)) +(assert (<= 0 x_227)) +(assert (>= 1 x_227)) +(assert (<= 0 x_228)) +(assert (>= 1 x_228)) +(assert (<= 0 x_229)) +(assert (>= 1 x_229)) +(assert (<= 0 x_231)) +(assert (>= 1 x_231)) +(assert (<= 0 x_232)) +(assert (>= 1 x_232)) +(assert (<= 0 x_233)) +(assert (>= 1 x_233)) +(assert (<= 0 x_234)) +(assert (>= 1 x_234)) +(assert (<= 0 x_236)) +(assert (>= 1 x_236)) +(assert (<= 0 x_237)) +(assert (>= 1 x_237)) +(assert (<= 0 x_238)) +(assert (>= 1 x_238)) +(assert (<= 0 x_239)) +(assert (>= 1 x_239)) +(assert (<= 0 x_241)) +(assert (>= 1 x_241)) +(assert (<= 0 x_242)) +(assert (>= 1 x_242)) +(assert (<= 0 x_243)) +(assert (>= 1 x_243)) +(assert (<= 0 x_244)) +(assert (>= 1 x_244)) +(assert (<= 0 x_246)) +(assert (>= 1 x_246)) +(assert (<= 0 x_247)) +(assert (>= 1 x_247)) +(assert (<= 0 x_248)) +(assert (>= 1 x_248)) +(assert (<= 0 x_249)) +(assert (>= 1 x_249)) +(assert (<= 0 x_251)) +(assert (>= 1 x_251)) +(assert (<= 0 x_252)) +(assert (>= 1 x_252)) +(assert (<= 0 x_253)) +(assert (>= 1 x_253)) +(assert (<= 0 x_254)) +(assert (>= 1 x_254)) +(assert (<= 0 x_256)) +(assert (>= 1 x_256)) +(assert (<= 0 x_257)) +(assert (>= 1 x_257)) +(assert (<= 0 x_258)) +(assert (>= 1 x_258)) +(assert (<= 0 x_259)) +(assert (>= 1 x_259)) +(assert (<= 0 x_261)) +(assert (>= 1 x_261)) +(assert (<= 0 x_262)) +(assert (>= 1 x_262)) +(assert (<= 0 x_263)) +(assert (>= 1 x_263)) +(assert (<= 0 x_264)) +(assert (>= 1 x_264)) +(assert (<= 0 x_266)) +(assert (>= 1 x_266)) +(assert (<= 0 x_267)) +(assert (>= 1 x_267)) +(assert (<= 0 x_268)) +(assert (>= 1 x_268)) +(assert (<= 0 x_269)) +(assert (>= 1 x_269)) +(assert (<= 0 x_271)) +(assert (>= 1 x_271)) +(assert (<= 0 x_272)) +(assert (>= 1 x_272)) +(assert (<= 0 x_273)) +(assert (>= 1 x_273)) +(assert (<= 0 x_274)) +(assert (>= 1 x_274)) +(assert (<= 0 x_276)) +(assert (>= 1 x_276)) +(assert (<= 0 x_277)) +(assert (>= 1 x_277)) +(assert (<= 0 x_278)) +(assert (>= 1 x_278)) +(assert (<= 0 x_279)) +(assert (>= 1 x_279)) +(assert (<= 0 x_281)) +(assert (>= 1 x_281)) +(assert (<= 0 x_282)) +(assert (>= 1 x_282)) +(assert (<= 0 x_283)) +(assert (>= 1 x_283)) +(assert (<= 0 x_284)) +(assert (>= 1 x_284)) +(assert (<= 0 x_286)) +(assert (>= 1 x_286)) +(assert (<= 0 x_287)) +(assert (>= 1 x_287)) +(assert (<= 0 x_288)) +(assert (>= 1 x_288)) +(assert (<= 0 x_289)) +(assert (>= 1 x_289)) +(assert (<= 0 x_291)) +(assert (>= 1 x_291)) +(assert (<= 0 x_292)) +(assert (>= 1 x_292)) +(assert (<= 0 x_293)) +(assert (>= 1 x_293)) +(assert (<= 0 x_294)) +(assert (>= 1 x_294)) +(assert (<= 0 x_296)) +(assert (>= 1 x_296)) +(assert (<= 0 x_297)) +(assert (>= 1 x_297)) +(assert (<= 0 x_298)) +(assert (>= 1 x_298)) +(assert (<= 0 x_299)) +(assert (>= 1 x_299)) +(assert (<= 0 x_301)) +(assert (>= 1 x_301)) +(assert (<= 0 x_302)) +(assert (>= 1 x_302)) +(assert (<= 0 x_303)) +(assert (>= 1 x_303)) +(assert (<= 0 x_304)) +(assert (>= 1 x_304)) +(assert (<= 0 x_306)) +(assert (>= 1 x_306)) +(assert (<= 0 x_307)) +(assert (>= 1 x_307)) +(assert (<= 0 x_308)) +(assert (>= 1 x_308)) +(assert (<= 0 x_309)) +(assert (>= 1 x_309)) +(assert (<= 0 x_311)) +(assert (>= 1 x_311)) +(assert (<= 0 x_312)) +(assert (>= 1 x_312)) +(assert (<= 0 x_313)) +(assert (>= 1 x_313)) +(assert (<= 0 x_314)) +(assert (>= 1 x_314)) +(assert (<= 0 x_316)) +(assert (>= 1 x_316)) +(assert (<= 0 x_317)) +(assert (>= 1 x_317)) +(assert (<= 0 x_318)) +(assert (>= 1 x_318)) +(assert (<= 0 x_319)) +(assert (>= 1 x_319)) +(assert (<= 0 x_321)) +(assert (>= 1 x_321)) +(assert (<= 0 x_322)) +(assert (>= 1 x_322)) +(assert (<= 0 x_323)) +(assert (>= 1 x_323)) +(assert (<= 0 x_324)) +(assert (>= 1 x_324)) +(assert (<= 0 x_326)) +(assert (>= 1 x_326)) +(assert (<= 0 x_327)) +(assert (>= 1 x_327)) +(assert (<= 0 x_328)) +(assert (>= 1 x_328)) +(assert (<= 0 x_329)) +(assert (>= 1 x_329)) +(assert (<= 0 x_331)) +(assert (>= 1 x_331)) +(assert (<= 0 x_332)) +(assert (>= 1 x_332)) +(assert (<= 0 x_333)) +(assert (>= 1 x_333)) +(assert (<= 0 x_334)) +(assert (>= 1 x_334)) +(assert (<= 0 x_336)) +(assert (>= 1 x_336)) +(assert (<= 0 x_337)) +(assert (>= 1 x_337)) +(assert (<= 0 x_338)) +(assert (>= 1 x_338)) +(assert (<= 0 x_339)) +(assert (>= 1 x_339)) +(assert (<= 0 x_341)) +(assert (>= 1 x_341)) +(assert (<= 0 x_342)) +(assert (>= 1 x_342)) +(assert (<= 0 x_343)) +(assert (>= 1 x_343)) +(assert (<= 0 x_344)) +(assert (>= 1 x_344)) +(assert (<= 0 x_346)) +(assert (>= 1 x_346)) +(assert (<= 0 x_347)) +(assert (>= 1 x_347)) +(assert (<= 0 x_348)) +(assert (>= 1 x_348)) +(assert (<= 0 x_349)) +(assert (>= 1 x_349)) +(assert (<= 0 x_351)) +(assert (>= 1 x_351)) +(assert (<= 0 x_352)) +(assert (>= 1 x_352)) +(assert (<= 0 x_353)) +(assert (>= 1 x_353)) +(assert (<= 0 x_354)) +(assert (>= 1 x_354)) +(assert (<= 0 x_356)) +(assert (>= 1 x_356)) +(assert (<= 0 x_357)) +(assert (>= 1 x_357)) +(assert (<= 0 x_358)) +(assert (>= 1 x_358)) +(assert (<= 0 x_359)) +(assert (>= 1 x_359)) +(assert (<= 0 x_361)) +(assert (>= 1 x_361)) +(assert (<= 0 x_362)) +(assert (>= 1 x_362)) +(assert (<= 0 x_363)) +(assert (>= 1 x_363)) +(assert (<= 0 x_364)) +(assert (>= 1 x_364)) +(assert (<= 0 x_366)) +(assert (>= 1 x_366)) +(assert (<= 0 x_367)) +(assert (>= 1 x_367)) +(assert (<= 0 x_368)) +(assert (>= 1 x_368)) +(assert (<= 0 x_369)) +(assert (>= 1 x_369)) +(assert (<= 0 x_371)) +(assert (>= 1 x_371)) +(assert (<= 0 x_372)) +(assert (>= 1 x_372)) +(assert (<= 0 x_373)) +(assert (>= 1 x_373)) +(assert (<= 0 x_374)) +(assert (>= 1 x_374)) +(assert (<= 0 x_376)) +(assert (>= 1 x_376)) +(assert (<= 0 x_377)) +(assert (>= 1 x_377)) +(assert (<= 0 x_378)) +(assert (>= 1 x_378)) +(assert (<= 0 x_379)) +(assert (>= 1 x_379)) +(assert (<= 0 x_381)) +(assert (>= 1 x_381)) +(assert (<= 0 x_382)) +(assert (>= 1 x_382)) +(assert (<= 0 x_383)) +(assert (>= 1 x_383)) +(assert (<= 0 x_384)) +(assert (>= 1 x_384)) +(assert (<= 0 x_386)) +(assert (>= 1 x_386)) +(assert (<= 0 x_387)) +(assert (>= 1 x_387)) +(assert (<= 0 x_388)) +(assert (>= 1 x_388)) +(assert (<= 0 x_389)) +(assert (>= 1 x_389)) +(assert (<= 0 x_391)) +(assert (>= 1 x_391)) +(assert (<= 0 x_392)) +(assert (>= 1 x_392)) +(assert (<= 0 x_393)) +(assert (>= 1 x_393)) +(assert (<= 0 x_394)) +(assert (>= 1 x_394)) +(assert (<= 0 x_396)) +(assert (>= 1 x_396)) +(assert (<= 0 x_397)) +(assert (>= 1 x_397)) +(assert (<= 0 x_398)) +(assert (>= 1 x_398)) +(assert (<= 0 x_399)) +(assert (>= 1 x_399)) +(assert (<= 0 x_401)) +(assert (>= 1 x_401)) +(assert (<= 0 x_402)) +(assert (>= 1 x_402)) +(assert (<= 0 x_403)) +(assert (>= 1 x_403)) +(assert (<= 0 x_404)) +(assert (>= 1 x_404)) +(assert (<= 0 x_406)) +(assert (>= 1 x_406)) +(assert (<= 0 x_407)) +(assert (>= 1 x_407)) +(assert (<= 0 x_408)) +(assert (>= 1 x_408)) +(assert (<= 0 x_409)) +(assert (>= 1 x_409)) +(assert (<= 0 x_411)) +(assert (>= 1 x_411)) +(assert (<= 0 x_412)) +(assert (>= 1 x_412)) +(assert (<= 0 x_413)) +(assert (>= 1 x_413)) +(assert (<= 0 x_414)) +(assert (>= 1 x_414)) +(assert (<= 0 x_416)) +(assert (>= 1 x_416)) +(assert (<= 0 x_417)) +(assert (>= 1 x_417)) +(assert (<= 0 x_418)) +(assert (>= 1 x_418)) +(assert (<= 0 x_419)) +(assert (>= 1 x_419)) +(assert (<= 0 x_421)) +(assert (>= 1 x_421)) +(assert (<= 0 x_422)) +(assert (>= 1 x_422)) +(assert (<= 0 x_423)) +(assert (>= 1 x_423)) +(assert (<= 0 x_424)) +(assert (>= 1 x_424)) +(assert (<= 0 x_426)) +(assert (>= 1 x_426)) +(assert (<= 0 x_427)) +(assert (>= 1 x_427)) +(assert (<= 0 x_428)) +(assert (>= 1 x_428)) +(assert (<= 0 x_429)) +(assert (>= 1 x_429)) +(assert (<= 0 x_431)) +(assert (>= 1 x_431)) +(assert (<= 0 x_432)) +(assert (>= 1 x_432)) +(assert (<= 0 x_433)) +(assert (>= 1 x_433)) +(assert (<= 0 x_434)) +(assert (>= 1 x_434)) +(assert (<= 0 x_436)) +(assert (>= 1 x_436)) +(assert (<= 0 x_437)) +(assert (>= 1 x_437)) +(assert (<= 0 x_438)) +(assert (>= 1 x_438)) +(assert (<= 0 x_439)) +(assert (>= 1 x_439)) +(assert (<= 0 x_441)) +(assert (>= 1 x_441)) +(assert (<= 0 x_442)) +(assert (>= 1 x_442)) +(assert (<= 0 x_443)) +(assert (>= 1 x_443)) +(assert (<= 0 x_444)) +(assert (>= 1 x_444)) +(assert (<= 0 x_446)) +(assert (>= 1 x_446)) +(assert (<= 0 x_447)) +(assert (>= 1 x_447)) +(assert (<= 0 x_448)) +(assert (>= 1 x_448)) +(assert (<= 0 x_449)) +(assert (>= 1 x_449)) +(assert (<= 0 x_451)) +(assert (>= 1 x_451)) +(assert (<= 0 x_452)) +(assert (>= 1 x_452)) +(assert (<= 0 x_453)) +(assert (>= 1 x_453)) +(assert (<= 0 x_454)) +(assert (>= 1 x_454)) +(assert (<= 0 x_456)) +(assert (>= 1 x_456)) +(assert (<= 0 x_457)) +(assert (>= 1 x_457)) +(assert (<= 0 x_458)) +(assert (>= 1 x_458)) +(assert (<= 0 x_459)) +(assert (>= 1 x_459)) +(assert (<= 0 x_461)) +(assert (>= 1 x_461)) +(assert (<= 0 x_462)) +(assert (>= 1 x_462)) +(assert (<= 0 x_463)) +(assert (>= 1 x_463)) +(assert (<= 0 x_464)) +(assert (>= 1 x_464)) +(assert (<= 0 x_466)) +(assert (>= 1 x_466)) +(assert (<= 0 x_467)) +(assert (>= 1 x_467)) +(assert (<= 0 x_468)) +(assert (>= 1 x_468)) +(assert (<= 0 x_469)) +(assert (>= 1 x_469)) +(assert (<= 0 x_471)) +(assert (>= 1 x_471)) +(assert (<= 0 x_472)) +(assert (>= 1 x_472)) +(assert (<= 0 x_473)) +(assert (>= 1 x_473)) +(assert (<= 0 x_474)) +(assert (>= 1 x_474)) +(assert (<= 0 x_476)) +(assert (>= 1 x_476)) +(assert (<= 0 x_477)) +(assert (>= 1 x_477)) +(assert (<= 0 x_478)) +(assert (>= 1 x_478)) +(assert (<= 0 x_479)) +(assert (>= 1 x_479)) +(assert (<= 0 x_481)) +(assert (>= 1 x_481)) +(assert (<= 0 x_482)) +(assert (>= 1 x_482)) +(assert (<= 0 x_483)) +(assert (>= 1 x_483)) +(assert (<= 0 x_484)) +(assert (>= 1 x_484)) +(assert (<= 0 x_486)) +(assert (>= 1 x_486)) +(assert (<= 0 x_487)) +(assert (>= 1 x_487)) +(assert (<= 0 x_488)) +(assert (>= 1 x_488)) +(assert (<= 0 x_489)) +(assert (>= 1 x_489)) +(assert (<= 0 x_491)) +(assert (>= 1 x_491)) +(assert (<= 0 x_492)) +(assert (>= 1 x_492)) +(assert (<= 0 x_493)) +(assert (>= 1 x_493)) +(assert (<= 0 x_494)) +(assert (>= 1 x_494)) +(assert (<= 0 x_496)) +(assert (>= 1 x_496)) +(assert (<= 0 x_497)) +(assert (>= 1 x_497)) +(assert (<= 0 x_498)) +(assert (>= 1 x_498)) +(assert (<= 0 x_499)) +(assert (>= 1 x_499)) +(assert (<= 0 x_501)) +(assert (>= 1 x_501)) +(assert (<= 0 x_502)) +(assert (>= 1 x_502)) +(assert (<= 0 x_503)) +(assert (>= 1 x_503)) +(assert (<= 0 x_504)) +(assert (>= 1 x_504)) +(assert (<= 0 x_506)) +(assert (>= 1 x_506)) +(assert (<= 0 x_507)) +(assert (>= 1 x_507)) +(assert (<= 0 x_508)) +(assert (>= 1 x_508)) +(assert (<= 0 x_509)) +(assert (>= 1 x_509)) +(assert (<= 0 x_511)) +(assert (>= 1 x_511)) +(assert (<= 0 x_512)) +(assert (>= 1 x_512)) +(assert (<= 0 x_513)) +(assert (>= 1 x_513)) +(assert (<= 0 x_514)) +(assert (>= 1 x_514)) +(assert (<= 0 x_516)) +(assert (>= 1 x_516)) +(assert (<= 0 x_517)) +(assert (>= 1 x_517)) +(assert (<= 0 x_518)) +(assert (>= 1 x_518)) +(assert (<= 0 x_519)) +(assert (>= 1 x_519)) +(assert (<= 0 x_521)) +(assert (>= 1 x_521)) +(assert (<= 0 x_522)) +(assert (>= 1 x_522)) +(assert (<= 0 x_523)) +(assert (>= 1 x_523)) +(assert (<= 0 x_524)) +(assert (>= 1 x_524)) +(assert (<= 0 x_526)) +(assert (>= 1 x_526)) +(assert (<= 0 x_527)) +(assert (>= 1 x_527)) +(assert (<= 0 x_528)) +(assert (>= 1 x_528)) +(assert (<= 0 x_529)) +(assert (>= 1 x_529)) +(assert (<= 0 x_531)) +(assert (>= 1 x_531)) +(assert (<= 0 x_532)) +(assert (>= 1 x_532)) +(assert (<= 0 x_533)) +(assert (>= 1 x_533)) +(assert (<= 0 x_534)) +(assert (>= 1 x_534)) +(assert (<= 0 x_536)) +(assert (>= 1 x_536)) +(assert (<= 0 x_537)) +(assert (>= 1 x_537)) +(assert (<= 0 x_538)) +(assert (>= 1 x_538)) +(assert (<= 0 x_539)) +(assert (>= 1 x_539)) +(assert (<= 0 x_541)) +(assert (>= 1 x_541)) +(assert (<= 0 x_542)) +(assert (>= 1 x_542)) +(assert (<= 0 x_543)) +(assert (>= 1 x_543)) +(assert (<= 0 x_544)) +(assert (>= 1 x_544)) +(assert (<= 0 x_546)) +(assert (>= 1 x_546)) +(assert (<= 0 x_547)) +(assert (>= 1 x_547)) +(assert (<= 0 x_548)) +(assert (>= 1 x_548)) +(assert (<= 0 x_549)) +(assert (>= 1 x_549)) +(assert (<= 0 x_551)) +(assert (>= 1 x_551)) +(assert (<= 0 x_552)) +(assert (>= 1 x_552)) +(assert (<= 0 x_553)) +(assert (>= 1 x_553)) +(assert (<= 0 x_554)) +(assert (>= 1 x_554)) +(assert (<= 0 x_556)) +(assert (>= 1 x_556)) +(assert (<= 0 x_557)) +(assert (>= 1 x_557)) +(assert (<= 0 x_558)) +(assert (>= 1 x_558)) +(assert (<= 0 x_559)) +(assert (>= 1 x_559)) +(assert (<= 0 x_561)) +(assert (>= 1 x_561)) +(assert (<= 0 x_562)) +(assert (>= 1 x_562)) +(assert (<= 0 x_563)) +(assert (>= 1 x_563)) +(assert (<= 0 x_564)) +(assert (>= 1 x_564)) +(assert (<= 0 x_566)) +(assert (>= 1 x_566)) +(assert (<= 0 x_567)) +(assert (>= 1 x_567)) +(assert (<= 0 x_568)) +(assert (>= 1 x_568)) +(assert (<= 0 x_569)) +(assert (>= 1 x_569)) +(assert (<= 0 x_571)) +(assert (>= 1 x_571)) +(assert (<= 0 x_572)) +(assert (>= 1 x_572)) +(assert (<= 0 x_573)) +(assert (>= 1 x_573)) +(assert (<= 0 x_574)) +(assert (>= 1 x_574)) +(assert (<= 0 x_576)) +(assert (>= 1 x_576)) +(assert (<= 0 x_577)) +(assert (>= 1 x_577)) +(assert (<= 0 x_578)) +(assert (>= 1 x_578)) +(assert (<= 0 x_579)) +(assert (>= 1 x_579)) +(assert (<= 0 x_581)) +(assert (>= 1 x_581)) +(assert (<= 0 x_582)) +(assert (>= 1 x_582)) +(assert (<= 0 x_583)) +(assert (>= 1 x_583)) +(assert (<= 0 x_584)) +(assert (>= 1 x_584)) +(assert (<= 0 x_586)) +(assert (>= 1 x_586)) +(assert (<= 0 x_587)) +(assert (>= 1 x_587)) +(assert (<= 0 x_588)) +(assert (>= 1 x_588)) +(assert (<= 0 x_589)) +(assert (>= 1 x_589)) +(assert (<= 0 x_591)) +(assert (>= 1 x_591)) +(assert (<= 0 x_592)) +(assert (>= 1 x_592)) +(assert (<= 0 x_593)) +(assert (>= 1 x_593)) +(assert (<= 0 x_594)) +(assert (>= 1 x_594)) +(assert (<= 0 x_596)) +(assert (>= 1 x_596)) +(assert (<= 0 x_597)) +(assert (>= 1 x_597)) +(assert (<= 0 x_598)) +(assert (>= 1 x_598)) +(assert (<= 0 x_599)) +(assert (>= 1 x_599)) +(assert (<= 0 x_601)) +(assert (>= 1 x_601)) +(assert (<= 0 x_602)) +(assert (>= 1 x_602)) +(assert (<= 0 x_603)) +(assert (>= 1 x_603)) +(assert (<= 0 x_604)) +(assert (>= 1 x_604)) +(assert (<= 0 x_606)) +(assert (>= 1 x_606)) +(assert (<= 0 x_607)) +(assert (>= 1 x_607)) +(assert (<= 0 x_608)) +(assert (>= 1 x_608)) +(assert (<= 0 x_609)) +(assert (>= 1 x_609)) +(assert (<= 0 x_611)) +(assert (>= 1 x_611)) +(assert (<= 0 x_612)) +(assert (>= 1 x_612)) +(assert (<= 0 x_613)) +(assert (>= 1 x_613)) +(assert (<= 0 x_614)) +(assert (>= 1 x_614)) +(assert (<= 0 x_616)) +(assert (>= 1 x_616)) +(assert (<= 0 x_617)) +(assert (>= 1 x_617)) +(assert (<= 0 x_618)) +(assert (>= 1 x_618)) +(assert (<= 0 x_619)) +(assert (>= 1 x_619)) +(assert (<= 0 x_621)) +(assert (>= 1 x_621)) +(assert (<= 0 x_622)) +(assert (>= 1 x_622)) +(assert (<= 0 x_623)) +(assert (>= 1 x_623)) +(assert (<= 0 x_624)) +(assert (>= 1 x_624)) +(assert (<= 0 x_626)) +(assert (>= 1 x_626)) +(assert (<= 0 x_627)) +(assert (>= 1 x_627)) +(assert (<= 0 x_628)) +(assert (>= 1 x_628)) +(assert (<= 0 x_629)) +(assert (>= 1 x_629)) +(assert (<= 0 x_631)) +(assert (>= 1 x_631)) +(assert (<= 0 x_632)) +(assert (>= 1 x_632)) +(assert (<= 0 x_633)) +(assert (>= 1 x_633)) +(assert (<= 0 x_634)) +(assert (>= 1 x_634)) +(assert (<= 0 x_636)) +(assert (>= 1 x_636)) +(assert (<= 0 x_637)) +(assert (>= 1 x_637)) +(assert (<= 0 x_638)) +(assert (>= 1 x_638)) +(assert (<= 0 x_639)) +(assert (>= 1 x_639)) +(assert (<= 0 x_641)) +(assert (>= 1 x_641)) +(assert (<= 0 x_642)) +(assert (>= 1 x_642)) +(assert (<= 0 x_643)) +(assert (>= 1 x_643)) +(assert (<= 0 x_644)) +(assert (>= 1 x_644)) +(assert (<= 0 x_646)) +(assert (>= 1 x_646)) +(assert (<= 0 x_647)) +(assert (>= 1 x_647)) +(assert (<= 0 x_648)) +(assert (>= 1 x_648)) +(assert (<= 0 x_649)) +(assert (>= 1 x_649)) +(assert (<= 0 x_651)) +(assert (>= 1 x_651)) +(assert (<= 0 x_652)) +(assert (>= 1 x_652)) +(assert (<= 0 x_653)) +(assert (>= 1 x_653)) +(assert (<= 0 x_654)) +(assert (>= 1 x_654)) +(assert (<= 0 x_656)) +(assert (>= 1 x_656)) +(assert (<= 0 x_657)) +(assert (>= 1 x_657)) +(assert (<= 0 x_658)) +(assert (>= 1 x_658)) +(assert (<= 0 x_659)) +(assert (>= 1 x_659)) +(assert (<= 0 x_661)) +(assert (>= 1 x_661)) +(assert (<= 0 x_662)) +(assert (>= 1 x_662)) +(assert (<= 0 x_663)) +(assert (>= 1 x_663)) +(assert (<= 0 x_664)) +(assert (>= 1 x_664)) +(assert (<= 0 x_666)) +(assert (>= 1 x_666)) +(assert (<= 0 x_667)) +(assert (>= 1 x_667)) +(assert (<= 0 x_668)) +(assert (>= 1 x_668)) +(assert (<= 0 x_669)) +(assert (>= 1 x_669)) +(assert (<= 0 x_671)) +(assert (>= 1 x_671)) +(assert (<= 0 x_672)) +(assert (>= 1 x_672)) +(assert (<= 0 x_673)) +(assert (>= 1 x_673)) +(assert (<= 0 x_674)) +(assert (>= 1 x_674)) +(assert (<= 0 x_676)) +(assert (>= 1 x_676)) +(assert (<= 0 x_677)) +(assert (>= 1 x_677)) +(assert (<= 0 x_678)) +(assert (>= 1 x_678)) +(assert (<= 0 x_679)) +(assert (>= 1 x_679)) +(assert (<= 0 x_681)) +(assert (>= 1 x_681)) +(assert (<= 0 x_682)) +(assert (>= 1 x_682)) +(assert (<= 0 x_683)) +(assert (>= 1 x_683)) +(assert (<= 0 x_684)) +(assert (>= 1 x_684)) +(assert (<= 0 x_686)) +(assert (>= 1 x_686)) +(assert (<= 0 x_687)) +(assert (>= 1 x_687)) +(assert (<= 0 x_688)) +(assert (>= 1 x_688)) +(assert (<= 0 x_689)) +(assert (>= 1 x_689)) +(assert (<= 0 x_691)) +(assert (>= 1 x_691)) +(assert (<= 0 x_692)) +(assert (>= 1 x_692)) +(assert (<= 0 x_693)) +(assert (>= 1 x_693)) +(assert (<= 0 x_694)) +(assert (>= 1 x_694)) +(assert (<= 0 x_696)) +(assert (>= 1 x_696)) +(assert (<= 0 x_697)) +(assert (>= 1 x_697)) +(assert (<= 0 x_698)) +(assert (>= 1 x_698)) +(assert (<= 0 x_699)) +(assert (>= 1 x_699)) +(assert (<= 0 x_701)) +(assert (>= 1 x_701)) +(assert (<= 0 x_702)) +(assert (>= 1 x_702)) +(assert (<= 0 x_703)) +(assert (>= 1 x_703)) +(assert (<= 0 x_704)) +(assert (>= 1 x_704)) +(assert (<= 0 x_706)) +(assert (>= 1 x_706)) +(assert (<= 0 x_707)) +(assert (>= 1 x_707)) +(assert (<= 0 x_708)) +(assert (>= 1 x_708)) +(assert (<= 0 x_709)) +(assert (>= 1 x_709)) +(assert (<= 0 x_711)) +(assert (>= 1 x_711)) +(assert (<= 0 x_712)) +(assert (>= 1 x_712)) +(assert (<= 0 x_713)) +(assert (>= 1 x_713)) +(assert (<= 0 x_714)) +(assert (>= 1 x_714)) +(assert (<= 0 x_716)) +(assert (>= 1 x_716)) +(assert (<= 0 x_717)) +(assert (>= 1 x_717)) +(assert (<= 0 x_718)) +(assert (>= 1 x_718)) +(assert (<= 0 x_719)) +(assert (>= 1 x_719)) +(assert (<= 0 x_721)) +(assert (>= 1 x_721)) +(assert (<= 0 x_722)) +(assert (>= 1 x_722)) +(assert (<= 0 x_723)) +(assert (>= 1 x_723)) +(assert (<= 0 x_724)) +(assert (>= 1 x_724)) +(assert (<= 0 x_726)) +(assert (>= 1 x_726)) +(assert (<= 0 x_727)) +(assert (>= 1 x_727)) +(assert (<= 0 x_728)) +(assert (>= 1 x_728)) +(assert (<= 0 x_729)) +(assert (>= 1 x_729)) +(assert (<= 0 x_731)) +(assert (>= 1 x_731)) +(assert (<= 0 x_732)) +(assert (>= 1 x_732)) +(assert (<= 0 x_733)) +(assert (>= 1 x_733)) +(assert (<= 0 x_734)) +(assert (>= 1 x_734)) +(assert (<= 0 x_736)) +(assert (>= 1 x_736)) +(assert (<= 0 x_737)) +(assert (>= 1 x_737)) +(assert (<= 0 x_738)) +(assert (>= 1 x_738)) +(assert (<= 0 x_739)) +(assert (>= 1 x_739)) +(assert (<= 0 x_741)) +(assert (>= 1 x_741)) +(assert (<= 0 x_742)) +(assert (>= 1 x_742)) +(assert (<= 0 x_743)) +(assert (>= 1 x_743)) +(assert (<= 0 x_744)) +(assert (>= 1 x_744)) +(assert (<= 0 x_746)) +(assert (>= 1 x_746)) +(assert (<= 0 x_747)) +(assert (>= 1 x_747)) +(assert (<= 0 x_748)) +(assert (>= 1 x_748)) +(assert (<= 0 x_749)) +(assert (>= 1 x_749)) +(assert (<= 0 x_751)) +(assert (>= 1 x_751)) +(assert (<= 0 x_752)) +(assert (>= 1 x_752)) +(assert (<= 0 x_753)) +(assert (>= 1 x_753)) +(assert (<= 0 x_754)) +(assert (>= 1 x_754)) +(assert (<= 0 x_756)) +(assert (>= 1 x_756)) +(assert (<= 0 x_757)) +(assert (>= 1 x_757)) +(assert (<= 0 x_758)) +(assert (>= 1 x_758)) +(assert (<= 0 x_759)) +(assert (>= 1 x_759)) +(assert (<= 0 x_761)) +(assert (>= 1 x_761)) +(assert (<= 0 x_762)) +(assert (>= 1 x_762)) +(assert (<= 0 x_763)) +(assert (>= 1 x_763)) +(assert (<= 0 x_764)) +(assert (>= 1 x_764)) +(assert (<= 0 x_766)) +(assert (>= 1 x_766)) +(assert (<= 0 x_767)) +(assert (>= 1 x_767)) +(assert (<= 0 x_768)) +(assert (>= 1 x_768)) +(assert (<= 0 x_769)) +(assert (>= 1 x_769)) +(assert (<= 0 x_771)) +(assert (>= 1 x_771)) +(assert (<= 0 x_772)) +(assert (>= 1 x_772)) +(assert (<= 0 x_773)) +(assert (>= 1 x_773)) +(assert (<= 0 x_774)) +(assert (>= 1 x_774)) +(assert (<= 0 x_776)) +(assert (>= 1 x_776)) +(assert (<= 0 x_777)) +(assert (>= 1 x_777)) +(assert (<= 0 x_778)) +(assert (>= 1 x_778)) +(assert (<= 0 x_779)) +(assert (>= 1 x_779)) +(assert (<= 0 x_781)) +(assert (>= 1 x_781)) +(assert (<= 0 x_782)) +(assert (>= 1 x_782)) +(assert (<= 0 x_783)) +(assert (>= 1 x_783)) +(assert (<= 0 x_784)) +(assert (>= 1 x_784)) +(assert (<= 0 x_786)) +(assert (>= 1 x_786)) +(assert (<= 0 x_787)) +(assert (>= 1 x_787)) +(assert (<= 0 x_788)) +(assert (>= 1 x_788)) +(assert (<= 0 x_789)) +(assert (>= 1 x_789)) +(assert (<= 0 x_791)) +(assert (>= 1 x_791)) +(assert (<= 0 x_792)) +(assert (>= 1 x_792)) +(assert (<= 0 x_793)) +(assert (>= 1 x_793)) +(assert (<= 0 x_794)) +(assert (>= 1 x_794)) +(assert (<= 0 x_796)) +(assert (>= 1 x_796)) +(assert (<= 0 x_797)) +(assert (>= 1 x_797)) +(assert (<= 0 x_798)) +(assert (>= 1 x_798)) +(assert (<= 0 x_799)) +(assert (>= 1 x_799)) +(assert (<= 0 x_801)) +(assert (>= 1 x_801)) +(assert (<= 0 x_802)) +(assert (>= 1 x_802)) +(assert (<= 0 x_803)) +(assert (>= 1 x_803)) +(assert (<= 0 x_804)) +(assert (>= 1 x_804)) +(assert (<= 0 x_806)) +(assert (>= 1 x_806)) +(assert (<= 0 x_807)) +(assert (>= 1 x_807)) +(assert (<= 0 x_808)) +(assert (>= 1 x_808)) +(assert (<= 0 x_809)) +(assert (>= 1 x_809)) +(assert (<= 0 x_811)) +(assert (>= 1 x_811)) +(assert (<= 0 x_812)) +(assert (>= 1 x_812)) +(assert (<= 0 x_813)) +(assert (>= 1 x_813)) +(assert (<= 0 x_814)) +(assert (>= 1 x_814)) +(assert (<= 0 x_816)) +(assert (>= 1 x_816)) +(assert (<= 0 x_817)) +(assert (>= 1 x_817)) +(assert (<= 0 x_818)) +(assert (>= 1 x_818)) +(assert (<= 0 x_819)) +(assert (>= 1 x_819)) +(assert (<= 0 x_821)) +(assert (>= 1 x_821)) +(assert (<= 0 x_822)) +(assert (>= 1 x_822)) +(assert (<= 0 x_823)) +(assert (>= 1 x_823)) +(assert (<= 0 x_824)) +(assert (>= 1 x_824)) +(assert (<= 0 x_826)) +(assert (>= 1 x_826)) +(assert (<= 0 x_827)) +(assert (>= 1 x_827)) +(assert (<= 0 x_828)) +(assert (>= 1 x_828)) +(assert (<= 0 x_829)) +(assert (>= 1 x_829)) +(assert (<= 0 x_831)) +(assert (>= 1 x_831)) +(assert (<= 0 x_832)) +(assert (>= 1 x_832)) +(assert (<= 0 x_833)) +(assert (>= 1 x_833)) +(assert (<= 0 x_834)) +(assert (>= 1 x_834)) +(assert (<= 0 x_836)) +(assert (>= 1 x_836)) +(assert (<= 0 x_837)) +(assert (>= 1 x_837)) +(assert (<= 0 x_838)) +(assert (>= 1 x_838)) +(assert (<= 0 x_839)) +(assert (>= 1 x_839)) +(assert (<= 0 x_841)) +(assert (>= 1 x_841)) +(assert (<= 0 x_842)) +(assert (>= 1 x_842)) +(assert (<= 0 x_843)) +(assert (>= 1 x_843)) +(assert (<= 0 x_844)) +(assert (>= 1 x_844)) +(assert (<= 0 x_846)) +(assert (>= 1 x_846)) +(assert (<= 0 x_847)) +(assert (>= 1 x_847)) +(assert (<= 0 x_848)) +(assert (>= 1 x_848)) +(assert (<= 0 x_849)) +(assert (>= 1 x_849)) +(assert (<= 0 x_851)) +(assert (>= 1 x_851)) +(assert (<= 0 x_852)) +(assert (>= 1 x_852)) +(assert (<= 0 x_853)) +(assert (>= 1 x_853)) +(assert (<= 0 x_854)) +(assert (>= 1 x_854)) +(assert (<= 0 x_856)) +(assert (>= 1 x_856)) +(assert (<= 0 x_857)) +(assert (>= 1 x_857)) +(assert (<= 0 x_858)) +(assert (>= 1 x_858)) +(assert (<= 0 x_859)) +(assert (>= 1 x_859)) +(assert (<= 0 x_861)) +(assert (>= 1 x_861)) +(assert (<= 0 x_862)) +(assert (>= 1 x_862)) +(assert (<= 0 x_863)) +(assert (>= 1 x_863)) +(assert (<= 0 x_864)) +(assert (>= 1 x_864)) +(assert (<= 0 x_866)) +(assert (>= 1 x_866)) +(assert (<= 0 x_867)) +(assert (>= 1 x_867)) +(assert (<= 0 x_868)) +(assert (>= 1 x_868)) +(assert (<= 0 x_869)) +(assert (>= 1 x_869)) +(assert (<= 0 x_871)) +(assert (>= 1 x_871)) +(assert (<= 0 x_872)) +(assert (>= 1 x_872)) +(assert (<= 0 x_873)) +(assert (>= 1 x_873)) +(assert (<= 0 x_874)) +(assert (>= 1 x_874)) +(assert (<= 0 x_876)) +(assert (>= 1 x_876)) +(assert (<= 0 x_877)) +(assert (>= 1 x_877)) +(assert (<= 0 x_878)) +(assert (>= 1 x_878)) +(assert (<= 0 x_879)) +(assert (>= 1 x_879)) +(assert (<= 0 x_881)) +(assert (>= 1 x_881)) +(assert (<= 0 x_882)) +(assert (>= 1 x_882)) +(assert (<= 0 x_883)) +(assert (>= 1 x_883)) +(assert (<= 0 x_884)) +(assert (>= 1 x_884)) +(assert (<= 0 x_886)) +(assert (>= 1 x_886)) +(assert (<= 0 x_887)) +(assert (>= 1 x_887)) +(assert (<= 0 x_888)) +(assert (>= 1 x_888)) +(assert (<= 0 x_889)) +(assert (>= 1 x_889)) +(assert (<= 0 x_891)) +(assert (>= 1 x_891)) +(assert (<= 0 x_892)) +(assert (>= 1 x_892)) +(assert (<= 0 x_893)) +(assert (>= 1 x_893)) +(assert (<= 0 x_894)) +(assert (>= 1 x_894)) +(assert (<= 0 x_896)) +(assert (>= 1 x_896)) +(assert (<= 0 x_897)) +(assert (>= 1 x_897)) +(assert (<= 0 x_898)) +(assert (>= 1 x_898)) +(assert (<= 0 x_899)) +(assert (>= 1 x_899)) +(assert (<= 0 x_901)) +(assert (>= 1 x_901)) +(assert (<= 0 x_902)) +(assert (>= 1 x_902)) +(assert (<= 0 x_903)) +(assert (>= 1 x_903)) +(assert (<= 0 x_904)) +(assert (>= 1 x_904)) +(assert (<= 0 x_906)) +(assert (>= 1 x_906)) +(assert (<= 0 x_907)) +(assert (>= 1 x_907)) +(assert (<= 0 x_908)) +(assert (>= 1 x_908)) +(assert (<= 0 x_909)) +(assert (>= 1 x_909)) +(assert (<= 0 x_911)) +(assert (>= 1 x_911)) +(assert (<= 0 x_912)) +(assert (>= 1 x_912)) +(assert (<= 0 x_913)) +(assert (>= 1 x_913)) +(assert (<= 0 x_914)) +(assert (>= 1 x_914)) +(assert (<= 0 x_916)) +(assert (>= 1 x_916)) +(assert (<= 0 x_917)) +(assert (>= 1 x_917)) +(assert (<= 0 x_918)) +(assert (>= 1 x_918)) +(assert (<= 0 x_919)) +(assert (>= 1 x_919)) +(assert (<= 0 x_921)) +(assert (>= 1 x_921)) +(assert (<= 0 x_922)) +(assert (>= 1 x_922)) +(assert (<= 0 x_923)) +(assert (>= 1 x_923)) +(assert (<= 0 x_924)) +(assert (>= 1 x_924)) +(assert (<= 0 x_926)) +(assert (>= 1 x_926)) +(assert (<= 0 x_927)) +(assert (>= 1 x_927)) +(assert (<= 0 x_928)) +(assert (>= 1 x_928)) +(assert (<= 0 x_929)) +(assert (>= 1 x_929)) +(assert (<= 0 x_931)) +(assert (>= 1 x_931)) +(assert (<= 0 x_932)) +(assert (>= 1 x_932)) +(assert (<= 0 x_933)) +(assert (>= 1 x_933)) +(assert (<= 0 x_934)) +(assert (>= 1 x_934)) +(assert (<= 0 x_936)) +(assert (>= 1 x_936)) +(assert (<= 0 x_937)) +(assert (>= 1 x_937)) +(assert (<= 0 x_938)) +(assert (>= 1 x_938)) +(assert (<= 0 x_939)) +(assert (>= 1 x_939)) +(assert (<= 0 x_941)) +(assert (>= 1 x_941)) +(assert (<= 0 x_942)) +(assert (>= 1 x_942)) +(assert (<= 0 x_943)) +(assert (>= 1 x_943)) +(assert (<= 0 x_944)) +(assert (>= 1 x_944)) +(assert (<= 0 x_946)) +(assert (>= 1 x_946)) +(assert (<= 0 x_947)) +(assert (>= 1 x_947)) +(assert (<= 0 x_948)) +(assert (>= 1 x_948)) +(assert (<= 0 x_949)) +(assert (>= 1 x_949)) +(assert (<= 0 x_951)) +(assert (>= 1 x_951)) +(assert (<= 0 x_952)) +(assert (>= 1 x_952)) +(assert (<= 0 x_953)) +(assert (>= 1 x_953)) +(assert (<= 0 x_954)) +(assert (>= 1 x_954)) +(assert (<= 0 x_956)) +(assert (>= 1 x_956)) +(assert (<= 0 x_957)) +(assert (>= 1 x_957)) +(assert (<= 0 x_958)) +(assert (>= 1 x_958)) +(assert (<= 0 x_959)) +(assert (>= 1 x_959)) +(assert (<= 0 x_961)) +(assert (>= 1 x_961)) +(assert (<= 0 x_962)) +(assert (>= 1 x_962)) +(assert (<= 0 x_963)) +(assert (>= 1 x_963)) +(assert (<= 0 x_964)) +(assert (>= 1 x_964)) +(assert (<= 0 x_966)) +(assert (>= 1 x_966)) +(assert (<= 0 x_967)) +(assert (>= 1 x_967)) +(assert (<= 0 x_968)) +(assert (>= 1 x_968)) +(assert (<= 0 x_969)) +(assert (>= 1 x_969)) +(assert (<= 0 x_971)) +(assert (>= 1 x_971)) +(assert (<= 0 x_972)) +(assert (>= 1 x_972)) +(assert (<= 0 x_973)) +(assert (>= 1 x_973)) +(assert (<= 0 x_974)) +(assert (>= 1 x_974)) +(assert (<= 0 x_976)) +(assert (>= 1 x_976)) +(assert (<= 0 x_977)) +(assert (>= 1 x_977)) +(assert (<= 0 x_978)) +(assert (>= 1 x_978)) +(assert (<= 0 x_979)) +(assert (>= 1 x_979)) +(assert (<= 0 x_981)) +(assert (>= 1 x_981)) +(assert (<= 0 x_982)) +(assert (>= 1 x_982)) +(assert (<= 0 x_983)) +(assert (>= 1 x_983)) +(assert (<= 0 x_984)) +(assert (>= 1 x_984)) +(assert (<= 0 x_986)) +(assert (>= 1 x_986)) +(assert (<= 0 x_987)) +(assert (>= 1 x_987)) +(assert (<= 0 x_988)) +(assert (>= 1 x_988)) +(assert (<= 0 x_989)) +(assert (>= 1 x_989)) +(assert (<= 0 x_991)) +(assert (>= 1 x_991)) +(assert (<= 0 x_992)) +(assert (>= 1 x_992)) +(assert (<= 0 x_993)) +(assert (>= 1 x_993)) +(assert (<= 0 x_994)) +(assert (>= 1 x_994)) +(assert (<= 0 x_996)) +(assert (>= 1 x_996)) +(assert (<= 0 x_997)) +(assert (>= 1 x_997)) +(assert (<= 0 x_998)) +(assert (>= 1 x_998)) +(assert (<= 0 x_999)) +(assert (>= 1 x_999)) +(assert (<= 0 x_1001)) +(assert (>= 1 x_1001)) +(assert (<= 0 x_1202)) +(assert (>= 1 x_1202)) +(assert (<= 0 x_1403)) +(assert (>= 1 x_1403)) +(assert (<= 0 x_1604)) +(assert (>= 1 x_1604)) +(assert (= 1 (+ x_1 x_2 x_3 x_4))) +(assert (= 1 (+ x_6 x_7 x_8 x_9))) +(assert (= 1 (+ x_11 x_12 x_13 x_14))) +(assert (= 1 (+ x_16 x_17 x_18 x_19))) +(assert (= 1 (+ x_21 x_22 x_23 x_24))) +(assert (= 1 (+ x_26 x_27 x_28 x_29))) +(assert (= 1 (+ x_31 x_32 x_33 x_34))) +(assert (= 1 (+ x_36 x_37 x_38 x_39))) +(assert (= 1 (+ x_41 x_42 x_43 x_44))) +(assert (= 1 (+ x_46 x_47 x_48 x_49))) +(assert (= 1 (+ x_51 x_52 x_53 x_54))) +(assert (= 1 (+ x_56 x_57 x_58 x_59))) +(assert (= 1 (+ x_61 x_62 x_63 x_64))) +(assert (= 1 (+ x_66 x_67 x_68 x_69))) +(assert (= 1 (+ x_71 x_72 x_73 x_74))) +(assert (= 1 (+ x_76 x_77 x_78 x_79))) +(assert (= 1 (+ x_81 x_82 x_83 x_84))) +(assert (= 1 (+ x_86 x_87 x_88 x_89))) +(assert (= 1 (+ x_91 x_92 x_93 x_94))) +(assert (= 1 (+ x_96 x_97 x_98 x_99))) +(assert (= 1 (+ x_101 x_102 x_103 x_104))) +(assert (= 1 (+ x_106 x_107 x_108 x_109))) +(assert (= 1 (+ x_111 x_112 x_113 x_114))) +(assert (= 1 (+ x_116 x_117 x_118 x_119))) +(assert (= 1 (+ x_121 x_122 x_123 x_124))) +(assert (= 1 (+ x_126 x_127 x_128 x_129))) +(assert (= 1 (+ x_131 x_132 x_133 x_134))) +(assert (= 1 (+ x_136 x_137 x_138 x_139))) +(assert (= 1 (+ x_141 x_142 x_143 x_144))) +(assert (= 1 (+ x_146 x_147 x_148 x_149))) +(assert (= 1 (+ x_151 x_152 x_153 x_154))) +(assert (= 1 (+ x_156 x_157 x_158 x_159))) +(assert (= 1 (+ x_161 x_162 x_163 x_164))) +(assert (= 1 (+ x_166 x_167 x_168 x_169))) +(assert (= 1 (+ x_171 x_172 x_173 x_174))) +(assert (= 1 (+ x_176 x_177 x_178 x_179))) +(assert (= 1 (+ x_181 x_182 x_183 x_184))) +(assert (= 1 (+ x_186 x_187 x_188 x_189))) +(assert (= 1 (+ x_191 x_192 x_193 x_194))) +(assert (= 1 (+ x_196 x_197 x_198 x_199))) +(assert (= 1 (+ x_201 x_202 x_203 x_204))) +(assert (= 1 (+ x_206 x_207 x_208 x_209))) +(assert (= 1 (+ x_211 x_212 x_213 x_214))) +(assert (= 1 (+ x_216 x_217 x_218 x_219))) +(assert (= 1 (+ x_221 x_222 x_223 x_224))) +(assert (= 1 (+ x_226 x_227 x_228 x_229))) +(assert (= 1 (+ x_231 x_232 x_233 x_234))) +(assert (= 1 (+ x_236 x_237 x_238 x_239))) +(assert (= 1 (+ x_241 x_242 x_243 x_244))) +(assert (= 1 (+ x_246 x_247 x_248 x_249))) +(assert (= 1 (+ x_251 x_252 x_253 x_254))) +(assert (= 1 (+ x_256 x_257 x_258 x_259))) +(assert (= 1 (+ x_261 x_262 x_263 x_264))) +(assert (= 1 (+ x_266 x_267 x_268 x_269))) +(assert (= 1 (+ x_271 x_272 x_273 x_274))) +(assert (= 1 (+ x_276 x_277 x_278 x_279))) +(assert (= 1 (+ x_281 x_282 x_283 x_284))) +(assert (= 1 (+ x_286 x_287 x_288 x_289))) +(assert (= 1 (+ x_291 x_292 x_293 x_294))) +(assert (= 1 (+ x_296 x_297 x_298 x_299))) +(assert (= 1 (+ x_301 x_302 x_303 x_304))) +(assert (= 1 (+ x_306 x_307 x_308 x_309))) +(assert (= 1 (+ x_311 x_312 x_313 x_314))) +(assert (= 1 (+ x_316 x_317 x_318 x_319))) +(assert (= 1 (+ x_321 x_322 x_323 x_324))) +(assert (= 1 (+ x_326 x_327 x_328 x_329))) +(assert (= 1 (+ x_331 x_332 x_333 x_334))) +(assert (= 1 (+ x_336 x_337 x_338 x_339))) +(assert (= 1 (+ x_341 x_342 x_343 x_344))) +(assert (= 1 (+ x_346 x_347 x_348 x_349))) +(assert (= 1 (+ x_351 x_352 x_353 x_354))) +(assert (= 1 (+ x_356 x_357 x_358 x_359))) +(assert (= 1 (+ x_361 x_362 x_363 x_364))) +(assert (= 1 (+ x_366 x_367 x_368 x_369))) +(assert (= 1 (+ x_371 x_372 x_373 x_374))) +(assert (= 1 (+ x_376 x_377 x_378 x_379))) +(assert (= 1 (+ x_381 x_382 x_383 x_384))) +(assert (= 1 (+ x_386 x_387 x_388 x_389))) +(assert (= 1 (+ x_391 x_392 x_393 x_394))) +(assert (= 1 (+ x_396 x_397 x_398 x_399))) +(assert (= 1 (+ x_401 x_402 x_403 x_404))) +(assert (= 1 (+ x_406 x_407 x_408 x_409))) +(assert (= 1 (+ x_411 x_412 x_413 x_414))) +(assert (= 1 (+ x_416 x_417 x_418 x_419))) +(assert (= 1 (+ x_421 x_422 x_423 x_424))) +(assert (= 1 (+ x_426 x_427 x_428 x_429))) +(assert (= 1 (+ x_431 x_432 x_433 x_434))) +(assert (= 1 (+ x_436 x_437 x_438 x_439))) +(assert (= 1 (+ x_441 x_442 x_443 x_444))) +(assert (= 1 (+ x_446 x_447 x_448 x_449))) +(assert (= 1 (+ x_451 x_452 x_453 x_454))) +(assert (= 1 (+ x_456 x_457 x_458 x_459))) +(assert (= 1 (+ x_461 x_462 x_463 x_464))) +(assert (= 1 (+ x_466 x_467 x_468 x_469))) +(assert (= 1 (+ x_471 x_472 x_473 x_474))) +(assert (= 1 (+ x_476 x_477 x_478 x_479))) +(assert (= 1 (+ x_481 x_482 x_483 x_484))) +(assert (= 1 (+ x_486 x_487 x_488 x_489))) +(assert (= 1 (+ x_491 x_492 x_493 x_494))) +(assert (= 1 (+ x_496 x_497 x_498 x_499))) +(assert (= 1 (+ x_501 x_502 x_503 x_504))) +(assert (= 1 (+ x_506 x_507 x_508 x_509))) +(assert (= 1 (+ x_511 x_512 x_513 x_514))) +(assert (= 1 (+ x_516 x_517 x_518 x_519))) +(assert (= 1 (+ x_521 x_522 x_523 x_524))) +(assert (= 1 (+ x_526 x_527 x_528 x_529))) +(assert (= 1 (+ x_531 x_532 x_533 x_534))) +(assert (= 1 (+ x_536 x_537 x_538 x_539))) +(assert (= 1 (+ x_541 x_542 x_543 x_544))) +(assert (= 1 (+ x_546 x_547 x_548 x_549))) +(assert (= 1 (+ x_551 x_552 x_553 x_554))) +(assert (= 1 (+ x_556 x_557 x_558 x_559))) +(assert (= 1 (+ x_561 x_562 x_563 x_564))) +(assert (= 1 (+ x_566 x_567 x_568 x_569))) +(assert (= 1 (+ x_571 x_572 x_573 x_574))) +(assert (= 1 (+ x_576 x_577 x_578 x_579))) +(assert (= 1 (+ x_581 x_582 x_583 x_584))) +(assert (= 1 (+ x_586 x_587 x_588 x_589))) +(assert (= 1 (+ x_591 x_592 x_593 x_594))) +(assert (= 1 (+ x_596 x_597 x_598 x_599))) +(assert (= 1 (+ x_601 x_602 x_603 x_604))) +(assert (= 1 (+ x_606 x_607 x_608 x_609))) +(assert (= 1 (+ x_611 x_612 x_613 x_614))) +(assert (= 1 (+ x_616 x_617 x_618 x_619))) +(assert (= 1 (+ x_621 x_622 x_623 x_624))) +(assert (= 1 (+ x_626 x_627 x_628 x_629))) +(assert (= 1 (+ x_631 x_632 x_633 x_634))) +(assert (= 1 (+ x_636 x_637 x_638 x_639))) +(assert (= 1 (+ x_641 x_642 x_643 x_644))) +(assert (= 1 (+ x_646 x_647 x_648 x_649))) +(assert (= 1 (+ x_651 x_652 x_653 x_654))) +(assert (= 1 (+ x_656 x_657 x_658 x_659))) +(assert (= 1 (+ x_661 x_662 x_663 x_664))) +(assert (= 1 (+ x_666 x_667 x_668 x_669))) +(assert (= 1 (+ x_671 x_672 x_673 x_674))) +(assert (= 1 (+ x_676 x_677 x_678 x_679))) +(assert (= 1 (+ x_681 x_682 x_683 x_684))) +(assert (= 1 (+ x_686 x_687 x_688 x_689))) +(assert (= 1 (+ x_691 x_692 x_693 x_694))) +(assert (= 1 (+ x_696 x_697 x_698 x_699))) +(assert (= 1 (+ x_701 x_702 x_703 x_704))) +(assert (= 1 (+ x_706 x_707 x_708 x_709))) +(assert (= 1 (+ x_711 x_712 x_713 x_714))) +(assert (= 1 (+ x_716 x_717 x_718 x_719))) +(assert (= 1 (+ x_721 x_722 x_723 x_724))) +(assert (= 1 (+ x_726 x_727 x_728 x_729))) +(assert (= 1 (+ x_731 x_732 x_733 x_734))) +(assert (= 1 (+ x_736 x_737 x_738 x_739))) +(assert (= 1 (+ x_741 x_742 x_743 x_744))) +(assert (= 1 (+ x_746 x_747 x_748 x_749))) +(assert (= 1 (+ x_751 x_752 x_753 x_754))) +(assert (= 1 (+ x_756 x_757 x_758 x_759))) +(assert (= 1 (+ x_761 x_762 x_763 x_764))) +(assert (= 1 (+ x_766 x_767 x_768 x_769))) +(assert (= 1 (+ x_771 x_772 x_773 x_774))) +(assert (= 1 (+ x_776 x_777 x_778 x_779))) +(assert (= 1 (+ x_781 x_782 x_783 x_784))) +(assert (= 1 (+ x_786 x_787 x_788 x_789))) +(assert (= 1 (+ x_791 x_792 x_793 x_794))) +(assert (= 1 (+ x_796 x_797 x_798 x_799))) +(assert (= 1 (+ x_801 x_802 x_803 x_804))) +(assert (= 1 (+ x_806 x_807 x_808 x_809))) +(assert (= 1 (+ x_811 x_812 x_813 x_814))) +(assert (= 1 (+ x_816 x_817 x_818 x_819))) +(assert (= 1 (+ x_821 x_822 x_823 x_824))) +(assert (= 1 (+ x_826 x_827 x_828 x_829))) +(assert (= 1 (+ x_831 x_832 x_833 x_834))) +(assert (= 1 (+ x_836 x_837 x_838 x_839))) +(assert (= 1 (+ x_841 x_842 x_843 x_844))) +(assert (= 1 (+ x_846 x_847 x_848 x_849))) +(assert (= 1 (+ x_851 x_852 x_853 x_854))) +(assert (= 1 (+ x_856 x_857 x_858 x_859))) +(assert (= 1 (+ x_861 x_862 x_863 x_864))) +(assert (= 1 (+ x_866 x_867 x_868 x_869))) +(assert (= 1 (+ x_871 x_872 x_873 x_874))) +(assert (= 1 (+ x_876 x_877 x_878 x_879))) +(assert (= 1 (+ x_881 x_882 x_883 x_884))) +(assert (= 1 (+ x_886 x_887 x_888 x_889))) +(assert (= 1 (+ x_891 x_892 x_893 x_894))) +(assert (= 1 (+ x_896 x_897 x_898 x_899))) +(assert (= 1 (+ x_901 x_902 x_903 x_904))) +(assert (= 1 (+ x_906 x_907 x_908 x_909))) +(assert (= 1 (+ x_911 x_912 x_913 x_914))) +(assert (= 1 (+ x_916 x_917 x_918 x_919))) +(assert (= 1 (+ x_921 x_922 x_923 x_924))) +(assert (= 1 (+ x_926 x_927 x_928 x_929))) +(assert (= 1 (+ x_931 x_932 x_933 x_934))) +(assert (= 1 (+ x_936 x_937 x_938 x_939))) +(assert (= 1 (+ x_941 x_942 x_943 x_944))) +(assert (= 1 (+ x_946 x_947 x_948 x_949))) +(assert (= 1 (+ x_951 x_952 x_953 x_954))) +(assert (= 1 (+ x_956 x_957 x_958 x_959))) +(assert (= 1 (+ x_961 x_962 x_963 x_964))) +(assert (= 1 (+ x_966 x_967 x_968 x_969))) +(assert (= 1 (+ x_971 x_972 x_973 x_974))) +(assert (= 1 (+ x_976 x_977 x_978 x_979))) +(assert (= 1 (+ x_981 x_982 x_983 x_984))) +(assert (= 1 (+ x_986 x_987 x_988 x_989))) +(assert (= 1 (+ x_991 x_992 x_993 x_994))) +(assert (= 1 (+ x_996 x_997 x_998 x_999))) +(assert (<= 0 (+ x_1001 (* (- 1) x_4)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_9)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_14)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_19)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_24)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_29)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_34)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_39)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_44)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_49)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_54)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_59)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_64)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_69)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_74)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_79)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_84)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_89)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_94)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_99)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_104)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_109)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_114)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_119)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_124)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_129)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_134)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_139)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_144)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_149)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_154)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_159)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_164)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_169)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_174)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_179)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_184)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_189)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_194)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_199)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_204)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_209)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_214)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_219)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_224)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_229)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_234)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_239)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_244)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_249)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_254)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_259)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_264)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_269)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_274)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_279)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_284)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_289)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_294)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_299)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_304)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_309)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_314)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_319)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_324)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_329)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_334)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_339)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_344)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_349)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_354)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_359)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_364)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_369)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_374)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_379)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_384)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_389)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_394)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_399)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_404)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_409)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_414)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_419)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_424)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_429)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_434)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_439)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_444)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_449)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_454)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_459)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_464)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_469)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_474)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_479)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_484)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_489)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_494)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_499)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_504)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_509)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_514)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_519)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_524)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_529)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_534)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_539)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_544)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_549)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_554)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_559)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_564)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_569)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_574)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_579)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_584)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_589)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_594)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_599)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_604)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_609)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_614)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_619)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_624)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_629)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_634)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_639)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_644)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_649)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_654)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_659)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_664)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_669)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_674)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_679)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_684)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_689)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_694)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_699)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_704)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_709)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_714)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_719)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_724)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_729)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_734)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_739)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_744)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_749)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_754)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_759)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_764)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_769)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_774)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_779)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_784)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_789)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_794)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_799)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_804)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_809)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_814)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_819)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_824)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_829)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_834)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_839)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_844)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_849)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_854)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_859)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_864)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_869)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_874)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_879)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_884)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_889)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_894)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_899)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_904)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_909)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_914)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_919)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_924)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_929)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_934)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_939)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_944)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_949)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_954)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_959)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_964)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_969)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_974)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_979)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_984)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_989)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_994)))) +(assert (<= 0 (+ x_1001 (* (- 1) x_999)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_1)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_6)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_11)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_16)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_21)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_26)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_31)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_36)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_41)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_46)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_51)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_56)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_61)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_66)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_71)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_76)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_81)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_86)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_91)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_96)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_101)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_106)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_111)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_116)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_121)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_126)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_131)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_136)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_141)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_146)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_151)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_156)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_161)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_166)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_171)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_176)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_181)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_186)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_191)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_196)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_201)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_206)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_211)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_216)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_221)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_226)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_231)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_236)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_241)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_246)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_251)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_256)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_261)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_266)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_271)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_276)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_281)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_286)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_291)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_296)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_301)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_306)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_311)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_316)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_321)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_326)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_331)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_336)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_341)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_346)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_351)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_356)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_361)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_366)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_371)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_376)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_381)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_386)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_391)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_396)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_401)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_406)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_411)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_416)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_421)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_426)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_431)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_436)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_441)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_446)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_451)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_456)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_461)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_466)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_471)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_476)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_481)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_486)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_491)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_496)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_501)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_506)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_511)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_516)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_521)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_526)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_531)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_536)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_541)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_546)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_551)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_556)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_561)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_566)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_571)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_576)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_581)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_586)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_591)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_596)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_601)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_606)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_611)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_616)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_621)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_626)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_631)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_636)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_641)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_646)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_651)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_656)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_661)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_666)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_671)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_676)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_681)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_686)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_691)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_696)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_701)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_706)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_711)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_716)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_721)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_726)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_731)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_736)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_741)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_746)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_751)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_756)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_761)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_766)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_771)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_776)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_781)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_786)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_791)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_796)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_801)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_806)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_811)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_816)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_821)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_826)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_831)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_836)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_841)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_846)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_851)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_856)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_861)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_866)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_871)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_876)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_881)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_886)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_891)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_896)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_901)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_906)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_911)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_916)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_921)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_926)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_931)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_936)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_941)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_946)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_951)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_956)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_961)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_966)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_971)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_976)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_981)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_986)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_991)))) +(assert (<= 0 (+ x_1202 (* (- 1) x_996)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_2)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_7)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_12)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_17)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_22)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_27)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_32)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_37)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_42)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_47)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_52)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_57)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_62)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_67)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_72)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_77)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_82)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_87)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_92)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_97)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_102)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_107)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_112)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_117)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_122)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_127)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_132)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_137)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_142)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_147)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_152)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_157)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_162)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_167)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_172)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_177)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_182)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_187)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_192)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_197)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_202)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_207)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_212)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_217)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_222)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_227)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_232)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_237)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_242)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_247)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_252)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_257)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_262)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_267)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_272)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_277)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_282)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_287)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_292)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_297)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_302)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_307)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_312)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_317)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_322)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_327)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_332)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_337)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_342)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_347)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_352)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_357)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_362)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_367)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_372)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_377)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_382)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_387)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_392)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_397)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_402)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_407)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_412)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_417)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_422)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_427)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_432)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_437)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_442)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_447)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_452)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_457)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_462)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_467)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_472)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_477)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_482)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_487)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_492)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_497)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_502)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_507)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_512)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_517)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_522)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_527)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_532)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_537)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_542)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_547)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_552)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_557)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_562)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_567)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_572)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_577)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_582)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_587)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_592)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_597)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_602)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_607)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_612)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_617)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_622)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_627)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_632)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_637)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_642)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_647)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_652)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_657)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_662)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_667)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_672)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_677)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_682)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_687)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_692)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_697)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_702)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_707)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_712)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_717)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_722)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_727)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_732)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_737)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_742)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_747)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_752)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_757)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_762)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_767)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_772)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_777)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_782)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_787)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_792)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_797)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_802)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_807)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_812)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_817)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_822)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_827)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_832)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_837)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_842)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_847)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_852)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_857)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_862)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_867)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_872)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_877)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_882)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_887)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_892)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_897)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_902)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_907)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_912)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_917)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_922)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_927)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_932)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_937)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_942)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_947)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_952)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_957)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_962)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_967)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_972)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_977)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_982)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_987)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_992)))) +(assert (<= 0 (+ x_1403 (* (- 1) x_997)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_3)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_8)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_13)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_18)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_23)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_28)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_33)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_38)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_43)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_48)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_53)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_58)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_63)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_68)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_73)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_78)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_83)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_88)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_93)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_98)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_103)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_108)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_113)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_118)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_123)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_128)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_133)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_138)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_143)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_148)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_153)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_158)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_163)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_168)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_173)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_178)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_183)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_188)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_193)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_198)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_203)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_208)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_213)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_218)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_223)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_228)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_233)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_238)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_243)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_248)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_253)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_258)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_263)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_268)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_273)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_278)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_283)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_288)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_293)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_298)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_303)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_308)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_313)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_318)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_323)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_328)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_333)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_338)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_343)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_348)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_353)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_358)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_363)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_368)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_373)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_378)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_383)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_388)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_393)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_398)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_403)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_408)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_413)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_418)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_423)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_428)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_433)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_438)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_443)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_448)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_453)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_458)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_463)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_468)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_473)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_478)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_483)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_488)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_493)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_498)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_503)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_508)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_513)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_518)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_523)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_528)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_533)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_538)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_543)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_548)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_553)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_558)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_563)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_568)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_573)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_578)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_583)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_588)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_593)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_598)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_603)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_608)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_613)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_618)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_623)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_628)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_633)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_638)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_643)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_648)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_653)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_658)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_663)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_668)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_673)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_678)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_683)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_688)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_693)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_698)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_703)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_708)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_713)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_718)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_723)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_728)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_733)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_738)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_743)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_748)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_753)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_758)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_763)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_768)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_773)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_778)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_783)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_788)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_793)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_798)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_803)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_808)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_813)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_818)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_823)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_828)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_833)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_838)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_843)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_848)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_853)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_858)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_863)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_868)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_873)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_878)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_883)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_888)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_893)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_898)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_903)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_908)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_913)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_918)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_923)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_928)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_933)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_938)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_943)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_948)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_953)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_958)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_963)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_968)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_973)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_978)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_983)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_988)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_993)))) +(assert (<= 0 (+ x_1604 (* (- 1) x_998)))) +(assert (<= 0 + (+ (* 21600 x_1001) + (* (- 50) x_9) + (* (- 40) x_14) + (* (- 50) x_19) + (* (- 60) x_24) + (* (- 40) x_29) + (* (- 40) x_34) + (* (- 50) x_39) + (* (- 40) x_44) + (* (- 40) x_49) + (* (- 40) x_54) + (* (- 50) x_59) + (* (- 40) x_64) + (* (- 40) x_69) + (* (- 50) x_74) + (* (- 60) x_79) + (* (- 70) x_84) + (* (- 80) x_89) + (* (- 90) x_94) + (* (- 100) x_99) + (* (- 40) x_104) + (* (- 50) x_109) + (* (- 60) x_114) + (* (- 70) x_119) + (* (- 40) x_124) + (* (- 50) x_129) + (* (- 60) x_134) + (* (- 70) x_139) + (* (- 80) x_144) + (* (- 90) x_149) + (* (- 100) x_154) + (* (- 110) x_159) + (* (- 120) x_164) + (* (- 40) x_169) + (* (- 50) x_174) + (* (- 60) x_179) + (* (- 70) x_184) + (* (- 40) x_189) + (* (- 50) x_194) + (* (- 60) x_199) + (* (- 40) x_204) + (* (- 50) x_209) + (* (- 40) x_214) + (* (- 50) x_219) + (* (- 60) x_224) + (* (- 70) x_229) + (* (- 80) x_234) + (* (- 90) x_239) + (* (- 100) x_244) + (* (- 110) x_249) + (* (- 40) x_254) + (* (- 50) x_259) + (* (- 60) x_264) + (* (- 70) x_269) + (* (- 80) x_274) + (* (- 90) x_279) + (* (- 100) x_284) + (* (- 40) x_289) + (* (- 50) x_294) + (* (- 60) x_299) + (* (- 70) x_304) + (* (- 80) x_309) + (* (- 90) x_314) + (* (- 100) x_319) + (* (- 110) x_324) + (* (- 40) x_329) + (* (- 50) x_334) + (* (- 60) x_339) + (* (- 70) x_344) + (* (- 80) x_349) + (* (- 90) x_354) + (* (- 100) x_359) + (* (- 40) x_364) + (* (- 50) x_369) + (* (- 60) x_374) + (* (- 70) x_379) + (* (- 80) x_384) + (* (- 90) x_389) + (* (- 100) x_394) + (* (- 40) x_399) + (* (- 50) x_404) + (* (- 60) x_409) + (* (- 40) x_414) + (* (- 50) x_419) + (* (- 60) x_424) + (* (- 70) x_429) + (* (- 80) x_434) + (* (- 90) x_439) + (* (- 100) x_444) + (* (- 110) x_449) + (* (- 120) x_454) + (* (- 130) x_459) + (* (- 40) x_464) + (* (- 50) x_469) + (* (- 60) x_474) + (* (- 70) x_479) + (* (- 80) x_484) + (* (- 90) x_489) + (* (- 40) x_494) + (* (- 40) x_499) + (* (- 50) x_504) + (* (- 60) x_509) + (* (- 70) x_514) + (* (- 80) x_519) + (* (- 90) x_524) + (* (- 40) x_529) + (* (- 50) x_534) + (* (- 60) x_539) + (* (- 40) x_544) + (* (- 50) x_549) + (* (- 60) x_554) + (* (- 70) x_559) + (* (- 40) x_564) + (* (- 50) x_569) + (* (- 60) x_574) + (* (- 70) x_579) + (* (- 80) x_584) + (* (- 90) x_589) + (* (- 40) x_594) + (* (- 40) x_599) + (* (- 50) x_604) + (* (- 60) x_609) + (* (- 70) x_614) + (* (- 80) x_619) + (* (- 40) x_624) + (* (- 50) x_629) + (* (- 60) x_634) + (* (- 70) x_639) + (* (- 80) x_644) + (* (- 90) x_649) + (* (- 100) x_654) + (* (- 110) x_659) + (* (- 40) x_664) + (* (- 50) x_669) + (* (- 60) x_674) + (* (- 70) x_679) + (* (- 40) x_684) + (* (- 50) x_689) + (* (- 60) x_694) + (* (- 70) x_699) + (* (- 80) x_704) + (* (- 90) x_709) + (* (- 100) x_714) + (* (- 110) x_719) + (* (- 120) x_724) + (* (- 40) x_729) + (* (- 50) x_734) + (* (- 60) x_739) + (* (- 70) x_744) + (* (- 80) x_749) + (* (- 90) x_754) + (* (- 100) x_759) + (* (- 110) x_764) + (* (- 40) x_769) + (* (- 50) x_774) + (* (- 40) x_779) + (* (- 50) x_784) + (* (- 40) x_789) + (* (- 50) x_794) + (* (- 60) x_799) + (* (- 70) x_804) + (* (- 80) x_809) + (* (- 90) x_814) + (* (- 100) x_819) + (* (- 40) x_824) + (* (- 50) x_829) + (* (- 60) x_834) + (* (- 70) x_839) + (* (- 80) x_844) + (* (- 90) x_849) + (* (- 100) x_854) + (* (- 110) x_859) + (* (- 40) x_864) + (* (- 50) x_869) + (* (- 60) x_874) + (* (- 70) x_879) + (* (- 80) x_884) + (* (- 90) x_889) + (* (- 40) x_894) + (* (- 50) x_899) + (* (- 60) x_904) + (* (- 70) x_909) + (* (- 80) x_914) + (* (- 90) x_919) + (* (- 100) x_924) + (* (- 52) x_929) + (* (- 52) x_934) + (* (- 65) x_939) + (* (- 52) x_944) + (* (- 52) x_949) + (* (- 65) x_954) + (* (- 52) x_959) + (* (- 65) x_964) + (* (- 52) x_969) + (* (- 65) x_974) + (* (- 78) x_979) + (* (- 91) x_984) + (* (- 104) x_989) + (* (- 117) x_994) + (* (- 130) x_999) + (* (- 40) x_4)))) +(assert (<= 0 + (+ (* 7400 x_1202) + (* (- 50) x_6) + (* (- 40) x_11) + (* (- 50) x_16) + (* (- 60) x_21) + (* (- 40) x_26) + (* (- 40) x_31) + (* (- 50) x_36) + (* (- 40) x_41) + (* (- 40) x_46) + (* (- 40) x_51) + (* (- 50) x_56) + (* (- 40) x_61) + (* (- 40) x_66) + (* (- 50) x_71) + (* (- 60) x_76) + (* (- 70) x_81) + (* (- 80) x_86) + (* (- 90) x_91) + (* (- 100) x_96) + (* (- 40) x_101) + (* (- 50) x_106) + (* (- 60) x_111) + (* (- 70) x_116) + (* (- 40) x_121) + (* (- 50) x_126) + (* (- 60) x_131) + (* (- 70) x_136) + (* (- 80) x_141) + (* (- 90) x_146) + (* (- 100) x_151) + (* (- 110) x_156) + (* (- 120) x_161) + (* (- 40) x_166) + (* (- 50) x_171) + (* (- 60) x_176) + (* (- 70) x_181) + (* (- 40) x_186) + (* (- 50) x_191) + (* (- 60) x_196) + (* (- 40) x_201) + (* (- 50) x_206) + (* (- 40) x_211) + (* (- 50) x_216) + (* (- 60) x_221) + (* (- 70) x_226) + (* (- 80) x_231) + (* (- 90) x_236) + (* (- 100) x_241) + (* (- 110) x_246) + (* (- 40) x_251) + (* (- 50) x_256) + (* (- 60) x_261) + (* (- 70) x_266) + (* (- 80) x_271) + (* (- 90) x_276) + (* (- 100) x_281) + (* (- 40) x_286) + (* (- 50) x_291) + (* (- 60) x_296) + (* (- 70) x_301) + (* (- 80) x_306) + (* (- 90) x_311) + (* (- 100) x_316) + (* (- 110) x_321) + (* (- 40) x_326) + (* (- 50) x_331) + (* (- 60) x_336) + (* (- 70) x_341) + (* (- 80) x_346) + (* (- 90) x_351) + (* (- 100) x_356) + (* (- 40) x_361) + (* (- 50) x_366) + (* (- 60) x_371) + (* (- 70) x_376) + (* (- 80) x_381) + (* (- 90) x_386) + (* (- 100) x_391) + (* (- 40) x_396) + (* (- 50) x_401) + (* (- 60) x_406) + (* (- 40) x_411) + (* (- 50) x_416) + (* (- 60) x_421) + (* (- 70) x_426) + (* (- 80) x_431) + (* (- 90) x_436) + (* (- 100) x_441) + (* (- 110) x_446) + (* (- 120) x_451) + (* (- 130) x_456) + (* (- 40) x_461) + (* (- 50) x_466) + (* (- 60) x_471) + (* (- 70) x_476) + (* (- 80) x_481) + (* (- 90) x_486) + (* (- 40) x_491) + (* (- 40) x_496) + (* (- 50) x_501) + (* (- 60) x_506) + (* (- 70) x_511) + (* (- 80) x_516) + (* (- 90) x_521) + (* (- 40) x_526) + (* (- 50) x_531) + (* (- 60) x_536) + (* (- 40) x_541) + (* (- 50) x_546) + (* (- 60) x_551) + (* (- 70) x_556) + (* (- 40) x_561) + (* (- 50) x_566) + (* (- 60) x_571) + (* (- 70) x_576) + (* (- 80) x_581) + (* (- 90) x_586) + (* (- 40) x_591) + (* (- 40) x_596) + (* (- 50) x_601) + (* (- 60) x_606) + (* (- 70) x_611) + (* (- 80) x_616) + (* (- 40) x_621) + (* (- 50) x_626) + (* (- 60) x_631) + (* (- 70) x_636) + (* (- 80) x_641) + (* (- 90) x_646) + (* (- 100) x_651) + (* (- 110) x_656) + (* (- 40) x_661) + (* (- 50) x_666) + (* (- 60) x_671) + (* (- 70) x_676) + (* (- 40) x_681) + (* (- 50) x_686) + (* (- 60) x_691) + (* (- 70) x_696) + (* (- 80) x_701) + (* (- 90) x_706) + (* (- 100) x_711) + (* (- 110) x_716) + (* (- 120) x_721) + (* (- 40) x_726) + (* (- 50) x_731) + (* (- 60) x_736) + (* (- 70) x_741) + (* (- 80) x_746) + (* (- 90) x_751) + (* (- 100) x_756) + (* (- 110) x_761) + (* (- 40) x_766) + (* (- 50) x_771) + (* (- 40) x_776) + (* (- 50) x_781) + (* (- 40) x_786) + (* (- 50) x_791) + (* (- 60) x_796) + (* (- 70) x_801) + (* (- 80) x_806) + (* (- 90) x_811) + (* (- 100) x_816) + (* (- 40) x_821) + (* (- 50) x_826) + (* (- 60) x_831) + (* (- 70) x_836) + (* (- 80) x_841) + (* (- 90) x_846) + (* (- 100) x_851) + (* (- 110) x_856) + (* (- 40) x_861) + (* (- 50) x_866) + (* (- 60) x_871) + (* (- 70) x_876) + (* (- 80) x_881) + (* (- 90) x_886) + (* (- 40) x_891) + (* (- 50) x_896) + (* (- 60) x_901) + (* (- 70) x_906) + (* (- 80) x_911) + (* (- 90) x_916) + (* (- 100) x_921) + (* (- 52) x_926) + (* (- 52) x_931) + (* (- 65) x_936) + (* (- 52) x_941) + (* (- 52) x_946) + (* (- 65) x_951) + (* (- 52) x_956) + (* (- 65) x_961) + (* (- 52) x_966) + (* (- 65) x_971) + (* (- 78) x_976) + (* (- 91) x_981) + (* (- 104) x_986) + (* (- 117) x_991) + (* (- 130) x_996) + (* (- 40) x_1)))) +(assert (<= 0 + (+ (* 26500 x_1403) + (* (- 50) x_7) + (* (- 40) x_12) + (* (- 50) x_17) + (* (- 60) x_22) + (* (- 40) x_27) + (* (- 40) x_32) + (* (- 50) x_37) + (* (- 40) x_42) + (* (- 40) x_47) + (* (- 40) x_52) + (* (- 50) x_57) + (* (- 40) x_62) + (* (- 40) x_67) + (* (- 50) x_72) + (* (- 60) x_77) + (* (- 70) x_82) + (* (- 80) x_87) + (* (- 90) x_92) + (* (- 100) x_97) + (* (- 40) x_102) + (* (- 50) x_107) + (* (- 60) x_112) + (* (- 70) x_117) + (* (- 40) x_122) + (* (- 50) x_127) + (* (- 60) x_132) + (* (- 70) x_137) + (* (- 80) x_142) + (* (- 90) x_147) + (* (- 100) x_152) + (* (- 110) x_157) + (* (- 120) x_162) + (* (- 40) x_167) + (* (- 50) x_172) + (* (- 60) x_177) + (* (- 70) x_182) + (* (- 40) x_187) + (* (- 50) x_192) + (* (- 60) x_197) + (* (- 40) x_202) + (* (- 50) x_207) + (* (- 40) x_212) + (* (- 50) x_217) + (* (- 60) x_222) + (* (- 70) x_227) + (* (- 80) x_232) + (* (- 90) x_237) + (* (- 100) x_242) + (* (- 110) x_247) + (* (- 40) x_252) + (* (- 50) x_257) + (* (- 60) x_262) + (* (- 70) x_267) + (* (- 80) x_272) + (* (- 90) x_277) + (* (- 100) x_282) + (* (- 40) x_287) + (* (- 50) x_292) + (* (- 60) x_297) + (* (- 70) x_302) + (* (- 80) x_307) + (* (- 90) x_312) + (* (- 100) x_317) + (* (- 110) x_322) + (* (- 40) x_327) + (* (- 50) x_332) + (* (- 60) x_337) + (* (- 70) x_342) + (* (- 80) x_347) + (* (- 90) x_352) + (* (- 100) x_357) + (* (- 40) x_362) + (* (- 50) x_367) + (* (- 60) x_372) + (* (- 70) x_377) + (* (- 80) x_382) + (* (- 90) x_387) + (* (- 100) x_392) + (* (- 40) x_397) + (* (- 50) x_402) + (* (- 60) x_407) + (* (- 40) x_412) + (* (- 50) x_417) + (* (- 60) x_422) + (* (- 70) x_427) + (* (- 80) x_432) + (* (- 90) x_437) + (* (- 100) x_442) + (* (- 110) x_447) + (* (- 120) x_452) + (* (- 130) x_457) + (* (- 40) x_462) + (* (- 50) x_467) + (* (- 60) x_472) + (* (- 70) x_477) + (* (- 80) x_482) + (* (- 90) x_487) + (* (- 40) x_492) + (* (- 40) x_497) + (* (- 50) x_502) + (* (- 60) x_507) + (* (- 70) x_512) + (* (- 80) x_517) + (* (- 90) x_522) + (* (- 40) x_527) + (* (- 50) x_532) + (* (- 60) x_537) + (* (- 40) x_542) + (* (- 50) x_547) + (* (- 60) x_552) + (* (- 70) x_557) + (* (- 40) x_562) + (* (- 50) x_567) + (* (- 60) x_572) + (* (- 70) x_577) + (* (- 80) x_582) + (* (- 90) x_587) + (* (- 40) x_592) + (* (- 40) x_597) + (* (- 50) x_602) + (* (- 60) x_607) + (* (- 70) x_612) + (* (- 80) x_617) + (* (- 40) x_622) + (* (- 50) x_627) + (* (- 60) x_632) + (* (- 70) x_637) + (* (- 80) x_642) + (* (- 90) x_647) + (* (- 100) x_652) + (* (- 110) x_657) + (* (- 40) x_662) + (* (- 50) x_667) + (* (- 60) x_672) + (* (- 70) x_677) + (* (- 40) x_682) + (* (- 50) x_687) + (* (- 60) x_692) + (* (- 70) x_697) + (* (- 80) x_702) + (* (- 90) x_707) + (* (- 100) x_712) + (* (- 110) x_717) + (* (- 120) x_722) + (* (- 40) x_727) + (* (- 50) x_732) + (* (- 60) x_737) + (* (- 70) x_742) + (* (- 80) x_747) + (* (- 90) x_752) + (* (- 100) x_757) + (* (- 110) x_762) + (* (- 40) x_767) + (* (- 50) x_772) + (* (- 40) x_777) + (* (- 50) x_782) + (* (- 40) x_787) + (* (- 50) x_792) + (* (- 60) x_797) + (* (- 70) x_802) + (* (- 80) x_807) + (* (- 90) x_812) + (* (- 100) x_817) + (* (- 40) x_822) + (* (- 50) x_827) + (* (- 60) x_832) + (* (- 70) x_837) + (* (- 80) x_842) + (* (- 90) x_847) + (* (- 100) x_852) + (* (- 110) x_857) + (* (- 40) x_862) + (* (- 50) x_867) + (* (- 60) x_872) + (* (- 70) x_877) + (* (- 80) x_882) + (* (- 90) x_887) + (* (- 40) x_892) + (* (- 50) x_897) + (* (- 60) x_902) + (* (- 70) x_907) + (* (- 80) x_912) + (* (- 90) x_917) + (* (- 100) x_922) + (* (- 52) x_927) + (* (- 52) x_932) + (* (- 65) x_937) + (* (- 52) x_942) + (* (- 52) x_947) + (* (- 65) x_952) + (* (- 52) x_957) + (* (- 65) x_962) + (* (- 52) x_967) + (* (- 65) x_972) + (* (- 78) x_977) + (* (- 91) x_982) + (* (- 104) x_987) + (* (- 117) x_992) + (* (- 130) x_997) + (* (- 40) x_2)))) +(assert (<= 0 + (+ (* 4500 x_1604) + (* (- 50) x_8) + (* (- 40) x_13) + (* (- 50) x_18) + (* (- 60) x_23) + (* (- 40) x_28) + (* (- 40) x_33) + (* (- 50) x_38) + (* (- 40) x_43) + (* (- 40) x_48) + (* (- 40) x_53) + (* (- 50) x_58) + (* (- 40) x_63) + (* (- 40) x_68) + (* (- 50) x_73) + (* (- 60) x_78) + (* (- 70) x_83) + (* (- 80) x_88) + (* (- 90) x_93) + (* (- 100) x_98) + (* (- 40) x_103) + (* (- 50) x_108) + (* (- 60) x_113) + (* (- 70) x_118) + (* (- 40) x_123) + (* (- 50) x_128) + (* (- 60) x_133) + (* (- 70) x_138) + (* (- 80) x_143) + (* (- 90) x_148) + (* (- 100) x_153) + (* (- 110) x_158) + (* (- 120) x_163) + (* (- 40) x_168) + (* (- 50) x_173) + (* (- 60) x_178) + (* (- 70) x_183) + (* (- 40) x_188) + (* (- 50) x_193) + (* (- 60) x_198) + (* (- 40) x_203) + (* (- 50) x_208) + (* (- 40) x_213) + (* (- 50) x_218) + (* (- 60) x_223) + (* (- 70) x_228) + (* (- 80) x_233) + (* (- 90) x_238) + (* (- 100) x_243) + (* (- 110) x_248) + (* (- 40) x_253) + (* (- 50) x_258) + (* (- 60) x_263) + (* (- 70) x_268) + (* (- 80) x_273) + (* (- 90) x_278) + (* (- 100) x_283) + (* (- 40) x_288) + (* (- 50) x_293) + (* (- 60) x_298) + (* (- 70) x_303) + (* (- 80) x_308) + (* (- 90) x_313) + (* (- 100) x_318) + (* (- 110) x_323) + (* (- 40) x_328) + (* (- 50) x_333) + (* (- 60) x_338) + (* (- 70) x_343) + (* (- 80) x_348) + (* (- 90) x_353) + (* (- 100) x_358) + (* (- 40) x_363) + (* (- 50) x_368) + (* (- 60) x_373) + (* (- 70) x_378) + (* (- 80) x_383) + (* (- 90) x_388) + (* (- 100) x_393) + (* (- 40) x_398) + (* (- 50) x_403) + (* (- 60) x_408) + (* (- 40) x_413) + (* (- 50) x_418) + (* (- 60) x_423) + (* (- 70) x_428) + (* (- 80) x_433) + (* (- 90) x_438) + (* (- 100) x_443) + (* (- 110) x_448) + (* (- 120) x_453) + (* (- 130) x_458) + (* (- 40) x_463) + (* (- 50) x_468) + (* (- 60) x_473) + (* (- 70) x_478) + (* (- 80) x_483) + (* (- 90) x_488) + (* (- 40) x_493) + (* (- 40) x_498) + (* (- 50) x_503) + (* (- 60) x_508) + (* (- 70) x_513) + (* (- 80) x_518) + (* (- 90) x_523) + (* (- 40) x_528) + (* (- 50) x_533) + (* (- 60) x_538) + (* (- 40) x_543) + (* (- 50) x_548) + (* (- 60) x_553) + (* (- 70) x_558) + (* (- 40) x_563) + (* (- 50) x_568) + (* (- 60) x_573) + (* (- 70) x_578) + (* (- 80) x_583) + (* (- 90) x_588) + (* (- 40) x_593) + (* (- 40) x_598) + (* (- 50) x_603) + (* (- 60) x_608) + (* (- 70) x_613) + (* (- 80) x_618) + (* (- 40) x_623) + (* (- 50) x_628) + (* (- 60) x_633) + (* (- 70) x_638) + (* (- 80) x_643) + (* (- 90) x_648) + (* (- 100) x_653) + (* (- 110) x_658) + (* (- 40) x_663) + (* (- 50) x_668) + (* (- 60) x_673) + (* (- 70) x_678) + (* (- 40) x_683) + (* (- 50) x_688) + (* (- 60) x_693) + (* (- 70) x_698) + (* (- 80) x_703) + (* (- 90) x_708) + (* (- 100) x_713) + (* (- 110) x_718) + (* (- 120) x_723) + (* (- 40) x_728) + (* (- 50) x_733) + (* (- 60) x_738) + (* (- 70) x_743) + (* (- 80) x_748) + (* (- 90) x_753) + (* (- 100) x_758) + (* (- 110) x_763) + (* (- 40) x_768) + (* (- 50) x_773) + (* (- 40) x_778) + (* (- 50) x_783) + (* (- 40) x_788) + (* (- 50) x_793) + (* (- 60) x_798) + (* (- 70) x_803) + (* (- 80) x_808) + (* (- 90) x_813) + (* (- 100) x_818) + (* (- 40) x_823) + (* (- 50) x_828) + (* (- 60) x_833) + (* (- 70) x_838) + (* (- 80) x_843) + (* (- 90) x_848) + (* (- 100) x_853) + (* (- 110) x_858) + (* (- 40) x_863) + (* (- 50) x_868) + (* (- 60) x_873) + (* (- 70) x_878) + (* (- 80) x_883) + (* (- 90) x_888) + (* (- 40) x_893) + (* (- 50) x_898) + (* (- 60) x_903) + (* (- 70) x_908) + (* (- 80) x_913) + (* (- 90) x_918) + (* (- 100) x_923) + (* (- 52) x_928) + (* (- 52) x_933) + (* (- 65) x_938) + (* (- 52) x_943) + (* (- 52) x_948) + (* (- 65) x_953) + (* (- 52) x_958) + (* (- 65) x_963) + (* (- 52) x_968) + (* (- 65) x_973) + (* (- 78) x_978) + (* (- 91) x_983) + (* (- 104) x_988) + (* (- 117) x_993) + (* (- 130) x_998) + (* (- 40) x_3)))) +(assert (<= 0 + (+ (* 3850 x_1001) + (* (- 30) x_9) + (* (- 24) x_14) + (* (- 30) x_19) + (* (- 36) x_24) + (* (- 24) x_29) + (* (- 24) x_34) + (* (- 30) x_39) + (* (- 24) x_44) + (* (- 24) x_49) + (* (- 24) x_54) + (* (- 30) x_59) + (* (- 24) x_64) + (* (- 24) x_69) + (* (- 30) x_74) + (* (- 36) x_79) + (* (- 42) x_84) + (* (- 48) x_89) + (* (- 54) x_94) + (* (- 60) x_99) + (* (- 24) x_104) + (* (- 30) x_109) + (* (- 36) x_114) + (* (- 42) x_119) + (* (- 24) x_124) + (* (- 30) x_129) + (* (- 36) x_134) + (* (- 42) x_139) + (* (- 48) x_144) + (* (- 54) x_149) + (* (- 60) x_154) + (* (- 66) x_159) + (* (- 72) x_164) + (* (- 24) x_169) + (* (- 30) x_174) + (* (- 36) x_179) + (* (- 42) x_184) + (* (- 24) x_189) + (* (- 30) x_194) + (* (- 36) x_199) + (* (- 24) x_204) + (* (- 30) x_209) + (* (- 24) x_214) + (* (- 30) x_219) + (* (- 36) x_224) + (* (- 42) x_229) + (* (- 48) x_234) + (* (- 54) x_239) + (* (- 60) x_244) + (* (- 66) x_249) + (* (- 24) x_254) + (* (- 30) x_259) + (* (- 36) x_264) + (* (- 42) x_269) + (* (- 48) x_274) + (* (- 54) x_279) + (* (- 60) x_284) + (* (- 24) x_289) + (* (- 30) x_294) + (* (- 36) x_299) + (* (- 42) x_304) + (* (- 48) x_309) + (* (- 54) x_314) + (* (- 60) x_319) + (* (- 66) x_324) + (* (- 24) x_329) + (* (- 30) x_334) + (* (- 36) x_339) + (* (- 42) x_344) + (* (- 48) x_349) + (* (- 54) x_354) + (* (- 60) x_359) + (* (- 24) x_364) + (* (- 30) x_369) + (* (- 36) x_374) + (* (- 42) x_379) + (* (- 48) x_384) + (* (- 54) x_389) + (* (- 60) x_394) + (* (- 24) x_399) + (* (- 30) x_404) + (* (- 36) x_409) + (* (- 24) x_414) + (* (- 30) x_419) + (* (- 36) x_424) + (* (- 42) x_429) + (* (- 48) x_434) + (* (- 54) x_439) + (* (- 60) x_444) + (* (- 66) x_449) + (* (- 72) x_454) + (* (- 78) x_459) + (* (- 24) x_464) + (* (- 30) x_469) + (* (- 36) x_474) + (* (- 42) x_479) + (* (- 48) x_484) + (* (- 54) x_489) + (* (- 24) x_494) + (* (- 24) x_499) + (* (- 30) x_504) + (* (- 36) x_509) + (* (- 42) x_514) + (* (- 48) x_519) + (* (- 54) x_524) + (* (- 24) x_529) + (* (- 30) x_534) + (* (- 36) x_539) + (* (- 24) x_544) + (* (- 30) x_549) + (* (- 36) x_554) + (* (- 42) x_559) + (* (- 24) x_564) + (* (- 30) x_569) + (* (- 36) x_574) + (* (- 42) x_579) + (* (- 48) x_584) + (* (- 54) x_589) + (* (- 24) x_594) + (* (- 24) x_599) + (* (- 30) x_604) + (* (- 36) x_609) + (* (- 42) x_614) + (* (- 48) x_619) + (* (- 24) x_624) + (* (- 30) x_629) + (* (- 36) x_634) + (* (- 42) x_639) + (* (- 48) x_644) + (* (- 54) x_649) + (* (- 60) x_654) + (* (- 66) x_659) + (* (- 24) x_664) + (* (- 30) x_669) + (* (- 36) x_674) + (* (- 42) x_679) + (* (- 24) x_684) + (* (- 30) x_689) + (* (- 36) x_694) + (* (- 42) x_699) + (* (- 48) x_704) + (* (- 54) x_709) + (* (- 60) x_714) + (* (- 66) x_719) + (* (- 72) x_724) + (* (- 24) x_729) + (* (- 30) x_734) + (* (- 36) x_739) + (* (- 42) x_744) + (* (- 48) x_749) + (* (- 54) x_754) + (* (- 60) x_759) + (* (- 66) x_764) + (* (- 24) x_769) + (* (- 30) x_774) + (* (- 24) x_779) + (* (- 30) x_784) + (* (- 24) x_789) + (* (- 30) x_794) + (* (- 36) x_799) + (* (- 42) x_804) + (* (- 48) x_809) + (* (- 54) x_814) + (* (- 60) x_819) + (* (- 24) x_824) + (* (- 30) x_829) + (* (- 36) x_834) + (* (- 42) x_839) + (* (- 48) x_844) + (* (- 54) x_849) + (* (- 60) x_854) + (* (- 66) x_859) + (* (- 24) x_864) + (* (- 30) x_869) + (* (- 36) x_874) + (* (- 42) x_879) + (* (- 48) x_884) + (* (- 54) x_889) + (* (- 24) x_894) + (* (- 30) x_899) + (* (- 36) x_904) + (* (- 42) x_909) + (* (- 48) x_914) + (* (- 54) x_919) + (* (- 60) x_924) + (* (- 36) x_929) + (* (- 36) x_934) + (* (- 45) x_939) + (* (- 36) x_944) + (* (- 36) x_949) + (* (- 45) x_954) + (* (- 36) x_959) + (* (- 45) x_964) + (* (- 36) x_969) + (* (- 45) x_974) + (* (- 54) x_979) + (* (- 63) x_984) + (* (- 72) x_989) + (* (- 81) x_994) + (* (- 90) x_999) + (* (- 24) x_4)))) +(assert (<= 0 + (+ (* 3000 x_1202) + (* (- 30) x_6) + (* (- 24) x_11) + (* (- 30) x_16) + (* (- 36) x_21) + (* (- 24) x_26) + (* (- 24) x_31) + (* (- 30) x_36) + (* (- 24) x_41) + (* (- 24) x_46) + (* (- 24) x_51) + (* (- 30) x_56) + (* (- 24) x_61) + (* (- 24) x_66) + (* (- 30) x_71) + (* (- 36) x_76) + (* (- 42) x_81) + (* (- 48) x_86) + (* (- 54) x_91) + (* (- 60) x_96) + (* (- 24) x_101) + (* (- 30) x_106) + (* (- 36) x_111) + (* (- 42) x_116) + (* (- 24) x_121) + (* (- 30) x_126) + (* (- 36) x_131) + (* (- 42) x_136) + (* (- 48) x_141) + (* (- 54) x_146) + (* (- 60) x_151) + (* (- 66) x_156) + (* (- 72) x_161) + (* (- 24) x_166) + (* (- 30) x_171) + (* (- 36) x_176) + (* (- 42) x_181) + (* (- 24) x_186) + (* (- 30) x_191) + (* (- 36) x_196) + (* (- 24) x_201) + (* (- 30) x_206) + (* (- 24) x_211) + (* (- 30) x_216) + (* (- 36) x_221) + (* (- 42) x_226) + (* (- 48) x_231) + (* (- 54) x_236) + (* (- 60) x_241) + (* (- 66) x_246) + (* (- 24) x_251) + (* (- 30) x_256) + (* (- 36) x_261) + (* (- 42) x_266) + (* (- 48) x_271) + (* (- 54) x_276) + (* (- 60) x_281) + (* (- 24) x_286) + (* (- 30) x_291) + (* (- 36) x_296) + (* (- 42) x_301) + (* (- 48) x_306) + (* (- 54) x_311) + (* (- 60) x_316) + (* (- 66) x_321) + (* (- 24) x_326) + (* (- 30) x_331) + (* (- 36) x_336) + (* (- 42) x_341) + (* (- 48) x_346) + (* (- 54) x_351) + (* (- 60) x_356) + (* (- 24) x_361) + (* (- 30) x_366) + (* (- 36) x_371) + (* (- 42) x_376) + (* (- 48) x_381) + (* (- 54) x_386) + (* (- 60) x_391) + (* (- 24) x_396) + (* (- 30) x_401) + (* (- 36) x_406) + (* (- 24) x_411) + (* (- 30) x_416) + (* (- 36) x_421) + (* (- 42) x_426) + (* (- 48) x_431) + (* (- 54) x_436) + (* (- 60) x_441) + (* (- 66) x_446) + (* (- 72) x_451) + (* (- 78) x_456) + (* (- 24) x_461) + (* (- 30) x_466) + (* (- 36) x_471) + (* (- 42) x_476) + (* (- 48) x_481) + (* (- 54) x_486) + (* (- 24) x_491) + (* (- 24) x_496) + (* (- 30) x_501) + (* (- 36) x_506) + (* (- 42) x_511) + (* (- 48) x_516) + (* (- 54) x_521) + (* (- 24) x_526) + (* (- 30) x_531) + (* (- 36) x_536) + (* (- 24) x_541) + (* (- 30) x_546) + (* (- 36) x_551) + (* (- 42) x_556) + (* (- 24) x_561) + (* (- 30) x_566) + (* (- 36) x_571) + (* (- 42) x_576) + (* (- 48) x_581) + (* (- 54) x_586) + (* (- 24) x_591) + (* (- 24) x_596) + (* (- 30) x_601) + (* (- 36) x_606) + (* (- 42) x_611) + (* (- 48) x_616) + (* (- 24) x_621) + (* (- 30) x_626) + (* (- 36) x_631) + (* (- 42) x_636) + (* (- 48) x_641) + (* (- 54) x_646) + (* (- 60) x_651) + (* (- 66) x_656) + (* (- 24) x_661) + (* (- 30) x_666) + (* (- 36) x_671) + (* (- 42) x_676) + (* (- 24) x_681) + (* (- 30) x_686) + (* (- 36) x_691) + (* (- 42) x_696) + (* (- 48) x_701) + (* (- 54) x_706) + (* (- 60) x_711) + (* (- 66) x_716) + (* (- 72) x_721) + (* (- 24) x_726) + (* (- 30) x_731) + (* (- 36) x_736) + (* (- 42) x_741) + (* (- 48) x_746) + (* (- 54) x_751) + (* (- 60) x_756) + (* (- 66) x_761) + (* (- 24) x_766) + (* (- 30) x_771) + (* (- 24) x_776) + (* (- 30) x_781) + (* (- 24) x_786) + (* (- 30) x_791) + (* (- 36) x_796) + (* (- 42) x_801) + (* (- 48) x_806) + (* (- 54) x_811) + (* (- 60) x_816) + (* (- 24) x_821) + (* (- 30) x_826) + (* (- 36) x_831) + (* (- 42) x_836) + (* (- 48) x_841) + (* (- 54) x_846) + (* (- 60) x_851) + (* (- 66) x_856) + (* (- 24) x_861) + (* (- 30) x_866) + (* (- 36) x_871) + (* (- 42) x_876) + (* (- 48) x_881) + (* (- 54) x_886) + (* (- 24) x_891) + (* (- 30) x_896) + (* (- 36) x_901) + (* (- 42) x_906) + (* (- 48) x_911) + (* (- 54) x_916) + (* (- 60) x_921) + (* (- 36) x_926) + (* (- 36) x_931) + (* (- 45) x_936) + (* (- 36) x_941) + (* (- 36) x_946) + (* (- 45) x_951) + (* (- 36) x_956) + (* (- 45) x_961) + (* (- 36) x_966) + (* (- 45) x_971) + (* (- 54) x_976) + (* (- 63) x_981) + (* (- 72) x_986) + (* (- 81) x_991) + (* (- 90) x_996) + (* (- 24) x_1)))) +(assert (<= 0 + (+ (* 7700 x_1403) + (* (- 30) x_7) + (* (- 24) x_12) + (* (- 30) x_17) + (* (- 36) x_22) + (* (- 24) x_27) + (* (- 24) x_32) + (* (- 30) x_37) + (* (- 24) x_42) + (* (- 24) x_47) + (* (- 24) x_52) + (* (- 30) x_57) + (* (- 24) x_62) + (* (- 24) x_67) + (* (- 30) x_72) + (* (- 36) x_77) + (* (- 42) x_82) + (* (- 48) x_87) + (* (- 54) x_92) + (* (- 60) x_97) + (* (- 24) x_102) + (* (- 30) x_107) + (* (- 36) x_112) + (* (- 42) x_117) + (* (- 24) x_122) + (* (- 30) x_127) + (* (- 36) x_132) + (* (- 42) x_137) + (* (- 48) x_142) + (* (- 54) x_147) + (* (- 60) x_152) + (* (- 66) x_157) + (* (- 72) x_162) + (* (- 24) x_167) + (* (- 30) x_172) + (* (- 36) x_177) + (* (- 42) x_182) + (* (- 24) x_187) + (* (- 30) x_192) + (* (- 36) x_197) + (* (- 24) x_202) + (* (- 30) x_207) + (* (- 24) x_212) + (* (- 30) x_217) + (* (- 36) x_222) + (* (- 42) x_227) + (* (- 48) x_232) + (* (- 54) x_237) + (* (- 60) x_242) + (* (- 66) x_247) + (* (- 24) x_252) + (* (- 30) x_257) + (* (- 36) x_262) + (* (- 42) x_267) + (* (- 48) x_272) + (* (- 54) x_277) + (* (- 60) x_282) + (* (- 24) x_287) + (* (- 30) x_292) + (* (- 36) x_297) + (* (- 42) x_302) + (* (- 48) x_307) + (* (- 54) x_312) + (* (- 60) x_317) + (* (- 66) x_322) + (* (- 24) x_327) + (* (- 30) x_332) + (* (- 36) x_337) + (* (- 42) x_342) + (* (- 48) x_347) + (* (- 54) x_352) + (* (- 60) x_357) + (* (- 24) x_362) + (* (- 30) x_367) + (* (- 36) x_372) + (* (- 42) x_377) + (* (- 48) x_382) + (* (- 54) x_387) + (* (- 60) x_392) + (* (- 24) x_397) + (* (- 30) x_402) + (* (- 36) x_407) + (* (- 24) x_412) + (* (- 30) x_417) + (* (- 36) x_422) + (* (- 42) x_427) + (* (- 48) x_432) + (* (- 54) x_437) + (* (- 60) x_442) + (* (- 66) x_447) + (* (- 72) x_452) + (* (- 78) x_457) + (* (- 24) x_462) + (* (- 30) x_467) + (* (- 36) x_472) + (* (- 42) x_477) + (* (- 48) x_482) + (* (- 54) x_487) + (* (- 24) x_492) + (* (- 24) x_497) + (* (- 30) x_502) + (* (- 36) x_507) + (* (- 42) x_512) + (* (- 48) x_517) + (* (- 54) x_522) + (* (- 24) x_527) + (* (- 30) x_532) + (* (- 36) x_537) + (* (- 24) x_542) + (* (- 30) x_547) + (* (- 36) x_552) + (* (- 42) x_557) + (* (- 24) x_562) + (* (- 30) x_567) + (* (- 36) x_572) + (* (- 42) x_577) + (* (- 48) x_582) + (* (- 54) x_587) + (* (- 24) x_592) + (* (- 24) x_597) + (* (- 30) x_602) + (* (- 36) x_607) + (* (- 42) x_612) + (* (- 48) x_617) + (* (- 24) x_622) + (* (- 30) x_627) + (* (- 36) x_632) + (* (- 42) x_637) + (* (- 48) x_642) + (* (- 54) x_647) + (* (- 60) x_652) + (* (- 66) x_657) + (* (- 24) x_662) + (* (- 30) x_667) + (* (- 36) x_672) + (* (- 42) x_677) + (* (- 24) x_682) + (* (- 30) x_687) + (* (- 36) x_692) + (* (- 42) x_697) + (* (- 48) x_702) + (* (- 54) x_707) + (* (- 60) x_712) + (* (- 66) x_717) + (* (- 72) x_722) + (* (- 24) x_727) + (* (- 30) x_732) + (* (- 36) x_737) + (* (- 42) x_742) + (* (- 48) x_747) + (* (- 54) x_752) + (* (- 60) x_757) + (* (- 66) x_762) + (* (- 24) x_767) + (* (- 30) x_772) + (* (- 24) x_777) + (* (- 30) x_782) + (* (- 24) x_787) + (* (- 30) x_792) + (* (- 36) x_797) + (* (- 42) x_802) + (* (- 48) x_807) + (* (- 54) x_812) + (* (- 60) x_817) + (* (- 24) x_822) + (* (- 30) x_827) + (* (- 36) x_832) + (* (- 42) x_837) + (* (- 48) x_842) + (* (- 54) x_847) + (* (- 60) x_852) + (* (- 66) x_857) + (* (- 24) x_862) + (* (- 30) x_867) + (* (- 36) x_872) + (* (- 42) x_877) + (* (- 48) x_882) + (* (- 54) x_887) + (* (- 24) x_892) + (* (- 30) x_897) + (* (- 36) x_902) + (* (- 42) x_907) + (* (- 48) x_912) + (* (- 54) x_917) + (* (- 60) x_922) + (* (- 36) x_927) + (* (- 36) x_932) + (* (- 45) x_937) + (* (- 36) x_942) + (* (- 36) x_947) + (* (- 45) x_952) + (* (- 36) x_957) + (* (- 45) x_962) + (* (- 36) x_967) + (* (- 45) x_972) + (* (- 54) x_977) + (* (- 63) x_982) + (* (- 72) x_987) + (* (- 81) x_992) + (* (- 90) x_997) + (* (- 24) x_2)))) +(assert (<= 0 + (+ (* 3960 x_1604) + (* (- 30) x_8) + (* (- 24) x_13) + (* (- 30) x_18) + (* (- 36) x_23) + (* (- 24) x_28) + (* (- 24) x_33) + (* (- 30) x_38) + (* (- 24) x_43) + (* (- 24) x_48) + (* (- 24) x_53) + (* (- 30) x_58) + (* (- 24) x_63) + (* (- 24) x_68) + (* (- 30) x_73) + (* (- 36) x_78) + (* (- 42) x_83) + (* (- 48) x_88) + (* (- 54) x_93) + (* (- 60) x_98) + (* (- 24) x_103) + (* (- 30) x_108) + (* (- 36) x_113) + (* (- 42) x_118) + (* (- 24) x_123) + (* (- 30) x_128) + (* (- 36) x_133) + (* (- 42) x_138) + (* (- 48) x_143) + (* (- 54) x_148) + (* (- 60) x_153) + (* (- 66) x_158) + (* (- 72) x_163) + (* (- 24) x_168) + (* (- 30) x_173) + (* (- 36) x_178) + (* (- 42) x_183) + (* (- 24) x_188) + (* (- 30) x_193) + (* (- 36) x_198) + (* (- 24) x_203) + (* (- 30) x_208) + (* (- 24) x_213) + (* (- 30) x_218) + (* (- 36) x_223) + (* (- 42) x_228) + (* (- 48) x_233) + (* (- 54) x_238) + (* (- 60) x_243) + (* (- 66) x_248) + (* (- 24) x_253) + (* (- 30) x_258) + (* (- 36) x_263) + (* (- 42) x_268) + (* (- 48) x_273) + (* (- 54) x_278) + (* (- 60) x_283) + (* (- 24) x_288) + (* (- 30) x_293) + (* (- 36) x_298) + (* (- 42) x_303) + (* (- 48) x_308) + (* (- 54) x_313) + (* (- 60) x_318) + (* (- 66) x_323) + (* (- 24) x_328) + (* (- 30) x_333) + (* (- 36) x_338) + (* (- 42) x_343) + (* (- 48) x_348) + (* (- 54) x_353) + (* (- 60) x_358) + (* (- 24) x_363) + (* (- 30) x_368) + (* (- 36) x_373) + (* (- 42) x_378) + (* (- 48) x_383) + (* (- 54) x_388) + (* (- 60) x_393) + (* (- 24) x_398) + (* (- 30) x_403) + (* (- 36) x_408) + (* (- 24) x_413) + (* (- 30) x_418) + (* (- 36) x_423) + (* (- 42) x_428) + (* (- 48) x_433) + (* (- 54) x_438) + (* (- 60) x_443) + (* (- 66) x_448) + (* (- 72) x_453) + (* (- 78) x_458) + (* (- 24) x_463) + (* (- 30) x_468) + (* (- 36) x_473) + (* (- 42) x_478) + (* (- 48) x_483) + (* (- 54) x_488) + (* (- 24) x_493) + (* (- 24) x_498) + (* (- 30) x_503) + (* (- 36) x_508) + (* (- 42) x_513) + (* (- 48) x_518) + (* (- 54) x_523) + (* (- 24) x_528) + (* (- 30) x_533) + (* (- 36) x_538) + (* (- 24) x_543) + (* (- 30) x_548) + (* (- 36) x_553) + (* (- 42) x_558) + (* (- 24) x_563) + (* (- 30) x_568) + (* (- 36) x_573) + (* (- 42) x_578) + (* (- 48) x_583) + (* (- 54) x_588) + (* (- 24) x_593) + (* (- 24) x_598) + (* (- 30) x_603) + (* (- 36) x_608) + (* (- 42) x_613) + (* (- 48) x_618) + (* (- 24) x_623) + (* (- 30) x_628) + (* (- 36) x_633) + (* (- 42) x_638) + (* (- 48) x_643) + (* (- 54) x_648) + (* (- 60) x_653) + (* (- 66) x_658) + (* (- 24) x_663) + (* (- 30) x_668) + (* (- 36) x_673) + (* (- 42) x_678) + (* (- 24) x_683) + (* (- 30) x_688) + (* (- 36) x_693) + (* (- 42) x_698) + (* (- 48) x_703) + (* (- 54) x_708) + (* (- 60) x_713) + (* (- 66) x_718) + (* (- 72) x_723) + (* (- 24) x_728) + (* (- 30) x_733) + (* (- 36) x_738) + (* (- 42) x_743) + (* (- 48) x_748) + (* (- 54) x_753) + (* (- 60) x_758) + (* (- 66) x_763) + (* (- 24) x_768) + (* (- 30) x_773) + (* (- 24) x_778) + (* (- 30) x_783) + (* (- 24) x_788) + (* (- 30) x_793) + (* (- 36) x_798) + (* (- 42) x_803) + (* (- 48) x_808) + (* (- 54) x_813) + (* (- 60) x_818) + (* (- 24) x_823) + (* (- 30) x_828) + (* (- 36) x_833) + (* (- 42) x_838) + (* (- 48) x_843) + (* (- 54) x_848) + (* (- 60) x_853) + (* (- 66) x_858) + (* (- 24) x_863) + (* (- 30) x_868) + (* (- 36) x_873) + (* (- 42) x_878) + (* (- 48) x_883) + (* (- 54) x_888) + (* (- 24) x_893) + (* (- 30) x_898) + (* (- 36) x_903) + (* (- 42) x_908) + (* (- 48) x_913) + (* (- 54) x_918) + (* (- 60) x_923) + (* (- 36) x_928) + (* (- 36) x_933) + (* (- 45) x_938) + (* (- 36) x_943) + (* (- 36) x_948) + (* (- 45) x_953) + (* (- 36) x_958) + (* (- 45) x_963) + (* (- 36) x_968) + (* (- 45) x_973) + (* (- 54) x_978) + (* (- 63) x_983) + (* (- 72) x_988) + (* (- 81) x_993) + (* (- 90) x_998) + (* (- 24) x_3)))) + +(assert (= x_1202 1)) +(assert (= x_1403 1)) +(assert (= x_1604 0)) +(assert (= x_1001 0)) + +;(minimize (+ x_1202 x_1403 x_1604 x_1001)) +(minimize (+ (* 2 x_1) + (* 3 x_2) + (* 4 x_3) + x_9 + (* 2 x_6) + (* 3 x_7) + (* 4 x_8) + x_14 + (* 2 x_11) + (* 3 x_12) + (* 4 x_13) + x_19 + (* 2 x_16) + (* 3 x_17) + (* 4 x_18) + x_24 + (* 2 x_21) + (* 3 x_22) + (* 4 x_23) + x_29 + (* 2 x_26) + (* 3 x_27) + (* 4 x_28) + x_34 + (* 2 x_31) + (* 3 x_32) + (* 4 x_33) + x_39 + (* 2 x_36) + (* 3 x_37) + (* 4 x_38) + x_44 + (* 2 x_41) + (* 3 x_42) + (* 4 x_43) + x_49 + (* 2 x_46) + (* 3 x_47) + (* 4 x_48) + x_54 + (* 2 x_51) + (* 3 x_52) + (* 4 x_53) + x_59 + (* 2 x_56) + (* 3 x_57) + (* 4 x_58) + x_64 + (* 2 x_61) + (* 3 x_62) + (* 4 x_63) + x_69 + (* 2 x_66) + (* 3 x_67) + (* 4 x_68) + x_74 + (* 2 x_71) + (* 3 x_72) + (* 4 x_73) + x_79 + (* 2 x_76) + (* 3 x_77) + (* 4 x_78) + x_84 + (* 2 x_81) + (* 3 x_82) + (* 4 x_83) + x_89 + (* 2 x_86) + (* 3 x_87) + (* 4 x_88) + x_94 + (* 2 x_91) + (* 3 x_92) + (* 4 x_93) + x_99 + (* 2 x_96) + (* 3 x_97) + (* 4 x_98) + x_104 + (* 2 x_101) + (* 3 x_102) + (* 4 x_103) + x_109 + (* 2 x_106) + (* 3 x_107) + (* 4 x_108) + x_114 + (* 2 x_111) + (* 3 x_112) + (* 4 x_113) + x_119 + (* 2 x_116) + (* 3 x_117) + (* 4 x_118) + x_124 + (* 2 x_121) + (* 3 x_122) + (* 4 x_123) + x_129 + (* 2 x_126) + (* 3 x_127) + (* 4 x_128) + x_134 + (* 2 x_131) + (* 3 x_132) + (* 4 x_133) + x_139 + (* 2 x_136) + (* 3 x_137) + (* 4 x_138) + x_144 + (* 2 x_141) + (* 3 x_142) + (* 4 x_143) + x_149 + (* 2 x_146) + (* 3 x_147) + (* 4 x_148) + x_154 + (* 2 x_151) + (* 3 x_152) + (* 4 x_153) + x_159 + (* 2 x_156) + (* 3 x_157) + (* 4 x_158) + x_164 + (* 2 x_161) + (* 3 x_162) + (* 4 x_163) + x_169 + (* 2 x_166) + (* 3 x_167) + (* 4 x_168) + x_174 + (* 2 x_171) + (* 3 x_172) + (* 4 x_173) + x_179 + (* 2 x_176) + (* 3 x_177) + (* 4 x_178) + x_184 + (* 2 x_181) + (* 3 x_182) + (* 4 x_183) + x_189 + (* 2 x_186) + (* 3 x_187) + (* 4 x_188) + x_194 + (* 2 x_191) + (* 3 x_192) + (* 4 x_193) + x_199 + (* 2 x_196) + (* 3 x_197) + (* 4 x_198) + x_204 + (* 2 x_201) + (* 3 x_202) + (* 4 x_203) + x_209 + (* 2 x_206) + (* 3 x_207) + (* 4 x_208) + x_214 + (* 2 x_211) + (* 3 x_212) + (* 4 x_213) + x_219 + (* 2 x_216) + (* 3 x_217) + (* 4 x_218) + x_224 + (* 2 x_221) + (* 3 x_222) + (* 4 x_223) + x_229 + (* 2 x_226) + (* 3 x_227) + (* 4 x_228) + x_234 + (* 2 x_231) + (* 3 x_232) + (* 4 x_233) + x_239 + (* 2 x_236) + (* 3 x_237) + (* 4 x_238) + x_244 + (* 2 x_241) + (* 3 x_242) + (* 4 x_243) + x_249 + (* 2 x_246) + (* 3 x_247) + (* 4 x_248) + x_254 + (* 2 x_251) + (* 3 x_252) + (* 4 x_253) + x_259 + (* 2 x_256) + (* 3 x_257) + (* 4 x_258) + x_264 + (* 2 x_261) + (* 3 x_262) + (* 4 x_263) + x_269 + (* 2 x_266) + (* 3 x_267) + (* 4 x_268) + x_274 + (* 2 x_271) + (* 3 x_272) + (* 4 x_273) + x_279 + (* 2 x_276) + (* 3 x_277) + (* 4 x_278) + x_284 + (* 2 x_281) + (* 3 x_282) + (* 4 x_283) + x_289 + (* 2 x_286) + (* 3 x_287) + (* 4 x_288) + x_294 + (* 2 x_291) + (* 3 x_292) + (* 4 x_293) + x_299 + (* 2 x_296) + (* 3 x_297) + (* 4 x_298) + x_304 + (* 2 x_301) + (* 3 x_302) + (* 4 x_303) + x_309 + (* 2 x_306) + (* 3 x_307) + (* 4 x_308) + x_314 + (* 2 x_311) + (* 3 x_312) + (* 4 x_313) + x_319 + (* 2 x_316) + (* 3 x_317) + (* 4 x_318) + x_324 + (* 2 x_321) + (* 3 x_322) + (* 4 x_323) + x_329 + (* 2 x_326) + (* 3 x_327) + (* 4 x_328) + x_334 + (* 2 x_331) + (* 3 x_332) + (* 4 x_333) + x_339 + (* 2 x_336) + (* 3 x_337) + (* 4 x_338) + x_344 + (* 2 x_341) + (* 3 x_342) + (* 4 x_343) + x_349 + (* 2 x_346) + (* 3 x_347) + (* 4 x_348) + x_354 + (* 2 x_351) + (* 3 x_352) + (* 4 x_353) + x_359 + (* 2 x_356) + (* 3 x_357) + (* 4 x_358) + x_364 + (* 2 x_361) + (* 3 x_362) + (* 4 x_363) + x_369 + (* 2 x_366) + (* 3 x_367) + (* 4 x_368) + x_374 + (* 2 x_371) + (* 3 x_372) + (* 4 x_373) + x_379 + (* 2 x_376) + (* 3 x_377) + (* 4 x_378) + x_384 + (* 2 x_381) + (* 3 x_382) + (* 4 x_383) + x_389 + (* 2 x_386) + (* 3 x_387) + (* 4 x_388) + x_394 + (* 2 x_391) + (* 3 x_392) + (* 4 x_393) + x_399 + (* 2 x_396) + (* 3 x_397) + (* 4 x_398) + x_404 + (* 2 x_401) + (* 3 x_402) + (* 4 x_403) + x_409 + (* 2 x_406) + (* 3 x_407) + (* 4 x_408) + x_414 + (* 2 x_411) + (* 3 x_412) + (* 4 x_413) + x_419 + (* 2 x_416) + (* 3 x_417) + (* 4 x_418) + x_424 + (* 2 x_421) + (* 3 x_422) + (* 4 x_423) + x_429 + (* 2 x_426) + (* 3 x_427) + (* 4 x_428) + x_434 + (* 2 x_431) + (* 3 x_432) + (* 4 x_433) + x_439 + (* 2 x_436) + (* 3 x_437) + (* 4 x_438) + x_444 + (* 2 x_441) + (* 3 x_442) + (* 4 x_443) + x_449 + (* 2 x_446) + (* 3 x_447) + (* 4 x_448) + x_454 + (* 2 x_451) + (* 3 x_452) + (* 4 x_453) + x_459 + (* 2 x_456) + (* 3 x_457) + (* 4 x_458) + x_464 + (* 2 x_461) + (* 3 x_462) + (* 4 x_463) + x_469 + (* 2 x_466) + (* 3 x_467) + (* 4 x_468) + x_474 + (* 2 x_471) + (* 3 x_472) + (* 4 x_473) + x_479 + (* 2 x_476) + (* 3 x_477) + (* 4 x_478) + x_484 + (* 2 x_481) + (* 3 x_482) + (* 4 x_483) + x_489 + (* 2 x_486) + (* 3 x_487) + (* 4 x_488) + x_494 + (* 2 x_491) + (* 3 x_492) + (* 4 x_493) + x_499 + (* 2 x_496) + (* 3 x_497) + (* 4 x_498) + x_504 + (* 2 x_501) + (* 3 x_502) + (* 4 x_503) + x_509 + (* 2 x_506) + (* 3 x_507) + (* 4 x_508) + x_514 + (* 2 x_511) + (* 3 x_512) + (* 4 x_513) + x_519 + (* 2 x_516) + (* 3 x_517) + (* 4 x_518) + x_524 + (* 2 x_521) + (* 3 x_522) + (* 4 x_523) + x_529 + (* 2 x_526) + (* 3 x_527) + (* 4 x_528) + x_534 + (* 2 x_531) + (* 3 x_532) + (* 4 x_533) + x_539 + (* 2 x_536) + (* 3 x_537) + (* 4 x_538) + x_544 + (* 2 x_541) + (* 3 x_542) + (* 4 x_543) + x_549 + (* 2 x_546) + (* 3 x_547) + (* 4 x_548) + x_554 + (* 2 x_551) + (* 3 x_552) + (* 4 x_553) + x_559 + (* 2 x_556) + (* 3 x_557) + (* 4 x_558) + x_564 + (* 2 x_561) + (* 3 x_562) + (* 4 x_563) + x_569 + (* 2 x_566) + (* 3 x_567) + (* 4 x_568) + x_574 + (* 2 x_571) + (* 3 x_572) + (* 4 x_573) + x_579 + (* 2 x_576) + (* 3 x_577) + (* 4 x_578) + x_584 + (* 2 x_581) + (* 3 x_582) + (* 4 x_583) + x_589 + (* 2 x_586) + (* 3 x_587) + (* 4 x_588) + x_594 + (* 2 x_591) + (* 3 x_592) + (* 4 x_593) + x_599 + (* 2 x_596) + (* 3 x_597) + (* 4 x_598) + x_604 + (* 2 x_601) + (* 3 x_602) + (* 4 x_603) + x_609 + (* 2 x_606) + (* 3 x_607) + (* 4 x_608) + x_614 + (* 2 x_611) + (* 3 x_612) + (* 4 x_613) + x_619 + (* 2 x_616) + (* 3 x_617) + (* 4 x_618) + x_624 + (* 2 x_621) + (* 3 x_622) + (* 4 x_623) + x_629 + (* 2 x_626) + (* 3 x_627) + (* 4 x_628) + x_634 + (* 2 x_631) + (* 3 x_632) + (* 4 x_633) + x_639 + (* 2 x_636) + (* 3 x_637) + (* 4 x_638) + x_644 + (* 2 x_641) + (* 3 x_642) + (* 4 x_643) + x_649 + (* 2 x_646) + (* 3 x_647) + (* 4 x_648) + x_654 + (* 2 x_651) + (* 3 x_652) + (* 4 x_653) + x_659 + (* 2 x_656) + (* 3 x_657) + (* 4 x_658) + x_664 + (* 2 x_661) + (* 3 x_662) + (* 4 x_663) + x_669 + (* 2 x_666) + (* 3 x_667) + (* 4 x_668) + x_674 + (* 2 x_671) + (* 3 x_672) + (* 4 x_673) + x_679 + (* 2 x_676) + (* 3 x_677) + (* 4 x_678) + x_684 + (* 2 x_681) + (* 3 x_682) + (* 4 x_683) + x_689 + (* 2 x_686) + (* 3 x_687) + (* 4 x_688) + x_694 + (* 2 x_691) + (* 3 x_692) + (* 4 x_693) + x_699 + (* 2 x_696) + (* 3 x_697) + (* 4 x_698) + x_704 + (* 2 x_701) + (* 3 x_702) + (* 4 x_703) + x_709 + (* 2 x_706) + (* 3 x_707) + (* 4 x_708) + x_714 + (* 2 x_711) + (* 3 x_712) + (* 4 x_713) + x_719 + (* 2 x_716) + (* 3 x_717) + (* 4 x_718) + x_724 + (* 2 x_721) + (* 3 x_722) + (* 4 x_723) + x_729 + (* 2 x_726) + (* 3 x_727) + (* 4 x_728) + x_734 + (* 2 x_731) + (* 3 x_732) + (* 4 x_733) + x_739 + (* 2 x_736) + (* 3 x_737) + (* 4 x_738) + x_744 + (* 2 x_741) + (* 3 x_742) + (* 4 x_743) + x_749 + (* 2 x_746) + (* 3 x_747) + (* 4 x_748) + x_754 + (* 2 x_751) + (* 3 x_752) + (* 4 x_753) + x_759 + (* 2 x_756) + (* 3 x_757) + (* 4 x_758) + x_764 + (* 2 x_761) + (* 3 x_762) + (* 4 x_763) + x_769 + (* 2 x_766) + (* 3 x_767) + (* 4 x_768) + x_774 + (* 2 x_771) + (* 3 x_772) + (* 4 x_773) + x_779 + (* 2 x_776) + (* 3 x_777) + (* 4 x_778) + x_784 + (* 2 x_781) + (* 3 x_782) + (* 4 x_783) + x_789 + (* 2 x_786) + (* 3 x_787) + (* 4 x_788) + x_794 + (* 2 x_791) + (* 3 x_792) + (* 4 x_793) + x_799 + (* 2 x_796) + (* 3 x_797) + (* 4 x_798) + x_804 + (* 2 x_801) + (* 3 x_802) + (* 4 x_803) + x_809 + (* 2 x_806) + (* 3 x_807) + (* 4 x_808) + x_814 + (* 2 x_811) + (* 3 x_812) + (* 4 x_813) + x_819 + (* 2 x_816) + (* 3 x_817) + (* 4 x_818) + x_824 + (* 2 x_821) + (* 3 x_822) + (* 4 x_823) + x_829 + (* 2 x_826) + (* 3 x_827) + (* 4 x_828) + x_834 + (* 2 x_831) + (* 3 x_832) + (* 4 x_833) + x_839 + (* 2 x_836) + (* 3 x_837) + (* 4 x_838) + x_844 + (* 2 x_841) + (* 3 x_842) + (* 4 x_843) + x_849 + (* 2 x_846) + (* 3 x_847) + (* 4 x_848) + x_854 + (* 2 x_851) + (* 3 x_852) + (* 4 x_853) + x_859 + (* 2 x_856) + (* 3 x_857) + (* 4 x_858) + x_864 + (* 2 x_861) + (* 3 x_862) + (* 4 x_863) + x_869 + (* 2 x_866) + (* 3 x_867) + (* 4 x_868) + x_874 + (* 2 x_871) + (* 3 x_872) + (* 4 x_873) + x_879 + (* 2 x_876) + (* 3 x_877) + (* 4 x_878) + x_884 + (* 2 x_881) + (* 3 x_882) + (* 4 x_883) + x_889 + (* 2 x_886) + (* 3 x_887) + (* 4 x_888) + x_894 + (* 2 x_891) + (* 3 x_892) + (* 4 x_893) + x_899 + (* 2 x_896) + (* 3 x_897) + (* 4 x_898) + x_904 + (* 2 x_901) + (* 3 x_902) + (* 4 x_903) + x_909 + (* 2 x_906) + (* 3 x_907) + (* 4 x_908) + x_914 + (* 2 x_911) + (* 3 x_912) + (* 4 x_913) + x_919 + (* 2 x_916) + (* 3 x_917) + (* 4 x_918) + x_924 + (* 2 x_921) + (* 3 x_922) + (* 4 x_923) + x_929 + (* 2 x_926) + (* 3 x_927) + (* 4 x_928) + x_934 + (* 2 x_931) + (* 3 x_932) + (* 4 x_933) + x_939 + (* 2 x_936) + (* 3 x_937) + (* 4 x_938) + x_944 + (* 2 x_941) + (* 3 x_942) + (* 4 x_943) + x_949 + (* 2 x_946) + (* 3 x_947) + (* 4 x_948) + x_954 + (* 2 x_951) + (* 3 x_952) + (* 4 x_953) + x_959 + (* 2 x_956) + (* 3 x_957) + (* 4 x_958) + x_964 + (* 2 x_961) + (* 3 x_962) + (* 4 x_963) + x_969 + (* 2 x_966) + (* 3 x_967) + (* 4 x_968) + x_974 + (* 2 x_971) + (* 3 x_972) + (* 4 x_973) + x_979 + (* 2 x_976) + (* 3 x_977) + (* 4 x_978) + x_984 + (* 2 x_981) + (* 3 x_982) + (* 4 x_983) + x_989 + (* 2 x_986) + (* 3 x_987) + (* 4 x_988) + x_994 + (* 2 x_991) + (* 3 x_992) + (* 4 x_993) + x_999 + (* 2 x_996) + (* 3 x_997) + (* 4 x_998) + x_4 + (* 100 x_1202) + (* 100 x_1403) + (* 100 x_1604) + (* 100 x_1001))) +(optimize :print_statistics true + :wmaxsat_engine wmax + :maxsat_engine weighted_maxsat)