mirror of
https://github.com/Z3Prover/z3
synced 2025-04-27 02:45:51 +00:00
Merge branch 'opt' of https://git01.codeplex.com/z3 into opt
This commit is contained in:
commit
f020b7c7b8
380 changed files with 66767 additions and 3722 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -18,6 +18,7 @@ ocamlz3
|
|||
# Emacs temp files
|
||||
\#*\#
|
||||
# Directories with generated code and documentation
|
||||
release/*
|
||||
build/*
|
||||
build-dist/*
|
||||
dist/*
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
RELEASE NOTES
|
||||
|
||||
Version 4.3.3
|
||||
=============
|
||||
|
||||
- Fixed bug in floating point models
|
||||
|
||||
Version 4.3.2
|
||||
=============
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
20
examples/msf/README
Normal file
20
examples/msf/README
Normal file
|
@ -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!
|
||||
|
||||
|
||||
|
||||
|
||||
|
60
examples/msf/SolverFoundation.Plugin.Z3.Tests/App.config
Normal file
60
examples/msf/SolverFoundation.Plugin.Z3.Tests/App.config
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="MsfConfig"
|
||||
type="Microsoft.SolverFoundation.Services.MsfConfigSection, Microsoft.Solver.Foundation"
|
||||
allowLocation="true"
|
||||
allowDefinition="Everywhere"
|
||||
allowExeDefinition="MachineToApplication"
|
||||
restartOnExternalChanges="true"
|
||||
requirePermission="true"/>
|
||||
</configSections>
|
||||
<MsfConfig>
|
||||
<MsfPluginSolvers>
|
||||
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
|
||||
capability="MILP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
|
||||
capability="LP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
|
||||
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="MILP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="LP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="MINLP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="NLP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
</MsfPluginSolvers>
|
||||
</MsfConfig>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
||||
</startup>
|
||||
</configuration>
|
|
@ -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")]
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{280AEE2F-1FDB-4A27-BE37-14DC154C873B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.SolverFoundation.Plugin.Z3.Tests</RootNamespace>
|
||||
<AssemblyName>SolverFoundation.Plugin.Z3.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Solver.Foundation">
|
||||
<HintPath>..\Microsoft.Solver.Foundation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ServiceTests.cs" />
|
||||
<Compile Include="SolverTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SolverFoundation.Plugin.Z3\SolverFoundation.Plugin.Z3.csproj">
|
||||
<Project>{7340e664-f648-4ff7-89b2-f4da424996d3}</Project>
|
||||
<Name>SolverFoundation.Plugin.Z3</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
132
examples/msf/SolverFoundation.Plugin.Z3.Tests/SolverTests.cs
Normal file
132
examples/msf/SolverFoundation.Plugin.Z3.Tests/SolverTests.cs
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
92
examples/msf/SolverFoundation.Plugin.Z3/AbortWorker.cs
Normal file
92
examples/msf/SolverFoundation.Plugin.Z3/AbortWorker.cs
Normal file
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
internal class AbortWorker
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
/// <summary>The Z3 solver</summary>
|
||||
private Microsoft.Z3.Context _context;
|
||||
/// <summary>The abort function to use to check if we are aborted</summary>
|
||||
private Func<bool> _QueryAbortFunction;
|
||||
/// <summary>Flag indicating that worker should stop</summary>
|
||||
private bool _stop = false;
|
||||
/// <summary>Flag indicating that we have been sent an abort signal</summary>
|
||||
private bool _aborted = false;
|
||||
|
||||
#endregion Private Members
|
||||
|
||||
#region Construction
|
||||
|
||||
/// <summary>
|
||||
/// Worker constructor taking a Z3 instance and a function to periodically
|
||||
/// check for aborts.
|
||||
/// </summary>
|
||||
/// <param name="z3">Z3 instance</param>
|
||||
/// <param name="queryAbortFunction">method to call to check for aborts</param>
|
||||
public AbortWorker(Context context, Func<bool> queryAbortFunction)
|
||||
{
|
||||
_context = context;
|
||||
_QueryAbortFunction = queryAbortFunction;
|
||||
}
|
||||
|
||||
#endregion Construction
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Stop the abort worker.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
_stop = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is true if we have been aborted.
|
||||
/// </summary>
|
||||
public bool Aborted
|
||||
{
|
||||
get
|
||||
{
|
||||
return _aborted;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
}
|
60
examples/msf/SolverFoundation.Plugin.Z3/App.config
Normal file
60
examples/msf/SolverFoundation.Plugin.Z3/App.config
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="MsfConfig"
|
||||
type="Microsoft.SolverFoundation.Services.MsfConfigSection, Microsoft.Solver.Foundation"
|
||||
allowLocation="true"
|
||||
allowDefinition="Everywhere"
|
||||
allowExeDefinition="MachineToApplication"
|
||||
restartOnExternalChanges="true"
|
||||
requirePermission="true"/>
|
||||
</configSections>
|
||||
<MsfConfig>
|
||||
<MsfPluginSolvers>
|
||||
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
|
||||
capability="MILP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
|
||||
capability="LP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
|
||||
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="MILP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="LP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="MINLP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="NLP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
</MsfPluginSolvers>
|
||||
</MsfConfig>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
||||
</startup>
|
||||
</configuration>
|
|
@ -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")]
|
|
@ -0,0 +1,149 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{7340E664-F648-4FF7-89B2-F4DA424996D3}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.SolverFoundation.Plugin.Z3</RootNamespace>
|
||||
<AssemblyName>SolverFoundation.Plugin.Z3</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'commercial|AnyCPU'">
|
||||
<OutputPath>bin\commercial\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'commercial_64|AnyCPU'">
|
||||
<OutputPath>bin\commercial_64\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'commercial|x86'">
|
||||
<OutputPath>bin\x86\commercial\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'commercial_64|x86'">
|
||||
<OutputPath>bin\x86\commercial_64\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Solver.Foundation">
|
||||
<HintPath>..\Microsoft.Solver.Foundation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Z3, Version=4.3.2.0, Culture=neutral, processorArchitecture=x86">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Microsoft.Z3.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
</Reference>
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Xml.Linq">
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AbortWorker.cs" />
|
||||
<Compile Include="Utils.cs" />
|
||||
<Compile Include="Z3BaseDirective.cs" />
|
||||
<Compile Include="Z3BaseParams.cs" />
|
||||
<Compile Include="Z3BaseSolver.cs" />
|
||||
<Compile Include="Z3MILPDirective.cs" />
|
||||
<Compile Include="Z3MILPParams.cs" />
|
||||
<Compile Include="Z3MILPSolver.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Z3TermDirective.cs" />
|
||||
<Compile Include="Z3TermParams.cs" />
|
||||
<Compile Include="Z3TermSolver.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
124
examples/msf/SolverFoundation.Plugin.Z3/Utils.cs
Normal file
124
examples/msf/SolverFoundation.Plugin.Z3/Utils.cs
Normal file
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the Z3 term corresponding to the MSF rational number.
|
||||
/// </summary>
|
||||
/// <param name="rational">The MSF rational</param>
|
||||
/// <returns>The Z3 term</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
101
examples/msf/SolverFoundation.Plugin.Z3/Z3BaseDirective.cs
Normal file
101
examples/msf/SolverFoundation.Plugin.Z3/Z3BaseDirective.cs
Normal file
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using Microsoft.SolverFoundation.Services;
|
||||
|
||||
namespace Microsoft.SolverFoundation.Plugin.Z3
|
||||
{
|
||||
/// <summary>
|
||||
/// Combining objective functions
|
||||
/// </summary>
|
||||
public enum OptimizationKind
|
||||
{
|
||||
Lexicographic,
|
||||
BoundingBox,
|
||||
ParetoOptimal
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Algorithm for solving cardinality constraints
|
||||
/// </summary>
|
||||
public enum CardinalityAlgorithm
|
||||
{
|
||||
FuMalik,
|
||||
CoreMaxSAT
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Algorithm for solving pseudo-boolean constraints
|
||||
/// </summary>
|
||||
public enum PseudoBooleanAlgorithm
|
||||
{
|
||||
WeightedMaxSAT,
|
||||
IterativeWeightedMaxSAT,
|
||||
BisectionWeightedMaxSAT,
|
||||
WeightedPartialMaxSAT2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Strategy for solving arithmetic optimization
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
103
examples/msf/SolverFoundation.Plugin.Z3/Z3BaseParams.cs
Normal file
103
examples/msf/SolverFoundation.Plugin.Z3/Z3BaseParams.cs
Normal file
|
@ -0,0 +1,103 @@
|
|||
using Microsoft.SolverFoundation.Services;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.SolverFoundation.Plugin.Z3
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of the solver parameters for Z3
|
||||
/// </summary>
|
||||
public class Z3BaseParams : ISolverParameters
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
/// <summary>The abort method we can call (defaults to always false)
|
||||
protected Func<bool> _queryAbortFunction = delegate() { return false; };
|
||||
|
||||
/// <summary>The directive to use</summary>
|
||||
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<bool> queryAbortFunction)
|
||||
{
|
||||
_queryAbortFunction = queryAbortFunction;
|
||||
}
|
||||
|
||||
public Z3BaseParams(Z3BaseParams z3Parameters)
|
||||
{
|
||||
_queryAbortFunction = z3Parameters._queryAbortFunction;
|
||||
}
|
||||
|
||||
#endregion Construction
|
||||
|
||||
#region ISolverParameters Members
|
||||
|
||||
/// <summary>
|
||||
/// Getter for the abort method
|
||||
/// </summary>
|
||||
public Func<bool> 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
|
||||
}
|
||||
|
||||
}
|
381
examples/msf/SolverFoundation.Plugin.Z3/Z3BaseSolver.cs
Normal file
381
examples/msf/SolverFoundation.Plugin.Z3/Z3BaseSolver.cs
Normal file
|
@ -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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The basic solver class to take care of transformation from an MSF instance to an Z3 instance
|
||||
/// </summary>
|
||||
internal class Z3BaseSolver
|
||||
{
|
||||
/// <summary>Representing MSF model</summary>
|
||||
private IRowVariableModel _model;
|
||||
|
||||
/// <summary>The Z3 solver we are currently using</summary>
|
||||
private Context _context = null;
|
||||
|
||||
/// <summary>Default optimization solver</summary>
|
||||
private Optimize _optSolver = null;
|
||||
|
||||
/// <summary>Marks when we are inside the Solve() method</summary>
|
||||
private bool _isSolving = false;
|
||||
|
||||
/// <summary>A map from MSF variable ids to Z3 variables</summary>
|
||||
private Dictionary<int, Expr> _variables = new Dictionary<int, Expr>();
|
||||
|
||||
/// <summary>A map from MSF variable ids to Z3 goal ids</summary>
|
||||
private Dictionary<IGoal, uint> _goals = new Dictionary<IGoal, uint>();
|
||||
|
||||
internal Z3BaseSolver(IRowVariableModel model)
|
||||
{
|
||||
_model = model;
|
||||
}
|
||||
|
||||
internal Context Context
|
||||
{
|
||||
get { return _context; }
|
||||
}
|
||||
|
||||
internal Dictionary<int, Expr> Variables
|
||||
{
|
||||
get { return _variables; }
|
||||
}
|
||||
|
||||
internal Dictionary<IGoal, uint> Goals
|
||||
{
|
||||
get { return _goals; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructs a currently active Z3 solver and the associated data.
|
||||
/// </summary>
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a Z3 solver to be used.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a MSF variable with the coresponding assertion to the Z3 variables.
|
||||
/// </summary>
|
||||
/// <param name="vid">The MSF id of the variable</param>
|
||||
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<IGoal> modelGoals,
|
||||
Action<int> addRow, Func<int, ArithExpr> mkGoalRow, Action<Z3Result> 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<int, Expr> 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<int, Expr> 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using Microsoft.SolverFoundation.Services;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.SolverFoundation.Plugin.Z3
|
||||
{
|
||||
public class Z3MILPDirective : Z3BaseDirective
|
||||
{
|
||||
}
|
||||
}
|
19
examples/msf/SolverFoundation.Plugin.Z3/Z3MILPParams.cs
Normal file
19
examples/msf/SolverFoundation.Plugin.Z3/Z3MILPParams.cs
Normal file
|
@ -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<bool> queryAbortFunction) : base(queryAbortFunction) { }
|
||||
|
||||
public Z3MILPParams(Z3BaseParams z3Parameters) : base (z3Parameters) { }
|
||||
}
|
||||
|
||||
}
|
230
examples/msf/SolverFoundation.Plugin.Z3/Z3MILPSolver.cs
Normal file
230
examples/msf/SolverFoundation.Plugin.Z3/Z3MILPSolver.cs
Normal file
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// The class is implementation of the MSF mixed linear programming solver
|
||||
/// using the Microsoft Z3 solver as the backend.
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>Constructor that initializes the base clases</summary>
|
||||
public Z3MILPSolver() : base(null)
|
||||
{
|
||||
_result = LinearResult.Feasible;
|
||||
_solver = new Z3BaseSolver(this);
|
||||
}
|
||||
|
||||
/// <summary>Constructor that initializes the base clases</summary>
|
||||
public Z3MILPSolver(ISolverEnvironment context) : this() { }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Get corresponding Z3 formula of a MSF row.
|
||||
/// </summary>
|
||||
/// <param name="rid">The MSF row id</param>
|
||||
private ArithExpr MkGoalRow(int rid)
|
||||
{
|
||||
// Start with the 0 term
|
||||
List<ArithExpr> row = new List<ArithExpr>();
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a MSF row to the Z3 assertions.
|
||||
/// </summary>
|
||||
/// <param name="rid">The MSF row id</param>
|
||||
private void AddRow(int rid)
|
||||
{
|
||||
// Start with the 0 term
|
||||
ArithExpr row = MkGoalRow(rid);
|
||||
_solver.AssertArith(rid, row);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set results based on internal solver status
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Starts solving the problem using the Z3 solver.
|
||||
/// </summary>
|
||||
/// <param name="parameters">Parameters to the solver</param>
|
||||
/// <returns>The solution to the problem</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class implementing the LinearReport.
|
||||
/// </summary>
|
||||
public class Z3LinearSolverReport : LinearReport
|
||||
{
|
||||
public Z3LinearSolverReport(SolverContext context, ISolver solver, Solution solution, LinearSolutionMapping solutionMapping)
|
||||
: base(context, solver, solution, solutionMapping) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using Microsoft.SolverFoundation.Services;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.SolverFoundation.Plugin.Z3
|
||||
{
|
||||
public class Z3TermDirective : Z3BaseDirective
|
||||
{
|
||||
}
|
||||
}
|
17
examples/msf/SolverFoundation.Plugin.Z3/Z3TermParams.cs
Normal file
17
examples/msf/SolverFoundation.Plugin.Z3/Z3TermParams.cs
Normal file
|
@ -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<bool> queryAbortFunction) : base(queryAbortFunction) { }
|
||||
|
||||
public Z3TermParams(Z3BaseParams z3Parameters) : base(z3Parameters) { }
|
||||
}
|
||||
|
||||
}
|
382
examples/msf/SolverFoundation.Plugin.Z3/Z3TermSolver.cs
Normal file
382
examples/msf/SolverFoundation.Plugin.Z3/Z3TermSolver.cs
Normal file
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public class Z3TermSolver : TermModel, ITermSolver, INonlinearSolution, IReportProvider
|
||||
{
|
||||
private NonlinearResult _result;
|
||||
private Z3BaseSolver _solver;
|
||||
|
||||
/// <summary>Constructor that initializes the base clases</summary>
|
||||
public Z3TermSolver() : base(null)
|
||||
{
|
||||
_solver = new Z3BaseSolver(this);
|
||||
}
|
||||
|
||||
/// <summary>Constructor that initializes the base clases</summary>
|
||||
public Z3TermSolver(ISolverEnvironment context) : this() { }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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<ArithExpr, ArithExpr, BoolExpr> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a MSF row to the Z3 assertions.
|
||||
/// </summary>
|
||||
/// <param name="rid">The MSF row id</param>
|
||||
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 };
|
||||
|
||||
/// <summary>
|
||||
/// Gets the operations supported by the solver.
|
||||
/// </summary>
|
||||
/// <returns>All the TermModelOperations supported by the solver.</returns>
|
||||
public IEnumerable<TermModelOperation> SupportedOperations
|
||||
{
|
||||
get { return _supportedOperations; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set results based on internal solver status
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts solving the problem using the Z3 solver.
|
||||
/// </summary>
|
||||
/// <param name="parameters">Parameters to the solver</param>
|
||||
/// <returns>The solution to the problem</returns>
|
||||
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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
60
examples/msf/Validator/App.config
Normal file
60
examples/msf/Validator/App.config
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="MsfConfig"
|
||||
type="Microsoft.SolverFoundation.Services.MsfConfigSection, Microsoft.Solver.Foundation"
|
||||
allowLocation="true"
|
||||
allowDefinition="Everywhere"
|
||||
allowExeDefinition="MachineToApplication"
|
||||
restartOnExternalChanges="true"
|
||||
requirePermission="true"/>
|
||||
</configSections>
|
||||
<MsfConfig>
|
||||
<MsfPluginSolvers>
|
||||
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
|
||||
capability="MILP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
|
||||
capability="LP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
|
||||
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="MILP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="LP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="MINLP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="NLP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
</MsfPluginSolvers>
|
||||
</MsfConfig>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
||||
</startup>
|
||||
</configuration>
|
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section
|
||||
name="MsfConfig"
|
||||
type="Microsoft.SolverFoundation.Services.MsfConfigSection, Microsoft.Solver.Foundation"
|
||||
allowLocation="true"
|
||||
allowDefinition="Everywhere"
|
||||
allowExeDefinition="MachineToApplication"
|
||||
restartOnExternalChanges="true"
|
||||
requirePermission="true" />
|
||||
</configSections>
|
||||
<MsfConfig>
|
||||
<MsfPluginSolvers>
|
||||
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
|
||||
capability="MILP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
|
||||
capability="LP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
|
||||
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="MILP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="LP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="MINLP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
<MsfPluginSolver name="Microsoft Z3 Term Solver"
|
||||
capability="NLP"
|
||||
assembly="SolverFoundation.Plugin.Z3.dll"
|
||||
interface="Microsoft.SolverFoundation.Services.ITermSolver"
|
||||
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
|
||||
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
|
||||
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
|
||||
</MsfPluginSolvers>
|
||||
</MsfConfig>
|
||||
</configuration>
|
194
examples/msf/Validator/Program.cs
Normal file
194
examples/msf/Validator/Program.cs
Normal file
|
@ -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 <file_name> : solving the model using Z3
|
||||
-convert <file_name> : converting the model into SMT2 format
|
||||
-validate <file_name> : validating by comparing results between Z3 and MSF solvers
|
||||
-term : change the default Z3 MILP solver to Z3 Term solver
|
||||
|
||||
where <file_name> is any file with OML, MPS or SMPS extension.
|
||||
|
||||
Examples:
|
||||
Validator.exe -convert model.mps
|
||||
Validator.exe -term -solve model.oml
|
||||
|
||||
");
|
||||
}
|
||||
}
|
||||
}
|
36
examples/msf/Validator/Properties/AssemblyInfo.cs
Normal file
36
examples/msf/Validator/Properties/AssemblyInfo.cs
Normal file
|
@ -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")]
|
123
examples/msf/Validator/Validator.csproj
Normal file
123
examples/msf/Validator/Validator.csproj
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{54835857-129F-44C9-B529-A42158647B36}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Validator</RootNamespace>
|
||||
<AssemblyName>Validator</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
|
||||
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
|
||||
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Solver.Foundation">
|
||||
<HintPath>..\Microsoft.Solver.Foundation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq">
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="MicrosoftSolverFoundationForExcel.dll.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SolverFoundation.Plugin.Z3\SolverFoundation.Plugin.Z3.csproj">
|
||||
<Project>{7340e664-f648-4ff7-89b2-f4da424996d3}</Project>
|
||||
<Name>SolverFoundation.Plugin.Z3</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
125
examples/msf/Z3MSFPlugin.sln
Normal file
125
examples/msf/Z3MSFPlugin.sln
Normal file
|
@ -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
|
|
@ -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',
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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<symbol> 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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
|
243
src/api/api_opt.cpp
Normal file
243
src/api/api_opt.cpp
Normal file
|
@ -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<iostream>
|
||||
#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<Z3_optimize_ref *>(o); }
|
||||
inline Z3_optimize of_optimize(Z3_optimize_ref * o) { return reinterpret_cast<Z3_optimize>(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<opt::context> 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
61
src/api/api_pb.cpp
Normal file
61
src/api/api_pb.cpp
Normal file
|
@ -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<iostream>
|
||||
#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<rational> 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);
|
||||
}
|
||||
|
||||
|
||||
};
|
|
@ -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<Z3_ast> 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();
|
||||
|
|
|
@ -449,6 +449,19 @@ namespace Microsoft.Z3
|
|||
return MkDatatypeSorts(MkSymbols(names), c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Create an at-most-k constraint.
|
||||
/// </summary>
|
||||
public BoolExpr MkAtMost(BoolExpr[] args, uint k)
|
||||
{
|
||||
Contract.Requires(args != null);
|
||||
Contract.Requires(Contract.Result<BoolExpr[]>() != null);
|
||||
CheckContextMatch(args);
|
||||
return new BoolExpr(this, Native.Z3_mk_atmost(nCtx, (uint) args.Length,
|
||||
AST.ArrayToNative(args), k));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a pseudo-Boolean less-or-equal constraint.
|
||||
/// </summary>
|
||||
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<BoolExpr[]>() != 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
|
||||
/// <summary>
|
||||
/// Create an Optimization context.
|
||||
/// </summary>
|
||||
public Optimize MkOptimize()
|
||||
{
|
||||
Contract.Ensures(Contract.Result<Optimize>() != null);
|
||||
|
||||
return new Optimize(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Miscellaneous
|
||||
/// <summary>
|
||||
|
@ -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<AST.DecRefQueue>() != null); return m_AST_DRQ; } }
|
||||
internal ASTMap.DecRefQueue ASTMap_DRQ { get { Contract.Ensures(Contract.Result<ASTMap.DecRefQueue>() != null); return m_ASTMap_DRQ; } }
|
||||
|
@ -3627,6 +3684,7 @@ namespace Microsoft.Z3
|
|||
internal Statistics.DecRefQueue Statistics_DRQ { get { Contract.Ensures(Contract.Result<Statistics.DecRefQueue>() != null); return m_Statistics_DRQ; } }
|
||||
internal Tactic.DecRefQueue Tactic_DRQ { get { Contract.Ensures(Contract.Result<Tactic.DecRefQueue>() != null); return m_Tactic_DRQ; } }
|
||||
internal Fixedpoint.DecRefQueue Fixedpoint_DRQ { get { Contract.Ensures(Contract.Result<Fixedpoint.DecRefQueue>() != null); return m_Fixedpoint_DRQ; } }
|
||||
internal Optimize.DecRefQueue Optimize_DRQ { get { Contract.Ensures(Contract.Result<Optimize.DecRefQueue>() != 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;
|
||||
|
|
111
src/api/dotnet/Deprecated.cs
Normal file
111
src/api/dotnet/Deprecated.cs
Normal file
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// The main interaction with Z3 happens via the Context.
|
||||
/// </summary>
|
||||
[ContractVerification(true)]
|
||||
public class Deprecated
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Creates a backtracking point.
|
||||
/// </summary>
|
||||
/// <seealso cref="Pop"/>
|
||||
public static void Push(Context ctx) {
|
||||
Native.Z3_push(ctx.nCtx);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backtracks <paramref name="n"/> backtracking points.
|
||||
/// </summary>
|
||||
/// <remarks>Note that an exception is thrown if <paramref name="n"/> is not smaller than <c>NumScopes</c></remarks>
|
||||
/// <seealso cref="Push"/>
|
||||
public static void Pop(Context ctx, uint n = 1) {
|
||||
Native.Z3_pop(ctx.nCtx, n);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assert a constraint (or multiple) into the solver.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Checks whether the assertions in the context are consistent or not.
|
||||
/// </summary>
|
||||
public static Status Check(Context ctx, List<BoolExpr> 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves an assignment to atomic propositions for a satisfiable context.
|
||||
/// </summary>
|
||||
public static BoolExpr GetAssignment(Context ctx)
|
||||
{
|
||||
IntPtr x = Native.Z3_get_context_assignment(ctx.nCtx);
|
||||
return (BoolExpr)Expr.Create(ctx, x);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -304,6 +304,19 @@ namespace Microsoft.Z3
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fixedpoint statistics.
|
||||
/// </summary>
|
||||
public Statistics Statistics
|
||||
{
|
||||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<Statistics>() != null);
|
||||
|
||||
return new Statistics(Context, Native.Z3_fixedpoint_get_statistics(Context.nCtx, NativeObject));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse an SMT-LIB2 file with fixedpoint rules.
|
||||
/// Add the rules to the current fixedpoint context.
|
||||
/// Return the set of queries in the file.
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\..\..\..\..\cwinter\bugs\z3bugs\Debug\</OutputPath>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DocumentationFile>C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML</DocumentationFile>
|
||||
<DocumentationFile>..\Debug\Microsoft.Z3.XML</DocumentationFile>
|
||||
<CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
|
||||
<CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
|
||||
<CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
|
||||
|
@ -254,7 +254,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\..\..\..\cwinter\bugs\z3bugs\Debug\</OutputPath>
|
||||
<OutputPath>..\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DebugType>full</DebugType>
|
||||
|
@ -266,7 +266,7 @@
|
|||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
|
||||
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
|
||||
<DocumentationFile>C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML</DocumentationFile>
|
||||
<DocumentationFile>..\x86\Debug\Microsoft.Z3.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
|
|
296
src/api/dotnet/Optimize.cs
Normal file
296
src/api/dotnet/Optimize.cs
Normal file
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Object for managing optimizization context
|
||||
/// </summary>
|
||||
[ContractVerification(true)]
|
||||
public class Optimize : Z3Object
|
||||
{
|
||||
/// <summary>
|
||||
/// A string that describes all available optimize solver parameters.
|
||||
/// </summary>
|
||||
public string Help
|
||||
{
|
||||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<string>() != null);
|
||||
return Native.Z3_optimize_get_help(Context.nCtx, NativeObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the optimize solver parameters.
|
||||
/// </summary>
|
||||
public Params Parameters
|
||||
{
|
||||
set
|
||||
{
|
||||
Contract.Requires(value != null);
|
||||
Context.CheckContextMatch(value);
|
||||
Native.Z3_optimize_set_params(Context.nCtx, NativeObject, value.NativeObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves parameter descriptions for Optimize solver.
|
||||
/// </summary>
|
||||
public ParamDescrs ParameterDescriptions
|
||||
{
|
||||
get { return new ParamDescrs(Context, Native.Z3_optimize_get_param_descrs(Context.nCtx, NativeObject)); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assert a constraint (or multiple) into the optimize solver.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alias for Assert.
|
||||
/// </summary>
|
||||
public void Add(params BoolExpr[] constraints)
|
||||
{
|
||||
Assert(constraints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle to objectives returned by objective functions.
|
||||
/// </summary>
|
||||
public class Handle
|
||||
{
|
||||
Optimize opt;
|
||||
uint handle;
|
||||
internal Handle(Optimize opt, uint h)
|
||||
{
|
||||
this.opt = opt;
|
||||
this.handle = h;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a lower bound for the objective handle.
|
||||
/// </summary>
|
||||
public ArithExpr Lower
|
||||
{
|
||||
get { return opt.GetLower(handle); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve an upper bound for the objective handle.
|
||||
/// </summary>
|
||||
public ArithExpr Upper
|
||||
{
|
||||
get { return opt.GetUpper(handle); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the value of an objective.
|
||||
/// </summary>
|
||||
public ArithExpr Value
|
||||
{
|
||||
get { return Lower; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assert soft constraint
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Return an objective which associates with the group of constraints.
|
||||
/// </remarks>
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// <summary>
|
||||
/// Check satisfiability of asserted constraints.
|
||||
/// Produce a model that (when the objectives are bounded and
|
||||
/// don't use strict inequalities) meets the objectives.
|
||||
/// </summary>
|
||||
///
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a backtracking point.
|
||||
/// </summary>
|
||||
/// <seealso cref="Pop"/>
|
||||
public void Push()
|
||||
{
|
||||
Native.Z3_optimize_push(Context.nCtx, NativeObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backtrack one backtracking point.
|
||||
/// </summary>
|
||||
/// <remarks>Note that an exception is thrown if Pop is called without a corresponding <c>Push</c></remarks>
|
||||
/// <seealso cref="Push"/>
|
||||
public void Pop()
|
||||
{
|
||||
Native.Z3_optimize_pop(Context.nCtx, NativeObject);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The model of the last <c>Check</c>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The result is <c>null</c> if <c>Check</c> was not invoked before,
|
||||
/// if its results was not <c>SATISFIABLE</c>, or if model production is not enabled.
|
||||
/// </remarks>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public Handle MkMaximize(ArithExpr e)
|
||||
{
|
||||
return new Handle(this, Native.Z3_optimize_maximize(Context.nCtx, NativeObject, e.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Declare an arithmetical minimization objective.
|
||||
/// Similar to MkMaximize.
|
||||
/// </summary>
|
||||
public Handle MkMinimize(ArithExpr e)
|
||||
{
|
||||
return new Handle(this, Native.Z3_optimize_minimize(Context.nCtx, NativeObject, e.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a lower bound for the objective handle.
|
||||
/// </summary>
|
||||
private ArithExpr GetLower(uint index)
|
||||
{
|
||||
return (ArithExpr)Expr.Create(Context, Native.Z3_optimize_get_lower(Context.nCtx, NativeObject, index));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve an upper bound for the objective handle.
|
||||
/// </summary>
|
||||
private ArithExpr GetUpper(uint index)
|
||||
{
|
||||
return (ArithExpr)Expr.Create(Context, Native.Z3_optimize_get_upper(Context.nCtx, NativeObject, index));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Print the context to a string (SMT-LIB parseable benchmark).
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return Native.Z3_optimize_to_string(Context.nCtx, NativeObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optimize statistics.
|
||||
/// </summary>
|
||||
public Statistics Statistics
|
||||
{
|
||||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<Statistics>() != 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
|
||||
}
|
||||
}
|
|
@ -79,6 +79,7 @@ namespace Microsoft.Z3
|
|||
Native.Z3_params_set_symbol(Context.nCtx, NativeObject, name.NativeObject, value.NativeObject);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a parameter setting.
|
||||
/// </summary>
|
||||
|
@ -118,6 +119,7 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
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);
|
||||
|
|
9
src/api/dotnet/Readme.NET35
Normal file
9
src/api/dotnet/Readme.NET35
Normal file
|
@ -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"
|
|
@ -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.
|
||||
**/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
264
src/api/z3_api.h
264
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
|
||||
/*@}*/
|
||||
|
||||
|
|
|
@ -22,12 +22,14 @@ Notes:
|
|||
#include"stream_buffer.h"
|
||||
#include"symbol.h"
|
||||
#include"trace.h"
|
||||
#include<sstream>
|
||||
|
||||
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<void *> m_heap;
|
||||
svector<z3_replayer_cmd> 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<ptr_vector<void> > m_obj_arrays;
|
||||
vector<svector<Z3_symbol> > m_sym_arrays;
|
||||
vector<unsigned_vector> m_unsigned_arrays;
|
||||
vector<svector<int> > 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<unsigned>(m_args[i].m_uint));
|
||||
}
|
||||
}
|
||||
if (k == INT64) {
|
||||
aidx = m_int_arrays.size();
|
||||
nk = INT_ARRAY;
|
||||
m_int_arrays.push_back(svector<int>());
|
||||
svector<int> & v = m_int_arrays.back();
|
||||
for (unsigned i = asz - sz; i < asz; i++) {
|
||||
v.push_back(static_cast<int>(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<unsigned>(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<unsigned>(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<unsigned>(m_args[pos].m_uint);
|
||||
ptr_vector<void> & 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<int>(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<unsigned>(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<Z3_symbol>(const_cast<char*>(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<unsigned>(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<unsigned>(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<unsigned>(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<unsigned>(m_args[pos].m_uint);
|
||||
ptr_vector<void> 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<int*>(&(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<unsigned*>(&(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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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<basic_op_kind>(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);
|
||||
|
|
|
@ -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<func_decl> & 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);
|
||||
|
|
|
@ -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<format> 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<expr*>(n), m) << std::endl;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<quantifier> 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";
|
||||
|
|
76
src/ast/ast_trail.h
Normal file
76
src/ast/ast_trail.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ast_trail.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<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<typename S, typename T>
|
||||
class ast2ast_trailmap {
|
||||
ref_vector<S, ast_manager> m_domain;
|
||||
ref_vector<T, ast_manager> m_range;
|
||||
obj_map<S, T*> 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<typename Ctx, typename S, typename T>
|
||||
class ast2ast_trail : public trail<Ctx> {
|
||||
ast2ast_trailmap<S,T>& m_map;
|
||||
public:
|
||||
ast2ast_trail(ast2ast_trailmap<S,T>& m, S* s, T* t) :
|
||||
m_map(m) {
|
||||
m.insert(s,t);
|
||||
}
|
||||
|
||||
virtual void undo(Ctx& ctx) {
|
||||
m_map.pop();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* _AST_TRAIL_H_ */
|
||||
|
|
@ -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<builtin_name> & 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<func_decl> 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<func_decl> 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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<builtin_name> & op_names, symbol const & logic);
|
||||
|
||||
private:
|
||||
bool is_value_visit(expr * arg, ptr_buffer<app> & 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<func_decl> 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(); }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<app> 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<app> & 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=<val>).",
|
||||
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()) {
|
||||
|
|
|
@ -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<expr> m_bindings;
|
||||
|
||||
typedef std::pair<expr *, expr *> 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);
|
||||
};
|
||||
|
||||
|
|
282
src/ast/pb_decl_plugin.cpp
Normal file
282
src/ast/pb_decl_plugin.cpp
Normal file
|
@ -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<parameter> 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<builtin_name> & 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<parameter> 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<parameter> 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<parameter> 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<rational> 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;
|
||||
}
|
123
src/ast/pb_decl_plugin.h
Normal file
123
src/ast/pb_decl_plugin.h
Normal file
|
@ -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<builtin_name> & 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_ */
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<int>(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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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<int> 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<sort> m_sorts;
|
||||
expr_fast_mark1 m_visited;
|
||||
expr_free_vars m_fv;
|
||||
ptr_vector<expr> 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<ast, int> 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); }
|
||||
|
|
|
@ -1038,6 +1038,11 @@ void bit_blaster_tpl<Cfg>::mk_ext_rotate_left_right(unsigned sz, expr * const *
|
|||
mk_rotate_right(sz, a_bits, static_cast<unsigned>(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());
|
||||
|
|
|
@ -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<func_decl> const * acc = m_util.get_constructor_accessors(c_decl);
|
||||
SASSERT(acc && acc->size() == a->get_num_args());
|
||||
unsigned num = acc->size();
|
||||
ptr_buffer<expr> 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();
|
||||
}
|
||||
|
|
|
@ -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<expr,expr*> cache;
|
||||
ptr_vector<expr> 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() {
|
||||
|
|
|
@ -29,9 +29,12 @@ class expr_safe_replace {
|
|||
expr_ref_vector m_src;
|
||||
expr_ref_vector m_dst;
|
||||
obj_map<expr, expr*> m_subst;
|
||||
obj_map<expr,expr*> m_cache;
|
||||
ptr_vector<expr> 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__ */
|
||||
|
|
275
src/ast/rewriter/pb_rewriter.cpp
Normal file
275
src/ast/rewriter/pb_rewriter.cpp
Normal file
|
@ -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<expr*, rational> arg_t;
|
||||
typedef vector<arg_t> 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<expr*,rational> const& a,
|
||||
std::pair<expr*,rational> const& b) {
|
||||
return a.first->get_id() < b.first->get_id();
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
expr_ref pb_rewriter::translate_pb2lia(obj_map<expr,expr*>& 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<expr,expr*> 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<std::pair<expr*,rational> > 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<pb_ast_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;
|
||||
}
|
||||
|
||||
|
65
src/ast/rewriter/pb_rewriter.h
Normal file
65
src/ast/rewriter/pb_rewriter.h
Normal file
|
@ -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<typename PBU>
|
||||
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<rational> m_coeffs;
|
||||
ptr_vector<expr> 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<expr,expr*>& vars, expr* fml);
|
||||
expr_ref mk_validate_rewrite(app_ref& e1, app_ref& e2);
|
||||
void dump_pb_rewrite(expr* fml);
|
||||
};
|
||||
|
||||
#endif
|
298
src/ast/rewriter/pb_rewriter_def.h
Normal file
298
src/ast/rewriter/pb_rewriter_def.h
Normal file
|
@ -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<typename PBU>
|
||||
void pb_rewriter_util<PBU>::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<typename PBU>
|
||||
void pb_rewriter_util<PBU>::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<typename PBU>
|
||||
lbool pb_rewriter_util<PBU>::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<typename PBU>
|
||||
void pb_rewriter_util<PBU>::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
|
|
@ -34,6 +34,8 @@ void poly_rewriter<Config>::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<typename Config>
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& sorts) {
|
||||
static void get_free_vars_offset(expr_sparse_mark& mark, ptr_vector<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& 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<expr>& todo, unsigne
|
|||
switch(e->get_kind()) {
|
||||
case AST_QUANTIFIER: {
|
||||
quantifier* q = to_quantifier(e);
|
||||
ast_mark mark1;
|
||||
expr_sparse_mark mark1;
|
||||
ptr_vector<expr> 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<expr>& todo, unsigne
|
|||
|
||||
|
||||
void get_free_vars(expr* e, ptr_vector<sort>& sorts) {
|
||||
ast_mark mark;
|
||||
expr_sparse_mark mark;
|
||||
ptr_vector<expr> todo;
|
||||
get_free_vars_offset(mark, todo, 0, e, sorts);
|
||||
}
|
||||
|
||||
void get_free_vars(ast_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& sorts) {
|
||||
void get_free_vars(expr_sparse_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& 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);
|
||||
}
|
||||
|
|
|
@ -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<sort>& sorts);
|
||||
|
||||
void get_free_vars(ast_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& sorts);
|
||||
class expr_free_vars {
|
||||
expr_sparse_mark m_mark;
|
||||
ptr_vector<sort> m_sorts;
|
||||
ptr_vector<expr> 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
|
||||
|
||||
|
|
|
@ -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<expr> 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_ */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<expr**>(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<expr> 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<expr> & 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<expr> & args, vector<rational>
|
|||
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<expr> & args, vector<rational>
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<substitution_tree::st_visit_mode Mode>
|
||||
|
|
|
@ -123,6 +123,8 @@ class substitution_tree {
|
|||
template<st_visit_mode Mode>
|
||||
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();
|
||||
|
|
|
@ -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<family_id>& 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<family_id> 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<family_id>::iterator it = fids.begin();
|
||||
svector<family_id>::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<opt_wrapper> eh(*get_opt());
|
||||
scoped_ctrl_c ctrlc(eh);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
ptr_vector<expr> 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<solver> 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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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<expr> & 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<scope> m_scopes;
|
||||
scoped_ptr<solver_factory> m_solver_factory;
|
||||
scoped_ptr<solver_factory> m_interpolating_solver_factory;
|
||||
ref<solver> m_solver;
|
||||
ref<solver> m_solver;
|
||||
ref<check_sat_result> m_check_sat_result;
|
||||
ref<opt_wrapper> 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<family_id>& 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<cmd_context*>(this)->init_manager(); return *m_manager; }
|
||||
ast_manager & m() const { const_cast<cmd_context*>(this)->init_manager(); return *m_manager; }
|
||||
virtual ast_manager & get_ast_manager() { return m(); }
|
||||
pdecl_manager & pm() const { if (!m_pmanager) const_cast<cmd_context*>(this)->init_manager(); return *m_pmanager; }
|
||||
sexpr_manager & sm() const { if (!m_sexpr_manager) const_cast<cmd_context*>(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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
4
src/duality/duality.h
Executable file → Normal file
4
src/duality/duality.h
Executable file → Normal file
|
@ -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);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue