mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 16:45:31 +00:00
Merge branch 'unstable' of https://git01.codeplex.com/z3 into unstable
This commit is contained in:
commit
4f2b7049ab
187 changed files with 493 additions and 33625 deletions
|
@ -80,7 +80,7 @@ extern "C" {
|
|||
LOG_Z3_mk_solver_from_tactic(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_solver_ref * s = alloc(Z3_solver_ref);
|
||||
s->m_solver = alloc(tactic2solver_api, to_tactic_ref(t));
|
||||
s->m_solver = alloc(tactic2solver, to_tactic_ref(t));
|
||||
s->m_solver->set_front_end_params(mk_c(c)->fparams());
|
||||
s->m_solver->init(mk_c(c)->m(), symbol::null);
|
||||
mk_c(c)->save_object(s);
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
using namespace System;
|
||||
using namespace System::Reflection;
|
||||
using namespace System::Runtime::CompilerServices;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using namespace System::Security::Permissions;
|
||||
|
||||
//
|
||||
// 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:AssemblyTitleAttribute("Z3 .NET Interface")];
|
||||
[assembly:AssemblyDescriptionAttribute(".NET Interface to the Z3 Theorem Prover")];
|
||||
[assembly:AssemblyConfigurationAttribute("")];
|
||||
[assembly:AssemblyCompanyAttribute("Microsoft Corporation")];
|
||||
[assembly:AssemblyProductAttribute("Z3")];
|
||||
[assembly:AssemblyCopyrightAttribute("Copyright (c) Microsoft Corporation 2006")];
|
||||
[assembly:AssemblyTrademarkAttribute("")];
|
||||
[assembly:AssemblyCultureAttribute("")];
|
||||
|
||||
[assembly:ComVisible(false)];
|
||||
[assembly:CLSCompliantAttribute(true)];
|
||||
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
|
||||
|
||||
[assembly:AssemblyVersionAttribute("4.2.0.0")];
|
||||
[assembly:AssemblyFileVersionAttribute("4.2.0.0")];
|
||||
|
||||
//#ifdef DELAYSIGN
|
||||
//[assembly:AssemblyKeyFile("35MSSharedLib1024.snk")];
|
||||
//[assembly:AssemblyDelaySign(true)];
|
||||
//#else
|
||||
//[assembly:AssemblyKeyFile("z3.snk")];
|
||||
//[assembly:AssemblyDelaySign(true)];
|
||||
//#endif
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,555 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="commercial|Win32">
|
||||
<Configuration>commercial</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="commercial|x64">
|
||||
<Configuration>commercial</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="external|Win32">
|
||||
<Configuration>external</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="external|x64">
|
||||
<Configuration>external</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="release_mt|Win32">
|
||||
<Configuration>release_mt</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="release_mt|x64">
|
||||
<Configuration>release_mt</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Trace|Win32">
|
||||
<Configuration>Trace</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Trace|x64">
|
||||
<Configuration>Trace</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{F008F2C4-D652-4A58-8DEF-DB83E2355454}</ProjectGuid>
|
||||
<RootNamespace>Microsoft.Z3V3</RootNamespace>
|
||||
<Keyword>ManagedCProj</Keyword>
|
||||
<ProjectName>Microsoft.Z3V3</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='external|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='commercial|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_mt|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Trace|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='external|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='commercial|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_mt|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Trace|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='external|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='commercial|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_mt|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Trace|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='external|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='commercial|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_mt|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Trace|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Trace|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Trace|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Trace|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Trace|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Trace|x64'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Trace|x64'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='release_mt|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='release_mt|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='release_mt|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='release_mt|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='release_mt|x64'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='external|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='commercial|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='external|Win32'">$(Configuration)\</IntDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='commercial|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='external|Win32'">false</LinkIncremental>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='commercial|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='external|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='commercial|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='external|x64'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='commercial|x64'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='external|x64'">false</LinkIncremental>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='commercial|x64'">false</LinkIncremental>
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='commercial_64|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='external|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='commercial|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='external|Win32'" />
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='commercial|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='external|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='commercial|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='external|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='commercial|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='external|x64'" />
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='commercial|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='external|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='commercial|x64'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='release_mt|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='release_mt|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='release_mt|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='release_mt|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='release_mt|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='release_mt|x64'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Trace|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Trace|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Trace|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Trace|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Trace|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Trace|x64'" />
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;Z3DEBUG;_WINDOWS;_TRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AssemblyDebug>true</AssemblyDebug>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_TRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AssemblyDebug>true</AssemblyDebug>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Trace|Win32'">
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Trace|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_mt|Win32'">
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='external|Win32'">
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_EXTERNAL_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<Profile>true</Profile>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='commercial|Win32'">
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_Z3_COMMERCIAL;_EXTERNAL_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='external|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_EXTERNAL_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
<Profile>true</Profile>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='commercial|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_Z3_COMMERCIAL;_AMD64_;_EXTERNAL_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)Microsoft.Z3V3.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_mt|x64'">
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_mt|x64'">
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System">
|
||||
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
</Reference>
|
||||
<Reference Include="System.Data">
|
||||
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
</Reference>
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Xml">
|
||||
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AssemblyInfo.cpp" />
|
||||
<ClCompile Include="Microsoft.Z3V3.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Microsoft.Z3V3.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\lib\lib.vcxproj">
|
||||
<Project>{4a7e5a93-19d8-4382-8950-fb2edec7a76e}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,67 +0,0 @@
|
|||
############################################
|
||||
# Copyright (c) 2012 Microsoft Corporation
|
||||
#
|
||||
# Z3 Polynomial interface
|
||||
#
|
||||
# Author: Leonardo de Moura (leonardo)
|
||||
############################################
|
||||
from z3 import *
|
||||
|
||||
class PolynomialManager:
|
||||
"""Polynomial Manager.
|
||||
"""
|
||||
def __init__(self, ctx=None):
|
||||
self.ctx = z3._get_ctx(ctx)
|
||||
self.manager = Z3_mk_polynomial_manager(self.ctx_ref())
|
||||
|
||||
def __del__(self):
|
||||
Z3_del_polynomial_manager(self.ctx_ref(), self.manager)
|
||||
|
||||
def ctx_ref(self):
|
||||
return self.ctx.ref()
|
||||
|
||||
def m(self):
|
||||
return self.manager
|
||||
|
||||
_main_pmanager = None
|
||||
def main_pmanager():
|
||||
"""Return a reference to the global Polynomial manager.
|
||||
"""
|
||||
global _main_pmanager
|
||||
if _main_pmanager == None:
|
||||
_main_pmanager = PolynomialManager()
|
||||
return _main_pmanager
|
||||
|
||||
def _get_pmanager(ctx):
|
||||
if ctx == None:
|
||||
return main_pmanager()
|
||||
else:
|
||||
return ctx
|
||||
|
||||
class Polynomial:
|
||||
"""Multivariate polynomials.
|
||||
"""
|
||||
def __init__(self, poly=None, m=None):
|
||||
self.pmanager = _get_pmanager(m)
|
||||
if poly == None:
|
||||
self.poly = Z3_mk_zero_polynomial(self.ctx_ref(), self.m())
|
||||
else:
|
||||
self.poly = poly
|
||||
Z3_polynomial_inc_ref(self.ctx_ref(), self.m(), self.poly)
|
||||
|
||||
def __del__(self):
|
||||
Z3_polynomial_dec_ref(self.ctx_ref(), self.m(), self.poly)
|
||||
|
||||
def m(self):
|
||||
return self.pmanager.m()
|
||||
|
||||
def ctx_ref(self):
|
||||
return self.pmanager.ctx_ref()
|
||||
|
||||
def __repr__(self):
|
||||
return Z3_polynomial_to_string(self.ctx_ref(), self.m(), self.poly)
|
||||
|
||||
# test
|
||||
p = Polynomial()
|
||||
print p
|
||||
|
|
@ -27,6 +27,7 @@ Notes:
|
|||
#include"cmd_util.h"
|
||||
#include"simplify_cmd.h"
|
||||
#include"eval_cmd.h"
|
||||
#include"front_end_params.h"
|
||||
|
||||
class help_cmd : public cmd {
|
||||
svector<symbol> m_cmds;
|
||||
|
|
|
@ -348,6 +348,18 @@ cmd_context::~cmd_context() {
|
|||
}
|
||||
}
|
||||
|
||||
bool cmd_context::is_smtlib2_compliant() const {
|
||||
return params().m_smtlib2_compliant;
|
||||
}
|
||||
|
||||
bool cmd_context::produce_models() const {
|
||||
return params().m_model;
|
||||
}
|
||||
|
||||
bool cmd_context::produce_proofs() const {
|
||||
return params().m_proof_mode != PGM_DISABLED;
|
||||
}
|
||||
|
||||
cmd_context::check_sat_state cmd_context::cs_state() const {
|
||||
if (m_check_sat_result.get() == 0)
|
||||
return css_clear;
|
||||
|
|
|
@ -249,7 +249,7 @@ protected:
|
|||
public:
|
||||
cmd_context(front_end_params * params = 0, bool main_ctx = true, ast_manager * m = 0, symbol const & l = symbol::null);
|
||||
~cmd_context();
|
||||
bool is_smtlib2_compliant() const { return params().m_smtlib2_compliant; }
|
||||
bool is_smtlib2_compliant() const;
|
||||
void set_logic(symbol const & s);
|
||||
bool has_logic() const { return m_logic != symbol::null; }
|
||||
symbol const & get_logic() const { return m_logic; }
|
||||
|
@ -269,8 +269,8 @@ public:
|
|||
void set_global_decls(bool flag) { SASSERT(!has_manager()); m_global_decls = flag; }
|
||||
unsigned random_seed() const { return m_random_seed; }
|
||||
void set_random_seed(unsigned s) { m_random_seed = s; }
|
||||
bool produce_models() const { return params().m_model; }
|
||||
bool produce_proofs() const { return params().m_proof_mode != PGM_DISABLED; }
|
||||
bool produce_models() const;
|
||||
bool produce_proofs() const;
|
||||
bool produce_unsat_cores() const { return m_produce_unsat_cores; }
|
||||
void set_produce_unsat_cores(bool flag) { m_produce_unsat_cores = flag; }
|
||||
bool produce_assignments() const { return m_produce_assignments; }
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
solver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
abstract solver interface
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-03-19
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _SOLVER_H_
|
||||
#define _SOLVER_H_
|
||||
|
||||
#include"check_sat_result.h"
|
||||
#include"front_end_params.h"
|
||||
#include"progress_callback.h"
|
||||
#include"params.h"
|
||||
|
||||
class solver : public check_sat_result {
|
||||
public:
|
||||
virtual ~solver() {}
|
||||
|
||||
// for backward compatibility
|
||||
virtual void set_front_end_params(front_end_params & p) {}
|
||||
|
||||
virtual void updt_params(params_ref const & p) {}
|
||||
virtual void collect_param_descrs(param_descrs & r) {}
|
||||
|
||||
virtual void set_produce_proofs(bool f) {}
|
||||
virtual void set_produce_models(bool f) {}
|
||||
virtual void set_produce_unsat_cores(bool f) {}
|
||||
|
||||
virtual void init(ast_manager & m, symbol const & logic) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual void assert_expr(expr * t) = 0;
|
||||
virtual void push() = 0;
|
||||
virtual void pop(unsigned n) = 0;
|
||||
virtual unsigned get_scope_level() const = 0;
|
||||
virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) = 0;
|
||||
|
||||
virtual void set_cancel(bool f) {}
|
||||
void cancel() { set_cancel(true); }
|
||||
void reset_cancel() { set_cancel(false); }
|
||||
|
||||
virtual void set_progress_callback(progress_callback * callback) = 0;
|
||||
|
||||
virtual unsigned get_num_assertions() const;
|
||||
virtual expr * get_assertion(unsigned idx) const;
|
||||
|
||||
virtual void display(std::ostream & out) const;
|
||||
};
|
||||
|
||||
#endif
|
34
src/cmd_context/strategic_solver_cmd.cpp
Normal file
34
src/cmd_context/strategic_solver_cmd.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
strategic_solver_cmd.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Specialization of the strategic solver that
|
||||
used cmd_context to access the assertion set.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2012-11-01
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"strategic_solver_cmd.h"
|
||||
#include"cmd_context.h"
|
||||
|
||||
strategic_solver_cmd::strategic_solver_cmd(cmd_context & ctx):
|
||||
m_ctx(ctx) {
|
||||
}
|
||||
|
||||
unsigned strategic_solver_cmd::get_num_assertions() const {
|
||||
return static_cast<unsigned>(m_ctx.end_assertions() - m_ctx.begin_assertions());
|
||||
}
|
||||
|
||||
expr * strategic_solver_cmd::get_assertion(unsigned idx) const {
|
||||
SASSERT(idx < get_num_assertions());
|
||||
return m_ctx.begin_assertions()[idx];
|
||||
}
|
40
src/cmd_context/strategic_solver_cmd.h
Normal file
40
src/cmd_context/strategic_solver_cmd.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
strategic_solver_cmd.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Specialization of the strategic solver that
|
||||
used cmd_context to access the assertion set.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2012-11-01
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _STRATEGIC_SOLVER_CMD_H_
|
||||
#define _STRATEGIC_SOLVER_CMD_H_
|
||||
|
||||
#include"strategic_solver.h"
|
||||
|
||||
class cmd_context;
|
||||
|
||||
/**
|
||||
Specialization for the SMT 2.0 command language frontend.
|
||||
|
||||
The strategic solver does not have to maintain a copy of the assertion set in the cmd_context.
|
||||
*/
|
||||
class strategic_solver_cmd : public strategic_solver_core {
|
||||
cmd_context & m_ctx;
|
||||
public:
|
||||
strategic_solver_cmd(cmd_context & ctx);
|
||||
virtual unsigned get_num_assertions() const;
|
||||
virtual expr * get_assertion(unsigned idx) const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,208 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_property_expander.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Expand array operations for the array property fragment formulas.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-16-12
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"array_property_expander.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"var_subst.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"for_each_expr.h"
|
||||
|
||||
array_property_expander::array_property_expander(ast_manager& m):
|
||||
m_manager(m) {
|
||||
}
|
||||
|
||||
namespace array_property_exp {
|
||||
class proc {
|
||||
ast_manager& m_manager;
|
||||
unsigned& m_offset;
|
||||
expr_ref_vector m_trail;
|
||||
family_id m_fid;
|
||||
array_util m_util;
|
||||
obj_map<expr, expr*> m_mem;
|
||||
|
||||
|
||||
void insert(expr* a, expr* b) {
|
||||
m_trail.push_back(b);
|
||||
m_mem.insert(a, b);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
proc(ast_manager& m, unsigned& offset) :
|
||||
m_manager(m),
|
||||
m_offset(offset),
|
||||
m_trail(m),
|
||||
m_fid(m.get_family_id("array")),
|
||||
m_util(m)
|
||||
{}
|
||||
|
||||
expr* find(expr* e) {
|
||||
expr* result = 0;
|
||||
VERIFY(m_mem.find(e, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void operator()(var* n) { insert(n, n); }
|
||||
|
||||
void operator()(quantifier* q) {
|
||||
expr* e = find(q->get_expr());
|
||||
quantifier* q2 = m_manager.update_quantifier(q, e);
|
||||
insert(q, q2);
|
||||
}
|
||||
|
||||
void operator()(app* n) {
|
||||
ast_manager& m = m_manager;
|
||||
unsigned num_args = n->get_num_args();
|
||||
ptr_buffer<expr> args;
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
args.push_back(find(n->get_arg(i)));
|
||||
}
|
||||
if (m_manager.is_eq(n) && m_util.is_array(args[0])) {
|
||||
visit_eq(n);
|
||||
return;
|
||||
}
|
||||
if (m_manager.is_distinct(n) && num_args > 0 && m_util.is_array(args[0])) {
|
||||
ptr_buffer<expr> eqs;
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
for (unsigned j = i + 1; j < num_args; ++j) {
|
||||
eqs.push_back(m.mk_not(m.mk_eq(args[i], args[j])));
|
||||
}
|
||||
}
|
||||
insert(n, m.mk_and(eqs.size(), eqs.c_ptr()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_util.is_select(n)) {
|
||||
SASSERT(num_args > 0);
|
||||
|
||||
// select(store(A,i,v),j) -> ite(i = j, v, select(A,j))
|
||||
if (m_util.is_store(args[0])) {
|
||||
app* a = to_app(args[0]);
|
||||
expr* b = find(a->get_arg(0));
|
||||
expr* v = find(a->get_arg(a->get_num_args()-1));
|
||||
ptr_buffer<expr> eqs;
|
||||
SASSERT(num_args + 1 == a->get_num_args());
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
eqs.push_back(m.mk_eq(args[i], find(a->get_arg(i))));
|
||||
}
|
||||
expr* r = m.mk_ite(m.mk_and(eqs.size(), eqs.c_ptr()), v, mk_select(b, num_args-1, args.c_ptr()+1));
|
||||
insert(n, r);
|
||||
return;
|
||||
}
|
||||
|
||||
// select(ite(a,b,c),i) -> ite(a, select(b,i), select(c, i))
|
||||
if (m.is_ite(args[0])) {
|
||||
app* k = to_app(args[0]);
|
||||
expr* a = k->get_arg(0);
|
||||
expr* b = mk_select(k->get_arg(1), args.size()-1, args.c_ptr()+1);
|
||||
expr* c = mk_select(k->get_arg(2), args.size()-1, args.c_ptr()+1);
|
||||
expr* r = m.mk_ite(a, b, c);
|
||||
insert(n, r);
|
||||
return;
|
||||
}
|
||||
|
||||
// select(map_f(A,B),i) -> f(select(A,i), select(B,i))
|
||||
if (m_util.is_map(args[0])) {
|
||||
app* a = to_app(args[0]);
|
||||
func_decl* f = a->get_decl();
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_ast());
|
||||
SASSERT(is_func_decl(f->get_parameter(0).get_ast()));
|
||||
parameter p = f->get_parameter(0);
|
||||
func_decl* d = to_func_decl(p.get_ast());
|
||||
ptr_buffer<expr> args2;
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
args2.push_back(mk_select(find(a->get_arg(i)), args.size()-1, args.c_ptr()+1));
|
||||
}
|
||||
expr* r = m.mk_app(d, args2.size(), args2.c_ptr());
|
||||
insert(n, r);
|
||||
return;
|
||||
}
|
||||
|
||||
// select(const v, i) -> v
|
||||
if (m_util.is_const(args[0])) {
|
||||
insert(n, to_app(args[0])->get_arg(0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
expr* r = m_manager.mk_app(n->get_decl(), args.size(), args.c_ptr());
|
||||
insert(n, r);
|
||||
}
|
||||
|
||||
private:
|
||||
void visit_eq(app* eq) {
|
||||
ast_manager& m = m_manager;
|
||||
SASSERT(m.is_eq(eq));
|
||||
sort* s = m.get_sort(eq->get_arg(0));
|
||||
SASSERT(is_sort_of(s, m_fid, ARRAY_SORT));
|
||||
// sort* rng = get_array_range(s);
|
||||
unsigned arity = get_array_arity(s);
|
||||
shift_vars sh(m);
|
||||
expr_ref e1(m), e2(m);
|
||||
sh(find(eq->get_arg(0)), arity, e1);
|
||||
sh(find(eq->get_arg(1)), arity, e2);
|
||||
expr_ref_vector args(m);
|
||||
buffer<symbol> names;
|
||||
ptr_buffer<sort> sorts;
|
||||
args.push_back(e1);
|
||||
for (unsigned i = 0; i < arity; ++i) {
|
||||
args.push_back(m.mk_var(i, get_array_domain(s, i)));
|
||||
sorts.push_back(get_array_domain(s, arity - i - 1));
|
||||
names.push_back(symbol(m_offset++));
|
||||
}
|
||||
e1 = mk_select(args.size(), args.c_ptr());
|
||||
args[0] = e2;
|
||||
e2 = mk_select(args.size(), args.c_ptr());
|
||||
e1 = m.mk_eq(e1, e2);
|
||||
|
||||
e1 = m.mk_quantifier(true, arity, sorts.c_ptr(), names.c_ptr(), e1, 1);
|
||||
insert(eq, e1);
|
||||
}
|
||||
|
||||
app* mk_select(unsigned n, expr* const* args) {
|
||||
return m_manager.mk_app(m_fid, OP_SELECT, 0, 0, n, args);
|
||||
}
|
||||
|
||||
app* mk_select(expr* a, unsigned n, expr* const* args) {
|
||||
ptr_buffer<expr> args2;
|
||||
args2.push_back(a);
|
||||
args2.append(n, args);
|
||||
return mk_select(n+1, args2.c_ptr());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void array_property_expander::operator()(unsigned num_fmls, expr* const* fmls, expr_ref_vector& result) {
|
||||
ast_manager& m = m_manager;
|
||||
unsigned offset = 0;
|
||||
for (unsigned i = 0; i < num_fmls; ++i) {
|
||||
bool change = false;
|
||||
expr_ref e(m);
|
||||
result.push_back(fmls[i]);
|
||||
do {
|
||||
array_property_exp::proc p(m, offset);
|
||||
e = result[i].get();
|
||||
for_each_expr(p, e);
|
||||
result[i] = p.find(e);
|
||||
change = e != result[i].get();
|
||||
}
|
||||
while (change);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_property_expander.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Expand array operations for the array property fragment formulas.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-16-12
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARRAY_PROPERTY_EXPANDER_H_
|
||||
#define _ARRAY_PROPERTY_EXPANDER_H_
|
||||
|
||||
#include"ast.h"
|
||||
|
||||
class array_property_expander {
|
||||
ast_manager& m_manager;
|
||||
public:
|
||||
array_property_expander(ast_manager& m);
|
||||
void operator()(unsigned num_fmls, expr* const* fmls, expr_ref_vector& result);
|
||||
};
|
||||
|
||||
|
||||
#endif /* _ARRAY_PROPERTY_EXPANDER_H_ */
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_property_recognizer.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-16-12
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"array_decl_plugin.h"
|
||||
#include"array_property_recognizer.h"
|
||||
#include"for_each_expr.h"
|
||||
|
||||
|
||||
array_property_recognizer::array_property_recognizer(ast_manager& m):
|
||||
m_manager(m) {}
|
||||
|
||||
namespace is_array_property_ns {
|
||||
struct bad {};
|
||||
class proc {
|
||||
ast_manager& m_manager;
|
||||
family_id m_fid;
|
||||
bool m_has_quantifier;
|
||||
|
||||
void check_array_sort(expr* n) {
|
||||
if (is_sort_of(m_manager.get_sort(n), m_fid, ARRAY_SORT)) {
|
||||
throw bad();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
proc(ast_manager& m) :
|
||||
m_manager(m),
|
||||
m_fid(m.get_family_id("array")),
|
||||
m_has_quantifier(false) {}
|
||||
|
||||
bool has_quantifier() const { return m_has_quantifier; }
|
||||
|
||||
void operator()(var* n) {
|
||||
check_array_sort(n);
|
||||
}
|
||||
|
||||
void operator()(quantifier * ) {
|
||||
m_has_quantifier = true;
|
||||
}
|
||||
|
||||
void operator()(app* n) {
|
||||
unsigned num_args = n->get_num_args();
|
||||
if (m_manager.is_eq(n) || m_manager.is_distinct(n)) {
|
||||
return;
|
||||
}
|
||||
family_id fid = n->get_family_id();
|
||||
if (fid == m_fid) {
|
||||
switch(n->get_decl_kind()) {
|
||||
case OP_STORE:
|
||||
for (unsigned i = 1; i + 1 < num_args; ++i) {
|
||||
check_array_sort(n->get_arg(i));
|
||||
}
|
||||
return;
|
||||
case OP_SELECT:
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
check_array_sort(n->get_arg(i));
|
||||
}
|
||||
return;
|
||||
case OP_CONST_ARRAY:
|
||||
case OP_ARRAY_MAP:
|
||||
return;
|
||||
default:
|
||||
throw bad();
|
||||
}
|
||||
}
|
||||
// arrays cannot be arguments of other functions.
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
check_array_sort(n->get_arg(i));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
bool array_property_recognizer::operator()(unsigned num_fmls, expr* const* fmls) {
|
||||
is_array_property_ns::proc p(m_manager);
|
||||
try {
|
||||
for (unsigned i = 0; i < num_fmls; ++i) {
|
||||
for_each_expr(p, fmls[i]);
|
||||
}
|
||||
}
|
||||
catch (is_array_property_ns::bad) {
|
||||
return false;
|
||||
}
|
||||
return p.has_quantifier();
|
||||
}
|
||||
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_property_recognizer.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-16-12
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARRAY_PROPERTY_RECOGNIZER_H_
|
||||
#define _ARRAY_PROPERTY_RECOGNIZER_H_
|
||||
|
||||
#include"ast.h"
|
||||
|
||||
class array_property_recognizer {
|
||||
ast_manager& m_manager;
|
||||
public:
|
||||
array_property_recognizer(ast_manager& m);
|
||||
bool operator()(unsigned num_fmls, expr* const* fmls);
|
||||
};
|
||||
|
||||
|
||||
#endif /* _ARRAY_PROPERTY_RECOGNIZER_H_ */
|
||||
|
|
@ -1,314 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_stack.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Assertion stacks
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-17
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"assertion_stack.h"
|
||||
#include"well_sorted.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"ref_util.h"
|
||||
|
||||
assertion_stack::assertion_stack(ast_manager & m, bool models_enabled, bool core_enabled):
|
||||
m_manager(m),
|
||||
m_forbidden(m),
|
||||
m_csubst(m, core_enabled),
|
||||
m_fsubst(m, core_enabled) {
|
||||
init(m.proofs_enabled(), models_enabled, core_enabled);
|
||||
}
|
||||
|
||||
assertion_stack::assertion_stack(ast_manager & m, bool proofs_enabled, bool models_enabled, bool core_enabled):
|
||||
m_manager(m),
|
||||
m_forbidden(m),
|
||||
m_csubst(m, core_enabled, proofs_enabled),
|
||||
m_fsubst(m, core_enabled, proofs_enabled) {
|
||||
init(proofs_enabled, models_enabled, core_enabled);
|
||||
}
|
||||
|
||||
void assertion_stack::init(bool proofs_enabled, bool models_enabled, bool core_enabled) {
|
||||
m_ref_count = 0;
|
||||
m_models_enabled = models_enabled;
|
||||
m_proofs_enabled = proofs_enabled;
|
||||
m_core_enabled = core_enabled;
|
||||
m_inconsistent = false;
|
||||
m_form_qhead = 0;
|
||||
}
|
||||
|
||||
assertion_stack::~assertion_stack() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void assertion_stack::reset() {
|
||||
m_inconsistent = false;
|
||||
m_form_qhead = 0;
|
||||
m_mc_qhead = 0;
|
||||
dec_ref_collection_values(m_manager, m_forms);
|
||||
dec_ref_collection_values(m_manager, m_proofs);
|
||||
dec_ref_collection_values(m_manager, m_deps);
|
||||
m_forbidden_set.reset();
|
||||
m_forbidden.reset();
|
||||
m_csubst.reset();
|
||||
m_fsubst.reset();
|
||||
m_mc.reset();
|
||||
m_scopes.reset();
|
||||
}
|
||||
|
||||
void assertion_stack::expand(expr * f, proof * pr, expr_dependency * dep, expr_ref & new_f, proof_ref & new_pr, expr_dependency_ref & new_dep) {
|
||||
// TODO: expand definitions
|
||||
new_f = f;
|
||||
new_pr = pr;
|
||||
new_dep = dep;
|
||||
}
|
||||
|
||||
void assertion_stack::push_back(expr * f, proof * pr, expr_dependency * d) {
|
||||
if (m().is_true(f))
|
||||
return;
|
||||
if (m().is_false(f)) {
|
||||
m_inconsistent = true;
|
||||
}
|
||||
else {
|
||||
SASSERT(!m_inconsistent);
|
||||
}
|
||||
m().inc_ref(f);
|
||||
m_forms.push_back(f);
|
||||
if (proofs_enabled()) {
|
||||
m().inc_ref(pr);
|
||||
m_proofs.push_back(pr);
|
||||
}
|
||||
if (unsat_core_enabled()) {
|
||||
m().inc_ref(d);
|
||||
m_deps.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::quick_process(bool save_first, expr * & f, expr_dependency * d) {
|
||||
if (!m().is_and(f) && !(m().is_not(f) && m().is_or(to_app(f)->get_arg(0)))) {
|
||||
if (!save_first) {
|
||||
push_back(f, 0, d);
|
||||
}
|
||||
return;
|
||||
}
|
||||
typedef std::pair<expr *, bool> expr_pol;
|
||||
sbuffer<expr_pol, 64> todo;
|
||||
todo.push_back(expr_pol(f, true));
|
||||
while (!todo.empty()) {
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
expr_pol p = todo.back();
|
||||
expr * curr = p.first;
|
||||
bool pol = p.second;
|
||||
todo.pop_back();
|
||||
if (pol && m().is_and(curr)) {
|
||||
app * t = to_app(curr);
|
||||
unsigned i = t->get_num_args();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
todo.push_back(expr_pol(t->get_arg(i), true));
|
||||
}
|
||||
}
|
||||
else if (!pol && m().is_or(curr)) {
|
||||
app * t = to_app(curr);
|
||||
unsigned i = t->get_num_args();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
todo.push_back(expr_pol(t->get_arg(i), false));
|
||||
}
|
||||
}
|
||||
else if (m().is_not(curr)) {
|
||||
todo.push_back(expr_pol(to_app(curr)->get_arg(0), !pol));
|
||||
}
|
||||
else {
|
||||
if (!pol)
|
||||
curr = m().mk_not(curr);
|
||||
if (save_first) {
|
||||
f = curr;
|
||||
save_first = false;
|
||||
}
|
||||
else {
|
||||
push_back(curr, 0, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::process_and(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr) {
|
||||
unsigned num = f->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
slow_process(save_first && i == 0, f->get_arg(i), m().mk_and_elim(pr, i), d, out_f, out_pr);
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::process_not_or(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr) {
|
||||
unsigned num = f->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
expr * child = f->get_arg(i);
|
||||
if (m().is_not(child)) {
|
||||
expr * not_child = to_app(child)->get_arg(0);
|
||||
slow_process(save_first && i == 0, not_child, m().mk_not_or_elim(pr, i), d, out_f, out_pr);
|
||||
}
|
||||
else {
|
||||
expr_ref not_child(m());
|
||||
not_child = m().mk_not(child);
|
||||
slow_process(save_first && i == 0, not_child, m().mk_not_or_elim(pr, i), d, out_f, out_pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::slow_process(bool save_first, expr * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr) {
|
||||
if (m().is_and(f))
|
||||
process_and(save_first, to_app(f), pr, d, out_f, out_pr);
|
||||
else if (m().is_not(f) && m().is_or(to_app(f)->get_arg(0)))
|
||||
process_not_or(save_first, to_app(to_app(f)->get_arg(0)), pr, d, out_f, out_pr);
|
||||
else if (save_first) {
|
||||
out_f = f;
|
||||
out_pr = pr;
|
||||
}
|
||||
else {
|
||||
push_back(f, pr, d);
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::slow_process(expr * f, proof * pr, expr_dependency * d) {
|
||||
expr_ref out_f(m());
|
||||
proof_ref out_pr(m());
|
||||
slow_process(false, f, pr, d, out_f, out_pr);
|
||||
}
|
||||
|
||||
|
||||
void assertion_stack::assert_expr(expr * f, proof * pr, expr_dependency * d) {
|
||||
SASSERT(proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr)));
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
expr_ref new_f(m()); proof_ref new_pr(m()); expr_dependency_ref new_d(m());
|
||||
expand(f, pr, d, new_f, new_pr, new_d);
|
||||
if (proofs_enabled())
|
||||
slow_process(f, pr, d);
|
||||
else
|
||||
quick_process(false, f, d);
|
||||
}
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
// bool assertion_stack::is_expanded(expr * f) {
|
||||
// }
|
||||
#endif
|
||||
|
||||
void assertion_stack::update(unsigned i, expr * f, proof * pr, expr_dependency * d) {
|
||||
SASSERT(i >= m_form_qhead);
|
||||
SASSERT(proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr)));
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
if (proofs_enabled()) {
|
||||
expr_ref out_f(m());
|
||||
proof_ref out_pr(m());
|
||||
slow_process(true, f, pr, d, out_f, out_pr);
|
||||
if (!m_inconsistent) {
|
||||
if (m().is_false(out_f)) {
|
||||
push_back(out_f, out_pr, d);
|
||||
}
|
||||
else {
|
||||
m().inc_ref(out_f);
|
||||
m().dec_ref(m_forms[i]);
|
||||
m_forms[i] = out_f;
|
||||
|
||||
m().inc_ref(out_pr);
|
||||
m().dec_ref(m_proofs[i]);
|
||||
m_proofs[i] = out_pr;
|
||||
|
||||
if (unsat_core_enabled()) {
|
||||
m().inc_ref(d);
|
||||
m().dec_ref(m_deps[i]);
|
||||
m_deps[i] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
quick_process(true, f, d);
|
||||
if (!m_inconsistent) {
|
||||
if (m().is_false(f)) {
|
||||
push_back(f, 0, d);
|
||||
}
|
||||
else {
|
||||
m().inc_ref(f);
|
||||
m().dec_ref(m_forms[i]);
|
||||
m_forms[i] = f;
|
||||
|
||||
if (unsat_core_enabled()) {
|
||||
m().inc_ref(d);
|
||||
m().dec_ref(m_deps[i]);
|
||||
m_deps[i] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::expand_and_update(unsigned i, expr * f, proof * pr, expr_dependency * d) {
|
||||
SASSERT(i >= m_form_qhead);
|
||||
SASSERT(proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr)));
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
expr_ref new_f(m()); proof_ref new_pr(m()); expr_dependency_ref new_d(m());
|
||||
expand(f, pr, d, new_f, new_pr, new_d);
|
||||
update(i, new_f, new_pr, new_d);
|
||||
}
|
||||
|
||||
void assertion_stack::push() {
|
||||
}
|
||||
|
||||
void assertion_stack::pop(unsigned num_scopes) {
|
||||
}
|
||||
|
||||
void assertion_stack::commit() {
|
||||
}
|
||||
|
||||
void assertion_stack::add_filter(func_decl * f) const {
|
||||
}
|
||||
|
||||
void assertion_stack::add_definition(app * c, expr * def, proof * pr, expr_dependency * dep) {
|
||||
|
||||
}
|
||||
|
||||
void assertion_stack::add_definition(func_decl * f, quantifier * q, proof * pr, expr_dependency * dep) {
|
||||
}
|
||||
|
||||
void assertion_stack::convert(model_ref & m) {
|
||||
}
|
||||
|
||||
void assertion_stack::display(std::ostream & out) const {
|
||||
out << "(assertion-stack";
|
||||
unsigned sz = size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
out << "\n ";
|
||||
if (i == m_form_qhead)
|
||||
out << "==>\n";
|
||||
out << mk_ismt2_pp(form(i), m(), 2);
|
||||
}
|
||||
out << ")" << std::endl;
|
||||
}
|
||||
|
||||
bool assertion_stack::is_well_sorted() const {
|
||||
unsigned sz = size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
expr * t = form(i);
|
||||
if (!::is_well_sorted(m(), t))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_stack.h
|
||||
|
||||
Abstract:
|
||||
|
||||
It should be viewed as the "goal" object for incremental solvers.
|
||||
The main difference is the support of push/pop operations. Like a
|
||||
goal, an assertion_stack contains expressions, their proofs (if
|
||||
proof generation is enabled), and dependencies (if unsat core
|
||||
generation is enabled).
|
||||
|
||||
The assertions on the stack are grouped by scope levels. Scoped
|
||||
levels are created using push, and removed using pop.
|
||||
|
||||
Assertions may be "committed". Whenever a push is executed, all
|
||||
"uncommitted" assertions are automatically committed.
|
||||
Only uncommitted assertions can be simplified/reduced.
|
||||
|
||||
An assertion set has a limited model converter that only supports
|
||||
definitions (for variable/function elimination) and filters (for fresh
|
||||
symbols introduced by tactics).
|
||||
|
||||
Some tactics support assertion_stacks and can be applied to them.
|
||||
However, a tactic can only access the assertions on the top level.
|
||||
The assertion stack also informs the tactic which declarations
|
||||
can't be eliminated since they occur in the already committed part.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-17
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ASSERTION_STACK_H_
|
||||
#define _ASSERTION_STACK_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"model.h"
|
||||
#include"expr_substitution.h"
|
||||
#include"macro_substitution.h"
|
||||
|
||||
class assertion_stack {
|
||||
ast_manager & m_manager;
|
||||
unsigned m_ref_count;
|
||||
bool m_models_enabled; // model generation is enabled.
|
||||
bool m_proofs_enabled; // proof production is enabled. m_manager.proofs_enabled() must be true if m_proofs_enabled == true
|
||||
bool m_core_enabled; // unsat core extraction is enabled.
|
||||
bool m_inconsistent;
|
||||
ptr_vector<expr> m_forms;
|
||||
ptr_vector<proof> m_proofs;
|
||||
ptr_vector<expr_dependency> m_deps;
|
||||
unsigned m_form_qhead; // position of first uncommitted assertion
|
||||
unsigned m_mc_qhead;
|
||||
|
||||
// Set of declarations that can't be eliminated
|
||||
obj_hashtable<func_decl> m_forbidden_set;
|
||||
func_decl_ref_vector m_forbidden;
|
||||
|
||||
// Limited model converter support, it supports only extensions
|
||||
// and filters.
|
||||
// It should be viewed as combination of extension_model_converter and
|
||||
// filter_model_converter for goals.
|
||||
expr_substitution m_csubst; // substitution for eliminated constants
|
||||
macro_substitution m_fsubst; // substitution for eliminated functions
|
||||
|
||||
// Model converter is just a sequence of tagged pointers.
|
||||
// Tag 0 (extension) func_decl was eliminated, and its definition is in m_vsubst or m_fsubst.
|
||||
// Tag 1 (filter) func_decl was introduced by tactic, and must be removed from model.
|
||||
ptr_vector<func_decl> m_mc;
|
||||
|
||||
struct scope {
|
||||
unsigned m_forms_lim;
|
||||
unsigned m_forbidden_vars_lim;
|
||||
unsigned m_mc_lim;
|
||||
bool m_inconsistent_old;
|
||||
};
|
||||
|
||||
svector<scope> m_scopes;
|
||||
|
||||
void init(bool proofs_enabled, bool models_enabled, bool core_enabled);
|
||||
void expand(expr * f, proof * pr, expr_dependency * dep, expr_ref & new_f, proof_ref & new_pr, expr_dependency_ref & new_dep);
|
||||
void push_back(expr * f, proof * pr, expr_dependency * d);
|
||||
void quick_process(bool save_first, expr * & f, expr_dependency * d);
|
||||
void process_and(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr);
|
||||
void process_not_or(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr);
|
||||
void slow_process(bool save_first, expr * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr);
|
||||
void slow_process(expr * f, proof * pr, expr_dependency * d);
|
||||
|
||||
public:
|
||||
assertion_stack(ast_manager & m, bool models_enabled = true, bool core_enabled = true);
|
||||
assertion_stack(ast_manager & m, bool proofs_enabled, bool models_enabled, bool core_enabled);
|
||||
~assertion_stack();
|
||||
|
||||
void reset();
|
||||
|
||||
void inc_ref() { ++m_ref_count; }
|
||||
void dec_ref() { --m_ref_count; if (m_ref_count == 0) dealloc(this); }
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
|
||||
bool models_enabled() const { return m_models_enabled; }
|
||||
bool proofs_enabled() const { return m_proofs_enabled; }
|
||||
bool unsat_core_enabled() const { return m_core_enabled; }
|
||||
bool inconsistent() const { return m_inconsistent; }
|
||||
|
||||
unsigned size() const { return m_forms.size(); }
|
||||
unsigned qhead() const { return m_form_qhead; }
|
||||
expr * form(unsigned i) const { return m_forms[i]; }
|
||||
proof * pr(unsigned i) const { return proofs_enabled() ? static_cast<proof*>(m_proofs[i]) : 0; }
|
||||
expr_dependency * dep(unsigned i) const { return unsat_core_enabled() ? m_deps[i] : 0; }
|
||||
|
||||
void assert_expr(expr * f, proof * pr, expr_dependency * d);
|
||||
void assert_expr(expr * f) {
|
||||
assert_expr(f, proofs_enabled() ? m().mk_asserted(f) : 0, 0);
|
||||
}
|
||||
void update(unsigned i, expr * f, proof * pr = 0, expr_dependency * dep = 0);
|
||||
void expand_and_update(unsigned i, expr * f, proof * pr = 0, expr_dependency * d = 0);
|
||||
|
||||
void commit();
|
||||
void push();
|
||||
void pop(unsigned num_scopes);
|
||||
unsigned scope_lvl() const { return m_scopes.size(); }
|
||||
|
||||
bool is_well_sorted() const;
|
||||
|
||||
bool is_forbidden(func_decl * f) const { return m_forbidden_set.contains(f); }
|
||||
void add_filter(func_decl * f) const;
|
||||
void add_definition(app * c, expr * def, proof * pr, expr_dependency * dep);
|
||||
void add_definition(func_decl * f, quantifier * q, proof * pr, expr_dependency * dep);
|
||||
|
||||
void convert(model_ref & m);
|
||||
|
||||
void display(std::ostream & out) const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,33 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
big_rational.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Big rational numbers
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2006-09-18.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _BIG_RATIONAL_H_
|
||||
#define _BIG_RATIONAL_H_
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include"..\msbig_rational\msbig_rational.h"
|
||||
#else
|
||||
#ifdef NO_GMP
|
||||
#include"dummy_big_rational.h"
|
||||
#else
|
||||
#include"gmp_big_rational.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* _BIG_RATIONAL_H_ */
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
AC_PREREQ(2.50)
|
||||
AC_INIT(lib/util.h)
|
||||
|
||||
ARITH="internal"
|
||||
AC_ARG_WITH([gmp], [AS_HELP_STRING([--with-gmp], [Use GMP for multi-precision naturals (default=no)])], [use_gmp=yes], [use_gmp=no])
|
||||
AS_IF([test "$use_gmp" = "yes"],[
|
||||
ARITH="gmp"
|
||||
CPPFLAGS="$CPPFLAGS -D_MP_GMP"
|
||||
],[
|
||||
CPPFLAGS="$CPPFLAGS -D_MP_INTERNAL"
|
||||
])
|
||||
AC_SUBST(EXTRA_LIB_SRCS)
|
||||
|
||||
AC_ARG_WITH(python,
|
||||
[AS_HELP_STRING([--with-python=PYTHON_PATH],
|
||||
[specify the location of the python 2.x executable.])])
|
||||
|
||||
PYTHON="python"
|
||||
if test "x$with_python" != x; then
|
||||
PYTHON="$with_python"
|
||||
fi
|
||||
|
||||
AC_SUBST(PYTHON)
|
||||
|
||||
AC_PATH_PROG([D2U], [dos2unix], [no], [~/bin$PATH_SEPARATOR$PATH])
|
||||
AS_IF([test "$D2U" = "no"], [AC_MSG_ERROR(dos2unix not found)])
|
||||
AC_SUBST(D2U)
|
||||
|
||||
AC_PROG_CXX(g++)
|
||||
AC_PROG_MAKE_SET
|
||||
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
host_os=`uname -s`
|
||||
|
||||
AS_IF([test "$host_os" = "Darwin"], [
|
||||
PLATFORM=osx
|
||||
SO_EXT=dylib
|
||||
SLIBFLAGS="-dynamiclib -fopenmp"
|
||||
COMP_VERSIONS="-compatibility_version \$(Z3_VERSION) -current_version \$(Z3_VERSION)"
|
||||
STATIC_FLAGS=
|
||||
CPPFLAGS+=""
|
||||
], [test "$host_os" = "Linux"], [
|
||||
PLATFORM=linux
|
||||
SO_EXT=so
|
||||
LDFLAGS=-lrt
|
||||
SLIBFLAGS="-shared -fopenmp"
|
||||
COMP_VERSIONS=
|
||||
STATIC_FLAGS=-static
|
||||
], [test "${host_os:0:6}" = "CYGWIN"], [
|
||||
PLATFORM=win
|
||||
SO_EXT=dll
|
||||
LDFLAGS=
|
||||
SLIBFLAGS="-shared -fopenmp"
|
||||
COMP_VERSIONS=
|
||||
STATIC_FLAGS=-static
|
||||
CPPFLAGS+=" -D_CYGWIN"
|
||||
],
|
||||
[
|
||||
AC_MSG_ERROR([Unknown host platform: $host_os])
|
||||
])
|
||||
AC_SUBST(PLATFORM)
|
||||
AC_SUBST(SO_EXT)
|
||||
AC_SUBST(SLIBFLAGS)
|
||||
AC_SUBST(COMP_VERSIONS)
|
||||
AC_SUBST(STATIC_FLAGS)
|
||||
|
||||
cat > tst_python.py <<EOF
|
||||
from sys import version
|
||||
if version >= "3":
|
||||
exit(1)
|
||||
exit(0)
|
||||
EOF
|
||||
|
||||
if $PYTHON tst_python.py; then
|
||||
HAS_PYTHON="1"
|
||||
HAS_PYTHON_MSG="yes"
|
||||
cat > get_py_dir.py << EOF
|
||||
import distutils.sysconfig
|
||||
print distutils.sysconfig.get_python_lib()
|
||||
EOF
|
||||
if $PYTHON get_py_dir.py > dir.txt; then
|
||||
PYTHON_PACKAGE_DIR=`cat dir.txt`
|
||||
else
|
||||
HAS_PYTHON="0"
|
||||
HAS_PYTHON_MSG="no"
|
||||
fi
|
||||
rm -f dir.txt
|
||||
rm -f get_py_dir.py
|
||||
else
|
||||
HAS_PYTHON="0"
|
||||
HAS_PYTHON_MSG="no"
|
||||
fi
|
||||
AC_SUBST(PYTHON_PACKAGE_DIR)
|
||||
AC_SUBST(HAS_PYTHON)
|
||||
rm -f tst_python.py
|
||||
|
||||
cat > tst64.c <<EOF
|
||||
int main() {
|
||||
return sizeof(unsigned) == sizeof(void*);
|
||||
}
|
||||
EOF
|
||||
|
||||
AC_SUBST(EXTRA_LIBS)
|
||||
|
||||
g++ $CPPFLAGS tst64.c -o tst64
|
||||
if ./tst64; then
|
||||
dnl In 64-bit systems we have to compile using -fPIC
|
||||
CPPFLAGS="$CPPFLAGS -D_AMD64_"
|
||||
dnl Only enable use of thread local storage for 64-bit Linux. It is disabled for OSX and 32-bit Linux
|
||||
if test $PLATFORM = "linux"; then
|
||||
CPPFLAGS="$CPPFLAGS -D_USE_THREAD_LOCAL"
|
||||
fi
|
||||
CXXFLAGS="-fPIC"
|
||||
EXTRA_LIBS=""
|
||||
dnl Rewrite -lz3-gmp to -lz3 in the files:
|
||||
dnl - test_capi/build-external-linux.sh
|
||||
dnl - test_user_theory/build-external-linux.sh
|
||||
dnl Reason: the library libz3-gmp.so is not available in 64-bit systems
|
||||
dnl sed 's|lz3-gmp|lz3|' test_capi/build-external-linux.sh > tmp.sh
|
||||
dnl mv tmp.sh test_capi/build-external-linux.sh
|
||||
dnl sed 's|lz3-gmp|lz3|' test_user_theory/build-external-linux.sh > tmp.sh
|
||||
dnl mv tmp.sh test_user_theory/build-external-linux.sh
|
||||
else
|
||||
CXXFLAGS=""
|
||||
dnl In 64-bit systems it is not possible to build a dynamic library using static gmp.
|
||||
dnl EXTRA_LIBS="\$(BIN_DIR)/lib\$(Z3)-gmp.so"
|
||||
fi
|
||||
rm -f tst64.c
|
||||
rm -f tst64
|
||||
|
||||
AC_SUBST(GMP_STATIC_LIB)
|
||||
GMP_STATIC_LIB=""
|
||||
|
||||
if test "$ARITH" = "gmp"; then
|
||||
AC_CHECK_HEADER([gmp.h], GMP='gmp', AC_MSG_ERROR([GMP include file not found]))
|
||||
AC_SUBST(LIBS)
|
||||
AC_CHECK_LIB(gmp, __gmpz_cmp, LIBS="-lgmp $LIBS", AC_MSG_ERROR([GMP library not found]))
|
||||
dnl Look for libgmp.a at /usr/local/lib and /usr/lib
|
||||
dnl TODO: make the following test more robust...
|
||||
if test -e /usr/local/lib/libgmp.a; then
|
||||
GMP_STATIC_LIB="/usr/local/lib/libgmp.a"
|
||||
else if test -e /usr/lib/libgmp.a; then
|
||||
GMP_STATIC_LIB="/usr/lib/libgmp.a"
|
||||
else if test -e /usr/lib/libgmp.dll.a; then
|
||||
GMP_STATIC_LIB="/usr/lib/libgmp.dll.a"
|
||||
else
|
||||
AC_MSG_ERROR([Failed to find libgmp.a])
|
||||
fi fi fi
|
||||
fi
|
||||
|
||||
AC_PROG_CXXCPP
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Z3 was configured with success.
|
||||
Host platform: $PLATFORM
|
||||
Arithmetic: $ARITH
|
||||
Python Support: $HAS_PYTHON_MSG
|
||||
Python: $PYTHON
|
||||
Prefix: $prefix
|
||||
|
||||
Type 'make' to compile Z3.
|
||||
Type 'sudo make install' to install Z3.
|
||||
Type 'sudo make install-z3py' to install Z3 Python (Z3Py) bindings.
|
||||
EOF
|
|
@ -1,27 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
contains_var.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2007-06-12.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _CONTAINS_VAR_H_
|
||||
#define _CONTAINS_VAR_H_
|
||||
|
||||
class ast;
|
||||
|
||||
bool contains_var(ast * n);
|
||||
|
||||
#endif /* _CONTAINS_VAR_H_ */
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_simplifier_plugin.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-08-10
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"dl_simplifier_plugin.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
dl_simplifier_plugin::dl_simplifier_plugin(ast_manager& m)
|
||||
: simplifier_plugin(symbol("datalog_relation"), m),
|
||||
m_util(m)
|
||||
{}
|
||||
|
||||
bool dl_simplifier_plugin::reduce(
|
||||
func_decl * f, unsigned num_args, expr* const* args, expr_ref& result) {
|
||||
uint64 v1, v2;
|
||||
switch(f->get_decl_kind()) {
|
||||
case OP_DL_LT:
|
||||
if (m_util.try_get_constant(args[0], v1) &&
|
||||
m_util.try_get_constant(args[1], v2)) {
|
||||
result = (v1 < v2)?m_manager.mk_true():m_manager.mk_false();
|
||||
return true;
|
||||
}
|
||||
// x < x <=> false
|
||||
if (args[0] == args[1]) {
|
||||
result = m_manager.mk_false();
|
||||
return true;
|
||||
}
|
||||
// x < 0 <=> false
|
||||
if (m_util.try_get_constant(args[1], v2) && v2 == 0) {
|
||||
result = m_manager.mk_false();
|
||||
return true;
|
||||
}
|
||||
// 0 < x <=> 0 != x
|
||||
if (m_util.try_get_constant(args[1], v1) && v1 == 0) {
|
||||
result = m_manager.mk_not(m_manager.mk_eq(args[0], args[1]));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_simplifier_plugin.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-08-10
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _DL_SIMPLIFIER_PLUGIN_H_
|
||||
#define _DL_SIMPLIFIER_PLUGIN_H_
|
||||
|
||||
#include"dl_decl_plugin.h"
|
||||
#include "simplifier_plugin.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
class dl_simplifier_plugin : public simplifier_plugin {
|
||||
dl_decl_util m_util;
|
||||
public:
|
||||
dl_simplifier_plugin(ast_manager& m);
|
||||
|
||||
virtual bool reduce(func_decl * f, unsigned num_args, expr* const* args, expr_ref& result);
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
#endif /* _DL_SIMPLIFIER_PLUGIN_H_ */
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dummy_big_rational.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Dummy big rational
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2006-09-26.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _DUMMY_BIG_RATIONAL_H_
|
||||
#define _DUMMY_BIG_RATIONAL_H_
|
||||
|
||||
#include<string>
|
||||
#include"debug.h"
|
||||
|
||||
class big_rational {
|
||||
public:
|
||||
big_rational() { }
|
||||
big_rational(int n) {}
|
||||
~big_rational() {}
|
||||
void reset() {}
|
||||
unsigned hash() const { return 0; }
|
||||
void set(int num, int den) { UNREACHABLE(); }
|
||||
void set(const char * str) { UNREACHABLE(); }
|
||||
bool is_int() const { UNREACHABLE(); return false; }
|
||||
long get_int() const { UNREACHABLE(); return 0; }
|
||||
void neg() { UNREACHABLE(); }
|
||||
big_rational & operator=(const big_rational & r) { UNREACHABLE(); return *this; }
|
||||
bool operator==(const big_rational & r) const { UNREACHABLE(); return false; }
|
||||
bool operator<(const big_rational & r) const { UNREACHABLE(); return false; }
|
||||
big_rational & operator+=(const big_rational & r) { UNREACHABLE(); return *this; }
|
||||
big_rational & operator-=(const big_rational & r) { UNREACHABLE(); return *this; }
|
||||
big_rational & operator*=(const big_rational & r) { UNREACHABLE(); return *this; }
|
||||
big_rational & operator/=(const big_rational & r) { UNREACHABLE(); return *this; }
|
||||
big_rational & operator%=(const big_rational & r) { UNREACHABLE(); return *this; }
|
||||
friend void div(const big_rational & r1, const big_rational & r2, big_rational & result) { UNREACHABLE(); }
|
||||
void get_numerator(big_rational & result) { UNREACHABLE(); }
|
||||
void get_denominator(big_rational & result) { UNREACHABLE(); }
|
||||
void get_floor(big_rational & result) { UNREACHABLE(); }
|
||||
std::string to_string() const { UNREACHABLE(); return std::string(""); }
|
||||
};
|
||||
|
||||
#endif /* _DUMMY_BIG_RATIONAL_H_ */
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2007 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
expr_weight.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Functor for computing the weight of an expression.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2008-01-11
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"expr_weight.h"
|
||||
#include"recurse_expr_def.h"
|
||||
|
||||
template class recurse_expr<weight, expr_weight_visitor, true>;
|
||||
|
||||
weight expr_weight_visitor::visit(app const * n, weight const * args) {
|
||||
weight r(1);
|
||||
unsigned j = n->get_num_args();
|
||||
while (j > 0) {
|
||||
--j;
|
||||
r += args[j];
|
||||
}
|
||||
return r;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2007 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
expr_weight.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Functor for computing the weight of an expression.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2008-01-11
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _EXPR_WEIGHT_H_
|
||||
#define _EXPR_WEIGHT_H_
|
||||
|
||||
#include"recurse_expr.h"
|
||||
#include"approx_nat.h"
|
||||
|
||||
typedef approx_nat weight;
|
||||
|
||||
struct expr_weight_visitor {
|
||||
weight visit(var * n) { return weight(1); }
|
||||
weight visit(app const * n, weight const * args);
|
||||
weight visit(quantifier * n, weight body, weight *, weight *) { body += 1; return body; }
|
||||
};
|
||||
|
||||
typedef recurse_expr<weight, expr_weight_visitor, true> expr_weight;
|
||||
|
||||
#endif /* _EXPR_WEIGHT_H_ */
|
File diff suppressed because it is too large
Load diff
|
@ -1,29 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
gl_tactic.h
|
||||
|
||||
Abstract:
|
||||
|
||||
A T-function/Goldreich Levin-based heuristic.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj (nbjorner) 2011-12-18
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _GL_TACTIC_H_
|
||||
#define _GL_TACTIC_H_
|
||||
|
||||
#include"tactic.h"
|
||||
|
||||
namespace gl {
|
||||
tactic * mk_tactic(ast_manager& m, params_ref const& p);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,117 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
gmp_big_rational.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Big rationals using GMP
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2006-09-26.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<limits.h>
|
||||
|
||||
#include"gmp_big_rational.h"
|
||||
#include"trace.h"
|
||||
#include"buffer.h"
|
||||
|
||||
#ifndef NO_GMP
|
||||
mpz_t big_rational::m_tmp;
|
||||
bool big_rational::m_tmp_initialized = false;
|
||||
mpz_t big_rational::m_int_min;
|
||||
mpz_t big_rational::m_int_max;
|
||||
mpz_t big_rational::m_uint_max;
|
||||
mpz_t big_rational::m_two32;
|
||||
mpz_t big_rational::m_int64_min;
|
||||
mpz_t big_rational::m_int64_max;
|
||||
mpz_t big_rational::m_uint64_max;
|
||||
bool big_rational::m_has_limits = false;
|
||||
|
||||
void big_rational::init_limits() {
|
||||
mpz_init(m_int_min);
|
||||
mpz_init(m_int_max);
|
||||
mpz_init(m_uint_max);
|
||||
mpz_init(m_two32);
|
||||
mpz_init(m_int64_min);
|
||||
mpz_init(m_int64_max);
|
||||
mpz_init(m_uint64_max);
|
||||
mpz_set_si(m_int_min, INT_MIN);
|
||||
mpz_set_si(m_int_max, INT_MAX);
|
||||
mpz_set_ui(m_uint_max, UINT_MAX);
|
||||
mpz_set_ui(m_two32, UINT_MAX);
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpz_set_si(tmp, 1);
|
||||
mpz_add(m_two32, m_two32, tmp);
|
||||
unsigned max_l = static_cast<unsigned>(INT64_MAX % static_cast<int64>(UINT_MAX));
|
||||
unsigned max_h = static_cast<unsigned>(INT64_MAX / static_cast<int64>(UINT_MAX));
|
||||
mpz_set_ui(m_int64_max, max_h);
|
||||
mpz_mul(m_int64_max, m_uint_max, m_int64_max);
|
||||
mpz_set_ui(tmp, max_l);
|
||||
mpz_add(m_int64_max, tmp, m_int64_max);
|
||||
mpz_neg(m_int64_min, m_int64_max);
|
||||
mpz_set_si(tmp, -1);
|
||||
mpz_add(m_int64_min, m_int64_min, tmp);
|
||||
mpz_set(m_uint64_max, m_int64_max);
|
||||
mpz_set_si(tmp, 2);
|
||||
mpz_mul(m_uint64_max, m_uint64_max, tmp);
|
||||
mpz_set_si(tmp, 1);
|
||||
mpz_add(m_uint64_max, m_uint64_max, tmp);
|
||||
m_has_limits = true;
|
||||
}
|
||||
|
||||
std::string big_rational::to_string() const {
|
||||
size_t sz = mpz_sizeinbase(mpq_numref(m_data), 10) + mpz_sizeinbase(mpq_numref(m_data), 10) + 3;
|
||||
buffer<char> b(sz, 0);
|
||||
mpq_get_str(b.c_ptr(), 10, m_data);
|
||||
std::string result(b.c_ptr());
|
||||
return result;
|
||||
}
|
||||
|
||||
int64 big_rational::get_int64() const {
|
||||
if (!m_has_limits) {
|
||||
init_limits();
|
||||
}
|
||||
SASSERT(is_int64());
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpq_get_num(tmp, m_data);
|
||||
if (sizeof(int64) == sizeof(long) || mpz_fits_slong_p(tmp)) {
|
||||
return mpz_get_si(tmp);
|
||||
}
|
||||
else {
|
||||
mpz_mod(tmp, tmp, two32());
|
||||
int64 r = static_cast<int64>(mpz_get_ui(tmp));
|
||||
mpq_get_num(tmp, m_data);
|
||||
mpz_div(tmp, tmp, two32());
|
||||
r += static_cast<int64>(mpz_get_si(tmp)) << static_cast<int64>(32);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
uint64 big_rational::get_uint64() const {
|
||||
if (!m_has_limits) {
|
||||
init_limits();
|
||||
}
|
||||
SASSERT(is_uint64());
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpq_get_num(tmp, m_data);
|
||||
if (sizeof(uint64) == sizeof(unsigned long) || mpz_fits_ulong_p(tmp)) {
|
||||
return mpz_get_ui(tmp);
|
||||
}
|
||||
else {
|
||||
mpz_mod(tmp, tmp, two32());
|
||||
uint64 r = static_cast<uint64>(mpz_get_ui(tmp));
|
||||
mpq_get_num(tmp, m_data);
|
||||
mpz_div(tmp, tmp, two32());
|
||||
r += static_cast<uint64>(mpz_get_ui(tmp)) << static_cast<uint64>(32);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,193 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
gmp_big_rational.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Big rationals using gmp
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2006-09-26.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _GMP_BIG_RATIONAL_H_
|
||||
#define _GMP_BIG_RATIONAL_H_
|
||||
|
||||
#ifndef NO_GMP
|
||||
|
||||
#include<string>
|
||||
#include<gmp.h>
|
||||
#include"util.h"
|
||||
#include"debug.h"
|
||||
#include"trace.h"
|
||||
|
||||
class big_rational {
|
||||
mpq_t m_data;
|
||||
static mpz_t m_tmp;
|
||||
static bool m_tmp_initialized;
|
||||
static mpz_t & get_tmp() {
|
||||
if (!m_tmp_initialized) {
|
||||
mpz_init(m_tmp);
|
||||
m_tmp_initialized = true;
|
||||
}
|
||||
return m_tmp;
|
||||
}
|
||||
static mpz_t m_int_min;
|
||||
static mpz_t m_int_max;
|
||||
static mpz_t m_uint_max;
|
||||
static mpz_t m_two32;
|
||||
static mpz_t m_int64_min;
|
||||
static mpz_t m_int64_max;
|
||||
static mpz_t m_uint64_max;
|
||||
static bool m_has_limits;
|
||||
static void init_limits();
|
||||
|
||||
static mpz_t & int64_min() {
|
||||
if (!m_has_limits) {
|
||||
init_limits();
|
||||
}
|
||||
return m_int64_min;
|
||||
}
|
||||
|
||||
static mpz_t & int64_max() {
|
||||
if (!m_has_limits) {
|
||||
init_limits();
|
||||
}
|
||||
return m_int64_max;
|
||||
}
|
||||
|
||||
static mpz_t & uint64_max() {
|
||||
if (!m_has_limits) {
|
||||
init_limits();
|
||||
}
|
||||
return m_uint64_max;
|
||||
}
|
||||
|
||||
static mpz_t & uint_max() {
|
||||
if (!m_has_limits) {
|
||||
init_limits();
|
||||
}
|
||||
return m_uint_max;
|
||||
}
|
||||
|
||||
static mpz_t & two32() {
|
||||
if (!m_has_limits) {
|
||||
init_limits();
|
||||
}
|
||||
return m_two32;
|
||||
}
|
||||
|
||||
public:
|
||||
big_rational() { mpq_init(m_data); reset(); }
|
||||
big_rational(int n) { mpq_init(m_data); mpq_set_si(m_data, n, 1); }
|
||||
~big_rational() { mpq_clear(m_data); }
|
||||
void reset() { mpq_set_si(m_data, 0, 1); }
|
||||
unsigned hash() const { return mpz_get_si(mpq_numref(m_data)); }
|
||||
void set(int num, int den) {
|
||||
mpq_set_si(m_data, num, den);
|
||||
mpq_canonicalize(m_data);
|
||||
}
|
||||
void setu(unsigned num) {
|
||||
mpq_set_ui(m_data, num, 1);
|
||||
mpq_canonicalize(m_data);
|
||||
}
|
||||
void set(const char * str) {
|
||||
mpq_set_str(m_data, str, 10);
|
||||
}
|
||||
bool is_int() const {
|
||||
return mpz_cmp_ui(mpq_denref(m_data), 1) == 0;
|
||||
}
|
||||
bool is_even() const {
|
||||
if (!is_int()) {
|
||||
return false;
|
||||
}
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpq_get_num(tmp, m_data);
|
||||
return mpz_even_p(tmp) != 0;
|
||||
}
|
||||
bool is_int64() const {
|
||||
if (!is_int()) {
|
||||
return false;
|
||||
}
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpq_get_num(tmp, m_data);
|
||||
return mpz_fits_slong_p(tmp) ||
|
||||
(mpz_cmp(tmp, int64_min()) >= 0 && mpz_cmp(tmp, int64_max()) <= 0);
|
||||
}
|
||||
bool is_uint64() const {
|
||||
if (!is_int()) {
|
||||
return false;
|
||||
}
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpq_get_num(tmp, m_data);
|
||||
return mpz_sgn(tmp) >= 0 && (mpz_fits_ulong_p(tmp) || mpz_cmp(tmp, uint64_max()) <= 0);
|
||||
}
|
||||
int64 get_int64() const;
|
||||
uint64 get_uint64() const;
|
||||
void neg() { mpq_neg(m_data, m_data); }
|
||||
big_rational & operator=(const big_rational & r) {
|
||||
mpq_set(m_data, r.m_data);
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const big_rational & r) const { return mpq_equal(m_data, r.m_data) != 0; }
|
||||
bool operator<(const big_rational & r) const { return mpq_cmp(m_data, r.m_data) < 0; }
|
||||
big_rational & operator+=(const big_rational & r) {
|
||||
mpq_add(m_data, m_data, r.m_data);
|
||||
return *this;
|
||||
}
|
||||
big_rational & operator-=(const big_rational & r) {
|
||||
mpq_sub(m_data, m_data, r.m_data);
|
||||
return *this;
|
||||
}
|
||||
big_rational & operator*=(const big_rational & r) {
|
||||
mpq_mul(m_data, m_data, r.m_data);
|
||||
return *this;
|
||||
}
|
||||
big_rational & operator/=(const big_rational & r) {
|
||||
mpq_div(m_data, m_data, r.m_data);
|
||||
return *this;
|
||||
}
|
||||
big_rational & operator%=(const big_rational & r) {
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpz_tdiv_r(tmp, mpq_numref(m_data), mpq_numref(r.m_data));
|
||||
mpq_set_z(m_data, tmp);
|
||||
return *this;
|
||||
}
|
||||
friend void div(const big_rational & r1, const big_rational & r2, big_rational & result) {
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpz_tdiv_q(tmp, mpq_numref(r1.m_data), mpq_numref(r2.m_data));
|
||||
mpq_set_z(result.m_data, tmp);
|
||||
}
|
||||
void get_numerator(big_rational & result) {
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpq_get_num(tmp, m_data);
|
||||
mpq_set_z(result.m_data, tmp);
|
||||
}
|
||||
void get_denominator(big_rational & result) {
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpq_get_den(tmp, m_data);
|
||||
mpq_set_z(result.m_data, tmp);
|
||||
}
|
||||
void get_floor(big_rational & result) {
|
||||
mpz_t & tmp = get_tmp();
|
||||
mpz_fdiv_q(tmp, mpq_numref(m_data), mpq_denref(m_data));
|
||||
mpq_set_z(result.m_data, tmp);
|
||||
}
|
||||
std::string to_string() const;
|
||||
#ifdef Z3DEBUG
|
||||
static void test() {
|
||||
init_limits();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _GMP_BIG_RATIONAL_H_ */
|
||||
|
|
@ -1,424 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
lru_cache.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
expr -> expr LRU cache
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-12
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"lru_cache.h"
|
||||
#include"ast_ll_pp.h"
|
||||
|
||||
#define MIN_MAX_SIZE 1024
|
||||
#define INITIAL_CAPACITY 128
|
||||
|
||||
lru_cache::cell * lru_cache::allocate(unsigned capacity) {
|
||||
cell * mem = static_cast<cell*>(memory::allocate(sizeof(cell) * capacity));
|
||||
memset(mem, 0, sizeof(cell)*capacity);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void lru_cache::deallocate(cell * table) {
|
||||
memory::deallocate(table);
|
||||
}
|
||||
|
||||
lru_cache::cell * lru_cache::copy_table(cell * old_head, cell * new_table, unsigned new_capacity) {
|
||||
SASSERT(old_head);
|
||||
cell * it = old_head;
|
||||
cell * new_head = 0;
|
||||
cell * prev = 0;
|
||||
do {
|
||||
expr * k = it->m_key;
|
||||
unsigned h = k->hash();
|
||||
unsigned mask = new_capacity - 1;
|
||||
unsigned idx = h & mask;
|
||||
|
||||
cell * begin = new_table + idx;
|
||||
cell * end = new_table + new_capacity;
|
||||
cell * curr = begin;
|
||||
|
||||
for (; curr != end; ++curr) {
|
||||
if (curr->m_key == 0) {
|
||||
curr->m_key = k;
|
||||
curr->m_value = it->m_value;
|
||||
LCS_CODE(curr->m_hits = it->m_hits;);
|
||||
LCS_CODE(curr->m_birthday = it->m_birthday;);
|
||||
if (prev == 0) {
|
||||
new_head = curr;
|
||||
}
|
||||
else {
|
||||
prev->m_next = curr;
|
||||
curr->m_prev = prev;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
for (curr = new_table; curr != begin; ++curr) {
|
||||
if (curr->m_key == 0) {
|
||||
curr->m_key = k;
|
||||
curr->m_value = it->m_value;
|
||||
SASSERT(prev != 0);
|
||||
prev->m_next = curr;
|
||||
curr->m_prev = prev;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
UNREACHABLE();
|
||||
end:
|
||||
prev = curr;
|
||||
it = it->m_next;
|
||||
}
|
||||
while (it != old_head);
|
||||
prev->m_next = new_head;
|
||||
new_head->m_prev = prev;
|
||||
return new_head;
|
||||
}
|
||||
|
||||
void lru_cache::expand_table() {
|
||||
SASSERT(m_head);
|
||||
unsigned new_capacity = m_capacity * 2;
|
||||
TRACE("lru_cache", tout << "expanding table new_capacity: " << new_capacity << "\n";);
|
||||
cell * new_table = allocate(new_capacity);
|
||||
m_head = copy_table(m_head, new_table, new_capacity);
|
||||
deallocate(m_table);
|
||||
m_table = new_table;
|
||||
m_capacity = new_capacity;
|
||||
m_num_deleted = 0;
|
||||
SASSERT(check_invariant());
|
||||
}
|
||||
|
||||
void lru_cache::remove_deleted() {
|
||||
SASSERT(m_head);
|
||||
TRACE("lru_cache", tout << "removing deleted entries\n";);
|
||||
cell * new_table = allocate(m_capacity);
|
||||
m_head = copy_table(m_head, new_table, m_capacity);
|
||||
deallocate(m_table);
|
||||
m_table = new_table;
|
||||
m_num_deleted = 0;
|
||||
SASSERT(check_invariant());
|
||||
}
|
||||
|
||||
void lru_cache::init() {
|
||||
if (m_max_size < MIN_MAX_SIZE)
|
||||
m_max_size = MIN_MAX_SIZE;
|
||||
m_size = 0;
|
||||
m_capacity = INITIAL_CAPACITY;
|
||||
m_table = allocate(m_capacity);
|
||||
m_head = 0;
|
||||
m_num_deleted = 0;
|
||||
}
|
||||
|
||||
lru_cache::lru_cache(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_max_size(m.get_num_asts() * 100) {
|
||||
init();
|
||||
TRACE("lru_cache", tout << "new lru cache, max-size: " << m_max_size << "\n";);
|
||||
}
|
||||
|
||||
lru_cache::lru_cache(ast_manager & m, unsigned max_size):
|
||||
m_manager(m),
|
||||
m_max_size(max_size) {
|
||||
init();
|
||||
}
|
||||
|
||||
void lru_cache::dec_refs() {
|
||||
if (m_head) {
|
||||
cell * curr = m_head;
|
||||
#ifdef Z3DEBUG
|
||||
unsigned sz = 0;
|
||||
#endif
|
||||
do {
|
||||
m_manager.dec_ref(curr->m_key);
|
||||
m_manager.dec_ref(curr->m_value);
|
||||
curr = curr->m_next;
|
||||
DEBUG_CODE(sz++;);
|
||||
}
|
||||
while (curr != m_head);
|
||||
SASSERT(sz == m_size);
|
||||
}
|
||||
}
|
||||
|
||||
lru_cache::~lru_cache() {
|
||||
TRACE("lru_cache", tout << "destructor invoked size: " << m_size << ", m_head: " << m_head << "\n";);
|
||||
LCS_CODE({
|
||||
if (m_head) {
|
||||
unsigned used = 0;
|
||||
cell * curr = m_head;
|
||||
do {
|
||||
if (curr->m_hits > 0)
|
||||
used++;
|
||||
curr = curr->m_next;
|
||||
}
|
||||
while (curr != m_head);
|
||||
verbose_stream() << "[lru_cache] num-used: " << used << " size: " << m_size << "\n";
|
||||
}
|
||||
});
|
||||
SASSERT(check_invariant());
|
||||
dec_refs();
|
||||
deallocate(m_table);
|
||||
}
|
||||
|
||||
void lru_cache::del_least_used() {
|
||||
SASSERT(m_head);
|
||||
SASSERT(m_size >= 2);
|
||||
cell * c = m_head->m_prev;
|
||||
TRACE("lru_cache", tout << "del least used: " << mk_bounded_pp(c->m_key, m_manager, 3) << "\n";);
|
||||
LCS_CODE({
|
||||
static unsigned non_zero = 0;
|
||||
static unsigned long long total_hits;
|
||||
static unsigned counter = 0;
|
||||
if (c->m_hits > 0) {
|
||||
counter++;
|
||||
total_hits += c->m_hits;
|
||||
non_zero++;
|
||||
if (non_zero % 1000 == 0)
|
||||
verbose_stream() << "[lru_cache] cell with non-zero hits was deleted: " << non_zero << " avg: " << ((double)total_hits/(double) counter) << std::endl;
|
||||
}
|
||||
});
|
||||
SASSERT(c->m_prev != c);
|
||||
SASSERT(c->m_next != c);
|
||||
m_manager.dec_ref(c->m_key);
|
||||
m_manager.dec_ref(c->m_value);
|
||||
c->m_prev->m_next = c->m_next;
|
||||
c->m_next->m_prev = c->m_prev;
|
||||
SASSERT(m_head->m_prev == c->m_prev);
|
||||
c->m_key = reinterpret_cast<expr*>(1);
|
||||
c->m_prev = 0;
|
||||
c->m_next = 0;
|
||||
m_size--;
|
||||
m_num_deleted++;
|
||||
CASSERT("lru_cache", check_invariant());
|
||||
if (m_num_deleted * 3 > m_capacity)
|
||||
remove_deleted();
|
||||
}
|
||||
|
||||
void lru_cache::add_front(cell * c) {
|
||||
SASSERT(c->m_next == 0);
|
||||
SASSERT(c->m_prev == 0);
|
||||
if (m_head == 0) {
|
||||
c->m_next = c;
|
||||
c->m_prev = c;
|
||||
m_head = c;
|
||||
}
|
||||
else {
|
||||
c->m_prev = m_head->m_prev;
|
||||
c->m_next = m_head;
|
||||
m_head->m_prev->m_next = c;
|
||||
m_head->m_prev = c;
|
||||
m_head = c;
|
||||
}
|
||||
CASSERT("lru_cache", check_invariant());
|
||||
SASSERT(m_head == c);
|
||||
}
|
||||
|
||||
void lru_cache::move_front(cell * c) {
|
||||
SASSERT(m_head);
|
||||
SASSERT(c->m_next);
|
||||
SASSERT(c->m_prev);
|
||||
if (m_head != c) {
|
||||
c->m_prev->m_next = c->m_next;
|
||||
c->m_next->m_prev = c->m_prev;
|
||||
|
||||
c->m_prev = m_head->m_prev;
|
||||
c->m_next = m_head;
|
||||
|
||||
m_head->m_prev->m_next = c;
|
||||
m_head->m_prev = c;
|
||||
|
||||
m_head = c;
|
||||
}
|
||||
CASSERT("lru_cache", check_invariant());
|
||||
SASSERT(m_head == c);
|
||||
}
|
||||
|
||||
void lru_cache::insert(expr * k, expr * v) {
|
||||
LCS_CODE(m_time++;);
|
||||
if (m_size == m_max_size)
|
||||
del_least_used();
|
||||
else if (m_size * 2 > m_capacity)
|
||||
expand_table();
|
||||
SASSERT(m_size < m_max_size);
|
||||
unsigned h = k->hash();
|
||||
unsigned mask = m_capacity - 1;
|
||||
unsigned idx = h & mask;
|
||||
|
||||
cell * begin = m_table + idx;
|
||||
cell * end = m_table + m_capacity;
|
||||
cell * curr = begin;
|
||||
cell * del_cell = 0;
|
||||
|
||||
#define INSERT_LOOP() \
|
||||
if (curr->m_key == 0) { \
|
||||
cell * new_cell; \
|
||||
if (del_cell) { \
|
||||
new_cell = del_cell; \
|
||||
m_num_deleted--; \
|
||||
} \
|
||||
else { \
|
||||
new_cell = curr; \
|
||||
} \
|
||||
m_manager.inc_ref(k); \
|
||||
m_manager.inc_ref(v); \
|
||||
new_cell->m_key = k; \
|
||||
new_cell->m_value = v; \
|
||||
LCS_CODE(new_cell->m_hits = 0;); \
|
||||
LCS_CODE(new_cell->m_birthday = m_time;); \
|
||||
m_size++; \
|
||||
add_front(new_cell); \
|
||||
return; \
|
||||
} \
|
||||
if (curr->m_key == reinterpret_cast<expr*>(1)) { \
|
||||
del_cell = curr; \
|
||||
continue; \
|
||||
} \
|
||||
if (curr->m_key == k) { \
|
||||
m_manager.inc_ref(v); \
|
||||
m_manager.dec_ref(curr->m_value); \
|
||||
curr->m_value = v; \
|
||||
LCS_CODE(curr->m_hits = 0;); \
|
||||
LCS_CODE(curr->m_birthday = m_time;); \
|
||||
move_front(curr); \
|
||||
return; \
|
||||
}
|
||||
|
||||
for (; curr != end; ++curr) {
|
||||
INSERT_LOOP();
|
||||
}
|
||||
for (curr = m_table; curr != begin; ++curr) {
|
||||
INSERT_LOOP();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
expr * lru_cache::find(expr * k) {
|
||||
unsigned h = k->hash();
|
||||
unsigned mask = m_capacity - 1;
|
||||
unsigned idx = h & mask;
|
||||
|
||||
#ifdef LRU_CACHE_STATISTICS
|
||||
static unsigned long long total_age = 0;
|
||||
static unsigned long long max_time = 0;
|
||||
static unsigned counter = 0;
|
||||
#define COLLECT() \
|
||||
if (curr->m_hits == 0) { \
|
||||
counter ++; \
|
||||
unsigned age = m_time - curr->m_birthday; \
|
||||
if (age > max_time) \
|
||||
max_time = age; \
|
||||
total_age += age; \
|
||||
if (counter % 1000 == 0) \
|
||||
verbose_stream() << "[lru_cache] avg time for first hit: " << ((double) total_age / (double) counter) << " max time: " << max_time << "\n"; \
|
||||
}
|
||||
#endif
|
||||
|
||||
cell * begin = m_table + idx;
|
||||
cell * end = m_table + m_capacity;
|
||||
cell * curr = begin;
|
||||
for (; curr != end; ++curr) {
|
||||
if (curr->m_key == k) {
|
||||
// LCS_CODE(COLLECT());
|
||||
LCS_CODE(if (curr->m_hits == 0 && m_time - curr->m_birthday >= 5000) return 0;)
|
||||
LCS_CODE(curr->m_hits++;);
|
||||
move_front(curr);
|
||||
return curr->m_value;
|
||||
}
|
||||
if (curr->m_key == 0)
|
||||
return 0;
|
||||
}
|
||||
for (curr = m_table; curr != begin; ++curr) {
|
||||
if (curr->m_key == k) {
|
||||
// LCS_CODE(COLLECT());
|
||||
LCS_CODE(curr->m_hits++;);
|
||||
LCS_CODE(if (curr->m_hits == 0 && m_time - curr->m_birthday >= 5000) return 0;);
|
||||
move_front(curr);
|
||||
return curr->m_value;
|
||||
}
|
||||
if (curr->m_key == 0)
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lru_cache::reset() {
|
||||
TRACE("lru_cache", tout << "reset... m_size: " << m_size << "\n";);
|
||||
LCS_CODE(m_time = 0;);
|
||||
if (m_head) {
|
||||
cell * curr = m_head;
|
||||
#ifdef Z3DEBUG
|
||||
unsigned sz = 0;
|
||||
#endif
|
||||
do {
|
||||
m_manager.dec_ref(curr->m_key);
|
||||
m_manager.dec_ref(curr->m_value);
|
||||
cell * next = curr->m_next;
|
||||
curr->m_key = 0;
|
||||
curr->m_value = 0;
|
||||
curr->m_next = 0;
|
||||
curr->m_prev = 0;
|
||||
LCS_CODE(curr->m_hits = 0;);
|
||||
LCS_CODE(curr->m_birthday = 0;);
|
||||
curr = next;
|
||||
DEBUG_CODE(sz++;);
|
||||
}
|
||||
while (curr != m_head);
|
||||
SASSERT(sz == m_size);
|
||||
m_head = 0;
|
||||
m_size = 0;
|
||||
SASSERT(check_invariant());
|
||||
}
|
||||
}
|
||||
|
||||
void lru_cache::cleanup() {
|
||||
dec_refs();
|
||||
deallocate(m_table);
|
||||
m_capacity = INITIAL_CAPACITY;
|
||||
m_table = allocate(m_capacity);
|
||||
m_head = 0;
|
||||
m_size = 0;
|
||||
m_num_deleted = 0;
|
||||
}
|
||||
|
||||
bool lru_cache::check_invariant() const {
|
||||
SASSERT(m_size <= m_max_size);
|
||||
cell * begin = m_table;
|
||||
cell * end = m_table + m_capacity;
|
||||
unsigned sz = 0;
|
||||
if (m_head) {
|
||||
cell * curr = m_head;
|
||||
do {
|
||||
sz++;
|
||||
SASSERT(curr->m_key != 0 && curr->m_key != reinterpret_cast<expr*>(1));
|
||||
SASSERT(curr->m_next->m_prev == curr);
|
||||
SASSERT(curr->m_prev->m_next == curr);
|
||||
SASSERT(curr < end);
|
||||
SASSERT(curr >= begin);
|
||||
curr = curr->m_next;
|
||||
}
|
||||
while (curr != m_head);
|
||||
}
|
||||
SASSERT(m_size == sz);
|
||||
sz = 0;
|
||||
unsigned num_deleted = 0;
|
||||
for (cell * it = begin; it != end; it++) {
|
||||
if (it->m_key == reinterpret_cast<expr*>(1)) {
|
||||
num_deleted++;
|
||||
continue;
|
||||
}
|
||||
if (it->m_key != 0) {
|
||||
sz++;
|
||||
}
|
||||
}
|
||||
SASSERT(m_size == sz);
|
||||
SASSERT(m_num_deleted == num_deleted);
|
||||
return true;
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
lru_cache.h
|
||||
|
||||
Abstract:
|
||||
|
||||
expr -> expr LRU cache
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-12
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _LRU_CACHE_H_
|
||||
#define _LRU_CACHE_H_
|
||||
|
||||
#include"ast.h"
|
||||
|
||||
// #define LRU_CACHE_STATISTICS
|
||||
|
||||
#ifdef LRU_CACHE_STATISTICS
|
||||
#define LCS_CODE(CODE) { CODE }
|
||||
#else
|
||||
#define LCS_CODE(CODE)
|
||||
#endif
|
||||
|
||||
class lru_cache {
|
||||
struct cell {
|
||||
expr * m_key;
|
||||
expr * m_value;
|
||||
cell * m_prev;
|
||||
cell * m_next;
|
||||
#ifdef LRU_CACHE_STATISTICS
|
||||
unsigned m_hits;
|
||||
unsigned m_birthday;
|
||||
#endif
|
||||
};
|
||||
|
||||
ast_manager & m_manager;
|
||||
cell * m_table;
|
||||
cell * m_head;
|
||||
unsigned m_size;
|
||||
unsigned m_max_size;
|
||||
unsigned m_capacity;
|
||||
unsigned m_num_deleted;
|
||||
#ifdef LRU_CACHE_STATISTICS
|
||||
unsigned m_time;
|
||||
#endif
|
||||
|
||||
static cell * allocate(unsigned capacity);
|
||||
static void deallocate(cell * table);
|
||||
static cell * copy_table(cell * old_head, cell * new_table, unsigned new_capacity);
|
||||
|
||||
void del_least_used();
|
||||
void add_front(cell * c);
|
||||
void move_front(cell * c);
|
||||
void expand_table();
|
||||
void remove_deleted();
|
||||
void init();
|
||||
void dec_refs();
|
||||
public:
|
||||
lru_cache(ast_manager & m);
|
||||
lru_cache(ast_manager & m, unsigned max_size);
|
||||
~lru_cache();
|
||||
void insert(expr * k, expr * v);
|
||||
expr * find(expr * k);
|
||||
void reset();
|
||||
void cleanup();
|
||||
unsigned size() const { return m_size; }
|
||||
unsigned capacity() const { return m_capacity; }
|
||||
bool empty() const { return m_size == 0; }
|
||||
bool check_invariant() const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2007 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
parameters.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Settings and parameters supplied to pre-processing and solver
|
||||
modules.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2006-10-18.
|
||||
Nikolaj Bjorner (nbjorner) 2007-02-15
|
||||
|
||||
Revision History:
|
||||
2007-02-15, nbjorner.
|
||||
Hoisted out from simplify_parser.h and core_theory_types.h
|
||||
in order to share functionality with SMTLIB and other
|
||||
front-ends without bringing in the simplifier and core_theory.
|
||||
|
||||
--*/
|
||||
#ifndef _PARAMETERS_H_
|
||||
#define _PARAMETERS_H_
|
||||
|
||||
#include"sat_params.h"
|
||||
#include"core_theory_params.h"
|
||||
#include"front_end_params.h"
|
||||
|
||||
#endif
|
|
@ -1,118 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
simple_sat.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2006-10-10.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<fstream>
|
||||
#include<time.h>
|
||||
#include"front_end_params.h"
|
||||
#include"sat_def.h"
|
||||
#include"dimacs_parser.h"
|
||||
#include"timeit.h"
|
||||
#include"mem_stat.h"
|
||||
|
||||
class simple_sat_solver : public no_extension {
|
||||
const front_end_params & m_params;
|
||||
sat_solver<simple_sat_solver> * m_sat;
|
||||
unsigned m_num_vars;
|
||||
svector<lbool> m_model;
|
||||
public:
|
||||
simple_sat_solver(const front_end_params & p):
|
||||
m_params(p),
|
||||
m_sat(new sat_solver<simple_sat_solver>(*this, p)),
|
||||
m_num_vars(0) {
|
||||
}
|
||||
|
||||
~simple_sat_solver() {
|
||||
delete m_sat;
|
||||
}
|
||||
|
||||
static bool enable_ref_counters() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void mk_var() {
|
||||
m_sat->mk_var();
|
||||
m_num_vars++;
|
||||
}
|
||||
|
||||
void mk_clause(const literal_vector & lits) {
|
||||
m_sat->mk_main_clause(lits);
|
||||
}
|
||||
|
||||
unsigned get_num_vars() const {
|
||||
return m_num_vars;
|
||||
}
|
||||
|
||||
lbool check() {
|
||||
return m_sat->check();
|
||||
}
|
||||
|
||||
void mk_model() {
|
||||
if (m_params.m_build_model) {
|
||||
m_sat->save_assignment(m_model);
|
||||
}
|
||||
}
|
||||
|
||||
void display_model(std::ostream & out) const {
|
||||
int sz = m_model.size();
|
||||
for (int i = 1; i < sz; i++) {
|
||||
if (m_model[i] == l_true) {
|
||||
out << i << " ";
|
||||
}
|
||||
else if (m_model[i] == l_false) {
|
||||
out << -i << " ";
|
||||
}
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
void display_statistics(std::ostream & out) const {
|
||||
m_sat->display_statistics(out);
|
||||
}
|
||||
};
|
||||
|
||||
extern bool g_display_statistics;
|
||||
extern front_end_params g_front_end_params;
|
||||
|
||||
void solve_cnf(const char * file) {
|
||||
clock_t start_time = clock();
|
||||
simple_sat_solver solver(g_front_end_params);
|
||||
std::ifstream in(file);
|
||||
parse_dimacs(in, solver);
|
||||
lbool r = solver.check();
|
||||
clock_t end_time = clock();
|
||||
switch(r) {
|
||||
case l_false:
|
||||
std::cout << "unsat\n";
|
||||
break;
|
||||
case l_undef:
|
||||
std::cout << "unknown\n";
|
||||
break;
|
||||
case l_true:
|
||||
std::cout << "sat\n";
|
||||
if (g_front_end_params.m_build_model) {
|
||||
solver.display_model(std::cout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (g_display_statistics) {
|
||||
solver.display_statistics(std::cerr);
|
||||
memory::display_max_usage(std::cerr);
|
||||
std::cerr << "time: " << ((static_cast<double>(end_time) - static_cast<double>(start_time)) / CLOCKS_PER_SEC) << "\n";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
simple_sat.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Simple SAT solver using the Z3 SAT template.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2006-10-10.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _SIMPLE_SAT_H_
|
||||
#define _SIMPLE_SAT_H_
|
||||
|
||||
void solve_cnf(const char * file);
|
||||
|
||||
#endif /* _SIMPLE_SAT_H_ */
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
smt_classifier.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-06-24.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SMT_CLASSIFIER_H_
|
||||
#define _SMT_CLASSIFIER_H_
|
||||
|
||||
#include"static_features.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
class classifier {
|
||||
context & m_context;
|
||||
ast_manager & m_manager;
|
||||
static_features m_static_features;
|
||||
symbol m_logic;
|
||||
public:
|
||||
classifier(context & c);
|
||||
/**
|
||||
\brief Give a hint by specifying the logic used to describe a problem.
|
||||
*/
|
||||
void set_logic(symbol & s);
|
||||
/**
|
||||
\brief Setup the logical context for solving the following formulas.
|
||||
*/
|
||||
void setup(unsigned num_formulas, expr * const * fs);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SMT_CLASSIFIER_H_ */
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
smt_euf.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Equality and uninterpreted functions
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-14.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"smt_euf.h"
|
||||
#include"smt_context.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
struct euf_manager::imp {
|
||||
context & m_context;
|
||||
ast_manager & m_manager;
|
||||
region & m_region;
|
||||
expr_ref_vector m_e_internalized_stack; // stack of the expressions already internalized as enodes.
|
||||
ptr_vector<enode> m_app2enode; // app -> enode
|
||||
ptr_vector<enode> m_enodes;
|
||||
vector<enode_vector> m_decl2enodes; // decl -> enode (for decls with arity > 0)
|
||||
cg_table m_cg_table;
|
||||
dyn_ack_manager m_dyn_ack_manager;
|
||||
struct new_eq {
|
||||
enode * m_lhs;
|
||||
enode * m_rhs;
|
||||
eq_justification m_justification;
|
||||
new_eq() {}
|
||||
new_eq(enode * lhs, enode * rhs, eq_justification const & js):
|
||||
m_lhs(lhs), m_rhs(rhs), m_justification(js) {}
|
||||
};
|
||||
svector<new_eq> m_eq_propagation_queue;
|
||||
struct new_th_eq {
|
||||
theory_id m_th_id;
|
||||
theory_var m_lhs;
|
||||
theory_var m_rhs;
|
||||
new_th_eq():m_th_id(null_theory_id), m_lhs(null_theory_var), m_rhs(null_theory_var) {}
|
||||
new_th_eq(theory_id id, theory_var l, theory_var r):m_th_id(id), m_lhs(l), m_rhs(r) {}
|
||||
};
|
||||
svector<new_th_eq> m_th_eq_propagation_queue;
|
||||
svector<new_th_eq> m_th_diseq_propagation_queue;
|
||||
enode * m_is_diseq_tmp; // auxiliary enode used to find congruent equality atoms.
|
||||
tmp_enode m_tmp_enode;
|
||||
ptr_vector<almost_cg_table> m_almost_cg_tables; // temporary field for is_ext_diseq
|
||||
obj_map<expr, unsigned> m_cached_generation;
|
||||
obj_hashtable<expr> m_cache_generation_visited;
|
||||
friend class mk_enode_trail;
|
||||
class mk_enode_trail : public trail<context> {
|
||||
imp & m_owner;
|
||||
public:
|
||||
mk_enode_trail(imp & o):m_owner(o) {}
|
||||
virtual void undo(context & ctx) { m_owner.undo_mk_enode(); }
|
||||
};
|
||||
mk_enode_trail m_mk_enode_trail;
|
||||
volatile bool m_cancel_flag;
|
||||
|
||||
// Statistics
|
||||
unsigned m_num_mk_enode;
|
||||
unsigned m_num_del_enode;
|
||||
|
||||
void push_eq(enode * lhs, enode * rhs, eq_justification const & js) {
|
||||
SASSERT(lhs != rhs);
|
||||
m_eq_propagation_queue.push_back(new_eq(lhs, rhs, js));
|
||||
}
|
||||
|
||||
void push_new_congruence(enode * n1, enode * n2, bool used_commutativity) {
|
||||
SASSERT(n1->m_cg == n2);
|
||||
push_eq(n1, n2, eq_justification::mk_cg(used_commutativity));
|
||||
}
|
||||
|
||||
bool e_internalized(expr const * n) const {
|
||||
return m_app2enode.get(n->get_id(), 0) != 0;
|
||||
}
|
||||
|
||||
void set_app2enode(expr const * n, enode * e) {
|
||||
m_app2enode.setx(n->get_id(), e, 0);
|
||||
}
|
||||
|
||||
enode * mk_enode(app * n, bool suppress_args, bool merge_tf, bool cgc_enabled, unsigned generation) {
|
||||
TRACE("mk_enode_detail",
|
||||
tout << mk_ismt2_pp(n, m_manager) << "\n";
|
||||
tout <<"suppress_args: " << suppress_args << ", merge_tf: " << merge_tf << ", cgc_enabled: " << cgc_enabled << "\n";);
|
||||
SASSERT(!e_internalized(n));
|
||||
unsigned scope_lvl = m_context.get_scope_level();
|
||||
unsigned id = n->get_id();
|
||||
unsigned _generation = 0;
|
||||
if (!m_cached_generation.empty() && m_cached_generation.find(n, _generation)) {
|
||||
generation = _generation;
|
||||
}
|
||||
enode * e = enode::mk(m_manager, m_region, m_app2enode, n, generation, suppress_args, merge_tf, scope_lvl, cgc_enabled, true);
|
||||
TRACE("mk_enode_detail", tout << "e.get_num_args() = " << e->get_num_args() << "\n";);
|
||||
if (n->get_num_args() == 0 && m_manager.is_value(n))
|
||||
e->mark_as_interpreted();
|
||||
TRACE("mk_var_bug", tout << "mk_enode: " << id << "\n";);
|
||||
TRACE("generation", tout << "mk_enode: " << id << " " << generation << "\n";);
|
||||
set_app2enode(n, e);
|
||||
m_e_internalized_stack.push_back(n);
|
||||
m_context.push_trail_ptr(&m_mk_enode_trail);
|
||||
m_enodes.push_back(e);
|
||||
if (e->get_num_args() > 0) {
|
||||
if (e->is_true_eq()) {
|
||||
/*
|
||||
bool_var v = enode2bool_var(e);
|
||||
assign(literal(v), mk_justification(eq_propagation_justification(e->get_arg(0), e->get_arg(1))));
|
||||
e->m_cg = e;
|
||||
*/
|
||||
}
|
||||
else {
|
||||
if (cgc_enabled) {
|
||||
enode_bool_pair pair = m_cg_table.insert(e);
|
||||
enode * e_prime = pair.first;
|
||||
if (e != e_prime) {
|
||||
e->m_cg = e_prime;
|
||||
bool used_commutativity = pair.second;
|
||||
push_new_congruence(e, e_prime, used_commutativity);
|
||||
}
|
||||
else {
|
||||
e->m_cg = e;
|
||||
}
|
||||
}
|
||||
else {
|
||||
e->m_cg = e;
|
||||
}
|
||||
}
|
||||
if (!e->is_eq()) {
|
||||
unsigned decl_id = n->get_decl()->get_decl_id();
|
||||
if (decl_id >= m_decl2enodes.size())
|
||||
m_decl2enodes.resize(decl_id+1);
|
||||
m_decl2enodes[decl_id].push_back(e);
|
||||
}
|
||||
}
|
||||
SASSERT(e_internalized(n));
|
||||
m_num_mk_enode++;
|
||||
|
||||
// #ifndef SMTCOMP
|
||||
// if (m_params.m_trace_stream != NULL)
|
||||
// *m_params.m_trace_stream << "[attach-enode] #" << n->get_id() << " " << m_generation << "\n";
|
||||
// #endif
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void undo_mk_enode() {
|
||||
SASSERT(!m_e_internalized_stack.empty());
|
||||
m_num_del_enode++;
|
||||
expr * n = m_e_internalized_stack.back();
|
||||
TRACE("undo_mk_enode", tout << "undo_enode: #" << n->get_id() << "\n" << mk_ismt2_pp(n, m_manager) << "\n";);
|
||||
TRACE("mk_var_bug", tout << "undo_mk_enode: " << n->get_id() << "\n";);
|
||||
unsigned n_id = n->get_id();
|
||||
SASSERT(is_app(n));
|
||||
enode * e = m_app2enode[n_id];
|
||||
m_app2enode[n_id] = 0;
|
||||
if (e->is_cgr() && !e->is_true_eq() && e->is_cgc_enabled()) {
|
||||
SASSERT(m_cg_table.contains_ptr(e));
|
||||
m_cg_table.erase(e);
|
||||
}
|
||||
if (e->get_num_args() > 0 && !e->is_eq()) {
|
||||
unsigned decl_id = to_app(n)->get_decl()->get_decl_id();
|
||||
SASSERT(decl_id < m_decl2enodes.size());
|
||||
SASSERT(m_decl2enodes[decl_id].back() == e);
|
||||
m_decl2enodes[decl_id].pop_back();
|
||||
}
|
||||
e->del_eh(m_manager);
|
||||
SASSERT(m_e_internalized_stack.size() == m_enodes.size());
|
||||
m_enodes.pop_back();
|
||||
m_e_internalized_stack.pop_back();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
euf_manager::euf_manager(context & ctx) {
|
||||
}
|
||||
|
||||
euf_manager::~euf_manager() {
|
||||
}
|
||||
};
|
|
@ -1,55 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
smt_euf.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Equality and uninterpreted functions
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-14.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SMT_EUF_H_
|
||||
#define _SMT_EUF_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"smt_enode.h"
|
||||
#include"smt_eq_justification.h"
|
||||
|
||||
namespace smt {
|
||||
class context;
|
||||
|
||||
class euf_manager {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
public:
|
||||
euf_manager(context & ctx);
|
||||
~euf_manager();
|
||||
|
||||
enode * mk_enode(app * n, bool suppress_args, bool merge_tf, bool cgc_enabled);
|
||||
|
||||
void add_eq(enode * n1, enode * n2, eq_justification js);
|
||||
bool assume_eq(enode * lhs, enode * rhs);
|
||||
void reset();
|
||||
|
||||
static bool is_eq(enode const * n1, enode const * n2) { return n1->get_root() == n2->get_root(); }
|
||||
bool is_diseq(enode * n1, enode * n2) const;
|
||||
bool is_ext_diseq(enode * n1, enode * n2, unsigned depth);
|
||||
enode * get_enode_eq_to(func_decl * f, unsigned num_args, enode * const * args);
|
||||
bool is_shared(enode * n) const;
|
||||
|
||||
unsigned get_num_enodes_of(func_decl const * decl) const;
|
||||
enode_vector::const_iterator begin_enodes_of(func_decl const * decl) const;
|
||||
enode_vector::const_iterator end_enodes_of(func_decl const * decl) const;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -1,131 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
smt_trail.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-19.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SMT_TRAIL_H_
|
||||
#define _SMT_TRAIL_H_
|
||||
|
||||
namespace smt {
|
||||
|
||||
class context;
|
||||
|
||||
class trail {
|
||||
public:
|
||||
virtual ~trail() {
|
||||
}
|
||||
virtual void undo(context & ctx) = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class value_trail : public trail {
|
||||
T & m_value;
|
||||
T m_old_value;
|
||||
|
||||
public:
|
||||
value_trail(T & value):
|
||||
m_value(value),
|
||||
m_old_value(value) {
|
||||
}
|
||||
|
||||
virtual ~value_trail() {
|
||||
}
|
||||
|
||||
virtual void undo(context & ctx) {
|
||||
m_value = m_old_value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class set_ptr_trail : public trail {
|
||||
T * & m_ptr;
|
||||
public:
|
||||
set_ptr_trail(T * & ptr):
|
||||
m_ptr(ptr) {
|
||||
SASSERT(m_ptr == 0);
|
||||
}
|
||||
|
||||
virtual void undo(context & ctx) {
|
||||
m_ptr = 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool CallDestructors=true>
|
||||
class vector_value_trail : public trail {
|
||||
vector<T, CallDestructors> & m_vector;
|
||||
unsigned m_idx;
|
||||
T m_old_value;
|
||||
public:
|
||||
vector_value_trail(vector<T, CallDestructors> & v, unsigned idx):
|
||||
m_vector(v),
|
||||
m_idx(idx),
|
||||
m_old_value(v[idx]) {
|
||||
}
|
||||
|
||||
virtual ~vector_value_trail() {
|
||||
}
|
||||
|
||||
virtual void undo(context & ctx) {
|
||||
m_vector[m_idx] = m_old_value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool CallDestructors=true>
|
||||
class push_back_trail : public trail {
|
||||
vector<T, CallDestructors> & m_vector;
|
||||
public:
|
||||
push_back_trail(vector<T, CallDestructors> & v):
|
||||
m_vector(v) {
|
||||
}
|
||||
|
||||
virtual void undo(context & ctx) {
|
||||
m_vector.pop_back();
|
||||
}
|
||||
};
|
||||
|
||||
class set_bitvector_trail : public trail {
|
||||
svector<bool> & m_vector;
|
||||
unsigned m_idx;
|
||||
public:
|
||||
set_bitvector_trail(svector<bool> & v, unsigned idx):
|
||||
m_vector(v),
|
||||
m_idx(idx) {
|
||||
SASSERT(m_vector[m_idx] == false);
|
||||
m_vector[m_idx] = true;
|
||||
}
|
||||
|
||||
virtual void undo(context & ctx) {
|
||||
m_vector[m_idx] = false;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class new_obj_trail : public trail {
|
||||
T * m_obj;
|
||||
public:
|
||||
new_obj_trail(T * obj):
|
||||
m_obj(obj) {
|
||||
}
|
||||
|
||||
virtual void undo(context & ctx) {
|
||||
dealloc(m_obj);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SMT_TRAIL_H_ */
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
Superposition Calculus.
|
||||
This module is currently disabled.
|
|
@ -1,214 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
fvi.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Feature Vector Indexing.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-01.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _FVI_H_
|
||||
#define _FVI_H_
|
||||
|
||||
#include"splay_tree_map.h"
|
||||
#include"hashtable.h"
|
||||
#include"vector.h"
|
||||
|
||||
/**
|
||||
\brief A feature vector indexing for objects of type T *.
|
||||
|
||||
ToVector is a functor for converting T into a vector of natural numbers.
|
||||
It should provide a method:
|
||||
- void operator(T * d, unsigned * f);
|
||||
This method should fill the vector f with the features of d.
|
||||
|
||||
Hash: functor for computing the hashcode of T *.
|
||||
|
||||
Eq : functor for comparing T pointers.
|
||||
*/
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq=ptr_eq<T> >
|
||||
class fvi : private ToVector {
|
||||
public:
|
||||
struct statistics {
|
||||
unsigned m_size;
|
||||
unsigned m_num_nodes;
|
||||
unsigned m_num_leaves;
|
||||
unsigned m_min_leaf_size;
|
||||
unsigned m_avg_leaf_size;
|
||||
unsigned m_max_leaf_size;
|
||||
statistics() { reset(); }
|
||||
|
||||
void reset() {
|
||||
m_size = m_num_nodes = m_num_leaves = m_avg_leaf_size = m_max_leaf_size = 0;
|
||||
m_min_leaf_size = UINT_MAX;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
struct ucompare {
|
||||
int operator()(unsigned i1, unsigned i2) const {
|
||||
if (i1 < i2) return -1;
|
||||
if (i1 > i2) return 1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct node {
|
||||
node() {}
|
||||
virtual ~node() {}
|
||||
virtual bool is_leaf() const = 0;
|
||||
};
|
||||
|
||||
typedef splay_tree_map<unsigned, node *, ucompare> children;
|
||||
|
||||
struct non_leaf : public node {
|
||||
children m_children;
|
||||
non_leaf() {}
|
||||
|
||||
struct delete_children {
|
||||
void operator()(unsigned k, node * n) const {
|
||||
dealloc(n);
|
||||
}
|
||||
};
|
||||
|
||||
virtual ~non_leaf() {
|
||||
delete_children visitor;
|
||||
m_children.visit(visitor);
|
||||
m_children.reset();
|
||||
}
|
||||
|
||||
virtual bool is_leaf() const { return false; }
|
||||
};
|
||||
|
||||
typedef ptr_hashtable<T, Hash, Eq> set;
|
||||
|
||||
struct leaf : public node {
|
||||
set m_set;
|
||||
leaf() {}
|
||||
virtual ~leaf() {}
|
||||
virtual bool is_leaf() const { return true; }
|
||||
};
|
||||
|
||||
unsigned m_num_features;
|
||||
svector<unsigned> m_tmp_buffer;
|
||||
non_leaf * m_root;
|
||||
|
||||
struct stop {};
|
||||
|
||||
template<typename Visitor>
|
||||
void visit_leaf(leaf * n, Visitor & v, bool le) const {
|
||||
typename set::iterator it = n->m_set.begin();
|
||||
typename set::iterator end = n->m_set.end();
|
||||
for (; it != end; ++it)
|
||||
if (!v(*it))
|
||||
throw stop();
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
struct non_leaf_visitor {
|
||||
fvi const & m_owner;
|
||||
unsigned m_fidx;
|
||||
Visitor & m_visitor;
|
||||
bool m_le;
|
||||
|
||||
non_leaf_visitor(fvi const & o, unsigned fidx, Visitor & v, bool le):
|
||||
m_owner(o), m_fidx(fidx), m_visitor(v), m_le(le) {}
|
||||
|
||||
void operator()(unsigned k, node * n) {
|
||||
if (n->is_leaf())
|
||||
m_owner.visit_leaf(static_cast<leaf*>(n), m_visitor, m_le);
|
||||
else
|
||||
m_owner.visit_non_leaf(static_cast<non_leaf*>(n), m_fidx + 1, m_visitor, m_le);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Visitor>
|
||||
void visit_non_leaf(non_leaf * n, unsigned fidx, Visitor & v, bool le) const {
|
||||
// Remark: this function is recursive, but there is no risk
|
||||
// of stack overflow since the number of features is small.
|
||||
non_leaf_visitor<Visitor> v2(*this, fidx, v, le);
|
||||
if (le)
|
||||
n->m_children.visit_le(v2, m_tmp_buffer[fidx]);
|
||||
else
|
||||
n->m_children.visit_ge(v2, m_tmp_buffer[fidx]);
|
||||
}
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
bool m_visiting;
|
||||
#endif
|
||||
|
||||
void to_fvector(T * d) const {
|
||||
fvi * _this = const_cast<fvi *>(this);
|
||||
_this->ToVector::operator()(d, _this->m_tmp_buffer.c_ptr());
|
||||
}
|
||||
|
||||
struct non_leaf_stat_visitor {
|
||||
fvi const & m_owner;
|
||||
statistics & m_stats;
|
||||
non_leaf_stat_visitor(fvi const & o, statistics & st):m_owner(o), m_stats(st) {}
|
||||
void operator()(unsigned k, node * n);
|
||||
};
|
||||
|
||||
void stats(leaf * n, statistics & result) const;
|
||||
void stats(non_leaf * n, statistics & result) const;
|
||||
|
||||
struct non_leaf_collect_visitor {
|
||||
fvi const & m_owner;
|
||||
ptr_vector<T> & m_elems;
|
||||
non_leaf_collect_visitor(fvi const & o, ptr_vector<T> & elems):m_owner(o), m_elems(elems) {}
|
||||
void operator()(unsigned k, node * n);
|
||||
};
|
||||
|
||||
void collect(leaf * n, ptr_vector<T> & result) const;
|
||||
void collect(non_leaf * n, ptr_vector<T> & result) const;
|
||||
|
||||
public:
|
||||
fvi(unsigned num_features, ToVector const & t = ToVector());
|
||||
~fvi() { reset(); dealloc(m_root); }
|
||||
|
||||
void insert(T * d);
|
||||
bool contains(T * d) const;
|
||||
void erase(T * d);
|
||||
void reset();
|
||||
|
||||
/**
|
||||
\brief Traverse the elements that have features smaller (greater) or equal than the one of the given element.
|
||||
|
||||
For each visited element the following method of v is executed:
|
||||
|
||||
- bool operator()(T * d)
|
||||
|
||||
If false is returned, the traversal is aborted.
|
||||
|
||||
\warning The object cannot be updated during the traversal.
|
||||
*/
|
||||
template<typename Visitor>
|
||||
void visit(T * d, Visitor & v, bool le = true) const {
|
||||
DEBUG_CODE(const_cast<fvi*>(this)->m_visiting = true;);
|
||||
to_fvector(d);
|
||||
try {
|
||||
visit_non_leaf(m_root, 0, v, le);
|
||||
}
|
||||
catch (stop) {
|
||||
}
|
||||
DEBUG_CODE(const_cast<fvi*>(this)->m_visiting = false;);
|
||||
}
|
||||
|
||||
void stats(statistics & result) const;
|
||||
|
||||
/**
|
||||
\brief Copy to result the set of elements stored in the index.
|
||||
*/
|
||||
void collect(ptr_vector<T> & result) const;
|
||||
};
|
||||
|
||||
#endif /* _FVI_H_ */
|
|
@ -1,199 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
fvi_def.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Feature Vector Indexing.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-01.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _FVI_DEF_H_
|
||||
#define _FVI_DEF_H_
|
||||
|
||||
#include"fvi.h"
|
||||
#include"splay_tree_def.h"
|
||||
#include"buffer.h"
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
fvi<T, ToVector, Hash, Eq>::fvi(unsigned num_features, ToVector const & t):
|
||||
ToVector(t),
|
||||
m_num_features(num_features),
|
||||
m_root(0) {
|
||||
m_tmp_buffer.resize(num_features, 0);
|
||||
m_root = alloc(non_leaf);
|
||||
SASSERT(num_features >= 2);
|
||||
DEBUG_CODE(m_visiting = false;);
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::reset() {
|
||||
SASSERT(!m_visiting);
|
||||
dealloc(m_root);
|
||||
m_root = alloc(non_leaf);
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::insert(T * d) {
|
||||
SASSERT(!m_visiting);
|
||||
to_fvector(d);
|
||||
non_leaf * n = m_root;
|
||||
unsigned i = 0;
|
||||
for (; i < m_num_features - 1; i++) {
|
||||
node * child = 0;
|
||||
if (!n->m_children.find(m_tmp_buffer[i], child)) {
|
||||
child = alloc(non_leaf);
|
||||
n->m_children.insert(m_tmp_buffer[i], child);
|
||||
}
|
||||
SASSERT(child);
|
||||
SASSERT(!child->is_leaf());
|
||||
n = static_cast<non_leaf*>(child);
|
||||
}
|
||||
node * l = 0;
|
||||
SASSERT(i == m_num_features - 1);
|
||||
if (!n->m_children.find(m_tmp_buffer[i], l)) {
|
||||
l = alloc(leaf);
|
||||
n->m_children.insert(m_tmp_buffer[i], l);
|
||||
}
|
||||
SASSERT(l);
|
||||
SASSERT(l->is_leaf());
|
||||
static_cast<leaf*>(l)->m_set.insert(d);
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
bool fvi<T, ToVector, Hash, Eq>::contains(T * d) const {
|
||||
to_fvector(d);
|
||||
non_leaf * n = m_root;
|
||||
node * child;
|
||||
unsigned i = 0;
|
||||
for (; i < m_num_features - 1; i++) {
|
||||
if (!n->m_children.find(m_tmp_buffer[i], child))
|
||||
return false;
|
||||
SASSERT(child);
|
||||
SASSERT(!child->is_leaf());
|
||||
n = static_cast<non_leaf*>(child);
|
||||
}
|
||||
SASSERT(i == m_num_features - 1);
|
||||
return
|
||||
n->m_children.find(m_tmp_buffer[i], child) &&
|
||||
static_cast<leaf*>(child)->m_set.contains(d);
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::erase(T * d) {
|
||||
SASSERT(!m_visiting);
|
||||
SASSERT(contains(d));
|
||||
ptr_buffer<non_leaf> path;
|
||||
to_fvector(d);
|
||||
non_leaf * n = m_root;
|
||||
node * child;
|
||||
unsigned i = 0;
|
||||
for (; i < m_num_features - 1; i++) {
|
||||
path.push_back(n);
|
||||
if (!n->m_children.find(m_tmp_buffer[i], child)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
SASSERT(child);
|
||||
SASSERT(!child->is_leaf());
|
||||
n = static_cast<non_leaf*>(child);
|
||||
}
|
||||
path.push_back(n);
|
||||
SASSERT(i == m_num_features - 1);
|
||||
if (!n->m_children.find(m_tmp_buffer[i], child)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
SASSERT(child);
|
||||
SASSERT(child->is_leaf());
|
||||
leaf * l = static_cast<leaf*>(child);
|
||||
l->m_set.erase(d);
|
||||
if (l->m_set.empty()) {
|
||||
dealloc(l);
|
||||
while (true) {
|
||||
non_leaf * n = path.back();
|
||||
n->m_children.erase(m_tmp_buffer[i]);
|
||||
path.pop_back();
|
||||
i--;
|
||||
if (!n->m_children.empty() || n == m_root)
|
||||
break;
|
||||
dealloc(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::non_leaf_stat_visitor::operator()(unsigned k, node * n) {
|
||||
if (n->is_leaf())
|
||||
m_owner.stats(static_cast<leaf*>(n), m_stats);
|
||||
else
|
||||
m_owner.stats(static_cast<non_leaf*>(n), m_stats);
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::stats(leaf * n, statistics & result) const {
|
||||
unsigned sz = n->m_set.size();
|
||||
result.m_size += sz;
|
||||
if (sz > result.m_max_leaf_size)
|
||||
result.m_max_leaf_size = sz;
|
||||
if (sz < result.m_min_leaf_size)
|
||||
result.m_min_leaf_size = sz;
|
||||
result.m_num_leaves ++;
|
||||
result.m_num_nodes ++;
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::stats(non_leaf * n, statistics & result) const {
|
||||
result.m_num_nodes++;
|
||||
// Remark: this function is recursive, but there is no risk
|
||||
// of stack overflow since the number of features is small.
|
||||
non_leaf_stat_visitor v(*this, result);
|
||||
n->m_children.visit(v);
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::stats(statistics & result) const {
|
||||
result.reset();
|
||||
stats(m_root, result);
|
||||
if (m_root->m_children.empty())
|
||||
result.m_min_leaf_size = 0;
|
||||
if (result.m_num_leaves > 0)
|
||||
result.m_avg_leaf_size = result.m_size / result.m_num_leaves;
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::non_leaf_collect_visitor::operator()(unsigned k, node * n) {
|
||||
if (n->is_leaf())
|
||||
m_owner.collect(static_cast<leaf*>(n), m_elems);
|
||||
else
|
||||
m_owner.collect(static_cast<non_leaf*>(n), m_elems);
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::collect(leaf * n, ptr_vector<T> & result) const {
|
||||
typename set::iterator it = n->m_set.begin();
|
||||
typename set::iterator end = n->m_set.end();
|
||||
for (; it != end; ++it)
|
||||
result.push_back(*it);
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::collect(non_leaf * n, ptr_vector<T> & result) const {
|
||||
// Remark: this function is recursive, but there is no risk
|
||||
// of stack overflow since the number of features is small.
|
||||
non_leaf_collect_visitor v(*this, result);
|
||||
n->m_children.visit(v);
|
||||
}
|
||||
|
||||
template<typename T, typename ToVector, typename Hash, typename Eq>
|
||||
void fvi<T, ToVector, Hash, Eq>::collect(ptr_vector<T> & result) const {
|
||||
collect(m_root, result);
|
||||
}
|
||||
|
||||
#endif /* _FVI_DEF_H_ */
|
|
@ -1,276 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
kbo.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Knuth-Bendix ordering.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-28.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"kbo.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
inline unsigned kbo::f_weight(func_decl * f) const {
|
||||
// TODO
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned kbo::var_weight() const {
|
||||
return m_var_weight;
|
||||
}
|
||||
|
||||
inline void kbo::reset() {
|
||||
m_weight_balance = 0;
|
||||
m_deltas.reset();
|
||||
m_num_pos = 0;
|
||||
m_num_neg = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Increase the balance of the given variable.
|
||||
*/
|
||||
inline void kbo::inc(expr_offset v) {
|
||||
SASSERT(is_var(v.get_expr()));
|
||||
int val;
|
||||
unsigned v_idx = to_var(v.get_expr())->get_idx();
|
||||
unsigned offset = v.get_offset();
|
||||
if (m_deltas.find(v_idx, offset, val)) {
|
||||
if (val == -1)
|
||||
m_num_neg--;
|
||||
else if (val == 0)
|
||||
m_num_pos++;
|
||||
m_deltas.insert(v_idx, offset, val + 1);
|
||||
}
|
||||
else {
|
||||
m_deltas.insert(v_idx, offset, 1);
|
||||
m_num_pos ++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Decreate the balance of the given variable.
|
||||
*/
|
||||
inline void kbo::dec(expr_offset v) {
|
||||
int val;
|
||||
unsigned v_idx = to_var(v.get_expr())->get_idx();
|
||||
unsigned offset = v.get_offset();
|
||||
if (m_deltas.find(v_idx, offset, val)) {
|
||||
if (val == 0)
|
||||
m_num_neg++;
|
||||
else if (val == 1)
|
||||
m_num_pos--;
|
||||
m_deltas.insert(v_idx, offset, val - 1);
|
||||
}
|
||||
else {
|
||||
m_deltas.insert(v_idx, offset, -1);
|
||||
m_num_neg ++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Accumulate the variables and weight balance of t. Return
|
||||
true if t contains target_var.
|
||||
*/
|
||||
template<bool pos>
|
||||
bool kbo::VWBc(expr_offset t, expr_offset target_var) {
|
||||
SASSERT(target_var.get_expr() == 0 || is_var(target_var.get_expr()));
|
||||
svector<expr_offset> & todo = m_vwbc_todo;
|
||||
expr_offset s;
|
||||
bool found = false;
|
||||
unsigned j;
|
||||
SASSERT(todo.empty());
|
||||
todo.push_back(t);
|
||||
while (!todo.empty()) {
|
||||
t = todo.back();
|
||||
if (t == target_var)
|
||||
found = true;
|
||||
expr * n = t.get_expr();
|
||||
unsigned offset = t.get_offset();
|
||||
todo.pop_back();
|
||||
switch (n->get_kind()) {
|
||||
case AST_VAR:
|
||||
if (m_subst && m_subst->find(to_var(n), offset, s))
|
||||
todo.push_back(s);
|
||||
else if (pos) {
|
||||
inc(t);
|
||||
m_weight_balance += var_weight();
|
||||
}
|
||||
else {
|
||||
dec(t);
|
||||
m_weight_balance -= var_weight();
|
||||
}
|
||||
break;
|
||||
case AST_APP:
|
||||
if (pos)
|
||||
m_weight_balance += f_weight(to_app(n)->get_decl());
|
||||
else
|
||||
m_weight_balance -= f_weight(to_app(n)->get_decl());
|
||||
j = to_app(n)->get_num_args();
|
||||
while (j > 0) {
|
||||
--j;
|
||||
todo.push_back(expr_offset(to_app(n)->get_arg(j), offset));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
template<bool pos>
|
||||
inline void kbo::VWB(expr_offset t, unsigned idx) {
|
||||
expr_offset null(0, 0);
|
||||
app * n = to_app(t.get_expr());
|
||||
unsigned num = n->get_num_args();
|
||||
for (; idx < num; idx++)
|
||||
VWBc<pos>(expr_offset(n->get_arg(idx), t.get_offset()), null);
|
||||
}
|
||||
|
||||
inline bool is_unary_app(expr * n) {
|
||||
return is_app(n) && to_app(n)->get_num_args() == 1;
|
||||
}
|
||||
|
||||
inline kbo::result kbo::no_neg() const {
|
||||
return m_num_neg == 0 ? GREATER : UNCOMPARABLE;
|
||||
}
|
||||
|
||||
inline kbo::result kbo::no_pos() const {
|
||||
return m_num_pos == 0 ? LESSER : UNCOMPARABLE;
|
||||
}
|
||||
|
||||
order::result kbo::compare(expr_offset const & t1, expr_offset const & t2, substitution * s) {
|
||||
reset();
|
||||
m_subst = s;
|
||||
|
||||
if (t1 == t2)
|
||||
return EQUAL;
|
||||
|
||||
expr * n1 = t1.get_expr();
|
||||
expr * n2 = t2.get_expr();
|
||||
|
||||
// f(s) >_{kbo} f(t) iff s >_{kbo} t
|
||||
while (is_unary_app(n1) && is_unary_app(n2) && to_app(n1)->get_decl() == to_app(n2)->get_decl()) {
|
||||
n1 = to_app(n1)->get_arg(0);
|
||||
n2 = to_app(n2)->get_arg(0);
|
||||
}
|
||||
|
||||
svector<entry> & todo = m_compare_todo;
|
||||
SASSERT(todo.empty());
|
||||
todo.push_back(entry(find(expr_offset(n1, t1.get_offset())),
|
||||
find(expr_offset(n2, t2.get_offset())),
|
||||
0));
|
||||
|
||||
result res = UNKNOWN;
|
||||
|
||||
while (!todo.empty()) {
|
||||
entry & e = todo.back();
|
||||
expr_offset t1 = e.m_t1;
|
||||
expr_offset t2 = e.m_t2;
|
||||
expr * n1 = t1.get_expr();
|
||||
expr * n2 = t2.get_expr();
|
||||
TRACE("kbo", tout << "processing with idx: " << e.m_idx << "\n" <<
|
||||
mk_pp(n1, m_manager) << "\n" << mk_pp(n2, m_manager) << "\n";
|
||||
tout << "wb : " << m_weight_balance << "\n";);
|
||||
SASSERT(!is_quantifier(n1) && !is_quantifier(n2));
|
||||
bool v1 = is_var(n1);
|
||||
bool v2 = is_var(n2);
|
||||
if (v1 && v2) {
|
||||
todo.pop_back();
|
||||
inc(t1);
|
||||
dec(t2);
|
||||
res = t1 == t2 ? EQUAL : UNCOMPARABLE;
|
||||
}
|
||||
else if (v1) {
|
||||
todo.pop_back();
|
||||
res = VWBc<false>(t2, t1) ? LESSER : UNCOMPARABLE;
|
||||
inc(t1);
|
||||
m_weight_balance += var_weight();
|
||||
}
|
||||
else if (v2) {
|
||||
todo.pop_back();
|
||||
res = VWBc<true>(t1, t2) ? GREATER : UNCOMPARABLE;
|
||||
dec(t2);
|
||||
m_weight_balance -= var_weight();
|
||||
}
|
||||
else {
|
||||
func_decl * f = to_app(n1)->get_decl();
|
||||
func_decl * g = to_app(n2)->get_decl();
|
||||
result lex;
|
||||
if (f != g || to_app(n1)->get_num_args() != to_app(n2)->get_num_args()) {
|
||||
VWB<true>(t1, 0);
|
||||
VWB<false>(t2, 0);
|
||||
lex = UNCOMPARABLE;
|
||||
}
|
||||
else {
|
||||
unsigned & idx = e.m_idx;
|
||||
// when idx > 0, res contains the result for child (idx - 1)
|
||||
if (idx > 0 && res != EQUAL) {
|
||||
VWB<true>(t1, idx);
|
||||
VWB<false>(t2, idx);
|
||||
lex = res;
|
||||
}
|
||||
else if (idx == to_app(n1)->get_num_args()) {
|
||||
// all children were visited
|
||||
lex = EQUAL;
|
||||
}
|
||||
else if (idx < to_app(n1)->get_num_args()) {
|
||||
expr_offset c1 = find(expr_offset(to_app(n1)->get_arg(idx), t1.get_offset()));
|
||||
expr_offset c2 = find(expr_offset(to_app(n2)->get_arg(idx), t2.get_offset()));
|
||||
idx++; // move curr entry child idx
|
||||
entry new_entry(c1, c2, 0);
|
||||
todo.push_back(new_entry);
|
||||
continue; // process child before continuing
|
||||
}
|
||||
}
|
||||
|
||||
todo.pop_back();
|
||||
m_weight_balance += f_weight(f);
|
||||
m_weight_balance -= f_weight(g);
|
||||
|
||||
if (m_weight_balance > 0)
|
||||
res = no_neg();
|
||||
else if (m_weight_balance < 0)
|
||||
res = no_pos();
|
||||
else if (f_greater(f, g))
|
||||
res = no_neg();
|
||||
else if (f_greater(g, f))
|
||||
res = no_pos();
|
||||
else if (f != g)
|
||||
res = UNCOMPARABLE;
|
||||
else if (lex == EQUAL)
|
||||
res = EQUAL;
|
||||
else if (lex == GREATER)
|
||||
res = no_neg();
|
||||
else if (lex == LESSER)
|
||||
res = no_pos();
|
||||
else
|
||||
res = UNCOMPARABLE;
|
||||
}
|
||||
TRACE("kbo", tout << "result: " << res << "\n";);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool kbo::greater(expr_offset const & t1, expr_offset const & t2, substitution * s) {
|
||||
return compare(t1, t2, s) == GREATER;
|
||||
}
|
||||
|
||||
int kbo::compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s) {
|
||||
switch (compare(t1, t2, s)) {
|
||||
case GREATER: return 1;
|
||||
case EQUAL: return 0;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
kbo.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Knuth-Bendix ordering.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-28.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _KBO_H_
|
||||
#define _KBO_H_
|
||||
|
||||
#include"order.h"
|
||||
|
||||
class kbo : public order {
|
||||
struct entry {
|
||||
expr_offset m_t1;
|
||||
expr_offset m_t2;
|
||||
unsigned m_idx;
|
||||
entry():m_idx(UINT_MAX) {}
|
||||
entry(expr_offset const & t1, expr_offset const & t2, unsigned idx):
|
||||
m_t1(t1), m_t2(t2), m_idx(idx) {}
|
||||
};
|
||||
|
||||
unsigned m_var_weight;
|
||||
int m_weight_balance;
|
||||
var_offset_map<int> m_deltas;
|
||||
unsigned m_num_pos;
|
||||
unsigned m_num_neg;
|
||||
svector<expr_offset> m_vwbc_todo;
|
||||
svector<entry> m_compare_todo;
|
||||
|
||||
unsigned f_weight(func_decl * f) const;
|
||||
unsigned var_weight() const;
|
||||
|
||||
void reset();
|
||||
void inc(expr_offset v);
|
||||
void dec(expr_offset v);
|
||||
|
||||
template<bool pos>
|
||||
bool VWBc(expr_offset t, expr_offset target_var);
|
||||
|
||||
template<bool pos>
|
||||
void VWB(expr_offset t, unsigned idx);
|
||||
|
||||
result no_neg() const;
|
||||
result no_pos() const;
|
||||
|
||||
public:
|
||||
kbo(ast_manager & m, precedence * p, unsigned var_weight = 1):order(m, p), m_var_weight(var_weight) {}
|
||||
virtual ~kbo() {}
|
||||
virtual void reserve(unsigned num_offsets, unsigned num_vars) { m_deltas.reserve(num_offsets, num_vars); }
|
||||
virtual void reserve_offsets(unsigned num_offsets) { m_deltas.reserve_offsets(num_offsets); }
|
||||
virtual void reserve_vars(unsigned num_vars) { m_deltas.reserve_vars(num_vars); }
|
||||
virtual result compare(expr_offset const & t1, expr_offset const & t2, substitution * s);
|
||||
result compare(expr * t1, expr * t2) { return compare(expr_offset(t1, 0), expr_offset(t2, 0), 0); }
|
||||
virtual bool greater(expr_offset const & t1, expr_offset const & t2, substitution * s);
|
||||
virtual int compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s);
|
||||
};
|
||||
|
||||
#endif /* _KBO_H_ */
|
|
@ -1,184 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
lpo.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Lexicographical Path Ordering
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-01.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"lpo.h"
|
||||
|
||||
/**
|
||||
\brief Check whether the variable in t1 occurs in t2.
|
||||
*/
|
||||
bool lpo::occurs(expr_offset const & t1, expr_offset const & t2) {
|
||||
SASSERT(is_var(t1.get_expr()));
|
||||
if (is_ground(t2.get_expr()))
|
||||
return false;
|
||||
m_todo.reset();
|
||||
m_todo.push_back(t2);
|
||||
while (!m_todo.empty()) {
|
||||
expr_offset t = m_todo.back();
|
||||
m_todo.pop_back();
|
||||
t = find(t);
|
||||
expr * n = t.get_expr();
|
||||
if (is_ground(n))
|
||||
continue;
|
||||
unsigned offset = t.get_offset();
|
||||
unsigned j;
|
||||
switch (n->get_kind()) {
|
||||
case AST_VAR:
|
||||
if (t == t1)
|
||||
return true;
|
||||
break;
|
||||
case AST_APP:
|
||||
j = to_app(n)->get_num_args();
|
||||
while (j > 0) {
|
||||
--j;
|
||||
expr * arg = to_app(n)->get_arg(j);
|
||||
if (!is_ground(arg))
|
||||
m_todo.push_back(expr_offset(arg, offset));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool lpo::greater(expr_offset s, expr_offset t, unsigned depth) {
|
||||
return lpo::compare(s, t, depth) == GREATER;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if s >_{lpo} t_i forall children t_i of t.
|
||||
*/
|
||||
bool lpo::dominates_args(expr_offset s, expr_offset t, unsigned depth) {
|
||||
SASSERT(is_app(t.get_expr()));
|
||||
unsigned num_args = to_app(t.get_expr())->get_num_args();
|
||||
unsigned off = t.get_offset();
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * t_i = to_app(t.get_expr())->get_arg(i);
|
||||
if (!greater(s, expr_offset(t_i, off), depth+1))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if s_i >=_{lpo} t for some arg s_i of s.
|
||||
*/
|
||||
bool lpo::arg_dominates_expr(expr_offset s, expr_offset t, unsigned depth) {
|
||||
SASSERT(is_app(s.get_expr()));
|
||||
unsigned num_args = to_app(s.get_expr())->get_num_args();
|
||||
unsigned off = s.get_offset();
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * s_i = to_app(s.get_expr())->get_arg(i);
|
||||
result r = compare(expr_offset(s_i, off), t, depth+1);
|
||||
if (r == EQUAL || r == GREATER)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
order::result lpo::lex_compare(expr_offset s, expr_offset t, unsigned depth) {
|
||||
SASSERT(is_app(s.get_expr()));
|
||||
SASSERT(is_app(t.get_expr()));
|
||||
app * _s = to_app(s.get_expr());
|
||||
app * _t = to_app(t.get_expr());
|
||||
unsigned num_args1 = _s->get_num_args();
|
||||
unsigned num_args2 = _t->get_num_args();
|
||||
unsigned num_args = std::min(num_args1, num_args2);
|
||||
unsigned off1 = s.get_offset();
|
||||
unsigned off2 = t.get_offset();
|
||||
result r = EQUAL;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
r = compare(expr_offset(_s->get_arg(i), off1), expr_offset(_t->get_arg(i), off2), depth+1);
|
||||
if (r != EQUAL)
|
||||
break;
|
||||
}
|
||||
if (r == EQUAL) {
|
||||
if (num_args1 > num_args2)
|
||||
return GREATER;
|
||||
if (num_args1 < num_args2)
|
||||
return NOT_GTEQ;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
inline order::result lpo::compare_core(expr_offset s, expr_offset t, unsigned depth) {
|
||||
s = find(s);
|
||||
t = find(t);
|
||||
|
||||
if (max_depth(depth))
|
||||
return UNKNOWN;
|
||||
|
||||
if (is_var(s.get_expr()))
|
||||
return s == t ? EQUAL : UNCOMPARABLE;
|
||||
else if (is_var(t.get_expr()))
|
||||
return occurs(t, s) ? GREATER : UNCOMPARABLE;
|
||||
else {
|
||||
func_decl * f = to_app(s.get_expr())->get_decl();
|
||||
func_decl * g = to_app(t.get_expr())->get_decl();
|
||||
if (f_greater(f, g))
|
||||
return dominates_args(s, t, depth) ? GREATER : NOT_GTEQ;
|
||||
else if (f != g)
|
||||
return arg_dominates_expr(s, t, depth) ? GREATER : NOT_GTEQ;
|
||||
else {
|
||||
result r = lex_compare(s, t, depth);
|
||||
if (r == GREATER) {
|
||||
if (dominates_args(s, t, depth))
|
||||
return GREATER;
|
||||
}
|
||||
else if (r == EQUAL)
|
||||
return EQUAL;
|
||||
return to_app(s.get_expr())->get_num_args() > 1 && arg_dominates_expr(s, t, depth) ? GREATER : NOT_GTEQ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
order::result lpo::compare(expr_offset s, expr_offset t, unsigned depth) {
|
||||
TRACE("lpo", tout << "comparing:\n" << mk_pp(s.get_expr(), m_manager) << "\n" << mk_pp(t.get_expr(), m_manager) << "\n";);
|
||||
result r = compare_core(s, t, depth);
|
||||
TRACE("lpo", tout << "result of comparing:\n" << mk_pp(s.get_expr(), m_manager) << "\n" << mk_pp(t.get_expr(), m_manager) << "\nresult: " << r << "\n";);
|
||||
return r;
|
||||
}
|
||||
|
||||
bool lpo::greater(expr_offset const & t1, expr_offset const & t2, substitution * s) {
|
||||
m_subst = s;
|
||||
return greater(t1, t2, static_cast<unsigned>(0));
|
||||
}
|
||||
|
||||
order::result lpo::compare(expr_offset const & t1, expr_offset const & t2, substitution * s) {
|
||||
m_subst = s;
|
||||
result r = compare(t1, t2, static_cast<unsigned>(0));
|
||||
if (r != NOT_GTEQ)
|
||||
return r;
|
||||
r = compare(t2, t1, static_cast<unsigned>(0));
|
||||
if (r == GREATER)
|
||||
return LESSER;
|
||||
if (r == UNKNOWN)
|
||||
return UNKNOWN;
|
||||
return UNCOMPARABLE;
|
||||
}
|
||||
|
||||
int lpo::compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s) {
|
||||
m_subst = s;
|
||||
result r = compare(t1, t2, static_cast<unsigned>(0));
|
||||
switch (r) {
|
||||
case GREATER: return 1;
|
||||
case EQUAL: return 0;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
lpo.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Lexicographical Path Ordering
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-01.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _LPO_H_
|
||||
#define _LPO_H_
|
||||
|
||||
#include"order.h"
|
||||
#include"vector.h"
|
||||
#include"map.h"
|
||||
|
||||
class lpo : public order {
|
||||
svector<expr_offset> m_todo;
|
||||
|
||||
bool occurs(expr_offset const & t1, expr_offset const & t2);
|
||||
bool greater(expr_offset s, expr_offset t, unsigned depth);
|
||||
bool dominates_args(expr_offset s, expr_offset t, unsigned depth);
|
||||
bool arg_dominates_expr(expr_offset s, expr_offset t, unsigned depth);
|
||||
result lex_compare(expr_offset s, expr_offset t, unsigned depth);
|
||||
result compare_core(expr_offset s, expr_offset t, unsigned depth);
|
||||
result compare(expr_offset s, expr_offset t, unsigned depth);
|
||||
bool max_depth(unsigned d) { /* TODO */ return false; }
|
||||
public:
|
||||
lpo(ast_manager & m, precedence * p):order(m, p) {}
|
||||
virtual ~lpo() {}
|
||||
|
||||
virtual result compare(expr_offset const & t1, expr_offset const & t2, substitution * s);
|
||||
result compare(expr * t1, expr * t2) { return compare(expr_offset(t1, 0), expr_offset(t2, 0), static_cast<substitution*>(0)); }
|
||||
|
||||
virtual bool greater(expr_offset const & t1, expr_offset const & t2, substitution * s);
|
||||
bool greater(expr_offset const & t1, expr_offset const & t2) { return greater(t1, t2); }
|
||||
virtual int compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s);
|
||||
};
|
||||
|
||||
#endif /* _LPO_H_ */
|
|
@ -1,56 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
marker.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Auxiliary object for managing markings
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-07.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _MARKER_H_
|
||||
#define _MARKER_H_
|
||||
|
||||
#include"vector.h"
|
||||
|
||||
/**
|
||||
\brief Keep track of all marked objects. Unmark them when the method
|
||||
unmark or destructor is invoked.
|
||||
*/
|
||||
template<typename T>
|
||||
class marker {
|
||||
ptr_vector<T> m_to_unmark;
|
||||
public:
|
||||
~marker() {
|
||||
unmark();
|
||||
}
|
||||
|
||||
void mark(T * obj) {
|
||||
obj->set_mark(true);
|
||||
m_to_unmark.push_back(obj);
|
||||
}
|
||||
|
||||
bool is_marked(T * obj) const {
|
||||
return obj->is_marked();
|
||||
}
|
||||
|
||||
void unmark() {
|
||||
typename ptr_vector<T>::iterator it = m_to_unmark.begin();
|
||||
typename ptr_vector<T>::iterator end = m_to_unmark.end();
|
||||
for (; it != end; ++it) {
|
||||
T * obj = *it;
|
||||
obj->set_mark(false);
|
||||
}
|
||||
m_to_unmark.reset();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _MARKER_H_ */
|
|
@ -1,88 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
normalize_vars.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-16.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"normalize_vars.h"
|
||||
|
||||
expr * normalize_vars::operator()(expr * n) {
|
||||
SASSERT(m_todo.empty());
|
||||
m_todo.push_back(n);
|
||||
while (!m_todo.empty()) {
|
||||
n = m_todo.back();
|
||||
if (m_cache.contains(n)) {
|
||||
m_todo.pop_back();
|
||||
continue;
|
||||
}
|
||||
if (is_var(n)) {
|
||||
m_todo.pop_back();
|
||||
unsigned idx = to_var(n)->get_idx();
|
||||
var * new_var = m_map.get(idx, 0);
|
||||
if (new_var == 0) {
|
||||
new_var = m_manager.mk_var(m_next_var, to_var(n)->get_sort());
|
||||
m_next_var++;
|
||||
m_new_vars.push_back(new_var);
|
||||
m_map.setx(idx, new_var, 0);
|
||||
}
|
||||
SASSERT(new_var->get_sort() == to_var(n)->get_sort());
|
||||
m_cache.insert(n, new_var);
|
||||
}
|
||||
else {
|
||||
SASSERT(is_app(n));
|
||||
bool visited = true;
|
||||
unsigned num_args = to_app(n)->get_num_args();
|
||||
unsigned j = num_args;
|
||||
while (j > 0) {
|
||||
--j;
|
||||
expr * child = to_app(n)->get_arg(j);
|
||||
if (!m_cache.contains(child)) {
|
||||
m_todo.push_back(child);
|
||||
visited = false;
|
||||
}
|
||||
}
|
||||
if (visited) {
|
||||
m_todo.pop_back();
|
||||
m_new_children.reset();
|
||||
bool modified = false;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * child = to_app(n)->get_arg(i);
|
||||
expr * new_child = 0;
|
||||
m_cache.find(child, new_child);
|
||||
SASSERT(new_child);
|
||||
if (child != new_child)
|
||||
modified = true;
|
||||
m_new_children.push_back(new_child);
|
||||
}
|
||||
if (!modified)
|
||||
m_cache.insert(n, n);
|
||||
else
|
||||
m_cache.insert(n, m_manager.mk_app(to_app(n)->get_decl(), m_new_children.size(), m_new_children.c_ptr()));
|
||||
}
|
||||
}
|
||||
}
|
||||
expr * r = 0;
|
||||
m_cache.find(n, r);
|
||||
SASSERT(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
void normalize_vars::reset() {
|
||||
m_cache.reset();
|
||||
m_map.reset();
|
||||
m_new_vars.reset();
|
||||
m_next_var = 0;
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
normalize_vars.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-16.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _NORMALIZE_VARS_H_
|
||||
#define _NORMALIZE_VARS_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
|
||||
class normalize_vars {
|
||||
ast_manager & m_manager;
|
||||
var_ref_vector m_new_vars;
|
||||
unsigned m_next_var;
|
||||
ptr_vector<var> m_map;
|
||||
typedef obj_map<expr, expr *> cache;
|
||||
cache m_cache;
|
||||
ptr_vector<expr> m_todo;
|
||||
ptr_vector<expr> m_new_children;
|
||||
public:
|
||||
normalize_vars(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_new_vars(m) {
|
||||
}
|
||||
|
||||
expr * operator()(expr * n);
|
||||
void reset();
|
||||
unsigned get_num_vars() const { return m_new_vars.size(); }
|
||||
var * const * get_vars() const { return m_new_vars.c_ptr(); }
|
||||
};
|
||||
|
||||
#endif /* _NORMALIZE_VARS_H_ */
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
order.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-15.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"order.h"
|
||||
|
||||
bool order::equal(expr_offset const & _t1, expr_offset const & _t2, substitution * s) {
|
||||
if (_t1 == _t2)
|
||||
return true;
|
||||
if (s == 0)
|
||||
return false;
|
||||
m_eq_todo.reset();
|
||||
m_eq_todo.push_back(expr_offset_pair(_t1, _t2));
|
||||
while (!m_eq_todo.empty()) {
|
||||
expr_offset_pair const & p = m_eq_todo.back();
|
||||
expr_offset t1 = find(p.first);
|
||||
expr_offset t2 = find(p.second);
|
||||
m_eq_todo.pop_back();
|
||||
if (t1 == t2)
|
||||
continue;
|
||||
expr * n1 = t1.get_expr();
|
||||
expr * n2 = t2.get_expr();
|
||||
if (!is_app(n1) || !is_app(n2))
|
||||
return false;
|
||||
if (to_app(n1)->get_decl() != to_app(n2)->get_decl())
|
||||
return false;
|
||||
if (to_app(n1)->get_num_args() != to_app(n2)->get_num_args())
|
||||
return false;
|
||||
unsigned num = to_app(n1)->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
m_eq_todo.push_back(expr_offset_pair(expr_offset(to_app(n1)->get_arg(i), t1.get_offset()),
|
||||
expr_offset(to_app(n2)->get_arg(i), t2.get_offset())));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
order.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Abstract class for term orderings.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-28.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ORDER_H_
|
||||
#define _ORDER_H_
|
||||
|
||||
#include"substitution.h"
|
||||
#include"precedence.h"
|
||||
#include"trace.h"
|
||||
|
||||
class order {
|
||||
protected:
|
||||
ast_manager & m_manager;
|
||||
precedence * m_precedence;
|
||||
substitution * m_subst;
|
||||
|
||||
typedef std::pair<expr_offset, expr_offset> expr_offset_pair;
|
||||
svector<expr_offset_pair> m_eq_todo;
|
||||
|
||||
expr_offset find(expr_offset t) {
|
||||
while (m_subst && is_var(t.get_expr()) && m_subst->find(to_var(t.get_expr()), t.get_offset(), t))
|
||||
;
|
||||
return t;
|
||||
}
|
||||
|
||||
bool f_greater(func_decl * f, func_decl * g) const {
|
||||
bool r = m_precedence->compare(f, g) > 0;
|
||||
TRACE("order", tout << f->get_name() << " greater than " << g->get_name() << " == " << r << "\n";);
|
||||
return r;
|
||||
}
|
||||
public:
|
||||
enum result {
|
||||
UNKNOWN,
|
||||
UNCOMPARABLE,
|
||||
EQUAL,
|
||||
GREATER,
|
||||
LESSER,
|
||||
NOT_GTEQ
|
||||
};
|
||||
static bool ok(result r) { return r == EQUAL || r == GREATER || r == LESSER; }
|
||||
order(ast_manager & m, precedence * p):m_manager(m), m_precedence(p) { SASSERT(p); }
|
||||
virtual ~order() { dealloc(m_precedence); }
|
||||
virtual void reserve(unsigned num_offsets, unsigned num_vars) {}
|
||||
virtual void reserve_offsets(unsigned num_offsets) {}
|
||||
virtual void reserve_vars(unsigned num_vars) {}
|
||||
ast_manager & get_manager() { return m_manager; }
|
||||
|
||||
virtual result compare(expr_offset const & t1, expr_offset const & t2, substitution * s) = 0;
|
||||
result compare(expr * t1, expr * t2, unsigned offset, substitution * s) { return compare(expr_offset(t1, offset), expr_offset(t2, offset), s); }
|
||||
result compare(expr * t1, expr * t2) { return compare(expr_offset(t1, 0), expr_offset(t2, 0), 0); }
|
||||
virtual bool greater(expr_offset const & t1, expr_offset const & t2, substitution * s) = 0;
|
||||
bool greater(expr * t1, expr * t2) { return greater(expr_offset(t1,0), expr_offset(t2,0), 0); }
|
||||
bool greater(expr * t1, expr * t2, substitution * s) { return greater(expr_offset(t1,0), expr_offset(t2,0), s); }
|
||||
bool greater(expr * t1, expr * t2, unsigned offset, substitution * s) {
|
||||
return greater(expr_offset(t1, offset), expr_offset(t2, offset), s);
|
||||
}
|
||||
/**
|
||||
\brief Return a value > 0 if t1 is greater than t2, 0 if t1 == t2, and < 0 otherwise (uncomparable, unknown, lesser).
|
||||
*/
|
||||
virtual int compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s) = 0;
|
||||
|
||||
/**
|
||||
\brief Return true if the given terms are equal modulo the given substitution
|
||||
*/
|
||||
bool equal(expr_offset const & t1, expr_offset const & t2, substitution * s);
|
||||
|
||||
bool equal(expr * t1, expr * t2, unsigned offset = 0, substitution * s = 0) {
|
||||
return equal(expr_offset(t1, offset), expr_offset(t2, offset), s);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _ORDER_H_ */
|
|
@ -1,191 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
precedence.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-08.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"precedence.h"
|
||||
#include"warning.h"
|
||||
|
||||
lex_precedence::lex_precedence(unsigned n, precedence ** ps):
|
||||
m_precedences(n, ps) {
|
||||
}
|
||||
|
||||
lex_precedence::~lex_precedence() {
|
||||
std::for_each(m_precedences.begin(), m_precedences.end(), delete_proc<precedence>());
|
||||
}
|
||||
|
||||
int lex_precedence::compare(func_decl * f, func_decl * g) {
|
||||
int r = 0;
|
||||
ptr_vector<precedence>::iterator it = m_precedences.begin();
|
||||
ptr_vector<precedence>::iterator end = m_precedences.end();
|
||||
for (; it != end; ++it) {
|
||||
r = (*it)->compare(f, g);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
inv_precedence::inv_precedence(precedence * p):
|
||||
m_precedence(p) {
|
||||
SASSERT(p);
|
||||
}
|
||||
|
||||
inv_precedence::~inv_precedence() {
|
||||
dealloc(m_precedence);
|
||||
}
|
||||
|
||||
int inv_precedence::compare(func_decl * f, func_decl * g) {
|
||||
return m_precedence->compare(g, f);
|
||||
}
|
||||
|
||||
int arbitrary_precedence::compare(func_decl * f, func_decl * g) {
|
||||
return static_cast<int>(f->get_decl_id()) - static_cast<int>(g->get_decl_id());
|
||||
}
|
||||
|
||||
int arity_precedence::compare(func_decl * f, func_decl * g) {
|
||||
return static_cast<int>(f->get_arity()) - static_cast<int>(g->get_arity());
|
||||
}
|
||||
|
||||
int interpreted_precedence::compare(func_decl * f, func_decl * g) {
|
||||
return static_cast<int>(f->get_family_id() == null_family_id) - static_cast<int>(g->get_family_id() == null_family_id);
|
||||
}
|
||||
|
||||
inline int ext_precedence::get_func_pos(func_decl * f) {
|
||||
unsigned id = f->get_decl_id();
|
||||
return m_cached.get(id, m_undefined);
|
||||
}
|
||||
|
||||
int ext_precedence::compare(func_decl * f, func_decl * g) {
|
||||
return get_func_pos(f) - get_func_pos(g);
|
||||
}
|
||||
|
||||
ext_precedence::ext_precedence(ast_manager & m, unsigned num_decls, func_decl ** decls):
|
||||
m_undefined(num_decls),
|
||||
m_cached_domain(m) {
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
m_cached.setx(decls[i]->get_decl_id(), i, m_undefined);
|
||||
m_cached_domain.push_back(decls[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ext_precedence::~ext_precedence() {
|
||||
}
|
||||
|
||||
int abstract_user_precedence::get_decl_pos(decl * d) {
|
||||
unsigned id = d->get_decl_id();
|
||||
int pos = m_cached.get(id, -1);
|
||||
if (pos == -1) {
|
||||
if (!m_symbol2pos.find(d->get_name(), pos))
|
||||
pos = m_undefined;
|
||||
m_cached.setx(id, pos, -1);
|
||||
SASSERT(pos != -1);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
abstract_user_precedence::abstract_user_precedence(ast_manager & m, unsigned num_syms, symbol * syms):
|
||||
m_undefined(num_syms),
|
||||
m_cached_domain(m) {
|
||||
for (unsigned i = 0; i < num_syms; i++)
|
||||
m_symbol2pos.insert(syms[i], i);
|
||||
}
|
||||
|
||||
abstract_user_precedence::~abstract_user_precedence() {
|
||||
}
|
||||
|
||||
int user_precedence::compare(func_decl * f, func_decl * g) {
|
||||
return get_decl_pos(f) - get_decl_pos(g);
|
||||
}
|
||||
|
||||
int user_sort_precedence::compare(func_decl * f, func_decl * g) {
|
||||
return get_decl_pos(f->get_range()) - get_decl_pos(g->get_range());
|
||||
}
|
||||
|
||||
static precedence * mk_default_precedence(ast_manager & m, order_params const & params) {
|
||||
ptr_buffer<precedence> ps;
|
||||
if (!params.m_order_precedence.empty())
|
||||
ps.push_back(alloc(user_precedence, m, params.m_order_precedence.size(), params.m_order_precedence.c_ptr()));
|
||||
ps.push_back(alloc(interpreted_precedence));
|
||||
ps.push_back(alloc(arity_precedence));
|
||||
ps.push_back(alloc(arbitrary_precedence));
|
||||
return alloc(lex_precedence, ps.size(), ps.c_ptr());
|
||||
}
|
||||
|
||||
static precedence * mk_inv_precedence(bool inv, precedence * p) {
|
||||
return inv ? alloc(inv_precedence,p) : p;
|
||||
}
|
||||
|
||||
static precedence * mk_lex_precedence(ptr_buffer<precedence> const & ps) {
|
||||
unsigned sz = ps.size();
|
||||
if (sz == 0)
|
||||
return alloc(arbitrary_precedence);
|
||||
else if (sz == 1)
|
||||
return ps[0];
|
||||
else
|
||||
return alloc(lex_precedence, sz, ps.c_ptr());
|
||||
}
|
||||
|
||||
precedence * mk_precedence(ast_manager & m, order_params const & params) {
|
||||
if (params.m_order_precedence_gen.empty())
|
||||
return mk_default_precedence(m, params);
|
||||
|
||||
symbol user("user");
|
||||
symbol definition("definition");
|
||||
symbol interpreted("interpreted");
|
||||
symbol frequency("frequency");
|
||||
symbol arity("arity");
|
||||
symbol arbitrary("arbitrary");
|
||||
symbol inv("-");
|
||||
|
||||
ptr_buffer<precedence> ps;
|
||||
|
||||
svector<symbol>::const_iterator it = params.m_order_precedence_gen.begin();
|
||||
svector<symbol>::const_iterator end = params.m_order_precedence_gen.end();
|
||||
bool prev_inv = false;
|
||||
for (; it != end; ++it) {
|
||||
symbol curr = *it;
|
||||
if (curr == user) {
|
||||
if (params.m_order_precedence.empty())
|
||||
ps.push_back(mk_inv_precedence(prev_inv, alloc(user_precedence, m, params.m_order_precedence.size(), params.m_order_precedence.c_ptr())));
|
||||
}
|
||||
else if (curr == definition) {
|
||||
warning_msg("definition precedence was not implement yet.");
|
||||
}
|
||||
else if (curr == interpreted) {
|
||||
ps.push_back(mk_inv_precedence(prev_inv, alloc(interpreted_precedence)));
|
||||
}
|
||||
else if (curr == frequency) {
|
||||
warning_msg("frequency precedence was not implement yet.");
|
||||
}
|
||||
else if (curr == arity) {
|
||||
ps.push_back(mk_inv_precedence(prev_inv, alloc(arity_precedence)));
|
||||
}
|
||||
else if (curr == arbitrary) {
|
||||
ps.push_back(mk_inv_precedence(prev_inv, alloc(arbitrary_precedence)));
|
||||
// it is pointless to continue, arbitrary_precedence is a total order
|
||||
return mk_lex_precedence(ps);
|
||||
}
|
||||
else if (curr == inv) {
|
||||
prev_inv = true;
|
||||
}
|
||||
else {
|
||||
warning_msg("invalid precedence generator: ignoring atom '%s'.", curr.bare_str());
|
||||
}
|
||||
}
|
||||
|
||||
return mk_lex_precedence(ps);
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
precedence.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-08.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _PRECEDENCE_H_
|
||||
#define _PRECEDENCE_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"order_params.h"
|
||||
|
||||
/**
|
||||
\brief Abstract functor used to implement an order on function symbols.
|
||||
*/
|
||||
class precedence {
|
||||
public:
|
||||
virtual ~precedence() {}
|
||||
virtual int compare(func_decl * f, func_decl * g) = 0;
|
||||
bool operator()(func_decl * f, func_decl * g) { return compare(f, g) < 0; }
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Compose different precedence functors using lexicographical order.
|
||||
*/
|
||||
class lex_precedence : public precedence {
|
||||
ptr_vector<precedence> m_precedences;
|
||||
public:
|
||||
lex_precedence(unsigned n, precedence ** ps);
|
||||
virtual ~lex_precedence();
|
||||
virtual int compare(func_decl * f, func_decl * g);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Invert functor
|
||||
*/
|
||||
class inv_precedence : public precedence {
|
||||
precedence * m_precedence;
|
||||
public:
|
||||
inv_precedence(precedence * p);
|
||||
virtual ~inv_precedence();
|
||||
virtual int compare(func_decl * f, func_decl * g);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief An arbitrary total order based on the func_decl ids.
|
||||
*/
|
||||
class arbitrary_precedence : public precedence {
|
||||
public:
|
||||
virtual int compare(func_decl * f, func_decl * g);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Precedence based on the arity.
|
||||
|
||||
\remark This is not a total order, so it must be combined
|
||||
with other precedence functors (e.g., arbitrary_precedence).
|
||||
*/
|
||||
class arity_precedence : public precedence {
|
||||
public:
|
||||
virtual int compare(func_decl * f, func_decl * g);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Interpreted function symbols are smaller.
|
||||
*/
|
||||
class interpreted_precedence : public precedence {
|
||||
public:
|
||||
virtual int compare(func_decl * f, func_decl * g);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief A precedence given as a sequence of func_decls.
|
||||
This functor is used to encapsulate automatically/externally generated
|
||||
precedences.
|
||||
*/
|
||||
class ext_precedence : public precedence {
|
||||
unsigned m_undefined; // position for func_decl's not specified by the user.
|
||||
int_vector m_cached; // mapping: decl -> int
|
||||
decl_ref_vector m_cached_domain;
|
||||
|
||||
int get_func_pos(func_decl * f);
|
||||
public:
|
||||
ext_precedence(ast_manager & m, unsigned num_decls, func_decl ** decls);
|
||||
virtual ~ext_precedence();
|
||||
virtual int compare(func_decl * f, func_decl * g);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Abstract class for user precedences based on
|
||||
function or sort symbols.
|
||||
*/
|
||||
class abstract_user_precedence : public precedence {
|
||||
protected:
|
||||
symbol_table<int> m_symbol2pos;
|
||||
unsigned m_undefined; // position for symbols not specified by the user.
|
||||
int_vector m_cached; // mapping: decl -> int
|
||||
decl_ref_vector m_cached_domain;
|
||||
|
||||
int get_decl_pos(decl * d);
|
||||
public:
|
||||
abstract_user_precedence(ast_manager & m, unsigned num_syms, symbol * syms);
|
||||
virtual ~abstract_user_precedence();
|
||||
};
|
||||
|
||||
/**
|
||||
\brief A user defined precedence given as a sequence of symbols.
|
||||
|
||||
\remark User provided precedences are usually not total.
|
||||
*/
|
||||
class user_precedence : public abstract_user_precedence {
|
||||
public:
|
||||
user_precedence(ast_manager & m, unsigned num_syms, symbol * syms):abstract_user_precedence(m, num_syms, syms) {}
|
||||
virtual int compare(func_decl * f, func_decl * g);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief A user defined precedence given as a sequence of sort symbols.
|
||||
The functions are ordered based on their range sort.
|
||||
*/
|
||||
class user_sort_precedence : public abstract_user_precedence {
|
||||
public:
|
||||
user_sort_precedence(ast_manager & m, unsigned num_syms, symbol * syms):abstract_user_precedence(m, num_syms, syms) {}
|
||||
virtual int compare(func_decl * f, func_decl * g);
|
||||
};
|
||||
|
||||
precedence * mk_precedence(ast_manager & m, order_params const & params);
|
||||
|
||||
#endif /* _PRECEDENCE_H_ */
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
preprocessor.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Preprocessor
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-17.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"preprocessor.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"num_occurs.h"
|
||||
|
||||
preprocessor::preprocessor(ast_manager & m, defined_names & d, simplifier & s, preprocessor_params & p):
|
||||
m_params(p),
|
||||
m_manager(m),
|
||||
m_simp(s),
|
||||
m_nnf(m, d, p),
|
||||
m_cnf(m, d, p),
|
||||
m_der(m),
|
||||
m_push_app_ite(s, p.m_lift_ite == LI_CONSERVATIVE),
|
||||
m_cnf_todo(m),
|
||||
m_cnf_todo_prs(m),
|
||||
m_push_todo(m),
|
||||
m_push_todo_prs(m) {
|
||||
switch (m_params.m_cnf_mode) {
|
||||
case CNF_QUANT:
|
||||
if (m_params.m_nnf_mode == NNF_SKOLEM)
|
||||
m_params.m_nnf_mode = NNF_QUANT;
|
||||
break;
|
||||
case CNF_OPPORTUNISTIC:
|
||||
if (m_params.m_nnf_mode == NNF_SKOLEM)
|
||||
m_params.m_nnf_mode = NNF_QUANT;
|
||||
break;
|
||||
case CNF_FULL:
|
||||
m_params.m_nnf_mode = NNF_FULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _TRACE
|
||||
struct num_occurs_pp {
|
||||
|
||||
ast_manager & m_manager;
|
||||
std::ostream & m_out;
|
||||
num_occurs m_occurs;
|
||||
|
||||
num_occurs_pp(ast_manager & m, std::ostream & out, expr * root):
|
||||
m_manager(m),
|
||||
m_out(out) {
|
||||
m_occurs(root);
|
||||
}
|
||||
void operator()(var * n) {}
|
||||
void operator()(app * n) {
|
||||
unsigned val = m_occurs.get_num_occs(n);
|
||||
if (val > 1 && m_manager.is_bool(n))
|
||||
m_out << "#" << n->get_id() << " -> " << val << " " << n->get_ref_count() << "\n";
|
||||
}
|
||||
void operator()(quantifier * n) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
void preprocessor::operator()(expr * e, proof * in_pr, expr_ref_vector & result, proof_ref_vector & result_prs) {
|
||||
m_cnf_todo.reset();
|
||||
m_cnf_todo_prs.reset();
|
||||
|
||||
expr_ref r1(m_manager);
|
||||
proof_ref pr1(m_manager);
|
||||
m_simp(e, r1, pr1);
|
||||
in_pr = m_manager.mk_modus_ponens(in_pr, pr1);
|
||||
|
||||
expr_ref r2(m_manager);
|
||||
proof_ref pr2(m_manager);
|
||||
m_nnf(r1, m_cnf_todo, m_cnf_todo_prs, r2, pr2);
|
||||
in_pr = m_manager.mk_modus_ponens(in_pr, pr2);
|
||||
|
||||
TRACE("preprocessor", tout << mk_ll_pp(r2, m_manager);
|
||||
num_occurs_pp proc(m_manager, tout, r2);
|
||||
for_each_expr(proc, r2););
|
||||
|
||||
m_cnf_todo.push_back(r2);
|
||||
m_cnf_todo_prs.push_back(in_pr);
|
||||
|
||||
unsigned sz = m_cnf_todo.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
m_push_todo.reset();
|
||||
m_push_todo_prs.reset();
|
||||
|
||||
expr * e = m_cnf_todo.get(i);
|
||||
if (m_params.m_lift_ite != LI_NONE) {
|
||||
m_push_app_ite(e, r1, pr1);
|
||||
}
|
||||
else {
|
||||
r1 = e;
|
||||
pr1 = 0;
|
||||
}
|
||||
|
||||
TRACE("preprocessor", tout << mk_ll_pp(r1, m_manager););
|
||||
|
||||
expr_ref aux(r1, m_manager);
|
||||
m_simp(aux, r1, pr2);
|
||||
pr1 = m_manager.mk_transitivity(pr1, pr2);
|
||||
|
||||
TRACE("preprocessor", tout << mk_ll_pp(r1, m_manager););
|
||||
|
||||
aux = r1;
|
||||
m_der(aux, r1, pr2);
|
||||
pr1 = m_manager.mk_transitivity(pr1, pr2);
|
||||
|
||||
TRACE("preprocessor", tout << mk_ll_pp(r1, m_manager););
|
||||
|
||||
if (m_manager.proofs_enabled())
|
||||
in_pr = m_manager.mk_modus_ponens(m_cnf_todo_prs.get(i), pr1);
|
||||
else
|
||||
in_pr = 0;
|
||||
|
||||
aux = r1;
|
||||
m_cnf(aux, m_push_todo, m_push_todo_prs, r1, pr1);
|
||||
m_push_todo.push_back(r1);
|
||||
|
||||
TRACE("preprocessor", tout << mk_ll_pp(r1, m_manager););
|
||||
|
||||
if (m_manager.proofs_enabled()) {
|
||||
in_pr = m_manager.mk_modus_ponens(in_pr, pr1);
|
||||
m_push_todo_prs.push_back(in_pr);
|
||||
}
|
||||
|
||||
unsigned sz2 = m_push_todo.size();
|
||||
for (unsigned j = 0; j < sz2; j++) {
|
||||
expr * e = m_push_todo.get(j);
|
||||
m_simp(e, r1, pr1);
|
||||
|
||||
TRACE("preprocessor", tout << mk_ll_pp(r1, m_manager););
|
||||
|
||||
if (m_manager.proofs_enabled())
|
||||
in_pr = m_manager.mk_modus_ponens(m_push_todo_prs.get(j), pr1);
|
||||
else
|
||||
in_pr = 0;
|
||||
push_assertion(m_manager, r1, in_pr, result, result_prs);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
preprocessor.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Preprocess AST before adding them to the logical context
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-17.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _PREPROCESSOR_H_
|
||||
#define _PREPROCESSOR_H_
|
||||
|
||||
#include"preprocessor_params.h"
|
||||
#include"simplifier.h"
|
||||
#include"pattern_inference.h"
|
||||
#include"nnf.h"
|
||||
#include"cnf.h"
|
||||
#include"der.h"
|
||||
#include"push_app_ite.h"
|
||||
|
||||
/**
|
||||
\brief Functor used to preprocess expressions before adding them to
|
||||
the logical context.
|
||||
*/
|
||||
class preprocessor {
|
||||
preprocessor_params & m_params;
|
||||
ast_manager & m_manager;
|
||||
simplifier & m_simp;
|
||||
nnf m_nnf;
|
||||
cnf m_cnf;
|
||||
der_star m_der;
|
||||
push_app_ite m_push_app_ite;
|
||||
expr_ref_vector m_cnf_todo;
|
||||
proof_ref_vector m_cnf_todo_prs;
|
||||
expr_ref_vector m_push_todo;
|
||||
proof_ref_vector m_push_todo_prs;
|
||||
public:
|
||||
preprocessor(ast_manager & m, defined_names & d, simplifier & s, preprocessor_params & p);
|
||||
void operator()(expr * e, proof * in_pr, expr_ref_vector & result, proof_ref_vector & result_prs);
|
||||
};
|
||||
|
||||
#endif /* _PREPROCESSOR_H_ */
|
|
@ -1,107 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sparse_use_list.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Sparse use list index.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-13.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPARSE_USE_LIST_H_
|
||||
#define _SPARSE_USE_LIST_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
|
||||
/**
|
||||
\brief (Generic sparse) use-list data-structure.
|
||||
*/
|
||||
template<typename T, typename Set>
|
||||
class sparse_use_list {
|
||||
typedef obj_map<T, Set *> use_list;
|
||||
use_list m_use_list;
|
||||
|
||||
public:
|
||||
typedef typename Set::iterator iterator;
|
||||
sparse_use_list() {}
|
||||
~sparse_use_list() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void insert(typename Set::data const & parent, T * child) {
|
||||
Set * parents = 0;
|
||||
if (!m_use_list.find(child, parents)) {
|
||||
parents = alloc(Set);
|
||||
m_use_list.insert(child, parents);
|
||||
}
|
||||
SASSERT(parents);
|
||||
parents->insert(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return 0 if child did not contain any parents.
|
||||
Return 1, if child does not have more parents after
|
||||
removing parent.
|
||||
Return 2 otherwise.
|
||||
*/
|
||||
unsigned erase(typename Set::data const & parent, T * child) {
|
||||
Set * parents = 0;
|
||||
if (m_use_list.find(child, parents)) {
|
||||
parents->erase(parent);
|
||||
if (parents->empty()) {
|
||||
dealloc(parents);
|
||||
m_use_list.erase(child);
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
typename use_list::iterator it = m_use_list.begin();
|
||||
typename use_list::iterator end = m_use_list.end();
|
||||
for (; it != end; ++it)
|
||||
dealloc(it->m_value);
|
||||
m_use_list.reset();
|
||||
}
|
||||
|
||||
Set * get_parents(T * e) {
|
||||
Set * parents = 0;
|
||||
m_use_list.find(e, parents);
|
||||
return parents;
|
||||
}
|
||||
|
||||
iterator begin(T * e) {
|
||||
Set * parents = 0;
|
||||
m_use_list.find(e, parents);
|
||||
SASSERT(parents);
|
||||
return parents->begin();
|
||||
}
|
||||
|
||||
iterator end(T * e) {
|
||||
Set * parents = 0;
|
||||
m_use_list.find(e, parents);
|
||||
SASSERT(parents);
|
||||
return parents->end();
|
||||
}
|
||||
|
||||
bool empty(T * e) const {
|
||||
Set * parents = 0;
|
||||
if (m_use_list.find(e, parents))
|
||||
return parents->empty();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _SPARSE_USE_LIST_H_ */
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_asserted_literals.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-14.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"spc_asserted_literals.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
asserted_literals::asserted_literals(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_subst(m),
|
||||
m_tmp_eq1(2),
|
||||
m_tmp_eq2(2) {
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
m_st[i] = alloc(substitution_tree, m_manager);
|
||||
m_expr2clause[i] = alloc(expr2clause);
|
||||
}
|
||||
m_subst.reserve_offsets(3);
|
||||
}
|
||||
|
||||
asserted_literals::~asserted_literals() {
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
dealloc(m_st[i]);
|
||||
dealloc(m_expr2clause[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void asserted_literals::insert(clause * cls) {
|
||||
if (cls->get_num_literals() == 1) {
|
||||
TRACE("asserted_literals", tout << "inserting clause into asserted_literals index:\n";
|
||||
cls->display(tout, m_manager); tout << "\n";);
|
||||
literal const & l = cls->get_literal(0);
|
||||
unsigned neg = static_cast<unsigned>(l.sign());
|
||||
expr * atom = l.atom();
|
||||
m_st[neg]->insert(to_app(atom));
|
||||
m_expr2clause[neg]->insert(atom, cls);
|
||||
m_subst.reserve_vars(m_st[neg]->get_approx_num_regs());
|
||||
}
|
||||
}
|
||||
|
||||
void asserted_literals::erase(clause * cls) {
|
||||
if (cls->get_num_literals() == 1) {
|
||||
literal const & l = cls->get_literal(0);
|
||||
unsigned neg = static_cast<unsigned>(l.sign());
|
||||
expr * atom = l.atom();
|
||||
m_expr2clause[neg]->erase(atom);
|
||||
m_st[neg]->erase(to_app(atom));
|
||||
}
|
||||
}
|
||||
|
||||
void asserted_literals::reset() {
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
m_st[i]->reset();
|
||||
m_expr2clause[i]->reset();
|
||||
}
|
||||
}
|
||||
|
||||
struct asserted_literals_visitor : public st_visitor {
|
||||
expr * m_target;
|
||||
asserted_literals_visitor(substitution & s):st_visitor(s), m_target(0) {}
|
||||
virtual bool operator()(expr * e) {
|
||||
m_target = e;
|
||||
return false; // stop
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Return an unit clause that is a generalization
|
||||
of the given literal.
|
||||
Return 0 if such clause does not exist.
|
||||
*/
|
||||
clause * asserted_literals::gen(expr * atom, bool n) {
|
||||
if (is_app(atom)) {
|
||||
TRACE("asserted_literals", tout << "checking if there is generalizer for: " << n << "\n" <<
|
||||
mk_pp(atom, m_manager) << "\n";);
|
||||
unsigned neg = static_cast<unsigned>(n);
|
||||
m_subst.reset_subst();
|
||||
asserted_literals_visitor visitor(m_subst);
|
||||
TRACE("asserted_literals_bug", tout << "query: " << mk_pp(atom, m_manager) << "\n"; m_st[neg]->display(tout);
|
||||
m_subst.display(tout););
|
||||
m_st[neg]->gen(to_app(atom), visitor);
|
||||
if (visitor.m_target != 0) {
|
||||
clause * cls = 0;
|
||||
m_expr2clause[neg]->find(visitor.m_target, cls);
|
||||
SASSERT(cls);
|
||||
return cls;
|
||||
}
|
||||
if (m_manager.is_eq(atom)) {
|
||||
m_subst.reset();
|
||||
m_tmp_eq1.copy_swapping_args(to_app(atom));
|
||||
m_st[neg]->gen(m_tmp_eq1.get_app(), visitor);
|
||||
if (visitor.m_target != 0) {
|
||||
clause * cls = 0;
|
||||
m_expr2clause[neg]->find(visitor.m_target, cls);
|
||||
SASSERT(cls);
|
||||
return cls;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return an unit clause that is a generalization
|
||||
of the equality (= lhs rhs)
|
||||
Return 0 if such clause does not exist.
|
||||
*/
|
||||
clause * asserted_literals::gen_eq(expr * lhs, expr * rhs) {
|
||||
expr * args[2] = { lhs, rhs };
|
||||
func_decl_ref eq_decl(m_manager.mk_func_decl(m_manager.get_basic_family_id(), OP_EQ, 0, 0, 2, args), m_manager);
|
||||
m_tmp_eq2.set_decl(eq_decl);
|
||||
m_tmp_eq2.set_arg(0, lhs);
|
||||
m_tmp_eq2.set_arg(1, rhs);
|
||||
return gen(m_tmp_eq2.get_app(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return a unit equality clause (= s t) that (eq) subsumes (= lhs rhs).
|
||||
That is, lhs and rhs have the form u[s'] and u[t'] and there is
|
||||
a substitution sigma s.t. sigma(s) = s' and sigma(t) = t'.
|
||||
Return 0 if such clause does not exist.
|
||||
*/
|
||||
clause * asserted_literals::subsumes(expr * lhs, expr * rhs) {
|
||||
while (true) {
|
||||
TRACE("eq_subsumption", tout << "eq_subsumption loop:\n" << mk_pp(lhs, m_manager) << "\n" <<
|
||||
mk_pp(rhs, m_manager) << "\n";);
|
||||
clause * subsumer = gen_eq(lhs, rhs);
|
||||
if (subsumer)
|
||||
return subsumer;
|
||||
if (!is_app(lhs) || !is_app(rhs) ||
|
||||
to_app(lhs)->get_decl() != to_app(rhs)->get_decl() ||
|
||||
to_app(lhs)->get_num_args() != to_app(rhs)->get_num_args())
|
||||
return 0;
|
||||
expr * d1 = 0;
|
||||
expr * d2 = 0;
|
||||
unsigned num_args = to_app(lhs)->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * c1 = to_app(lhs)->get_arg(i);
|
||||
expr * c2 = to_app(rhs)->get_arg(i);
|
||||
if (c1 != c2) {
|
||||
if (d1)
|
||||
return 0;
|
||||
d1 = c1;
|
||||
d2 = c2;
|
||||
}
|
||||
}
|
||||
SASSERT(d1);
|
||||
lhs = d1;
|
||||
rhs = d2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
|
@ -1,69 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_asserted_literals.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-14.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_ASSERTED_LITERALS_H_
|
||||
#define _SPC_ASSERTED_LITERALS_H_
|
||||
|
||||
#include"spc_clause.h"
|
||||
#include"substitution_tree.h"
|
||||
#include"obj_hashtable.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Index for the asserted literals in the logical context.
|
||||
|
||||
This index is used to implement forward unit subsumption,
|
||||
equality subsumption, positive simplify-reflect, and
|
||||
negative simplify-reflect.
|
||||
*/
|
||||
class asserted_literals {
|
||||
protected:
|
||||
typedef obj_map<expr, clause*> expr2clause;
|
||||
ast_manager & m_manager;
|
||||
substitution_tree * m_st[2];
|
||||
expr2clause * m_expr2clause[2];
|
||||
substitution m_subst;
|
||||
tmp_app m_tmp_eq1;
|
||||
tmp_app m_tmp_eq2;
|
||||
public:
|
||||
asserted_literals(ast_manager & m);
|
||||
~asserted_literals();
|
||||
|
||||
void insert(clause * cls);
|
||||
void erase(clause * cls);
|
||||
void reset();
|
||||
void reserve_vars(unsigned num_vars) { m_subst.reserve_vars(num_vars); }
|
||||
|
||||
clause * gen(literal const & l) {
|
||||
return gen(l.atom(), l.sign());
|
||||
}
|
||||
|
||||
clause * gen(expr * atom, bool neg);
|
||||
clause * gen_eq(expr * lhs, expr * rhs);
|
||||
clause * subsumes(expr * lhs, expr * rhs);
|
||||
|
||||
bool has_pos_literals() const { return !m_st[0]->empty(); }
|
||||
bool has_neg_literals() const { return !m_st[1]->empty(); }
|
||||
bool has_literals() const { return has_pos_literals() || has_neg_literals(); }
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SPC_ASSERTED_LITERALS_H_ */
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_clause.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Superposition Calculus Clause
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_clause.h"
|
||||
#include"splay_tree_def.h"
|
||||
|
||||
template class splay_tree<spc::clause *, spc::clause::compare>;
|
||||
|
||||
namespace spc {
|
||||
|
||||
clause::clause(ast_manager & m, unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl):
|
||||
m_id(UINT_MAX),
|
||||
m_time(UINT_MAX),
|
||||
m_scope_lvl(scope_lvl),
|
||||
m_bidx(UINT_MAX),
|
||||
m_processed(false),
|
||||
m_indexed(false),
|
||||
m_has_sel_lit(false),
|
||||
m_justification(p) {
|
||||
|
||||
set_fields(num_lits, lits);
|
||||
|
||||
m_num_lits_capacity = m_num_lits[0] + m_num_lits[1];
|
||||
|
||||
memcpy(m_lits, lits, sizeof(literal) * get_num_literals());
|
||||
|
||||
for (unsigned i = 0; i < num_lits; i++)
|
||||
m.inc_ref(m_lits[i].atom());
|
||||
m_justification->inc_ref();
|
||||
m_justification->set_owner(this);
|
||||
|
||||
sort_literals();
|
||||
}
|
||||
|
||||
clause * clause::mk(ast_manager & m, unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl) {
|
||||
void * mem = m.get_allocator().allocate(sizeof(clause) + num_lits * sizeof(literal));
|
||||
return new (mem) clause(m, num_lits, lits, p, scope_lvl);
|
||||
}
|
||||
|
||||
void clause::init(unsigned id, unsigned time) {
|
||||
SASSERT(m_id == UINT_MAX);
|
||||
SASSERT(m_time == UINT_MAX);
|
||||
|
||||
m_id = id;
|
||||
m_time = time;
|
||||
m_proof_depth = 0;
|
||||
|
||||
justification_stat j_stat;
|
||||
get_justification_stat(m_justification, j_stat);
|
||||
|
||||
m_proof_depth = j_stat.m_proof_depth;
|
||||
|
||||
if (j_stat.m_max_scope_lvl > m_scope_lvl)
|
||||
m_scope_lvl = j_stat.m_max_scope_lvl;
|
||||
|
||||
update_parents(j_stat.m_parent_clauses);
|
||||
}
|
||||
|
||||
void clause::update_parents(ptr_buffer<clause> & parents) {
|
||||
ptr_buffer<clause>::iterator it = parents.begin();
|
||||
ptr_buffer<clause>::iterator end = parents.end();
|
||||
for (; it != end; ++it) {
|
||||
clause * parent = *it;
|
||||
parent->add_child(this);
|
||||
}
|
||||
}
|
||||
|
||||
void clause::deallocate(ast_manager & m) {
|
||||
|
||||
justification_stat j_stat;
|
||||
get_justification_stat(get_justification(), j_stat);
|
||||
|
||||
ptr_buffer<clause>::iterator it = j_stat.m_parent_clauses.begin();
|
||||
ptr_buffer<clause>::iterator end = j_stat.m_parent_clauses.end();
|
||||
for (; it != end; ++it) {
|
||||
clause * parent = *it;
|
||||
parent->del_child(this);
|
||||
}
|
||||
|
||||
dec_ref(get_justification(), m);
|
||||
|
||||
unsigned num_lits = get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++)
|
||||
m.dec_ref(get_literal(i).atom());
|
||||
|
||||
unsigned capacity = get_num_literals_capacity();
|
||||
this->~clause();
|
||||
m.get_allocator().deallocate(sizeof(clause) + capacity * sizeof(literal), this);
|
||||
}
|
||||
|
||||
void clause::select_literal(unsigned idx) {
|
||||
SASSERT(idx < get_num_literals());
|
||||
m_lits[idx].set_selected(true);
|
||||
m_has_sel_lit = true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if l is maximal in the clause, given a substitution s.
|
||||
|
||||
s(l) is considered maximal if there is no literal l' in the clause such s(l') is greater
|
||||
than s(l).
|
||||
*/
|
||||
bool clause::is_maximal(order & o, literal const & l, unsigned offset, substitution * s) const {
|
||||
unsigned num_lits = get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l_prime = m_lits[i];
|
||||
if (l != l_prime && greater(o, l_prime, l, offset, s))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if l is a maximal selected literal in the clause, given a substitution s.
|
||||
|
||||
s(l) is considered maximal selected literal if there is no
|
||||
selected literal l' in the clause such s(l') is greater than s(l).
|
||||
*/
|
||||
bool clause::is_sel_maximal(order & o, literal const & l, unsigned offset, substitution * s) const {
|
||||
if (!l.is_selected())
|
||||
return false;
|
||||
unsigned num_lits = get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l_prime = m_lits[i];
|
||||
if (l != l_prime && l_prime.is_selected() && greater(o, l_prime, l, offset, s))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if l is eligible for resolution.
|
||||
*/
|
||||
bool clause::is_eligible_for_resolution(order & o, literal const & l, unsigned offset, substitution * s) const {
|
||||
if (has_sel_lit())
|
||||
return is_sel_maximal(o, l, offset, s);
|
||||
else
|
||||
return is_maximal(o, l, offset, s);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if l is eligible for paramodulation.
|
||||
*/
|
||||
bool clause::is_eligible_for_paramodulation(order & o, literal const & l, unsigned offset, substitution * s) const {
|
||||
return !has_sel_lit() && is_maximal(o, l, offset, s);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Try to orient literals.
|
||||
*/
|
||||
void clause::try_to_orient_literals(order & o) {
|
||||
o.reserve_vars(get_num_vars());
|
||||
unsigned num_lits = get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal & l = m_lits[i];
|
||||
l.try_to_orient(o);
|
||||
}
|
||||
}
|
||||
|
||||
void clause::set_fields(unsigned num_lits, literal * lits) {
|
||||
clause_stat c_stat;
|
||||
get_clause_stat(num_lits, lits, c_stat);
|
||||
|
||||
m_num_vars = c_stat.m_max_var_idx + 1;
|
||||
m_sym_count = c_stat.m_sym_count;
|
||||
m_const_count = c_stat.m_const_count;
|
||||
m_depth = c_stat.m_depth;
|
||||
m_num_lits[0] = c_stat.m_num_lits[0];
|
||||
m_num_lits[1] = c_stat.m_num_lits[1];
|
||||
m_ground = c_stat.m_ground;
|
||||
}
|
||||
|
||||
struct lit_lt {
|
||||
bool operator()(literal const & l1, literal const & l2) const {
|
||||
if (l1.is_ground() > l2.is_ground())
|
||||
return true;
|
||||
if (l1.is_ground() != l2.is_ground())
|
||||
return false;
|
||||
if (l1.get_approx_depth() > l2.get_approx_depth())
|
||||
return true;
|
||||
if (l1.get_approx_depth() != l2.get_approx_depth())
|
||||
return false;
|
||||
if (l1.get_approx_sym_count() > l2.get_approx_sym_count())
|
||||
return true;
|
||||
if (l1.get_approx_sym_count() != l2.get_approx_sym_count())
|
||||
return false;
|
||||
if (l1.get_approx_const_count() > l2.get_approx_const_count())
|
||||
return true;
|
||||
if (l1.get_approx_const_count() != l2.get_approx_const_count())
|
||||
return false;
|
||||
return l1.get_id() < l2.get_id();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Sort literals to improve the performance of subsumption tests.
|
||||
*/
|
||||
void clause::sort_literals() {
|
||||
DEBUG_CODE({
|
||||
unsigned num_lits = get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
SASSERT(m_lits[i].has_stats());
|
||||
}
|
||||
});
|
||||
std::sort(m_lits, m_lits + get_num_literals(), lit_lt());
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Replace clause literal with the given literals.
|
||||
Use the given justification to justify the new clause.
|
||||
*/
|
||||
void clause::update_lits(ast_manager & m, unsigned num_lits, literal * lits, justification * j) {
|
||||
unsigned old_num_lits = get_num_literals();
|
||||
SASSERT(num_lits <= old_num_lits);
|
||||
|
||||
for (unsigned i = 0; i < num_lits; i++)
|
||||
m.inc_ref(lits[i].atom());
|
||||
|
||||
for (unsigned i = 0; i < old_num_lits; i++)
|
||||
m.dec_ref(m_lits[i].atom());
|
||||
|
||||
for (unsigned i = 0; i < num_lits; i++)
|
||||
m_lits[i] = lits[i];
|
||||
|
||||
set_fields(num_lits, m_lits);
|
||||
|
||||
SASSERT(get_num_literals() == num_lits);
|
||||
|
||||
j->inc_ref();
|
||||
m_justification->set_owner(0); // release ownership
|
||||
dec_ref(m_justification, m);
|
||||
m_justification = j;
|
||||
m_justification->set_owner(this);
|
||||
|
||||
sort_literals();
|
||||
|
||||
justification_stat j_stat;
|
||||
get_justification_stat(m_justification, j_stat);
|
||||
|
||||
m_proof_depth = j_stat.m_proof_depth;
|
||||
|
||||
SASSERT(m_scope_lvl == j_stat.m_max_scope_lvl);
|
||||
|
||||
update_parents(j_stat.m_parent_clauses);
|
||||
}
|
||||
|
||||
void clause::display(std::ostream & out, ast_manager & m, bool detailed) {
|
||||
if (get_num_literals() == 0) {
|
||||
out << "empty-clause";
|
||||
return;
|
||||
}
|
||||
out << "#" << m_id << ": (clause ";
|
||||
spc::display(out, get_num_literals(), m_lits, m, detailed);
|
||||
out << ")";
|
||||
if (m_processed)
|
||||
out << "*";
|
||||
}
|
||||
|
||||
void get_clause_stat(unsigned num_lits, literal * lits, clause_stat & stat) {
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal_stat c;
|
||||
lits[i].get_stat(c);
|
||||
stat.m_sym_count += c.m_sym_count;
|
||||
stat.m_depth = std::max(stat.m_depth, c.m_depth);
|
||||
stat.m_max_var_idx = std::max(stat.m_max_var_idx, c.m_max_var_idx);
|
||||
stat.m_const_count += c.m_const_count;
|
||||
stat.m_ground &= c.m_ground;
|
||||
stat.m_num_lits[static_cast<unsigned>(lits[i].sign())]++;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
|
@ -1,152 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_clause.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Superposition Calculus Clause
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_CLAUSE_H_
|
||||
#define _SPC_CLAUSE_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"splay_tree.h"
|
||||
#include"use_list.h"
|
||||
#include"spc_literal.h"
|
||||
#include"spc_justification.h"
|
||||
#include"use_list.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
class context;
|
||||
|
||||
/**
|
||||
\brief Superposition Calculus clause.
|
||||
*/
|
||||
class clause {
|
||||
struct compare {
|
||||
// ignoring potential overflow/underflow
|
||||
int operator()(clause * c1, clause * c2) const {
|
||||
return static_cast<int>(c1->get_id()) - static_cast<int>(c2->get_id());
|
||||
}
|
||||
};
|
||||
public:
|
||||
typedef splay_tree<clause *, compare> set;
|
||||
private:
|
||||
unsigned m_id; // clause unique id
|
||||
unsigned m_time; // how old is the clause.
|
||||
unsigned m_num_vars; // approx. number of variables (i.e., max_var_id + 1)
|
||||
unsigned m_sym_count; // number of symbols
|
||||
unsigned m_const_count; // number of constants
|
||||
unsigned m_depth; // depth (i.e., max depth of a literal)
|
||||
unsigned m_proof_depth;
|
||||
unsigned m_scope_lvl; // which scope level owns the clause
|
||||
unsigned m_num_lits[2]; // number of positive [0] and negative [1] literals.
|
||||
unsigned m_num_lits_capacity; // some of the clause literals can be simplified and removed, this field contains the original number of literals (used for GC).
|
||||
unsigned m_bidx; // position on the backtracking stack
|
||||
bool m_ground:1;
|
||||
bool m_processed:1;
|
||||
bool m_indexed:1;
|
||||
bool m_has_sel_lit:1;
|
||||
justification * m_justification;
|
||||
set m_children;
|
||||
literal m_lits[0];
|
||||
friend class context;
|
||||
|
||||
void set_fields(unsigned num_lits, literal * lits);
|
||||
unsigned get_bidx() const { return m_bidx; }
|
||||
void init(unsigned idx, unsigned time);
|
||||
void update_parents(ptr_buffer<clause> & parents);
|
||||
void set_bidx(unsigned idx) { SASSERT(m_bidx == UINT_MAX); m_bidx = idx; }
|
||||
void add_child(clause * c) { m_children.insert(c); }
|
||||
void del_child(clause * c) { m_children.erase(c); }
|
||||
void set_processed(bool f) { m_processed = f; }
|
||||
void set_indexed(bool f) { m_indexed = f; }
|
||||
void sort_literals();
|
||||
/**
|
||||
\brief Release ownership of the justification.
|
||||
*/
|
||||
justification * release_justification() { justification * r = m_justification; m_justification = 0; return r; }
|
||||
|
||||
clause(ast_manager & m, unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl);
|
||||
|
||||
public:
|
||||
static clause * mk(ast_manager & m, unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl);
|
||||
void deallocate(ast_manager & m);
|
||||
|
||||
unsigned get_id() const { SASSERT(m_id != UINT_MAX); return m_id; }
|
||||
unsigned get_time() const { return m_time; }
|
||||
unsigned get_symbol_count() const { return m_sym_count; }
|
||||
unsigned get_proof_depth() const { return m_proof_depth; }
|
||||
unsigned get_num_literals() const { return m_num_lits[0] + m_num_lits[1]; }
|
||||
unsigned get_num_literals_capacity() const { return m_num_lits_capacity; }
|
||||
unsigned get_num_pos_literals() const { return m_num_lits[0]; }
|
||||
unsigned get_num_neg_literals() const { return m_num_lits[1]; }
|
||||
unsigned get_depth() const { return m_depth; }
|
||||
unsigned get_const_count() const { return m_const_count; }
|
||||
unsigned get_scope_lvl() const { return m_scope_lvl; }
|
||||
unsigned get_num_vars() const { return m_num_vars; }
|
||||
bool empty() const { return m_num_lits[0] == 0 && m_num_lits[1] == 0; }
|
||||
literal const & get_literal(unsigned idx) const { return m_lits[idx]; }
|
||||
literal & get_literal(unsigned idx) { return m_lits[idx]; }
|
||||
literal * get_literals() const { return const_cast<literal*>(m_lits); }
|
||||
justification * get_justification() const { return m_justification; }
|
||||
bool is_processed() const { return m_processed; }
|
||||
bool is_indexed() const { return m_indexed; }
|
||||
bool is_ground() const { return m_ground; }
|
||||
void select_literal(unsigned idx);
|
||||
bool is_maximal(order & o, literal const & l, unsigned offset = 0, substitution * s = 0) const;
|
||||
bool is_sel_maximal(order & o, literal const & l, unsigned offset = 0, substitution * s = 0) const ;
|
||||
bool is_eligible_for_resolution(order & o, literal const & l, unsigned offset = 0, substitution * s = 0) const;
|
||||
bool is_eligible_for_paramodulation(order & o, literal const & l, unsigned offset = 0, substitution * s = 0) const;
|
||||
bool has_sel_lit() const { return m_has_sel_lit; }
|
||||
void try_to_orient_literals(order & o);
|
||||
void update_lits(ast_manager & m, unsigned num_lits, literal * lits, justification * j);
|
||||
|
||||
void display(std::ostream & out, ast_manager & m, bool detailed = false);
|
||||
unsigned hash() const { return m_id; }
|
||||
};
|
||||
|
||||
typedef ptr_vector<clause> clause_vector;
|
||||
|
||||
/**
|
||||
\brief Clause Statistics (used to build clauses, subsumption, etc).
|
||||
*/
|
||||
struct clause_stat : public expr_stat {
|
||||
unsigned m_num_lits[2];
|
||||
clause_stat() {
|
||||
m_num_lits[0] = 0;
|
||||
m_num_lits[1] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Compute the statistics for a clause with num_lits
|
||||
literals lits, and store the results in stat.
|
||||
*/
|
||||
void get_clause_stat(unsigned num_lits, literal * lits, clause_stat & stat);
|
||||
|
||||
/**
|
||||
\brief A mapping from clause-id's to clauses
|
||||
*/
|
||||
class id2clause {
|
||||
ptr_vector<clause> m_clauses;
|
||||
public:
|
||||
void insert(clause * c) { return m_clauses.setx(c->get_id(), c, 0); }
|
||||
void erase(clause * c) { unsigned id = c->get_id(); if (id < m_clauses.size()) m_clauses[id] = 0; }
|
||||
clause * operator()(unsigned id) const { return m_clauses.get(id, 0); }
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _SPC_CLAUSE_H_ */
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_clause_pos_set.h
|
||||
|
||||
Abstract:
|
||||
|
||||
A set of pairs (clause, index).
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-16.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_CLAUSE_POS_SET_H_
|
||||
#define _SPC_CLAUSE_POS_SET_H_
|
||||
|
||||
#include"hashtable.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
typedef std::pair<clause *, unsigned> clause_pos_pair;
|
||||
|
||||
class clause_pos_entry {
|
||||
clause_pos_pair m_data;
|
||||
public:
|
||||
typedef clause_pos_pair data;
|
||||
clause_pos_entry() { m_data.first = 0; }
|
||||
unsigned get_hash() const { return m_data.first->get_id(); }
|
||||
bool is_free() const { return m_data.first == 0; }
|
||||
bool is_deleted() const { return m_data.first == reinterpret_cast<clause *>(1); }
|
||||
bool is_used() const {
|
||||
return m_data.first != reinterpret_cast<clause *>(0) && m_data.first != reinterpret_cast<clause *>(1);
|
||||
}
|
||||
clause_pos_pair const & get_data() const { return m_data; }
|
||||
clause_pos_pair & get_data() { return m_data; }
|
||||
void set_data(clause_pos_pair const & d) {
|
||||
SASSERT(d.first != 0 && d.first != reinterpret_cast<clause*>(1));
|
||||
m_data = d;
|
||||
}
|
||||
void set_hash(unsigned h) { SASSERT(m_data.first->get_id() == h); }
|
||||
void mark_as_deleted() { m_data.first = reinterpret_cast<clause *>(1); }
|
||||
void mark_as_free() { m_data.first = 0; }
|
||||
};
|
||||
|
||||
struct clause_pos_pair_hash {
|
||||
unsigned operator()(clause_pos_pair const & p) const { return p.first->get_id(); }
|
||||
};
|
||||
|
||||
typedef core_hashtable<clause_pos_entry, clause_pos_pair_hash, default_eq<clause_pos_pair> > clause_pos_set;
|
||||
};
|
||||
|
||||
#endif /* _SPC_CLAUSE_POS_SET_H_ */
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_clause_selection.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Superposition Calculus Clause Selection
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_clause_selection.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
const unsigned default_heap_size = 1024;
|
||||
|
||||
clause_selection::clause_selection(unsigned num_heaps, clause_eval * const * fs, unsigned * slot_size):
|
||||
m_curr_slot(0),
|
||||
m_counter(0),
|
||||
m_fs(num_heaps, fs) {
|
||||
SASSERT(num_heaps > 0);
|
||||
for (unsigned i = 0; i < num_heaps; i++) {
|
||||
m_heaps.push_back(alloc(heap<lt>, default_heap_size, lt(m_id2clause, *(fs[i]))));
|
||||
SASSERT(slot_size[i] > 0);
|
||||
m_slot_size.push_back(slot_size[i]);
|
||||
}
|
||||
}
|
||||
|
||||
clause_selection::~clause_selection() {
|
||||
std::for_each(m_heaps.begin(), m_heaps.end(), delete_proc<heap<lt> >());
|
||||
std::for_each(m_fs.begin(), m_fs.end(), delete_proc<clause_eval>());
|
||||
}
|
||||
|
||||
void clause_selection::reserve(unsigned cid) {
|
||||
unsigned capacity = m_heaps[0]->get_bounds();
|
||||
if (cid >= capacity) {
|
||||
unsigned new_capacity = 2 * cid + 1;
|
||||
SASSERT(cid < new_capacity);
|
||||
ptr_vector<heap<lt> >::iterator it = m_heaps.begin();
|
||||
ptr_vector<heap<lt> >::iterator end = m_heaps.end();
|
||||
for (; it != end; ++it) {
|
||||
heap<lt> * h = *it;
|
||||
h->reserve(new_capacity);;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clause_selection::reset() {
|
||||
ptr_vector<heap<lt> >::iterator it = m_heaps.begin();
|
||||
ptr_vector<heap<lt> >::iterator end = m_heaps.end();
|
||||
for (; it != end; ++it) {
|
||||
heap<lt> * h = *it;
|
||||
h->reset();
|
||||
}
|
||||
}
|
||||
|
||||
void clause_selection::insert(clause * c) {
|
||||
reserve(c->get_id());
|
||||
m_id2clause.insert(c);
|
||||
ptr_vector<heap<lt> >::iterator it = m_heaps.begin();
|
||||
ptr_vector<heap<lt> >::iterator end = m_heaps.end();
|
||||
for (; it != end; ++it) {
|
||||
heap<lt> * h = *it;
|
||||
h->insert(c->get_id());
|
||||
}
|
||||
}
|
||||
|
||||
void clause_selection::erase(clause * c) {
|
||||
// remark: it is not necessary to remove c from m_id2clause
|
||||
ptr_vector<heap<lt> >::iterator it = m_heaps.begin();
|
||||
ptr_vector<heap<lt> >::iterator end = m_heaps.end();
|
||||
SASSERT(it != end);
|
||||
if (!(*it)->contains(c->get_id()))
|
||||
return;
|
||||
for (; it != end; ++it) {
|
||||
heap<lt> * h = *it;
|
||||
h->erase(c->get_id());
|
||||
}
|
||||
}
|
||||
|
||||
bool clause_selection::empty() const {
|
||||
ptr_vector<heap<lt> >::const_iterator it = m_heaps.begin();
|
||||
ptr_vector<heap<lt> >::const_iterator end = m_heaps.end();
|
||||
for (; it != end; ++it)
|
||||
if (!(*it)->empty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
clause * clause_selection::get_best() {
|
||||
heap<lt> * h = m_heaps[m_curr_slot];
|
||||
if (h->empty())
|
||||
return 0;
|
||||
unsigned cid = m_heaps[m_curr_slot]->erase_min();
|
||||
clause * c = m_id2clause(cid);
|
||||
SASSERT(c);
|
||||
// remove clause from the other heaps
|
||||
unsigned num_heaps = m_heaps.size();
|
||||
for (unsigned i = 0; i < num_heaps; i++) {
|
||||
if (m_curr_slot != i)
|
||||
m_heaps[i]->erase(cid);
|
||||
}
|
||||
// remark: it is not necessary to remove c from m_id2clause
|
||||
m_counter++;
|
||||
if (m_counter >= m_slot_size[m_curr_slot]) {
|
||||
m_counter = 0;
|
||||
m_curr_slot++;
|
||||
if (m_curr_slot >= m_slot_size.size())
|
||||
m_curr_slot = 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
};
|
|
@ -1,85 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_clause_selection.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Superposition Calculus Clause Selection
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_CLAUSE_SELECTION_H_
|
||||
#define _SPC_CLAUSE_SELECTION_H_
|
||||
|
||||
#include"spc_clause.h"
|
||||
#include"heap.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Abstract functor for evaluating how 'good' a clause is.
|
||||
Smaller values mean better clauses.
|
||||
*/
|
||||
struct clause_eval {
|
||||
virtual ~clause_eval() {}
|
||||
virtual unsigned operator()(clause * c) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Clause selection heuristic. It supports different priority queues.
|
||||
*/
|
||||
class clause_selection {
|
||||
class lt {
|
||||
id2clause & m_id2clause;
|
||||
clause_eval & m_func;
|
||||
public:
|
||||
lt(id2clause & m, clause_eval & f):
|
||||
m_id2clause(m), m_func(f) {}
|
||||
bool operator()(int cidx1, int cidx2) const {
|
||||
return m_func(m_id2clause(cidx1)) < m_func(m_id2clause(cidx2));
|
||||
}
|
||||
};
|
||||
|
||||
id2clause m_id2clause;
|
||||
ptr_vector<heap<lt> > m_heaps;
|
||||
unsigned_vector m_slot_size;
|
||||
unsigned m_curr_slot;
|
||||
unsigned m_counter;
|
||||
ptr_vector<clause_eval> m_fs;
|
||||
void reserve(unsigned cid);
|
||||
public:
|
||||
clause_selection(unsigned num_heaps, clause_eval * const * fs, unsigned * slots);
|
||||
~clause_selection();
|
||||
void insert(clause * c);
|
||||
void erase(clause * c);
|
||||
bool empty() const;
|
||||
void reset();
|
||||
clause * get_best();
|
||||
};
|
||||
|
||||
struct symbol_count_clause_eval : public clause_eval {
|
||||
virtual ~symbol_count_clause_eval() {}
|
||||
virtual unsigned operator()(clause * c) const { return c->get_symbol_count(); }
|
||||
};
|
||||
|
||||
struct time_clause_eval : public clause_eval {
|
||||
virtual ~time_clause_eval() {}
|
||||
virtual unsigned operator()(clause * c) const { return c->get_time(); }
|
||||
};
|
||||
|
||||
struct proof_depth_clause_eval : public clause_eval {
|
||||
virtual ~proof_depth_clause_eval() {}
|
||||
virtual unsigned operator()(clause * c) const { return c->get_proof_depth(); }
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _SPC_CLAUSE_SELECTION_H_ */
|
||||
|
|
@ -1,504 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_context.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Superposition Calculus Engine
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_context.h"
|
||||
#include"buffer.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"warning.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
context::context(ast_manager & m, order & o, clause_selection & cs, literal_selection & ls, simplifier & s, spc_params & params):
|
||||
m_manager(m),
|
||||
m_params(params),
|
||||
m_alloc(m.get_allocator()),
|
||||
m_order(o),
|
||||
m_cls_sel(cs),
|
||||
m_lit_sel(ls),
|
||||
m_simplifier(s),
|
||||
m_time(0),
|
||||
m_scope_lvl(0),
|
||||
m_sem_taut(m),
|
||||
m_asserted_literals(m),
|
||||
m_rewriter(m, s, m_order, m_asserted_literals),
|
||||
m_der(m),
|
||||
m_subsumption(m, m_asserted_literals, params),
|
||||
m_eq_resolution(m, m_order, m_stats),
|
||||
m_factoring(m, m_order, m_stats),
|
||||
m_superposition(m, m_order, m_stats),
|
||||
m_unsat(0) {
|
||||
m_order.reserve_offsets(3);
|
||||
}
|
||||
|
||||
context::~context() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void context::reset() {
|
||||
m_cls_sel.reset();
|
||||
m_time = 0;
|
||||
m_scope_lvl = 0;
|
||||
|
||||
if (m_unsat)
|
||||
m_unsat = 0;
|
||||
for (unsigned i = 0; i <= m_scope_lvl; i++) {
|
||||
del_clauses(i);
|
||||
if (i < m_clauses_to_unfreeze.size())
|
||||
m_clauses_to_unfreeze[i].reset();
|
||||
}
|
||||
|
||||
m_asserted_literals.reset();
|
||||
m_rewriter.reset();
|
||||
m_subsumption.reset();
|
||||
m_superposition.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Insert the given clause into the indexes of processed clauses.
|
||||
*/
|
||||
void context::insert_index(clause * cls) {
|
||||
TRACE("insert_index", tout << "indexing clause, num_vars: " << cls->get_num_vars() << "\n";
|
||||
cls->display(tout, m_manager); tout << "\n";);
|
||||
m_order.reserve_vars(cls->get_num_vars());
|
||||
m_lit_sel(cls);
|
||||
m_asserted_literals.insert(cls);
|
||||
m_rewriter.insert(cls);
|
||||
m_subsumption.insert(cls);
|
||||
m_superposition.insert(cls);
|
||||
cls->set_indexed(true);
|
||||
}
|
||||
|
||||
void context::erase_index(clause * cls) {
|
||||
if (cls->is_indexed()) {
|
||||
m_asserted_literals.erase(cls);
|
||||
m_rewriter.erase(cls);
|
||||
m_subsumption.erase(cls);
|
||||
m_superposition.erase(cls);
|
||||
cls->set_indexed(false);
|
||||
}
|
||||
}
|
||||
|
||||
void context::set_conflict(clause * cls) {
|
||||
SASSERT(cls->get_num_literals() == 0);
|
||||
m_unsat = cls;
|
||||
if (m_params.m_spc_trace) {
|
||||
cls->display(std::cout, m_manager); std::cout << " ";
|
||||
cls->get_justification()->display(std::cout);
|
||||
std::cout << "\n";
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
|
||||
void context::del_clause(clause * cls) {
|
||||
TRACE("context", tout << "deleting clause:\n"; cls->display(tout, m_manager); tout << "\n";);
|
||||
m_stats.m_num_del_clause++;
|
||||
|
||||
erase_index(cls);
|
||||
if (!cls->is_processed())
|
||||
m_cls_sel.erase(cls);
|
||||
|
||||
unsigned scope_lvl = cls->get_scope_lvl();
|
||||
unsigned bidx = cls->get_bidx();
|
||||
m_clauses_to_delete[scope_lvl][bidx] = 0;
|
||||
|
||||
cls->deallocate(m_manager);
|
||||
}
|
||||
|
||||
void context::freeze_clause_until(clause * cls, unsigned scope_lvl) {
|
||||
if (cls->get_scope_lvl() >= scope_lvl) {
|
||||
del_clause(cls);
|
||||
return;
|
||||
}
|
||||
TRACE("context", tout << "freezing clause until: " << scope_lvl << ":\n"; cls->display(tout, m_manager); tout << "\n";);
|
||||
if (scope_lvl >= m_clauses_to_unfreeze.size())
|
||||
m_clauses_to_unfreeze.resize(scope_lvl+1, clause_vector());
|
||||
|
||||
erase_index(cls);
|
||||
cls->set_processed(false);
|
||||
|
||||
m_clauses_to_unfreeze[scope_lvl].push_back(cls);
|
||||
}
|
||||
|
||||
void context::unfreeze_clause(clause * cls) {
|
||||
TRACE("context", tout << "unfreezing clausel: "; cls->display(tout, m_manager); tout << "\n";);
|
||||
SASSERT(!cls->is_processed());
|
||||
m_cls_sel.insert(cls);
|
||||
}
|
||||
|
||||
void context::init_clause(clause * cls) {
|
||||
m_stats.m_num_mk_clause++;
|
||||
|
||||
cls->init(m_cls_id_gen.mk(), m_time);
|
||||
m_time++;
|
||||
unsigned scope_lvl = cls->get_scope_lvl();
|
||||
|
||||
if (scope_lvl >= m_clauses_to_delete.size())
|
||||
m_clauses_to_delete.resize(scope_lvl+1, clause_vector());
|
||||
|
||||
clause_vector & cv = m_clauses_to_delete[scope_lvl];
|
||||
unsigned bidx = cv.size();
|
||||
cv.push_back(cls);
|
||||
cls->set_bidx(bidx);
|
||||
}
|
||||
|
||||
clause * context::mk_clause(unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl) {
|
||||
clause * cls = clause::mk(m_manager, num_lits, lits, p, scope_lvl);
|
||||
init_clause(cls);
|
||||
return cls;
|
||||
}
|
||||
|
||||
void context::assert_expr(expr * n, proof * p, unsigned scope_lvl) {
|
||||
TRACE("spc_assert_expr", tout << mk_ismt2_pp(n, m_manager) << "\n";);
|
||||
SASSERT(scope_lvl <= m_scope_lvl);
|
||||
justification_ref ref(m_manager);
|
||||
ref = justification_proof_wrapper::mk(p, m_manager);
|
||||
assert_expr(n, ref, scope_lvl);
|
||||
}
|
||||
|
||||
void invalid_clause(expr * n) {
|
||||
warning_msg("ignoring formula containing an universally quantified boolean variable.");
|
||||
}
|
||||
|
||||
void context::assert_expr(expr * n, justification * p, unsigned scope_lvl) {
|
||||
SASSERT(scope_lvl <= m_scope_lvl);
|
||||
buffer<literal> lits;
|
||||
if (is_forall(n))
|
||||
n = to_quantifier(n)->get_expr();
|
||||
if (m_manager.is_or(n)) {
|
||||
unsigned num = to_app(n)->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
expr * c = to_app(n)->get_arg(i);
|
||||
bool is_neg = m_manager.is_not(c);
|
||||
if (is_var(c) || (is_neg && is_var(to_app(c)->get_arg(0)))) {
|
||||
invalid_clause(n);
|
||||
return;
|
||||
}
|
||||
if (is_neg)
|
||||
lits.push_back(literal(to_app(c)->get_arg(0), true));
|
||||
else
|
||||
lits.push_back(literal(c, false));
|
||||
}
|
||||
}
|
||||
else if (m_manager.is_false(n)) {
|
||||
// skip
|
||||
}
|
||||
else if (m_manager.is_not(n)) {
|
||||
if (is_var(to_app(n)->get_arg(0))) {
|
||||
invalid_clause(n);
|
||||
return;
|
||||
}
|
||||
lits.push_back(literal(to_app(n)->get_arg(0), true));
|
||||
}
|
||||
else {
|
||||
if (is_var(n)) {
|
||||
invalid_clause(n);
|
||||
return;
|
||||
}
|
||||
lits.push_back(literal(n, false));
|
||||
}
|
||||
|
||||
if (trivial(lits.size(), lits.c_ptr()))
|
||||
return;
|
||||
|
||||
clause * cls = mk_clause(lits.size(), lits.c_ptr(), p, scope_lvl);
|
||||
m_cls_sel.insert(cls);
|
||||
if (cls->get_num_literals() == 0)
|
||||
set_conflict(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if the given clause (set of literals) is trivial.
|
||||
That is, it contains the literal s = s or complementary literals.
|
||||
*/
|
||||
bool context::trivial(unsigned num_lits, literal * lits) {
|
||||
SASSERT(m_found_literals.empty());
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal l = lits[i];
|
||||
if (m_found_literals.contains_neg(l) || l.is_true(m_manager)) {
|
||||
m_found_literals.reset();
|
||||
m_stats.m_num_trivial++;
|
||||
return true;
|
||||
}
|
||||
m_found_literals.insert(l);
|
||||
}
|
||||
m_found_literals.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool context::trivial(clause * cls) {
|
||||
return trivial(cls->get_num_literals(), cls->get_literals());
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Simplify the given clause using the set of processed clauses.
|
||||
Return the simplified clause.
|
||||
*/
|
||||
clause * context::simplify(clause * cls) {
|
||||
clause * old_cls = cls;
|
||||
m_der(cls);
|
||||
cls = m_rewriter(old_cls);
|
||||
if (cls != old_cls) {
|
||||
// freeze old clause until simplified clause is deleted.
|
||||
freeze_clause_until(old_cls, cls->get_scope_lvl());
|
||||
init_clause(cls);
|
||||
m_stats.m_num_simplified++;
|
||||
}
|
||||
m_der(cls);
|
||||
return cls;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Use the given clause to simplify the set of processed clauses.
|
||||
|
||||
\remark: processed clauses that can be simplified, are moved to the
|
||||
set of unprocessed clauses.
|
||||
*/
|
||||
void context::simplify_processed(clause * cls) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if the clause is redundant.
|
||||
*/
|
||||
bool context::redundant(clause * cls) {
|
||||
int r_scope_lvl = -1;
|
||||
if (trivial(cls)) {
|
||||
TRACE("redundant", tout << "clause is trivial:\n"; cls->display(tout, m_manager); tout << "\n";);
|
||||
r_scope_lvl = 0;
|
||||
}
|
||||
else if (m_sem_taut(cls->get_num_literals(), cls->get_literals())) {
|
||||
TRACE("redundant", tout << "clause is a semantic tautology:\n"; cls->display(tout, m_manager); tout << "\n";);
|
||||
r_scope_lvl = 0;
|
||||
}
|
||||
else {
|
||||
clause * subsumer = m_subsumption.forward(cls);
|
||||
if (subsumer != 0) {
|
||||
TRACE("redundant", tout << "clause was subsumed: "; cls->display(tout, m_manager);
|
||||
tout << "\nsubsumer:\n"; subsumer->display(tout, m_manager); tout << "\n";);
|
||||
r_scope_lvl = subsumer->get_scope_lvl();
|
||||
m_stats.m_num_subsumed++;
|
||||
}
|
||||
}
|
||||
|
||||
if (r_scope_lvl >= 0) {
|
||||
m_stats.m_num_redundant++;
|
||||
TRACE("spc_saturate", tout << "clause is redundant until level: " << r_scope_lvl << " ...\n";);
|
||||
freeze_clause_until(cls, r_scope_lvl);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Process a newly generated clause.
|
||||
*/
|
||||
void context::process_new_clause(clause * cls) {
|
||||
if (cls) {
|
||||
SASSERT(cls->get_justification() != 0);
|
||||
init_clause(cls);
|
||||
if (trivial(cls)) {
|
||||
del_clause(cls);
|
||||
return;
|
||||
}
|
||||
cls = simplify(cls);
|
||||
if (trivial(cls)) {
|
||||
del_clause(cls);
|
||||
return;
|
||||
}
|
||||
// if (!redundant(cls)) {
|
||||
m_cls_sel.insert(cls);
|
||||
if (cls->get_num_literals() == 0)
|
||||
set_conflict(cls);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Apply superposition (left&right), resolution, (equality) factoring, and equality resolution
|
||||
with the given clause and the set of processed clauses.
|
||||
*/
|
||||
void context::generate(clause * cls) {
|
||||
m_new_clauses.reset();
|
||||
m_eq_resolution(cls, m_new_clauses);
|
||||
m_factoring(cls, m_new_clauses);
|
||||
m_superposition(cls, m_new_clauses);
|
||||
|
||||
ptr_vector<clause>::iterator it = m_new_clauses.begin();
|
||||
ptr_vector<clause>::iterator end = m_new_clauses.end();
|
||||
for (; it != end; ++it) {
|
||||
TRACE("spc_generate", tout << "new generated clause:\n"; (*it)->display(tout, m_manager); tout << "\n";);
|
||||
process_new_clause(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void context::saturate(unsigned threshold) {
|
||||
if (inconsistent())
|
||||
return;
|
||||
TRACE("spc_saturate", tout << "initial state:\n"; display(tout););
|
||||
unsigned i = 0;
|
||||
ptr_buffer<clause> to_simplify;
|
||||
while (i < threshold && !processed_all()) {
|
||||
i++;
|
||||
m_stats.m_num_processed++;
|
||||
clause * cls = m_cls_sel.get_best();
|
||||
if (m_params.m_spc_trace) {
|
||||
cls->display(std::cout, m_manager); std::cout << " ";
|
||||
cls->get_justification()->display(std::cout);
|
||||
std::cout << "\n";
|
||||
std::cout.flush();
|
||||
}
|
||||
cls->set_processed(true);
|
||||
TRACE("spc_saturate", tout << "get best: "; cls->display(tout, m_manager); tout << "\n";);
|
||||
cls = simplify(cls);
|
||||
|
||||
TRACE("spc_saturate", tout << "clause after simplification: "; cls->display(tout, m_manager); tout << "\n";);
|
||||
if (redundant(cls))
|
||||
continue;
|
||||
if (cls->empty()) {
|
||||
set_conflict(cls);
|
||||
break;
|
||||
}
|
||||
cls->try_to_orient_literals(m_order);
|
||||
simplify_processed(cls);
|
||||
insert_index(cls);
|
||||
generate(cls);
|
||||
if (inconsistent())
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE("spc_saturate", tout << "final state:\n"; display(tout););
|
||||
|
||||
#if 0
|
||||
IF_VERBOSE(10000,
|
||||
display(std::cout););
|
||||
display_statistics(std::cout);
|
||||
if (m_unsat && m_manager.fine_grain_proofs()) {
|
||||
std::cout << mk_ll_pp(m_unsat->get_justification()->get_proof(), m_manager);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void context::push_scope() {
|
||||
m_scope_lvl++;
|
||||
m_time_trail.push_back(m_time);
|
||||
}
|
||||
|
||||
void context::del_clauses(unsigned scope_lvl) {
|
||||
if (scope_lvl < m_clauses_to_delete.size()) {
|
||||
clause_vector & cv = m_clauses_to_delete[m_scope_lvl];
|
||||
clause_vector::iterator it = cv.begin();
|
||||
clause_vector::iterator end = cv.end();
|
||||
for (; it != end; ++it) {
|
||||
clause * cls = *it;
|
||||
if (cls)
|
||||
del_clause(cls);
|
||||
}
|
||||
cv.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void context::unfreeze_clauses(unsigned scope_lvl) {
|
||||
if (scope_lvl < m_clauses_to_unfreeze.size()) {
|
||||
clause_vector & cv = m_clauses_to_unfreeze[m_scope_lvl];
|
||||
clause_vector::iterator it = cv.begin();
|
||||
clause_vector::iterator end = cv.end();
|
||||
for (; it != end; ++it)
|
||||
unfreeze_clause(*it);
|
||||
cv.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void context::pop_scope(unsigned num_scopes) {
|
||||
SASSERT(num_scopes >= m_scope_lvl);
|
||||
unsigned new_lvl = m_scope_lvl - num_scopes;
|
||||
m_time = m_time_trail[new_lvl];
|
||||
m_time_trail.shrink(new_lvl);
|
||||
|
||||
if (m_unsat && new_lvl < m_unsat->get_scope_lvl())
|
||||
m_unsat = 0;
|
||||
|
||||
while (m_scope_lvl > new_lvl) {
|
||||
del_clauses(m_scope_lvl);
|
||||
unfreeze_clauses(m_scope_lvl);
|
||||
m_scope_lvl --;
|
||||
}
|
||||
}
|
||||
|
||||
void context::display(std::ostream & out, vector<clause_vector> const & cvs, unsigned scope_lvl, bool frozen) const {
|
||||
if (scope_lvl < cvs.size()) {
|
||||
bool first = true;
|
||||
clause_vector const & cv = cvs[scope_lvl];
|
||||
clause_vector::const_iterator it = cv.begin();
|
||||
clause_vector::const_iterator end = cv.end();
|
||||
for (; it != end; ++it) {
|
||||
clause * cls = *it;
|
||||
if (cls) {
|
||||
if (first) {
|
||||
out << "level " << scope_lvl << ":\n";
|
||||
first = false;
|
||||
}
|
||||
cls->display(out, m_manager);
|
||||
if (frozen)
|
||||
out << " [frozen]";
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void context::display(std::ostream & out) const {
|
||||
for (unsigned i = 0; i <= m_scope_lvl; i++) {
|
||||
display(out, m_clauses_to_delete, i, false);
|
||||
display(out, m_clauses_to_unfreeze, i, true);
|
||||
}
|
||||
}
|
||||
|
||||
void context::display_statistics(std::ostream & out) const {
|
||||
m_stats.display(out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Generate new clauses
|
||||
|
||||
5) Object equality resolution 1
|
||||
|
||||
(R or X = i)
|
||||
==>
|
||||
sigma(R)
|
||||
|
||||
sigma = { X -> j }
|
||||
where i and j are distinct objects
|
||||
sigma(X = i) is not smaller or equal than any other literal in the clause
|
||||
|
||||
6) Object equality resolution 2
|
||||
|
||||
(R or X = Y)
|
||||
==>
|
||||
sigma(R)
|
||||
|
||||
sigma = { X -> i, Y -> j }
|
||||
For every pair of distinct objects i and j
|
||||
sigma(X = Y) is not smaller or equal than any other literal in the clause
|
||||
|
||||
*/
|
||||
|
||||
};
|
|
@ -1,122 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_context.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Superposition Calculus Engine
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_CONTEXT_H_
|
||||
#define _SPC_CONTEXT_H_
|
||||
|
||||
#include"spc_params.h"
|
||||
#include"spc_clause.h"
|
||||
#include"spc_clause_selection.h"
|
||||
#include"spc_literal_selection.h"
|
||||
#include"spc_semantic_tautology.h"
|
||||
#include"spc_rewriter.h"
|
||||
#include"spc_asserted_literals.h"
|
||||
#include"spc_subsumption.h"
|
||||
#include"spc_eq_resolution.h"
|
||||
#include"spc_factoring.h"
|
||||
#include"spc_superposition.h"
|
||||
#include"spc_statistics.h"
|
||||
#include"spc_der.h"
|
||||
#include"substitution_tree.h"
|
||||
#include"order.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Logical context of the superposition calculus engine.
|
||||
*/
|
||||
class context {
|
||||
public:
|
||||
statistics m_stats;
|
||||
protected:
|
||||
typedef clause::set clause_set;
|
||||
|
||||
ast_manager & m_manager;
|
||||
spc_params & m_params;
|
||||
small_object_allocator & m_alloc;
|
||||
order & m_order;
|
||||
clause_selection & m_cls_sel;
|
||||
literal_selection & m_lit_sel;
|
||||
simplifier & m_simplifier;
|
||||
unsigned m_time;
|
||||
unsigned m_scope_lvl;
|
||||
id_gen m_cls_id_gen;
|
||||
found_literals m_found_literals;
|
||||
semantic_tautology m_sem_taut;
|
||||
asserted_literals m_asserted_literals;
|
||||
rewriter m_rewriter;
|
||||
der m_der;
|
||||
subsumption m_subsumption;
|
||||
eq_resolution m_eq_resolution;
|
||||
factoring m_factoring;
|
||||
superposition m_superposition;
|
||||
vector<clause_vector> m_clauses_to_unfreeze;
|
||||
vector<clause_vector> m_clauses_to_delete;
|
||||
unsigned_vector m_time_trail;
|
||||
clause * m_unsat;
|
||||
ptr_vector<clause> m_new_clauses;
|
||||
|
||||
void insert_index(clause * cls);
|
||||
void erase_index(clause * cls);
|
||||
|
||||
void init_clause(clause * cls);
|
||||
clause * mk_clause(unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl);
|
||||
|
||||
void del_clause(clause * cls);
|
||||
void del_clauses(unsigned scope_lvl);
|
||||
|
||||
void freeze_clause_until(clause * cls, unsigned scope_lvl);
|
||||
void unfreeze_clause(clause * cls);
|
||||
void unfreeze_clauses(unsigned scope_lvl);
|
||||
|
||||
bool trivial(unsigned num_lits, literal * lits);
|
||||
bool trivial(clause * cls);
|
||||
clause * simplify(clause * cls);
|
||||
void simplify_processed(clause * cls);
|
||||
bool redundant(clause * cls);
|
||||
void generate(clause * cls);
|
||||
void process_new_clause(clause * cls);
|
||||
|
||||
void display(std::ostream & out, vector<clause_vector> const & cvs, unsigned scope_lvl, bool frozen) const;
|
||||
|
||||
void set_conflict(clause * cls);
|
||||
|
||||
public:
|
||||
context(ast_manager & m, order & o, clause_selection & cs, literal_selection & ls, simplifier & s, spc_params & params);
|
||||
~context();
|
||||
|
||||
simplifier & get_simplifier() { return m_simplifier; }
|
||||
order & get_order() { return m_order; }
|
||||
ast_manager & get_manager() { return m_manager; }
|
||||
|
||||
unsigned get_scope_lvl() const { return m_scope_lvl; }
|
||||
|
||||
void assert_expr(expr * n, proof * p, unsigned scope_lvl = 0);
|
||||
void assert_expr(expr * n, justification * p, unsigned scope_lvl = 0);
|
||||
void saturate(unsigned threshold);
|
||||
bool inconsistent() const { return m_unsat != 0; }
|
||||
bool processed_all() const { return m_cls_sel.empty(); }
|
||||
void push_scope();
|
||||
void pop_scope(unsigned num_scopes);
|
||||
void reset();
|
||||
void display(std::ostream & out) const;
|
||||
void display_statistics(std::ostream & out) const;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _SPC_CONTEXT_H_ */
|
|
@ -1,135 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_decl_plugin.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-12.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_decl_plugin.h"
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, spc_op_kind k) {
|
||||
switch (k) {
|
||||
case PR_DEMODULATION: out << "demod"; break;
|
||||
case PR_SPC_REWRITE: out << "rewrite"; break;
|
||||
case PR_SPC_RESOLUTION: out << "res"; break;
|
||||
case PR_SUPERPOSITION: out << "sup"; break;
|
||||
case PR_EQUALITY_RESOLUTION: out << "eq_res"; break;
|
||||
case PR_FACTORING: out << "fact"; break;
|
||||
case PR_SPC_DER: out << "der"; break;
|
||||
case PR_SPC_ASSERTED: out << "asserted"; break;
|
||||
default: out << "unknown"; break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
spc_decl_plugin::spc_decl_plugin() :
|
||||
m_demodulation("demod"),
|
||||
m_spc_rewrite("sp-rw"),
|
||||
m_spc_resolution("sp-res"),
|
||||
m_superposition("sp"),
|
||||
m_equality_resolution("eq-res"),
|
||||
m_factoring("fact"),
|
||||
m_spc_der("spc-der") {
|
||||
}
|
||||
|
||||
spc_decl_plugin::~spc_decl_plugin() {
|
||||
}
|
||||
|
||||
sort * spc_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const* parameters) {
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
func_decl * spc_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
|
||||
#define MK_PROOF(SYM) m_manager->mk_func_decl(SYM, arity, domain, m_manager->mk_proof_sort(), func_decl_info(m_family_id, k))
|
||||
|
||||
SASSERT(num_parameters == 0);
|
||||
switch (k) {
|
||||
/*
|
||||
#1: (forall (x) (= t[x] s[x]))
|
||||
[demod #1] (= t[a] s[a])
|
||||
*/
|
||||
case PR_DEMODULATION: return MK_PROOF(m_demodulation);
|
||||
/*
|
||||
Justifies a rewriting (simplification step) in the superposition engine.
|
||||
It has n+1 antecedents. The first antecedent is the clause being simplified.
|
||||
The other antecedents are demodulators.
|
||||
The consequent is the simplied clause.
|
||||
*/
|
||||
case PR_SPC_REWRITE: return MK_PROOF(m_spc_rewrite);
|
||||
/*
|
||||
Resolution proof:
|
||||
|
||||
#1: (or C l)
|
||||
#2: (or D (not l'))
|
||||
[sp-res #1 #2]: sigma(or C D)
|
||||
|
||||
where sigma is the mgu of l and l'
|
||||
|
||||
*/
|
||||
case PR_SPC_RESOLUTION: return MK_PROOF(m_spc_resolution);
|
||||
/*
|
||||
Superposition proof:
|
||||
|
||||
#1: (or (= s t) R)
|
||||
#2: D[u]
|
||||
[sp #1 #2]: sigma(or R D[t])
|
||||
|
||||
where sigma is the mgu(u, s)
|
||||
*/
|
||||
case PR_SUPERPOSITION: return MK_PROOF(m_superposition);
|
||||
/*
|
||||
Equality resolution proof:
|
||||
|
||||
#1: (or (not (= s t)) R)
|
||||
[eq-res #1]: sigma R
|
||||
|
||||
where sigma is the mgu of s and t.
|
||||
*/
|
||||
case PR_EQUALITY_RESOLUTION: return MK_PROOF(m_equality_resolution);
|
||||
/*
|
||||
Proof object for factoring and equality-factoring:
|
||||
|
||||
#1: (or P[t] P[s] R)
|
||||
[fact #1]: sigma(or P[t] R)
|
||||
|
||||
where sigma is the mgu(t,s)
|
||||
|
||||
#1: (or (= s t) (= u v) R)
|
||||
[fact #1]: sigma(or (not (= t v)) (= u v) R)
|
||||
|
||||
where sigma = mgu(s, u)
|
||||
*/
|
||||
case PR_FACTORING: return MK_PROOF(m_factoring);
|
||||
/*
|
||||
Proof object for destructive equality resolution:
|
||||
|
||||
#1: (or (not (= x t)) C[x])
|
||||
[spc-der #1]: C[t]
|
||||
|
||||
t does not contain x.
|
||||
|
||||
Several variables may be eliminated simultaneously.
|
||||
*/
|
||||
case PR_SPC_DER: return MK_PROOF(m_spc_der);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_decl_plugin.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Proof declarations for Superposition Calculus Engine.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-12.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_DECL_PLUGIN_H_
|
||||
#define _SPC_DECL_PLUGIN_H_
|
||||
|
||||
#include"ast.h"
|
||||
|
||||
enum spc_op_kind {
|
||||
PR_DEMODULATION,
|
||||
PR_SPC_REWRITE,
|
||||
PR_SPC_RESOLUTION,
|
||||
PR_SUPERPOSITION,
|
||||
PR_EQUALITY_RESOLUTION,
|
||||
PR_FACTORING,
|
||||
PR_SPC_DER,
|
||||
PR_SPC_ASSERTED,
|
||||
PR_SPC_LAST_ID
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, spc_op_kind k);
|
||||
|
||||
class spc_decl_plugin : public decl_plugin {
|
||||
symbol m_demodulation;
|
||||
symbol m_spc_rewrite;
|
||||
symbol m_spc_resolution;
|
||||
symbol m_superposition;
|
||||
symbol m_equality_resolution;
|
||||
symbol m_factoring;
|
||||
symbol m_spc_der;
|
||||
|
||||
public:
|
||||
spc_decl_plugin();
|
||||
|
||||
virtual ~spc_decl_plugin();
|
||||
|
||||
virtual decl_plugin * mk_fresh() { return alloc(spc_decl_plugin); }
|
||||
|
||||
virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const* parameters);
|
||||
|
||||
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
};
|
||||
|
||||
#endif /* _SPC_DECL_PLUGIN_H_ */
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_der.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-17.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_der.h"
|
||||
#include"occurs.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
der::der(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_subst(m),
|
||||
m_spc_fid(m.get_family_id("spc")) {
|
||||
m_subst.reserve_offsets(1);
|
||||
}
|
||||
|
||||
void der::apply(clause * cls, unsigned j, expr * lhs, expr * rhs) {
|
||||
TRACE("der", tout << "applying der at: " << j << "\n"; cls->display(tout, m_manager); tout << "\n";);
|
||||
m_subst.reserve_vars(cls->get_num_vars());
|
||||
m_subst.reset();
|
||||
m_subst.insert(expr_offset(lhs, 0), expr_offset(rhs, 0));
|
||||
literal_buffer new_lits(m_manager);
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
if (i != j) {
|
||||
literal const & l = cls->get_literal(i);
|
||||
expr_ref new_atom(m_manager);
|
||||
m_subst.apply(l.atom(), new_atom);
|
||||
new_lits.push_back(literal(new_atom, l.sign()));
|
||||
}
|
||||
}
|
||||
justification * js = mk_der_justification(m_manager, m_spc_fid, cls->get_justification(), new_lits.size(), new_lits.c_ptr());
|
||||
cls->update_lits(m_manager, new_lits.size(), new_lits.c_ptr(), js);
|
||||
}
|
||||
|
||||
bool der::apply(clause * cls) {
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l = cls->get_literal(i);
|
||||
if (l.sign() && m_manager.is_eq(l.atom())) {
|
||||
expr * lhs = l.lhs();
|
||||
expr * rhs = l.rhs();
|
||||
if (is_var(lhs) && !occurs(lhs, rhs)) {
|
||||
apply(cls, i, lhs, rhs);
|
||||
return true;
|
||||
}
|
||||
else if (is_var(rhs) && !occurs(rhs, lhs)) {
|
||||
apply(cls, i, rhs, lhs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Clause cls is destructively updated.
|
||||
*/
|
||||
void der::operator()(clause * cls) {
|
||||
while(apply(cls))
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_der.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-17.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_DER_H_
|
||||
#define _SPC_DER_H_
|
||||
|
||||
#include"spc_clause.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Functor for applying destructive equality resolution.
|
||||
This is similar to the Functor in der.h, but this one applies
|
||||
the simplification on clauses instead of ast's.
|
||||
|
||||
x != s or R
|
||||
==>
|
||||
sigma(R)
|
||||
|
||||
where
|
||||
sigma = mgu(x, s)
|
||||
*/
|
||||
class der {
|
||||
ast_manager & m_manager;
|
||||
substitution m_subst;
|
||||
unsigned_vector m_to_keep;
|
||||
family_id m_spc_fid;
|
||||
void apply(clause * cls, unsigned j, expr * lhs, expr * rhs);
|
||||
bool apply(clause * cls);
|
||||
public:
|
||||
der(ast_manager & m);
|
||||
void operator()(clause * cls);
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _SPC_DER_H_ */
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_eq_resolution.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-14.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_eq_resolution.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Apply equality resolution rule on the given clause.
|
||||
Store the produced clauses in new_clauses.
|
||||
*/
|
||||
void eq_resolution::operator()(clause * cls, ptr_vector<clause> & new_clauses) {
|
||||
m_subst.reserve_vars(cls->get_num_vars());
|
||||
unsigned num = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
literal const & l = cls->get_literal(i);
|
||||
expr * atom = l.atom();
|
||||
if (l.sign() && m_manager.is_eq(atom)) {
|
||||
expr * lhs = to_app(atom)->get_arg(0);
|
||||
expr * rhs = to_app(atom)->get_arg(1);
|
||||
m_subst.reset();
|
||||
if (m_unifier(lhs, rhs, m_subst, false) && cls->is_eligible_for_resolution(m_order, l, 0, &m_subst)) {
|
||||
m_stats.m_num_eq_resolution++;
|
||||
new_clauses.push_back(mk_result(cls, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,50 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_eq_resolution.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-14.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_EQ_RESOLUTION_H_
|
||||
#define _SPC_EQ_RESOLUTION_H_
|
||||
|
||||
#include"spc_unary_inference.h"
|
||||
#include"spc_statistics.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Functor for applying equality resolution.
|
||||
|
||||
s != t or R
|
||||
==>
|
||||
sigma(R)
|
||||
*/
|
||||
class eq_resolution : public unary_inference {
|
||||
protected:
|
||||
statistics & m_stats;
|
||||
family_id m_spc_fid;
|
||||
virtual justification * mk_justification(justification * parent, unsigned num_lits, literal * new_lits) {
|
||||
return mk_eq_res_justification(m_manager, m_spc_fid, parent, num_lits, new_lits);
|
||||
}
|
||||
public:
|
||||
eq_resolution(ast_manager & m, order & ord, statistics & stats):unary_inference(m, ord), m_stats(stats), m_spc_fid(m.get_family_id("spc")) {}
|
||||
virtual ~eq_resolution() {}
|
||||
void operator()(clause * cls, ptr_vector<clause> & new_clauses);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif /* _SPC_EQ_RESOLUTION_H_ */
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_factoring.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-14.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_factoring.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Create a new clause by removing literal at position j, apply substitution m_subst,
|
||||
and adding a disequality lhs != rhs.
|
||||
*/
|
||||
clause * factoring::mk_eq_fact_result(clause * cls, unsigned j, expr * lhs, expr * rhs) {
|
||||
sbuffer<literal> new_literals;
|
||||
|
||||
expr_ref new_eq(m_manager.mk_eq(lhs, rhs), m_manager);
|
||||
expr_ref new_eq_after_subst(m_manager);
|
||||
m_subst.apply(new_eq, new_eq_after_subst);
|
||||
new_literals.push_back(literal(new_eq_after_subst, true));
|
||||
|
||||
unsigned num = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (i != j) {
|
||||
literal const & l = cls->get_literal(i);
|
||||
expr_ref new_atom(m_manager);
|
||||
m_subst.apply(l.atom(), new_atom);
|
||||
new_literals.push_back(literal(new_atom, l.sign()));
|
||||
}
|
||||
}
|
||||
|
||||
justification * js = mk_factoring_justification(m_manager, m_spc_fid, cls->get_justification(), new_literals.size(),
|
||||
new_literals.c_ptr());
|
||||
clause * new_cls = clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), js, cls->get_scope_lvl());
|
||||
m_stats.m_num_eq_factoring++;
|
||||
return new_cls;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Try to apply equality factoring using the eq literal stored at position j.
|
||||
Assume lhs and rhs are the left hand side of this equality (they may be swapped).
|
||||
*/
|
||||
void factoring::try_eq_factoring(clause * cls, unsigned j, expr * lhs, expr * rhs, ptr_vector<clause> & new_clauses) {
|
||||
literal const & l1 = cls->get_literal(j);
|
||||
sort * s = m_manager.get_sort(lhs);
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l2 = cls->get_literal(i);
|
||||
if (i == j)
|
||||
continue;
|
||||
if (l2.sign())
|
||||
continue;
|
||||
expr * atom = l2.atom();
|
||||
if (!m_manager.is_eq(atom))
|
||||
continue;
|
||||
expr * lhs2 = to_app(atom)->get_arg(0);
|
||||
if (m_manager.get_sort(lhs2) != s)
|
||||
continue;
|
||||
expr * rhs2 = to_app(atom)->get_arg(1);
|
||||
m_subst.reset();
|
||||
if (m_unifier(lhs, lhs2, m_subst, false) &&
|
||||
(l1.is_oriented() || !m_order.greater(rhs, lhs, &m_subst)) &&
|
||||
cls->is_eligible_for_paramodulation(m_order, l1, 0, &m_subst)) {
|
||||
new_clauses.push_back(mk_eq_fact_result(cls, j, rhs, rhs2));
|
||||
}
|
||||
m_subst.reset();
|
||||
if (m_unifier(lhs, rhs2, m_subst, false) &&
|
||||
(l1.is_oriented() || !m_order.greater(rhs, lhs, &m_subst)) &&
|
||||
cls->is_eligible_for_paramodulation(m_order, l1, 0, &m_subst)) {
|
||||
new_clauses.push_back(mk_eq_fact_result(cls, j, rhs, lhs2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Try to apply equality factoring using the eq literal stored at position i.
|
||||
*/
|
||||
void factoring::try_eq_factoring(clause * cls, unsigned i, ptr_vector<clause> & new_clauses) {
|
||||
if (cls->get_num_pos_literals() <= 1)
|
||||
return;
|
||||
literal const & l = cls->get_literal(i);
|
||||
app * eq = to_app(l.atom());
|
||||
expr * lhs = eq->get_arg(0);
|
||||
expr * rhs = eq->get_arg(1);
|
||||
if (l.is_oriented()) {
|
||||
if (!l.is_left())
|
||||
std::swap(lhs, rhs);
|
||||
try_eq_factoring(cls, i, lhs, rhs, new_clauses);
|
||||
}
|
||||
else {
|
||||
try_eq_factoring(cls, i, lhs, rhs, new_clauses);
|
||||
try_eq_factoring(cls, i, rhs, lhs, new_clauses);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Try to apply (ordering) factoring rule.
|
||||
*/
|
||||
void factoring::try_factoring(clause * cls, unsigned j, ptr_vector<clause> & new_clauses) {
|
||||
literal const & l1 = cls->get_literal(j);
|
||||
if (l1.sign() && cls->get_num_neg_literals() <= 1)
|
||||
return;
|
||||
if (!l1.sign() && cls->get_num_pos_literals() <= 1)
|
||||
return;
|
||||
unsigned num = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (i == j)
|
||||
continue;
|
||||
literal const & l2 = cls->get_literal(i);
|
||||
if (l1.sign() != l2.sign())
|
||||
continue;
|
||||
m_subst.reset();
|
||||
if (m_unifier(l1.atom(), l2.atom(), m_subst, false) &&
|
||||
cls->is_eligible_for_resolution(m_order, l1, 0, &m_subst)) {
|
||||
new_clauses.push_back(mk_result(cls, i));
|
||||
m_stats.m_num_factoring++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Apply factoring rule on the given clause.
|
||||
Store the produced clauses into new_clauses.
|
||||
*/
|
||||
void factoring::operator()(clause * cls, ptr_vector<clause> & new_clauses) {
|
||||
if (cls->get_num_pos_literals() <= 1 && cls->get_num_neg_literals() <= 1)
|
||||
return;
|
||||
|
||||
m_subst.reserve_vars(cls->get_num_vars());
|
||||
unsigned num = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
literal const & l = cls->get_literal(i);
|
||||
expr * atom = l.atom();
|
||||
// remark: if the clause has selected literals then the literal will not be eligible
|
||||
// for paramodulation and eq_resolution will not be applied.
|
||||
if (!l.sign() && m_manager.is_eq(atom) && !cls->has_sel_lit())
|
||||
try_eq_factoring(cls, i, new_clauses);
|
||||
if (l.is_selected() || !cls->has_sel_lit())
|
||||
try_factoring(cls, i, new_clauses);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
|
@ -1,66 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_factoring.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-14.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_FACTORING_H_
|
||||
#define _SPC_FACTORING_H_
|
||||
|
||||
#include"spc_unary_inference.h"
|
||||
#include"spc_statistics.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Functor for applying factoring.
|
||||
|
||||
- Equality Factoring
|
||||
s = t or u = v or R
|
||||
==>
|
||||
sigma(t != v or u = v or R)
|
||||
|
||||
sigma = mgu(s, u)
|
||||
sigma(s) not greater than sigma(t)
|
||||
sigma(s = t) is eligible for paramodulation.
|
||||
|
||||
- Factoring
|
||||
P(t) or P(s) or R
|
||||
==>
|
||||
sigma(P(t) or R)
|
||||
|
||||
sigma = mgu(t,s)
|
||||
sigma(P(t)) is eligible for resolution.
|
||||
*/
|
||||
class factoring : public unary_inference {
|
||||
protected:
|
||||
statistics & m_stats;
|
||||
family_id m_spc_fid;
|
||||
virtual justification * mk_justification(justification * parent, unsigned num_lits, literal * new_lits) {
|
||||
return mk_factoring_justification(m_manager, m_spc_fid, parent, num_lits, new_lits);
|
||||
}
|
||||
clause * mk_eq_fact_result(clause * cls, unsigned j, expr * lhs, expr * rhs);
|
||||
void try_eq_factoring(clause * cls, unsigned j, expr * lhs, expr * rhs, ptr_vector<clause> & new_clauses);
|
||||
void try_eq_factoring(clause * cls, unsigned i, ptr_vector<clause> & new_clauses);
|
||||
void try_factoring(clause * cls, unsigned j, ptr_vector<clause> & new_clauses);
|
||||
public:
|
||||
factoring(ast_manager & m, order & ord, statistics & stats):unary_inference(m, ord), m_stats(stats), m_spc_fid(m.get_family_id("spc")) {}
|
||||
virtual ~factoring() {}
|
||||
void operator()(clause * cls, ptr_vector<clause> & new_clauses);
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _SPC_FACTORING_H_ */
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_justification.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-08.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_justification.h"
|
||||
#include"spc_clause.h"
|
||||
#include"marker.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
void get_justification_stat(justification * p, justification_stat & stat) {
|
||||
// Remark: justification objects that are not associated
|
||||
// with clauses may be shared. That is, they may be parent of
|
||||
// several different justification objects.
|
||||
marker<justification> m;
|
||||
ptr_buffer<justification> todo;
|
||||
todo.push_back(p);
|
||||
while (!todo.empty()) {
|
||||
justification * p = todo.back();
|
||||
todo.pop_back();
|
||||
if (!m.is_marked(p)) {
|
||||
m.mark(p);
|
||||
clause * cls = p->get_clause();
|
||||
if (cls) {
|
||||
if (cls->get_proof_depth() > stat.m_proof_depth)
|
||||
stat.m_proof_depth = cls->get_proof_depth();
|
||||
if (cls->get_scope_lvl() > stat.m_max_scope_lvl)
|
||||
stat.m_max_scope_lvl = cls->get_scope_lvl();
|
||||
stat.m_parent_clauses.push_back(cls);
|
||||
}
|
||||
else {
|
||||
p->get_parents(todo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void justification::display(std::ostream & out) {
|
||||
out << "[" << get_rule_id();
|
||||
ptr_buffer<justification> ps;
|
||||
get_parents(ps);
|
||||
unsigned sz = ps.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
out << " ";
|
||||
justification * js = ps[i];
|
||||
clause * cls = js->get_clause();
|
||||
if (cls)
|
||||
out << "#" << cls->get_id();
|
||||
else
|
||||
js->display(out);
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
|
||||
justification * justification_proof_wrapper::mk(proof * p, ast_manager & m) {
|
||||
void * mem = m.get_allocator().allocate(sizeof(justification_proof_wrapper));
|
||||
return new (mem) justification_proof_wrapper(p, m);
|
||||
}
|
||||
|
||||
proof * justification_proof_wrapper::get_proof() const {
|
||||
return m_proof;
|
||||
}
|
||||
|
||||
unsigned justification_proof_wrapper::del_eh(ast_manager & m) {
|
||||
m.dec_ref(m_proof);
|
||||
return sizeof(justification_proof_wrapper);
|
||||
}
|
||||
|
||||
void dec_ref(justification * p, ast_manager & m) {
|
||||
if (p->dec_ref()) {
|
||||
ptr_buffer<justification> to_delete;
|
||||
ptr_buffer<justification> parents;
|
||||
to_delete.push_back(p);
|
||||
while (!to_delete.empty()) {
|
||||
justification * p = to_delete.back();
|
||||
to_delete.pop_back();
|
||||
SASSERT(p->get_ref_count() == 0);
|
||||
parents.reset();
|
||||
p->get_parents(parents);
|
||||
ptr_buffer<justification>::iterator it = parents.begin();
|
||||
ptr_buffer<justification>::iterator end = parents.end();
|
||||
for (; it != end; ++it) {
|
||||
justification * parent = *it;
|
||||
if (parent->dec_ref())
|
||||
to_delete.push_back(parent);
|
||||
}
|
||||
unsigned sz = p->del_eh(m);
|
||||
p->~justification();
|
||||
m.get_allocator().deallocate(sz, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return a proof for a new clause formed by the literals lits[0] ... lits[num_lits - 1].
|
||||
This clause was produced using a main clause C, where the proof of C is \c main_pr,
|
||||
and the auxiliary proofs auxs[0] ... aux[num_auxs-1].
|
||||
|
||||
\remark If fine_grain_proofs() is false, then 0 is returned.
|
||||
*/
|
||||
proof * mk_proof(ast_manager & m, family_id spc_fid, spc_op_kind pid, unsigned num_lits, literal * lits, proof * main_pr,
|
||||
unsigned num_auxs, proof * const * auxs) {
|
||||
if (m.fine_grain_proofs()) {
|
||||
expr * new_fact_body = mk_or(m, num_lits, lits);
|
||||
|
||||
SASSERT(main_pr);
|
||||
SASSERT(m.has_fact(main_pr));
|
||||
expr * fact = m.get_fact(main_pr);
|
||||
expr * new_fact = 0;
|
||||
if (is_quantifier(fact))
|
||||
new_fact = m.update_quantifier(to_quantifier(fact), new_fact_body);
|
||||
else
|
||||
new_fact = new_fact_body;
|
||||
|
||||
ptr_buffer<expr> args;
|
||||
args.push_back(main_pr);
|
||||
args.append(num_auxs, (expr**) auxs);
|
||||
args.push_back(new_fact);
|
||||
|
||||
return m.mk_app(spc_fid, pid, args.size(), args.c_ptr());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
justification * rewrite_justification::mk(ast_manager & m, justification * head,
|
||||
unsigned num_demodulators, justification * const * demodulators, proof * pr) {
|
||||
void * mem = m.get_allocator().allocate(get_obj_size(num_demodulators, m.fine_grain_proofs()));
|
||||
return new (mem) rewrite_justification(m, head, num_demodulators, demodulators, pr);
|
||||
}
|
||||
|
||||
rewrite_justification::rewrite_justification(ast_manager & m, justification * head,
|
||||
unsigned num_demodulators, justification * const * demodulators, proof * pr):
|
||||
m_num_demodulators(num_demodulators) {
|
||||
SASSERT(m.fine_grain_proofs() == (pr != 0));
|
||||
m_fields[0] = head;
|
||||
head->inc_ref();
|
||||
for (unsigned i = 0; i < num_demodulators; i++) {
|
||||
m_fields[i+1] = demodulators[i];
|
||||
demodulators[i]->inc_ref();
|
||||
}
|
||||
if (m.fine_grain_proofs()) {
|
||||
SASSERT(pr);
|
||||
m_fields[num_demodulators+1] = pr;
|
||||
m.inc_ref(pr);
|
||||
}
|
||||
}
|
||||
|
||||
void rewrite_justification::get_parents(ptr_buffer<justification> & parents) {
|
||||
unsigned num_parents = m_num_demodulators+1;
|
||||
for (unsigned i = 0; i < num_parents; i++)
|
||||
parents.push_back(reinterpret_cast<justification*>(m_fields[i]));
|
||||
}
|
||||
|
||||
proof * rewrite_justification::get_proof() const {
|
||||
return reinterpret_cast<proof*>(m_fields[m_num_demodulators+1]);
|
||||
}
|
||||
|
||||
unsigned rewrite_justification::del_eh(ast_manager & m) {
|
||||
if (m.fine_grain_proofs()) {
|
||||
m.dec_ref(reinterpret_cast<proof*>(m_fields[m_num_demodulators+1]));
|
||||
return get_obj_size(m_num_demodulators, true);
|
||||
}
|
||||
return get_obj_size(m_num_demodulators, false);
|
||||
}
|
||||
|
||||
proof * mk_rewrite_proof(ast_manager & m, family_id spc_fid, unsigned num_lits, literal * lits, proof * main_pr,
|
||||
unsigned num_auxs, proof * const * auxs) {
|
||||
return mk_proof(m, spc_fid, PR_SPC_REWRITE, num_lits, lits, main_pr, num_auxs, auxs);
|
||||
}
|
||||
};
|
|
@ -1,337 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_justification.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Proof-like objects for tracking dependencies in the superposition
|
||||
calculus engine, and generating proofs.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_JUSTIFICATION_H_
|
||||
#define _SPC_JUSTIFICATION_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"spc_literal.h"
|
||||
#include"spc_decl_plugin.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
class clause;
|
||||
|
||||
/**
|
||||
\brief Proof-like object use to track dependencies and produce
|
||||
proofs.
|
||||
|
||||
\remark All justification objects must be allocated using the
|
||||
small_object_allocator in ast_manager.
|
||||
*/
|
||||
class justification {
|
||||
clause * m_owner;
|
||||
unsigned m_ref_count:30;
|
||||
unsigned m_mark:1;
|
||||
unsigned m_assumption:1;
|
||||
|
||||
friend class clause;
|
||||
void set_owner(clause * cls) { m_owner = cls; }
|
||||
|
||||
public:
|
||||
justification(bool assumption = false):
|
||||
m_owner(0),
|
||||
m_ref_count(0),
|
||||
m_mark(false),
|
||||
m_assumption(assumption) {
|
||||
}
|
||||
|
||||
virtual ~justification() {}
|
||||
|
||||
void inc_ref() {
|
||||
m_ref_count++;
|
||||
}
|
||||
|
||||
bool dec_ref() {
|
||||
SASSERT(m_ref_count > 0);
|
||||
m_ref_count--;
|
||||
return m_ref_count == 0;
|
||||
}
|
||||
|
||||
unsigned get_ref_count() {
|
||||
return m_ref_count;
|
||||
}
|
||||
|
||||
void set_mark(bool f) { m_mark = f; }
|
||||
|
||||
bool is_marked() const { return m_mark; }
|
||||
|
||||
/**
|
||||
\brief Return the clause justified by this object.
|
||||
|
||||
\remark for some justification objects that clause is
|
||||
supressed. Example: intermediate steps.
|
||||
*/
|
||||
clause * get_clause() { return m_owner; }
|
||||
|
||||
/**
|
||||
\brief Return the expr justified by this object.
|
||||
This method returns a non null value only when
|
||||
proof generation is enabled.
|
||||
*/
|
||||
virtual expr * get_expr(ast_manager & m) { return 0; }
|
||||
|
||||
/**
|
||||
\brief Return a non-zero value if the justification
|
||||
is wrapping a proof object.
|
||||
*/
|
||||
virtual proof * get_proof() const { return 0; }
|
||||
|
||||
/**
|
||||
\brief Return the parent justifications.
|
||||
*/
|
||||
virtual void get_parents(ptr_buffer<justification> & parents) {}
|
||||
|
||||
/**
|
||||
\brief Return the name of the rule used.
|
||||
*/
|
||||
virtual spc_op_kind get_rule_id() = 0;
|
||||
|
||||
/**
|
||||
\brief Return true if the justification is an external assumption.
|
||||
*/
|
||||
bool assumption() const { return m_assumption; }
|
||||
|
||||
void display(std::ostream & out);
|
||||
|
||||
/**
|
||||
\brief This method is invoked before the object is deleted.
|
||||
Return the amount of memory consumed by this object.
|
||||
*/
|
||||
virtual unsigned del_eh(ast_manager & m) = 0;
|
||||
};
|
||||
|
||||
struct justification_stat {
|
||||
unsigned m_proof_depth;
|
||||
unsigned m_max_scope_lvl;
|
||||
ptr_buffer<clause> m_parent_clauses;
|
||||
justification_stat():
|
||||
m_proof_depth(0),
|
||||
m_max_scope_lvl(0) {
|
||||
}
|
||||
};
|
||||
|
||||
void get_justification_stat(justification * p, justification_stat & stat);
|
||||
|
||||
void dec_ref(justification * p, ast_manager & m);
|
||||
|
||||
/**
|
||||
\brief Smart pointer for justification objects.
|
||||
*/
|
||||
class justification_ref {
|
||||
justification * m_obj;
|
||||
ast_manager & m_manager;
|
||||
void inc_ref() { if (m_obj) m_obj->inc_ref(); }
|
||||
void dec_ref() { if (m_obj) spc::dec_ref(m_obj, m_manager); }
|
||||
public:
|
||||
justification_ref(ast_manager & m):m_obj(0), m_manager(m) {}
|
||||
justification_ref(justification * j, ast_manager & m):
|
||||
m_obj(j), m_manager(m) {
|
||||
inc_ref();
|
||||
}
|
||||
~justification_ref() {
|
||||
dec_ref();
|
||||
}
|
||||
operator justification*() const { return m_obj; }
|
||||
operator bool() const { return m_obj != 0; }
|
||||
bool operator!() const { return m_obj == 0; }
|
||||
justification * operator->() const { return m_obj; }
|
||||
justification const & operator*() const { return *m_obj; }
|
||||
justification_ref & operator=(justification * n) {
|
||||
if (n)
|
||||
n->inc_ref();
|
||||
dec_ref();
|
||||
m_obj = n;
|
||||
return *this;
|
||||
}
|
||||
justification_ref & operator=(justification_ref & n) {
|
||||
SASSERT(&m_manager == &n.m_manager);
|
||||
n.inc_ref();
|
||||
dec_ref();
|
||||
m_obj = n.m_obj;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class justification_proof_wrapper : public justification {
|
||||
proof * m_proof;
|
||||
justification_proof_wrapper(proof * p, ast_manager & m):m_proof(p) { m.inc_ref(m_proof); }
|
||||
public:
|
||||
static justification * mk(proof * p, ast_manager & m);
|
||||
virtual ~justification_proof_wrapper() {}
|
||||
virtual proof * get_proof() const;
|
||||
virtual spc_op_kind get_rule_id() { return PR_SPC_ASSERTED; };
|
||||
virtual unsigned del_eh(ast_manager & m);
|
||||
};
|
||||
|
||||
proof * mk_proof(ast_manager & m, family_id spc_fid, spc_op_kind pid, unsigned num_lits, literal * lits, proof * main_pr, unsigned num_auxs,
|
||||
proof * const * auxs);
|
||||
|
||||
/**
|
||||
\brief Justification for rewriting steps: demodulation, duplicate literal deletion, resolved literal deletion.
|
||||
*/
|
||||
class rewrite_justification : public justification {
|
||||
unsigned m_num_demodulators;
|
||||
void * m_fields[0];
|
||||
static unsigned get_obj_size(unsigned num_demodulators, bool fine_grain) {
|
||||
return sizeof(rewrite_justification) + (num_demodulators + (fine_grain ? 2 : 1)) * sizeof(void *);
|
||||
}
|
||||
rewrite_justification(ast_manager & m, justification * head,
|
||||
unsigned num_demodulators, justification * const * demodulators, proof * pr);
|
||||
public:
|
||||
static justification * mk(ast_manager & m, justification * head,
|
||||
unsigned num_demodulators, justification * const * demodulators, proof * pr = 0);
|
||||
virtual ~rewrite_justification() {}
|
||||
virtual proof * get_proof() const;
|
||||
virtual spc_op_kind get_rule_id() { return PR_SPC_REWRITE; }
|
||||
virtual void get_parents(ptr_buffer<justification> & parents);
|
||||
virtual unsigned del_eh(ast_manager & m);
|
||||
};
|
||||
|
||||
proof * mk_rewrite_proof(ast_manager & m, family_id spc_fid, unsigned num_lits, literal * lits, proof * main_pr, unsigned num_auxs,
|
||||
proof * const * auxs);
|
||||
|
||||
template<spc_op_kind Kind>
|
||||
class unary_justification : public justification {
|
||||
protected:
|
||||
justification * m_parent;
|
||||
proof * m_proof;
|
||||
|
||||
unary_justification(ast_manager & m, justification * p, proof * pr):
|
||||
m_parent(p),
|
||||
m_proof(pr) {
|
||||
p->inc_ref();
|
||||
SASSERT(m.fine_grain_proofs() == (pr != 0));
|
||||
if (m.fine_grain_proofs())
|
||||
m.inc_ref(pr);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual proof * get_proof() const {
|
||||
return m_proof;
|
||||
}
|
||||
|
||||
virtual void get_parents(ptr_buffer<justification> & parents) {
|
||||
parents.push_back(m_parent);
|
||||
}
|
||||
|
||||
virtual unsigned del_eh(ast_manager & m) {
|
||||
if (m.fine_grain_proofs())
|
||||
m.dec_ref(m_proof);
|
||||
return sizeof(unary_justification);
|
||||
}
|
||||
|
||||
virtual spc_op_kind get_rule_id() {
|
||||
return Kind;
|
||||
}
|
||||
|
||||
static justification * mk(ast_manager & m, family_id spc_fid, justification * p, unsigned num_lits, literal * lits) {
|
||||
proof * pr = 0;
|
||||
if (m.fine_grain_proofs())
|
||||
pr = mk_proof(m, spc_fid, Kind, num_lits, lits, p->get_proof(), 0, 0);
|
||||
void * mem = m.get_allocator().allocate(sizeof(unary_justification));
|
||||
return new (mem) unary_justification(m, p, pr);
|
||||
}
|
||||
};
|
||||
|
||||
inline justification * mk_eq_res_justification(ast_manager & m, family_id spc_fid, justification * p, unsigned num_lits, literal * lits) {
|
||||
return unary_justification<PR_EQUALITY_RESOLUTION>::mk(m, spc_fid, p, num_lits, lits);
|
||||
}
|
||||
|
||||
inline justification * mk_factoring_justification(ast_manager & m, family_id spc_fid, justification * p, unsigned num_lits, literal * lits) {
|
||||
return unary_justification<PR_FACTORING>::mk(m, spc_fid, p, num_lits, lits);
|
||||
}
|
||||
|
||||
inline justification * mk_der_justification(ast_manager & m, family_id spc_fid, justification * p, unsigned num_lits, literal * lits) {
|
||||
return unary_justification<PR_SPC_DER>::mk(m, spc_fid, p, num_lits, lits);
|
||||
}
|
||||
|
||||
template<spc_op_kind Kind>
|
||||
class binary_justification : public justification {
|
||||
protected:
|
||||
justification * m_parent1;
|
||||
justification * m_parent2;
|
||||
proof * m_proof;
|
||||
|
||||
binary_justification(ast_manager & m, justification * p1, justification * p2, proof * pr):
|
||||
m_parent1(p1),
|
||||
m_parent2(p2),
|
||||
m_proof(pr) {
|
||||
p1->inc_ref();
|
||||
p2->inc_ref();
|
||||
SASSERT(m.fine_grain_proofs() == (pr != 0));
|
||||
if (m.fine_grain_proofs())
|
||||
m.inc_ref(pr);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual proof * get_proof() const {
|
||||
return m_proof;
|
||||
}
|
||||
|
||||
virtual void get_parents(ptr_buffer<justification> & parents) {
|
||||
parents.push_back(m_parent1);
|
||||
parents.push_back(m_parent2);
|
||||
}
|
||||
|
||||
virtual unsigned del_eh(ast_manager & m) {
|
||||
if (m.fine_grain_proofs())
|
||||
m.dec_ref(m_proof);
|
||||
return sizeof(binary_justification);
|
||||
}
|
||||
|
||||
virtual spc_op_kind get_rule_id() {
|
||||
return Kind;
|
||||
}
|
||||
|
||||
static justification * mk(ast_manager & m, family_id spc_fid, justification * p1, justification * p2, unsigned num_lits, literal * lits,
|
||||
unsigned num_vars, var * const * vars) {
|
||||
proof * pr = 0;
|
||||
if (m.fine_grain_proofs()) {
|
||||
ptr_buffer<sort> sorts;
|
||||
sbuffer<symbol> names;
|
||||
for (unsigned i = 0; i < num_vars; i++) {
|
||||
sorts.push_back(vars[num_vars - i - 1]->get_sort());
|
||||
names.push_back(symbol(num_vars - i - 1));
|
||||
}
|
||||
expr * body = mk_or(m, num_lits, lits);
|
||||
expr * new_fact = 0;
|
||||
if (num_vars == 0)
|
||||
new_fact = body;
|
||||
else
|
||||
new_fact = m.mk_forall(sorts.size(), sorts.c_ptr(), names.c_ptr(), body);
|
||||
pr = m.mk_app(spc_fid, Kind, p1->get_proof(), p2->get_proof(), new_fact);
|
||||
}
|
||||
void * mem = m.get_allocator().allocate(sizeof(binary_justification));
|
||||
return new (mem) binary_justification(m, p1, p2, pr);
|
||||
}
|
||||
};
|
||||
|
||||
inline justification * mk_superposition_justification(ast_manager & m, family_id spc_fid, justification * p1, justification * p2,
|
||||
unsigned num_lits, literal * lits, unsigned num_vars, var * const * vars) {
|
||||
return binary_justification<PR_SUPERPOSITION>::mk(m, spc_fid, p1, p2, num_lits, lits, num_vars, vars);
|
||||
}
|
||||
|
||||
inline justification * mk_resolution_justification(ast_manager & m, family_id spc_fid, justification * p1, justification * p2,
|
||||
unsigned num_lits, literal * lits, unsigned num_vars, var * const * vars) {
|
||||
return binary_justification<PR_SPC_RESOLUTION>::mk(m, spc_fid, p1, p2, num_lits, lits, num_vars, vars);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _SPC_JUSTIFICATION_H_ */
|
|
@ -1,432 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_literal.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Superposition Calculus literal
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_literal.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
void literal::try_to_orient(order & o) {
|
||||
ast_manager & m = o.get_manager();
|
||||
if (!m_sign && m.is_eq(m_atom)) {
|
||||
expr * lhs = to_app(m_atom)->get_arg(0);
|
||||
expr * rhs = to_app(m_atom)->get_arg(1);
|
||||
TRACE("spc_orient", tout << "trying to orient:\n" << mk_pp(lhs, m) << "\n" << mk_pp(rhs, m) << "\n";);
|
||||
switch (o.compare(lhs, rhs)) {
|
||||
case order::GREATER:
|
||||
m_oriented = true;
|
||||
m_left = true;
|
||||
TRACE("spc_orient", tout << "greater\n";);
|
||||
return;
|
||||
case order::LESSER:
|
||||
m_oriented = true;
|
||||
m_left = false;
|
||||
TRACE("spc_orient", tout << "smaller\n";);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void literal::get_stat(literal_stat & stat) {
|
||||
get_expr_stat(m_atom, stat);
|
||||
m_stats = true;
|
||||
m_ground = stat.m_ground;
|
||||
m_sym_count = stat.m_sym_count > SYM_COUNT_MAX ? SYM_COUNT_MAX : stat.m_sym_count;
|
||||
m_depth = stat.m_depth > DEPTH_MAX ? DEPTH_MAX : stat.m_depth;
|
||||
m_const_count = stat.m_const_count > CONST_COUNT_MAX ? CONST_COUNT_MAX : stat.m_const_count;
|
||||
}
|
||||
|
||||
expr * literal::to_expr(ast_manager & m) const {
|
||||
if (is_true(m))
|
||||
return m.mk_true();
|
||||
else if (is_false(m))
|
||||
return m.mk_false();
|
||||
else if (m_sign)
|
||||
return m.mk_not(m_atom);
|
||||
else
|
||||
return m_atom;
|
||||
}
|
||||
|
||||
void literal::display(std::ostream & out, ast_manager & m, bool detailed) const {
|
||||
pp_params p;
|
||||
p.m_pp_single_line = true;
|
||||
|
||||
if (m_sign)
|
||||
out << "(not ";
|
||||
|
||||
if (m_oriented) {
|
||||
expr * lhs = to_app(m_atom)->get_arg(0);
|
||||
expr * rhs = to_app(m_atom)->get_arg(1);
|
||||
if (!m_left)
|
||||
std::swap(lhs, rhs);
|
||||
out << "(-> ";
|
||||
ast_pp(out, lhs, m, p);
|
||||
out << " ";
|
||||
ast_pp(out, rhs, m, p);
|
||||
out << ")";
|
||||
}
|
||||
else {
|
||||
ast_pp(out, m_atom, m, p);
|
||||
}
|
||||
|
||||
if (m_sign)
|
||||
out << ")";
|
||||
|
||||
if (detailed && m_stats) {
|
||||
out << "[" << m_ground << ", " << m_depth << ", " << m_sym_count << ", " << m_const_count << "]";
|
||||
}
|
||||
|
||||
if (m_selected)
|
||||
out << "$";
|
||||
if (m_p_indexed)
|
||||
out << "!";
|
||||
if (m_r_indexed)
|
||||
out << "@";
|
||||
}
|
||||
|
||||
void display(std::ostream & out, unsigned num_lists, literal * lits, ast_manager & m, bool detailed) {
|
||||
for (unsigned i = 0; i < num_lists; i++) {
|
||||
if (i > 0) out << " ";
|
||||
lits[i].display(out, m, detailed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Given an eq literal store in lhs and rhs the left and right hand sides. If they can be oriented
|
||||
given the substitution s, then return true, and make lhs the maximal one.
|
||||
*/
|
||||
bool can_orient(order & o, literal const & l, unsigned offset, substitution * s, expr * & lhs, expr * & rhs) {
|
||||
SASSERT(o.get_manager().is_eq(l.atom()));
|
||||
lhs = l.lhs();
|
||||
rhs = l.rhs();
|
||||
if (l.is_oriented()) {
|
||||
if (!l.is_left())
|
||||
std::swap(lhs, rhs);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
order::result comp = o.compare(lhs, rhs, offset, s);
|
||||
if (comp == order::GREATER)
|
||||
return true;
|
||||
else if (comp == order::LESSER) {
|
||||
std::swap(lhs, rhs);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Compare literal signs. Negative sign is bigger than the positive one.
|
||||
*/
|
||||
inline order::result compare_signs(bool sign1, bool sign2) {
|
||||
if (sign1 && !sign2)
|
||||
return order::GREATER;
|
||||
else if (!sign1 && sign2)
|
||||
return order::LESSER;
|
||||
else
|
||||
return order::EQUAL;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Compare two literals (modulo a substitution) using the given term ordering.
|
||||
*/
|
||||
order::result compare(order & o, literal const & l1, literal const & l2, unsigned offset, substitution * s) {
|
||||
ast_manager & m = o.get_manager();
|
||||
expr * n1 = l1.atom();
|
||||
expr * n2 = l2.atom();
|
||||
bool is_eq1 = m.is_eq(n1);
|
||||
bool is_eq2 = m.is_eq(n2);
|
||||
if (is_eq1 && is_eq2) {
|
||||
expr * lhs1 = 0;
|
||||
expr * rhs1 = 0;
|
||||
expr * lhs2 = 0;
|
||||
expr * rhs2 = 0;
|
||||
bool oriented1 = can_orient(o, l1, offset, s, lhs1, rhs1);
|
||||
bool oriented2 = can_orient(o, l2, offset, s, lhs2, rhs2);
|
||||
if (oriented1) {
|
||||
// equation 1 can be oriented
|
||||
if (oriented2) {
|
||||
// equation 2 can be oriented
|
||||
// both equations are oriented
|
||||
SASSERT(oriented1);
|
||||
SASSERT(oriented2);
|
||||
order::result r = o.compare(lhs1, lhs2, offset, s);
|
||||
if (r == order::EQUAL) {
|
||||
if (l1.pos()) {
|
||||
if (l2.pos())
|
||||
return o.compare(rhs1, rhs2, offset, s);
|
||||
else
|
||||
return order::LESSER;
|
||||
}
|
||||
else {
|
||||
if (l2.pos())
|
||||
return order::GREATER;
|
||||
else
|
||||
return o.compare(rhs1, rhs2, offset, s);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
// equation 2 cannot be oriented
|
||||
SASSERT(oriented1);
|
||||
SASSERT(!oriented2);
|
||||
SASSERT(o.compare(lhs1, rhs1, offset, s) == order::GREATER);
|
||||
if (o.equal(lhs1, lhs2, offset, s)) {
|
||||
order::result r = o.compare(rhs1, rhs2, offset, s);
|
||||
if (r == order::EQUAL)
|
||||
return compare_signs(l1.sign(), l2.sign());
|
||||
return r;
|
||||
}
|
||||
if (o.equal(lhs1, rhs2, offset, s)) {
|
||||
order::result r = o.compare(rhs1, lhs2, offset, s);
|
||||
if (r == order::EQUAL)
|
||||
return compare_signs(l1.sign(), l2.sign());
|
||||
return r;
|
||||
}
|
||||
order::result lhs1_lhs2 = o.compare(lhs1, lhs2, offset, s);
|
||||
order::result lhs1_rhs2 = o.compare(lhs1, rhs2, offset, s);
|
||||
if (lhs1_lhs2 == lhs1_rhs2)
|
||||
return lhs1_lhs2;
|
||||
order::result rhs1_rhs2 = o.compare(rhs1, rhs2, offset, s);
|
||||
if (lhs1_lhs2 == rhs1_rhs2)
|
||||
return lhs1_lhs2;
|
||||
if (lhs1_rhs2 == order::LESSER && rhs1_rhs2 == order::LESSER)
|
||||
return order::LESSER;
|
||||
order::result rhs1_lhs2 = o.compare(rhs1, lhs2, offset, s);
|
||||
if (lhs1_lhs2 == order::LESSER && rhs1_lhs2 == order::LESSER)
|
||||
return order::LESSER;
|
||||
return order::UNCOMPARABLE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// equation 1 cannot be oriented
|
||||
if (oriented2) {
|
||||
SASSERT(!oriented1);
|
||||
SASSERT(oriented2);
|
||||
// equation 2 can be oriented
|
||||
if (o.equal(lhs1, lhs2, offset, s)) {
|
||||
order::result r = o.compare(rhs1, rhs2, offset, s);
|
||||
if (r == order::EQUAL)
|
||||
return compare_signs(l1.sign(), l2.sign());
|
||||
return r;
|
||||
}
|
||||
if (o.equal(rhs1, lhs2, offset, s)) {
|
||||
order::result r = o.compare(lhs1, rhs2, offset, s);
|
||||
if (r == order::EQUAL)
|
||||
return compare_signs(l1.sign(), l2.sign());
|
||||
return r;
|
||||
}
|
||||
order::result lhs1_lhs2 = o.compare(lhs1, lhs2, offset, s);
|
||||
order::result rhs1_lhs2 = o.compare(rhs1, lhs2, offset, s);
|
||||
if (lhs1_lhs2 == rhs1_lhs2)
|
||||
return lhs1_lhs2;
|
||||
order::result rhs1_rhs2 = o.compare(rhs1, rhs2, offset, s);
|
||||
if (lhs1_lhs2 == rhs1_rhs2)
|
||||
return lhs1_lhs2;
|
||||
if (rhs1_lhs2 == order::GREATER && rhs1_rhs2 == order::GREATER)
|
||||
return order::GREATER;
|
||||
order::result lhs1_rhs2 = o.compare(lhs1, rhs2, offset, s);
|
||||
if (lhs1_lhs2 == order::GREATER && lhs1_rhs2 == order::GREATER)
|
||||
return order::GREATER;
|
||||
return order::UNCOMPARABLE;
|
||||
}
|
||||
else {
|
||||
SASSERT(!oriented1);
|
||||
SASSERT(!oriented2);
|
||||
if (o.equal(lhs1, lhs2, offset, s)) {
|
||||
order::result r = o.compare(rhs1, rhs2, offset, s);
|
||||
if (r == order::EQUAL)
|
||||
return compare_signs(l1.sign(), l2.sign());
|
||||
return r;
|
||||
}
|
||||
if (o.equal(rhs1, lhs2, offset, s)) {
|
||||
order::result r = o.compare(lhs1, rhs2, offset, s);
|
||||
if (r == order::EQUAL)
|
||||
return compare_signs(l1.sign(), l2.sign());
|
||||
return r;
|
||||
}
|
||||
if (o.equal(lhs1, rhs2, offset, s)) {
|
||||
order::result r = o.compare(rhs1, lhs2, offset, s);
|
||||
if (r == order::EQUAL)
|
||||
return compare_signs(l1.sign(), l2.sign());
|
||||
return r;
|
||||
}
|
||||
if (o.equal(rhs1, rhs2, offset, s)) {
|
||||
order::result r = o.compare(lhs1, lhs2, offset, s);
|
||||
if (r == order::EQUAL)
|
||||
return compare_signs(l1.sign(), l2.sign());
|
||||
return r;
|
||||
}
|
||||
|
||||
order::result r;
|
||||
order::result aux;
|
||||
switch (o.compare(lhs1, lhs2, offset, s)) {
|
||||
case order::GREATER:
|
||||
r = o.compare(lhs1, rhs2, offset, s);
|
||||
if (r == order::GREATER)
|
||||
return order::GREATER;
|
||||
aux = o.compare(rhs1, rhs2, offset, s);
|
||||
if (aux == order::GREATER)
|
||||
return order::GREATER;
|
||||
if (r == order::LESSER && aux == order::LESSER)
|
||||
return order::LESSER;
|
||||
SASSERT(r != order::EQUAL);
|
||||
SASSERT(aux != order::EQUAL);
|
||||
return order::UNCOMPARABLE;
|
||||
case order::LESSER:
|
||||
r = o.compare(rhs1, lhs2, offset, s);
|
||||
if (r == order::LESSER)
|
||||
return order::LESSER;
|
||||
aux = o.compare(rhs1, rhs2, offset, s);
|
||||
if (aux == order::LESSER)
|
||||
return order::LESSER;
|
||||
if (r == order::GREATER && aux == order::GREATER)
|
||||
return order::GREATER;
|
||||
SASSERT(r != order::EQUAL);
|
||||
SASSERT(aux != order::EQUAL);
|
||||
return order::UNCOMPARABLE;
|
||||
case order::EQUAL:
|
||||
UNREACHABLE();
|
||||
return order::UNKNOWN;
|
||||
default:
|
||||
switch (o.compare(lhs1, rhs2, offset, s)) {
|
||||
case order::GREATER:
|
||||
if (o.compare(rhs1, lhs2, offset, s) == order::GREATER)
|
||||
return order::GREATER;
|
||||
return order::UNCOMPARABLE;
|
||||
case order::LESSER:
|
||||
if (o.compare(rhs1, lhs2, offset, s) == order::LESSER ||
|
||||
o.compare(rhs1, rhs2, offset, s) == order::LESSER)
|
||||
return order::LESSER;
|
||||
return order::UNCOMPARABLE;
|
||||
case order::EQUAL:
|
||||
UNREACHABLE();
|
||||
return order::UNKNOWN;
|
||||
default:
|
||||
if (o.compare(rhs1, lhs2, offset, s) == order::GREATER &&
|
||||
o.compare(rhs1, rhs2, offset, s) == order::GREATER)
|
||||
return order::GREATER;
|
||||
return order::UNCOMPARABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_eq1) {
|
||||
expr * lhs1 = l1.lhs();
|
||||
expr * rhs1 = l1.rhs();
|
||||
if (l1.is_oriented() && !l1.is_left())
|
||||
std::swap(lhs1, rhs1);
|
||||
order::result r = o.compare(lhs1, n2, offset, s);
|
||||
if (!l1.is_oriented() || r != order::GREATER) {
|
||||
order::result r2 = o.compare(rhs1, n2, offset, s);
|
||||
if (r2 == order::GREATER)
|
||||
return order::GREATER;
|
||||
else if (r != r2)
|
||||
return order::UNCOMPARABLE;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
else if (is_eq2) {
|
||||
expr * lhs2 = l2.lhs();
|
||||
expr * rhs2 = l2.rhs();
|
||||
if (l2.is_oriented() && !l2.is_left())
|
||||
std::swap(lhs2, rhs2);
|
||||
order::result r = o.compare(n1, lhs2, offset, s);
|
||||
if (!l1.is_oriented() || r != order::LESSER) {
|
||||
order::result r2 = o.compare(n1, rhs2, offset, s);
|
||||
if (r2 == order::LESSER)
|
||||
return order::LESSER;
|
||||
else if (r != r2)
|
||||
return order::UNCOMPARABLE;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
order::result r = o.compare(n1, n2, offset, s);
|
||||
if (r == order::EQUAL)
|
||||
return compare_signs(l1.sign(), l2.sign());
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
bool greater(order & o, literal const & l1, literal const & l2, unsigned offset, substitution * s) {
|
||||
order::result r = compare(o, l1, l2, offset, s);
|
||||
TRACE("literal_order", ast_manager & m = o.get_manager();
|
||||
tout << "comparing ";
|
||||
l1.display(tout, m);
|
||||
tout << " ";
|
||||
l2.display(tout, m);
|
||||
tout << " : " << r << "\n";);
|
||||
return r == order::GREATER;
|
||||
}
|
||||
|
||||
void found_literals::insert(literal const & l) {
|
||||
unsigned id = l.get_id();
|
||||
m_marks.reserve(id+1);
|
||||
if (!m_marks.get(id)) {
|
||||
m_marks.set(id);
|
||||
m_lit_ids.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
bool found_literals::contains(literal const & l) const {
|
||||
unsigned id = l.get_id();
|
||||
return id < m_marks.size() && m_marks.get(id);
|
||||
}
|
||||
|
||||
bool found_literals::contains_neg(literal const & l) const {
|
||||
unsigned id = l.get_neg_id();
|
||||
return id < m_marks.size() && m_marks.get(id);
|
||||
}
|
||||
|
||||
void found_literals::reset() {
|
||||
unsigned_vector::iterator it = m_lit_ids.begin();
|
||||
unsigned_vector::iterator end = m_lit_ids.end();
|
||||
for (; it != end; ++it)
|
||||
m_marks.unset(*it);
|
||||
m_lit_ids.reset();
|
||||
}
|
||||
|
||||
void literal_buffer::reset() {
|
||||
buffer<literal>::iterator it = m_lits.begin();
|
||||
buffer<literal>::iterator end = m_lits.end();
|
||||
for (; it != end; ++it)
|
||||
m_manager.dec_ref(it->atom());
|
||||
m_lits.reset();
|
||||
}
|
||||
|
||||
|
||||
expr * mk_or(ast_manager & m, unsigned num_lists, literal * lits) {
|
||||
if (num_lists == 0)
|
||||
return m.mk_false();
|
||||
else if (num_lists == 1)
|
||||
return lits[0].to_expr(m);
|
||||
else {
|
||||
ptr_buffer<expr> new_exprs;
|
||||
for (unsigned i = 0; i < num_lists; i++)
|
||||
new_exprs.push_back(lits[i].to_expr(m));
|
||||
return m.mk_or(new_exprs.size(), new_exprs.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
};
|
|
@ -1,212 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_literal.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Superposition Calculus literal
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_LITERAL_H_
|
||||
#define _SPC_LITERAL_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"order.h"
|
||||
#include"expr_stat.h"
|
||||
|
||||
namespace spc {
|
||||
typedef expr_stat literal_stat;
|
||||
|
||||
#define DEPTH_NUM_BITS 4
|
||||
#define DEPTH_MAX ((1 << DEPTH_NUM_BITS) - 1)
|
||||
#define CONST_COUNT_NUM_BITS 4
|
||||
#define CONST_COUNT_MAX ((1 << CONST_COUNT_NUM_BITS) - 1)
|
||||
#define SYM_COUNT_NUM_BITS 16
|
||||
#define SYM_COUNT_MAX ((1 << SYM_COUNT_NUM_BITS) - 1)
|
||||
|
||||
/**
|
||||
\brief Superposition Calculus literal.
|
||||
*/
|
||||
class literal {
|
||||
expr * m_atom;
|
||||
unsigned m_sign:1; // true if a negative literal.
|
||||
unsigned m_oriented:1; // true if it is an oriented equality.
|
||||
unsigned m_left:1; // true if the largest term is on the left-hand-side of the equality (only meaningful if m_oriented == true).
|
||||
unsigned m_selected:1; // true if it is a selected literal.
|
||||
unsigned m_stats:1; // true if the following fields were initialized.
|
||||
unsigned m_ground:1; // true if it is a ground literal
|
||||
unsigned m_p_indexed:1; // true if the literal was inserted into the p (paramodulation) superposition index.
|
||||
unsigned m_r_indexed:1; // true if the literal was inserted into the r (resolution) superposition index.
|
||||
unsigned m_depth:DEPTH_NUM_BITS; // approx. depth
|
||||
unsigned m_const_count:CONST_COUNT_NUM_BITS; // approx. number of constants
|
||||
unsigned m_sym_count:SYM_COUNT_NUM_BITS; // approx. size
|
||||
|
||||
friend class clause;
|
||||
|
||||
void set_selected(bool f) {
|
||||
m_selected = f;
|
||||
}
|
||||
|
||||
public:
|
||||
literal():
|
||||
m_atom(0),
|
||||
m_sign(false),
|
||||
m_oriented(false),
|
||||
m_left(false),
|
||||
m_selected(false),
|
||||
m_stats(false),
|
||||
m_ground(false),
|
||||
m_p_indexed(false),
|
||||
m_r_indexed(false),
|
||||
m_depth(0),
|
||||
m_const_count(0),
|
||||
m_sym_count(0) {
|
||||
}
|
||||
|
||||
literal(expr * atom, bool sign = false):
|
||||
m_atom(atom),
|
||||
m_sign(sign),
|
||||
m_oriented(false),
|
||||
m_left(false),
|
||||
m_selected(false),
|
||||
m_stats(false),
|
||||
m_ground(false),
|
||||
m_p_indexed(false),
|
||||
m_r_indexed(false),
|
||||
m_depth(0),
|
||||
m_const_count(0),
|
||||
m_sym_count(0) {
|
||||
}
|
||||
|
||||
bool sign() const { return m_sign; }
|
||||
bool pos() const { return !m_sign; }
|
||||
bool neg() const { return m_sign; }
|
||||
bool is_oriented() const { return m_oriented; }
|
||||
bool is_left() const { return m_left; }
|
||||
bool is_selected() const { return m_selected; }
|
||||
expr * atom() const { return m_atom; }
|
||||
expr * lhs() const { return to_app(m_atom)->get_arg(0); }
|
||||
expr * rhs() const { return to_app(m_atom)->get_arg(1); }
|
||||
unsigned get_id() const { return m_sign ? (to_app(m_atom)->get_id() << 1) + 1 : (to_app(m_atom)->get_id() << 1); }
|
||||
unsigned get_neg_id() const { return m_sign ? (to_app(m_atom)->get_id() << 1) : (to_app(m_atom)->get_id() << 1) + 1; }
|
||||
|
||||
bool operator==(literal const & other) const { return m_atom == other.m_atom && m_sign == other.m_sign; }
|
||||
bool operator!=(literal const & other) const { return !operator==(other); }
|
||||
|
||||
void set_p_indexed(bool f) { m_p_indexed = f; }
|
||||
void set_r_indexed(bool f) { m_r_indexed = f; }
|
||||
bool is_p_indexed() const { return m_p_indexed; }
|
||||
bool is_r_indexed() const { return m_r_indexed; }
|
||||
|
||||
void try_to_orient(order & o);
|
||||
bool is_true(ast_manager & m) const {
|
||||
return
|
||||
(!m_sign && m.is_true(m_atom)) ||
|
||||
(!m_sign && m.is_eq(m_atom) && to_app(m_atom)->get_arg(0) == to_app(m_atom)->get_arg(1)) ||
|
||||
(m_sign && m.is_false(m_atom));
|
||||
}
|
||||
bool is_false(ast_manager & m) const {
|
||||
return
|
||||
(m_sign && m.is_true(m_atom)) ||
|
||||
(m_sign && m.is_eq(m_atom) && to_app(m_atom)->get_arg(0) == to_app(m_atom)->get_arg(1)) ||
|
||||
(!m_sign && m.is_false(m_atom));
|
||||
}
|
||||
expr * to_expr(ast_manager & m) const;
|
||||
|
||||
/**
|
||||
\brief Collect literal statistics
|
||||
*/
|
||||
void get_stat(literal_stat & stat);
|
||||
void init_stat() { literal_stat st; get_stat(st); }
|
||||
bool has_stats() const { return m_stats; }
|
||||
bool is_ground() const { SASSERT(m_stats); return m_ground; }
|
||||
unsigned get_approx_depth() const { SASSERT(m_stats); return m_depth; }
|
||||
unsigned get_approx_const_count() const { SASSERT(m_stats); return m_const_count; }
|
||||
unsigned get_approx_sym_count() const { SASSERT(m_stats); return m_sym_count; }
|
||||
|
||||
void display(std::ostream & out, ast_manager & m, bool detailed = false) const;
|
||||
};
|
||||
|
||||
COMPILE_TIME_ASSERT(sizeof(expr*) != 4 || sizeof(literal) == sizeof(expr *) + sizeof(unsigned)); // 32 bit machine
|
||||
COMPILE_TIME_ASSERT(sizeof(expr*) != 8 || sizeof(literal) == sizeof(expr *) + sizeof(unsigned) + /* a structure must be aligned */ sizeof(unsigned)); // 64 bit machine
|
||||
|
||||
void display(std::ostream & out, unsigned num_lists, literal * lits, ast_manager & m, bool detailed = false);
|
||||
|
||||
order::result compare(order & o, literal const & l1, literal const & l2, unsigned offset = 0, substitution * s = 0);
|
||||
bool greater(order & o, literal const & l1, literal const & l2, unsigned offset = 0, substitution * s = 0);
|
||||
bool is_maximal(order & o, unsigned num_lists, literal * lits, literal const & l, unsigned offset = 0, substitution * s = 0);
|
||||
bool is_sel_maximal(order & o, unsigned num_lists, literal * lits, literal const & l, unsigned offset = 0, substitution * s = 0);
|
||||
|
||||
/**
|
||||
\brief Set of found literals.
|
||||
|
||||
This object is used to implement duplicate literal elimination, ans syntatic tautology.
|
||||
*/
|
||||
class found_literals {
|
||||
bit_vector m_marks;
|
||||
unsigned_vector m_lit_ids;
|
||||
public:
|
||||
/**
|
||||
\brief Insert the given literal into the set.
|
||||
*/
|
||||
void insert(literal const & l);
|
||||
|
||||
/**
|
||||
\brief Return true if the set contains \c l.
|
||||
*/
|
||||
bool contains(literal const & l) const;
|
||||
|
||||
/**
|
||||
\brief Return true if the set contains the negation of \c l.
|
||||
*/
|
||||
bool contains_neg(literal const & l) const;
|
||||
|
||||
bool empty() const { return m_lit_ids.empty(); }
|
||||
|
||||
/**
|
||||
\brief Remove all literals from the set.
|
||||
*/
|
||||
void reset();
|
||||
};
|
||||
|
||||
class literal_buffer {
|
||||
ast_manager & m_manager;
|
||||
buffer<literal> m_lits;
|
||||
public:
|
||||
literal_buffer(ast_manager & m):
|
||||
m_manager(m) {
|
||||
}
|
||||
|
||||
~literal_buffer() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void push_back(literal const & l) {
|
||||
m_manager.inc_ref(l.atom());
|
||||
m_lits.push_back(l);
|
||||
}
|
||||
|
||||
void reset();
|
||||
|
||||
unsigned size() const {
|
||||
return m_lits.size();
|
||||
}
|
||||
|
||||
literal * c_ptr() const {
|
||||
return m_lits.c_ptr();
|
||||
}
|
||||
};
|
||||
|
||||
expr * mk_or(ast_manager & m, unsigned num_lists, literal * lits);
|
||||
};
|
||||
|
||||
#endif /* _SPC_LITERAL_H_ */
|
|
@ -1,107 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_literal_selection.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Superposition Calculus Literal Selection
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-05.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_literal_selection.h"
|
||||
#include"expr_stat.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
void diff_literal_selection::operator()(clause * cls) {
|
||||
bool found = false;
|
||||
unsigned target = UINT_MAX;
|
||||
unsigned best_count = 0;
|
||||
unsigned num = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
literal & l = cls->get_literal(i);
|
||||
if (l.sign()) {
|
||||
unsigned count;
|
||||
if (m_manager.is_eq(l.atom())) {
|
||||
unsigned c1 = get_symbol_count(to_app(l.atom())->get_arg(0));
|
||||
unsigned c2 = get_symbol_count(to_app(l.atom())->get_arg(1));
|
||||
count = c1 >= c2 ? c1 - c2 : c2 - c1;
|
||||
}
|
||||
else {
|
||||
count = get_symbol_count(l.atom());
|
||||
}
|
||||
if (count > best_count) {
|
||||
found = true;
|
||||
target = i;
|
||||
best_count = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
cls->select_literal(target);
|
||||
}
|
||||
|
||||
void complex_literal_selection::operator()(clause * cls) {
|
||||
// look for x != y
|
||||
unsigned num = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
literal & l = cls->get_literal(i);
|
||||
if (l.sign() && m_manager.is_eq(l.atom()) && is_var(to_app(l.atom())->get_arg(0)) && is_var(to_app(l.atom())->get_arg(1))) {
|
||||
cls->select_literal(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// look for min ground neg literal
|
||||
bool found = false;
|
||||
unsigned target = UINT_MAX;
|
||||
unsigned best_count = UINT_MAX;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
literal & l = cls->get_literal(i);
|
||||
if (l.sign() && is_ground(l.atom())) {
|
||||
unsigned count = get_symbol_count(l.atom());
|
||||
if (count < best_count) {
|
||||
found = true;
|
||||
target = i;
|
||||
best_count = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
cls->select_literal(target);
|
||||
return;
|
||||
}
|
||||
|
||||
diff_literal_selection::operator()(cls);
|
||||
}
|
||||
|
||||
void max_no_selection::operator()(clause * cls) {
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l1 = cls->get_literal(i);
|
||||
if (!l1.sign()) {
|
||||
unsigned j = 0;
|
||||
for (; j < num_lits; j++) {
|
||||
if (i != j) {
|
||||
literal const & l2 = cls->get_literal(j);
|
||||
if (!greater(m_order, l1, l2))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == num_lits)
|
||||
return; // clause has maximal positive literal.
|
||||
}
|
||||
}
|
||||
diff_literal_selection::operator()(cls);
|
||||
}
|
||||
|
||||
};
|
|
@ -1,95 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_literal_selection.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Superposition Calculus Literal Selection
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-05.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_LITERAL_SELECTION_H_
|
||||
#define _SPC_LITERAL_SELECTION_H_
|
||||
|
||||
#include"spc_clause.h"
|
||||
#include"order.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Abstract functor for literal selection.
|
||||
*/
|
||||
class literal_selection {
|
||||
public:
|
||||
virtual ~literal_selection() {}
|
||||
/**
|
||||
\brief Updates the selected status flag of the literals of the given clause.
|
||||
*/
|
||||
virtual void operator()(clause * cls) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Never selects a literal. This strategy is supposed to be good for planning problems
|
||||
of TPTP.
|
||||
*/
|
||||
class no_literal_selection : public literal_selection {
|
||||
public:
|
||||
virtual void operator()(clause * cls) {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
\brief Selects a negative literal l with the largest V(l)
|
||||
where V is defined as:
|
||||
|
||||
- difference in symbol count for the left-right hand sides of equalities, .
|
||||
|
||||
- symbol count for other predicates
|
||||
|
||||
*/
|
||||
class diff_literal_selection : public literal_selection {
|
||||
protected:
|
||||
ast_manager & m_manager;
|
||||
public:
|
||||
diff_literal_selection(ast_manager & m):m_manager(m) {}
|
||||
virtual void operator()(clause * cls);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Selects a negative literal using the following algo:
|
||||
|
||||
- if there is x != y, select it.
|
||||
|
||||
- else if there is negative ground literal, select the smallest one.
|
||||
|
||||
- else if use the approach in diff_literal_selection.
|
||||
*/
|
||||
class complex_literal_selection : public diff_literal_selection {
|
||||
public:
|
||||
complex_literal_selection(ast_manager & m):diff_literal_selection(m) {}
|
||||
virtual void operator()(clause * cls);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Similar to diff_literal_selection, but a literal
|
||||
is not selected if the clause contains a positive literal
|
||||
greater than all other literals.
|
||||
*/
|
||||
class max_no_selection : public diff_literal_selection {
|
||||
order & m_order;
|
||||
public:
|
||||
max_no_selection(order & o):diff_literal_selection(o.get_manager()), m_order(o) {}
|
||||
virtual void operator()(clause * cls);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SPC_LITERAL_SELECTION_H_ */
|
|
@ -1,132 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_prover.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Stand-alone SPC prover (it is mainly for debugging purposes).
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-08.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_prover.h"
|
||||
#include"spc_decl_plugin.h"
|
||||
#include"for_each_expr.h"
|
||||
|
||||
namespace spc {
|
||||
prover::prover(ast_manager & m, front_end_params & params):
|
||||
m_manager(m),
|
||||
m_params(params),
|
||||
m_simplifier(m),
|
||||
m_defined_names(m),
|
||||
m_preprocessor(m, m_defined_names, m_simplifier, params),
|
||||
m_order(0),
|
||||
m_cls_sel(0),
|
||||
m_lit_sel(0),
|
||||
m_context(0),
|
||||
m_exprs(m),
|
||||
m_expr_proofs(m),
|
||||
m_has_theories(false) {
|
||||
|
||||
family_id fid = m_manager.get_family_id("spc");
|
||||
if (!m_manager.has_plugin(fid))
|
||||
m_manager.register_plugin(fid, alloc(spc_decl_plugin));
|
||||
|
||||
// This piece of code shows why the old model for passing parameters is broken.
|
||||
// spc::prover must overwrite some parameters, but this modification affects other
|
||||
// components. :-(
|
||||
// TODO: move everything to the new params_ref object
|
||||
params.m_nnf_mode = NNF_FULL;
|
||||
params.m_cnf_mode = CNF_FULL;
|
||||
params.m_lift_ite = LI_CONSERVATIVE;
|
||||
|
||||
basic_simplifier_plugin * basic = alloc(basic_simplifier_plugin, m_manager);
|
||||
m_simplifier.register_plugin(basic);
|
||||
m_simplifier.register_plugin(alloc(arith_simplifier_plugin, m_manager, *basic, params));
|
||||
}
|
||||
|
||||
prover::~prover() {
|
||||
if (m_context) {
|
||||
dealloc(m_context);
|
||||
dealloc(m_lit_sel);
|
||||
dealloc(m_cls_sel);
|
||||
dealloc(m_order);
|
||||
}
|
||||
}
|
||||
|
||||
void prover::init() {
|
||||
if (m_context)
|
||||
return;
|
||||
precedence * p = mk_precedence(m_manager, m_params);
|
||||
|
||||
// TODO use params to configure the following functors.
|
||||
m_order = alloc(kbo, m_manager, p);
|
||||
|
||||
clause_eval * evals[2] = { alloc(symbol_count_clause_eval), alloc(time_clause_eval) };
|
||||
unsigned slots[2] = { 10, 1 };
|
||||
m_cls_sel = alloc(clause_selection, 2, evals, slots);
|
||||
|
||||
m_lit_sel = alloc(max_no_selection, *m_order);
|
||||
// m_lit_sel = new complex_literal_selection(m_manager);
|
||||
// m_lit_sel = new diff_literal_selection(m_manager);
|
||||
// m_lit_sel = new no_literal_selection(); // new diff_literal_selection(m_manager);
|
||||
// END TODO
|
||||
|
||||
m_context = alloc(context, m_manager, *m_order, *m_cls_sel, *m_lit_sel, m_simplifier, m_params);
|
||||
}
|
||||
|
||||
struct has_theories_proc {
|
||||
ast_manager & m_manager;
|
||||
has_theories_proc(ast_manager & m):m_manager(m) {}
|
||||
struct found {};
|
||||
void operator()(var * n) {}
|
||||
void operator()(app * n) { if (!m_manager.is_builtin_family_id(n->get_family_id())) throw found(); }
|
||||
void operator()(quantifier * n) {}
|
||||
};
|
||||
|
||||
bool has_theories(ast_manager & m, expr * e) {
|
||||
has_theories_proc p(m);
|
||||
try {
|
||||
for_each_expr(p, e);
|
||||
}
|
||||
catch (has_theories_proc::found) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void prover::assert_expr(expr * e) {
|
||||
if (!m_has_theories && has_theories(m_manager, e))
|
||||
m_has_theories = true;
|
||||
TRACE("spc_assert", tout << mk_pp(e, m_manager) << "\nhas_theories: " << m_has_theories << "\n";);
|
||||
m_preprocessor(e, m_manager.mk_asserted(e), m_exprs, m_expr_proofs);
|
||||
}
|
||||
|
||||
lbool prover::check() {
|
||||
init();
|
||||
unsigned sz = m_exprs.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
expr * curr = m_exprs.get(i);
|
||||
proof * p = m_manager.proofs_enabled() ? m_expr_proofs.get(i) : m_manager.mk_undef_proof();
|
||||
m_context->assert_expr(curr, p);
|
||||
}
|
||||
m_exprs.reset();
|
||||
m_expr_proofs.reset();
|
||||
|
||||
m_context->saturate(m_params.m_spc_num_iterations);
|
||||
if (m_context->inconsistent())
|
||||
return l_false;
|
||||
else if (m_context->processed_all())
|
||||
return m_has_theories ? l_undef : l_true;
|
||||
else
|
||||
return l_undef;
|
||||
}
|
||||
};
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_prover.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Stand-alone SPC prover (it is mainly for debugging purposes).
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-08.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_PROVER_H_
|
||||
#define _SPC_PROVER_H_
|
||||
|
||||
#include"spc_context.h"
|
||||
#include"front_end_params.h"
|
||||
#include"kbo.h"
|
||||
#include"lpo.h"
|
||||
#include"basic_simplifier_plugin.h"
|
||||
#include"arith_simplifier_plugin.h"
|
||||
#include"preprocessor.h"
|
||||
#include"defined_names.h"
|
||||
#include"lbool.h"
|
||||
|
||||
namespace spc {
|
||||
class prover {
|
||||
ast_manager & m_manager;
|
||||
front_end_params & m_params;
|
||||
simplifier m_simplifier;
|
||||
defined_names m_defined_names;
|
||||
preprocessor m_preprocessor;
|
||||
order * m_order;
|
||||
clause_selection * m_cls_sel;
|
||||
literal_selection * m_lit_sel;
|
||||
context * m_context;
|
||||
expr_ref_vector m_exprs;
|
||||
proof_ref_vector m_expr_proofs;
|
||||
bool m_has_theories;
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
prover(ast_manager & m, front_end_params & params);
|
||||
~prover();
|
||||
void assert_expr(expr * e);
|
||||
lbool check();
|
||||
void display_statistics(std::ostream & out) const { if (m_context) m_context->display_statistics(out); }
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _SPC_PROVER_H_ */
|
||||
|
|
@ -1,269 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_rewrite.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-12.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_rewriter.h"
|
||||
#include"spc_decl_plugin.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
rewriter::rewriter(ast_manager & m, simplifier & simp, order & ord, asserted_literals & al):
|
||||
simplifier(m),
|
||||
m_asserted_literals(al),
|
||||
m_order(ord),
|
||||
m_spc_fid(m.get_family_id("spc")),
|
||||
m_subst(m),
|
||||
m_st(m),
|
||||
m_visitor(m_order, m_subst, m_cls_use_list) {
|
||||
|
||||
reserve_offsets(3);
|
||||
|
||||
borrow_plugins(simp);
|
||||
}
|
||||
|
||||
rewriter::~rewriter() {
|
||||
release_plugins();
|
||||
}
|
||||
|
||||
inline void rewriter::reserve_vars(unsigned num_vars) {
|
||||
m_subst.reserve_vars(num_vars);
|
||||
m_order.reserve_vars(num_vars);
|
||||
m_asserted_literals.reserve_vars(num_vars);
|
||||
}
|
||||
|
||||
void rewriter::reserve_offsets(unsigned num_offsets) {
|
||||
m_subst.reserve_offsets(num_offsets);
|
||||
m_order.reserve_offsets(num_offsets);
|
||||
}
|
||||
|
||||
inline bool rewriter::demodulator(clause * cls) const {
|
||||
if (cls->get_num_literals() != 1)
|
||||
return false;
|
||||
literal const & l = cls->get_literal(0);
|
||||
return !l.sign() && m_manager.is_eq(l.atom());
|
||||
}
|
||||
|
||||
inline void rewriter::insert(clause * cls, expr * source) {
|
||||
if (!is_var(source)) {
|
||||
TRACE("rewriter_detail", tout << "inserting into rewriter index:\n"; cls->display(tout, m_manager); tout << "\n";);
|
||||
flush_cache();
|
||||
m_st.insert(to_app(source));
|
||||
m_cls_use_list.insert(cls, source);
|
||||
}
|
||||
}
|
||||
|
||||
void rewriter::insert(clause * cls) {
|
||||
if (demodulator(cls)) {
|
||||
reserve_vars(cls->get_num_vars());
|
||||
literal const & l = cls->get_literal(0);
|
||||
app * eq = to_app(l.atom());
|
||||
if (l.is_oriented()) {
|
||||
expr * source = l.is_left() ? eq->get_arg(0) : eq->get_arg(1);
|
||||
insert(cls, source);
|
||||
}
|
||||
else {
|
||||
insert(cls, eq->get_arg(0));
|
||||
insert(cls, eq->get_arg(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void rewriter::erase(clause * cls, expr * source) {
|
||||
if (!is_var(source)) {
|
||||
flush_cache();
|
||||
m_cls_use_list.erase(cls, source);
|
||||
if (m_cls_use_list.empty(source))
|
||||
m_st.erase(to_app(source));
|
||||
}
|
||||
}
|
||||
|
||||
void rewriter::erase(clause * cls) {
|
||||
if (demodulator(cls)) {
|
||||
literal const & l = cls->get_literal(0);
|
||||
app * eq = to_app(l.atom());
|
||||
if (l.is_oriented()) {
|
||||
expr * source = l.is_left() ? eq->get_arg(0) : eq->get_arg(1);
|
||||
erase(cls, source);
|
||||
}
|
||||
else {
|
||||
erase(cls, eq->get_arg(0));
|
||||
erase(cls, eq->get_arg(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool rewriter::visitor::operator()(expr * e) {
|
||||
if (m_cls_use_list.empty(e))
|
||||
return true; // continue;
|
||||
clause_use_list::iterator it = m_cls_use_list.begin(e);
|
||||
clause_use_list::iterator end = m_cls_use_list.end(e);
|
||||
for (; it != end; ++it) {
|
||||
m_clause = *it;
|
||||
SASSERT(m_clause->get_num_literals() == 1);
|
||||
literal & l = m_clause->get_literal(0);
|
||||
expr * atom = l.atom();
|
||||
SASSERT(!l.sign() && m_manager.is_eq(atom));
|
||||
SASSERT(to_app(atom)->get_arg(0) == e || to_app(atom)->get_arg(1) == e);
|
||||
m_source = to_app(atom)->get_arg(0);
|
||||
m_target = to_app(atom)->get_arg(1);
|
||||
if (m_source != e)
|
||||
std::swap(m_source, m_target);
|
||||
SASSERT(m_source == e);
|
||||
TRACE("rewriter", tout << "found generalization:\n" << mk_pp(m_source, m_manager) << "\n" <<
|
||||
mk_pp(m_target, m_manager) << "\nsubstitution\n";
|
||||
m_subst.display(tout); tout << "m_subst: " << &m_subst << "\n";
|
||||
tout << "checking ordering constraints...\n";);
|
||||
if (l.is_oriented() || m_order.greater(expr_offset(m_source, 1), expr_offset(m_target, 1), &m_subst)) {
|
||||
m_found = true;
|
||||
return false; // stop
|
||||
}
|
||||
TRACE("rewriter", tout << "failed ordering constraints...\n";);
|
||||
}
|
||||
return true; // continue
|
||||
}
|
||||
|
||||
void rewriter::save_justification(justification * j) {
|
||||
if (std::find(m_justifications.begin(), m_justifications.end(), j) == m_justifications.end())
|
||||
m_justifications.push_back(j);
|
||||
}
|
||||
|
||||
proof * rewriter::mk_demodulation_proof(expr * old_expr, expr * new_expr, proof * parent) {
|
||||
if (m_manager.fine_grain_proofs()) {
|
||||
SASSERT(parent);
|
||||
return m_manager.mk_app(m_spc_fid, PR_DEMODULATION, parent, m_manager.mk_eq(old_expr, new_expr));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rewriter::reset() {
|
||||
m_st.reset();
|
||||
m_cls_use_list.reset();
|
||||
}
|
||||
|
||||
void rewriter::reduce_literal(literal const & l, literal & l_r, proof * & l_pr) {
|
||||
if (m_st.empty()) {
|
||||
l_r = l;
|
||||
l_pr = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
expr * atom = l.atom();
|
||||
expr * r;
|
||||
proof * r_pr;
|
||||
m_proofs.reset();
|
||||
while (true) {
|
||||
reduce_core(atom);
|
||||
get_cached(atom, r, r_pr);
|
||||
if (m_manager.fine_grain_proofs() && r_pr)
|
||||
m_proofs.push_back(r_pr);
|
||||
if (atom == r)
|
||||
break;
|
||||
atom = r;
|
||||
}
|
||||
l_r = literal(atom, l.sign());
|
||||
if (m_manager.fine_grain_proofs())
|
||||
l_pr = m_proofs.empty() ? 0 : m_manager.mk_transitivity(m_proofs.size(), m_proofs.c_ptr());
|
||||
}
|
||||
|
||||
clause * rewriter::operator()(clause * cls) {
|
||||
reserve_vars(cls->get_num_vars());
|
||||
SASSERT(m_found_literals.empty());
|
||||
m_justifications.reset();
|
||||
m_max_scope_lvl = cls->get_scope_lvl();
|
||||
|
||||
literal_buffer new_literals(m_manager);
|
||||
proof_ref_buffer new_proofs(m_manager);
|
||||
bool changed = false;
|
||||
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal & l = cls->get_literal(i);
|
||||
literal l_r;
|
||||
proof * l_pr = 0;
|
||||
reduce_literal(l, l_r, l_pr);
|
||||
|
||||
if (l != l_r) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (!l_r.is_false(m_manager) && !m_found_literals.contains(l_r)) {
|
||||
m_found_literals.insert(l_r);
|
||||
|
||||
// apply simplify reflect rules
|
||||
expr * atom = l_r.atom();
|
||||
clause * unit = 0;
|
||||
TRACE("rewriter", tout << "adding literal: " << mk_pp(atom, m_manager) << "\n";);
|
||||
if (l_r.sign()) {
|
||||
if (m_manager.is_eq(atom))
|
||||
unit = m_asserted_literals.subsumes(to_app(atom)->get_arg(0), to_app(atom)->get_arg(1));
|
||||
else
|
||||
unit = m_asserted_literals.gen(atom, false);
|
||||
}
|
||||
else {
|
||||
// check if there is a generalization of the negation of the current literal.
|
||||
unit = m_asserted_literals.gen(atom, true);
|
||||
}
|
||||
|
||||
if (unit) {
|
||||
// new literal was resolved
|
||||
justification * j = unit->get_justification();
|
||||
m_justifications.push_back(j);
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
// keep new literal
|
||||
new_literals.push_back(l_r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// removed duplicate or resolved literal.
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (m_manager.fine_grain_proofs() && l_pr != 0) {
|
||||
new_proofs.push_back(l_pr);
|
||||
}
|
||||
}
|
||||
|
||||
m_found_literals.reset();
|
||||
|
||||
if (!changed) {
|
||||
m_found_literals.reset();
|
||||
return cls;
|
||||
}
|
||||
|
||||
proof * new_pr = mk_rewrite_proof(m_manager, m_spc_fid, new_literals.size(), new_literals.c_ptr(), cls->get_justification()->get_proof(),
|
||||
new_proofs.size(), new_proofs.c_ptr());
|
||||
|
||||
justification * new_j = rewrite_justification::mk(m_manager, cls->get_justification(), m_justifications.size(), m_justifications.c_ptr(), new_pr);
|
||||
|
||||
if (m_max_scope_lvl == cls->get_scope_lvl()) {
|
||||
// peform destructive update
|
||||
cls->update_lits(m_manager, new_literals.size(), new_literals.c_ptr(), new_j);
|
||||
return cls;
|
||||
}
|
||||
else {
|
||||
SASSERT(m_max_scope_lvl > cls->get_scope_lvl());
|
||||
// create new clause
|
||||
// the old clause will be frozen
|
||||
return clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), new_j, m_max_scope_lvl);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_rewriter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-11.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_REWRITER_H_
|
||||
#define _SPC_REWRITER_H_
|
||||
|
||||
#include"simplifier.h"
|
||||
#include"order.h"
|
||||
#include"substitution_tree.h"
|
||||
#include"spc_clause.h"
|
||||
#include"spc_asserted_literals.h"
|
||||
#include"sparse_use_list.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Apply rewriting steps using demodulation rule:
|
||||
|
||||
C[s] ==> C[sigma(r)]
|
||||
when
|
||||
|
||||
l = r is a known equality (demodulator)
|
||||
sigma(l) = s
|
||||
sigma(l) > sigma(r)
|
||||
|
||||
It also applies the following rules:
|
||||
|
||||
- Duplicate literal deletion
|
||||
|
||||
- Resolved literal deletion
|
||||
|
||||
- Positive simplify reflect
|
||||
s = t, (u[p <- sigma(s)] != u[p <- sigma(t)] or R)
|
||||
==>
|
||||
R
|
||||
|
||||
- Negative simplify reflect
|
||||
s != t (sigma(s = t) or R)
|
||||
===>
|
||||
R
|
||||
*/
|
||||
class rewriter : public simplifier {
|
||||
protected:
|
||||
typedef sparse_use_list<expr, ptr_vector<clause> > clause_use_list;
|
||||
asserted_literals & m_asserted_literals;
|
||||
order & m_order;
|
||||
family_id m_spc_fid;
|
||||
|
||||
substitution m_subst;
|
||||
substitution_tree m_st; // index for potential demodulators left-hand-side
|
||||
clause_use_list m_cls_use_list; // index for demodulators left-hand-side to equation.
|
||||
found_literals m_found_literals;
|
||||
|
||||
ptr_vector<justification> m_justifications;
|
||||
|
||||
struct visitor : public st_visitor {
|
||||
ast_manager & m_manager;
|
||||
order & m_order;
|
||||
clause_use_list & m_cls_use_list;
|
||||
bool m_found;
|
||||
clause * m_clause;
|
||||
expr * m_source;
|
||||
expr * m_target;
|
||||
|
||||
visitor(order & ord, substitution & subst, clause_use_list & ul):
|
||||
st_visitor(subst), m_manager(ord.get_manager()), m_order(ord), m_cls_use_list(ul) {
|
||||
}
|
||||
|
||||
virtual bool operator()(expr * e);
|
||||
};
|
||||
|
||||
unsigned m_max_scope_lvl; // maximal scope level used during rewrite.
|
||||
visitor m_visitor;
|
||||
|
||||
proof * mk_demodulation_proof(expr * old_expr, expr * new_expr, proof * parent);
|
||||
|
||||
bool demodulator(clause * cls) const;
|
||||
void insert(clause * cls, expr * source);
|
||||
void erase(clause * cls, expr * source);
|
||||
void reserve_vars(unsigned num_vars);
|
||||
void reserve_offsets(unsigned num_offsets);
|
||||
void save_justification(justification * j);
|
||||
|
||||
void reduce_literal(literal const & l, literal & l_r, proof * & l_pr);
|
||||
|
||||
public:
|
||||
rewriter(ast_manager & m, simplifier & s, order & ord, asserted_literals & al);
|
||||
virtual ~rewriter();
|
||||
|
||||
/**
|
||||
\brief Insert clause into rewriter indexes
|
||||
*/
|
||||
void insert(clause * cls);
|
||||
|
||||
/**
|
||||
\brief Remove clause from rewriter indexes
|
||||
*/
|
||||
void erase(clause * cls);
|
||||
|
||||
clause * operator()(clause * cls);
|
||||
|
||||
void reset();
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _SPC_REWRITER_H_ */
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_semantic_tautology.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-11.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_semantic_tautology.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
expr * find(expr2expr & f, expr * n) {
|
||||
#ifdef _TRACE
|
||||
expr * _n = n;
|
||||
#endif
|
||||
ptr_buffer<expr> path;
|
||||
expr * next;
|
||||
while (f.find(n, next)) {
|
||||
path.push_back(n);
|
||||
n = next;
|
||||
}
|
||||
ptr_buffer<expr>::iterator it = path.begin();
|
||||
ptr_buffer<expr>::iterator end = path.end();
|
||||
for (; it != end; ++it) {
|
||||
expr * prev = *it;
|
||||
f.insert(prev, n);
|
||||
}
|
||||
SASSERT(n);
|
||||
TRACE("semantic_tautology_detail", tout << "find(#" << _n->get_id() << ") = #" << n->get_id() << "\n";);
|
||||
return n;
|
||||
}
|
||||
|
||||
semantic_tautology::semantic_tautology(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_cg_table(DEFAULT_HASHTABLE_INITIAL_CAPACITY, cg_hash(m_manager, m_find), cg_eq(m_find)) {
|
||||
}
|
||||
|
||||
unsigned semantic_tautology::cg_hash::operator()(app * n) const {
|
||||
TRACE("semantic_tautology_detail", tout << "hash code of:\n" << mk_pp(n, m_manager) << "\n";);
|
||||
unsigned r = get_composite_hash<app *, k_hash, c_hash>(n, n->get_num_args(), m_k_hash, m_c_hash);
|
||||
TRACE("semantic_tautology_detail", tout << "result: " << r << "\n";);
|
||||
return r;
|
||||
}
|
||||
|
||||
bool semantic_tautology::cg_eq::operator()(app * n1, app * n2) const {
|
||||
if (n1->get_decl() != n2->get_decl() || n1->get_num_args() != n2->get_num_args())
|
||||
return false;
|
||||
unsigned num_args = n1->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; i++)
|
||||
if (spc::find(m_find, n1->get_arg(i)) != spc::find(m_find, n2->get_arg(i)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool semantic_tautology::is_target(unsigned num_lits, literal * lits) {
|
||||
bool has_diseq = false;
|
||||
bool has_non_diseq = false;
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l = lits[i];
|
||||
if (l.sign() && m_manager.is_eq(l.atom()))
|
||||
has_diseq = true;
|
||||
else
|
||||
has_non_diseq = true;
|
||||
}
|
||||
return has_diseq && has_non_diseq;
|
||||
}
|
||||
|
||||
void semantic_tautology::reset() {
|
||||
m_region.reset();
|
||||
m_init_todo.reset();
|
||||
m_todo.reset();
|
||||
m_already_found.reset();
|
||||
m_use_list.reset();
|
||||
m_find.reset();
|
||||
m_size.reset();
|
||||
m_cg_table.reset();
|
||||
}
|
||||
|
||||
void semantic_tautology::update_use_list(app * parent, expr * child) {
|
||||
list<app*> * use_list = 0;
|
||||
m_use_list.find(child, use_list);
|
||||
use_list = new (m_region) list<app*>(parent, use_list);
|
||||
m_use_list.insert(child, use_list);
|
||||
}
|
||||
|
||||
inline void semantic_tautology::push_init_core(expr * n) {
|
||||
if (is_app(n) && to_app(n)->get_num_args() > 0)
|
||||
m_init_todo.push_back(to_app(n));
|
||||
}
|
||||
|
||||
inline void semantic_tautology::push_init(expr * atom) {
|
||||
if (m_manager.is_eq(atom)) {
|
||||
push_init_core(to_app(atom)->get_arg(0));
|
||||
push_init_core(to_app(atom)->get_arg(1));
|
||||
}
|
||||
else
|
||||
push_init_core(atom);
|
||||
}
|
||||
|
||||
void semantic_tautology::init_use_list() {
|
||||
while (!m_init_todo.empty()) {
|
||||
app * n = m_init_todo.back();
|
||||
m_init_todo.pop_back();
|
||||
if (!m_already_found.contains(n)) {
|
||||
unsigned num_args = n->get_num_args();
|
||||
SASSERT(num_args > 0);
|
||||
m_cg_table.insert(n);
|
||||
m_already_found.insert(n);
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * c = n->get_arg(i);
|
||||
update_use_list(n, c);
|
||||
push_init_core(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void semantic_tautology::init(unsigned num_lits, literal * lits) {
|
||||
reset();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l = lits[i];
|
||||
expr * atom = l.atom();
|
||||
push_init(atom);
|
||||
if (l.sign() && m_manager.is_eq(atom))
|
||||
m_todo.push_back(expr_pair(to_app(atom)->get_arg(0), to_app(atom)->get_arg(1)));
|
||||
}
|
||||
init_use_list();
|
||||
}
|
||||
|
||||
void semantic_tautology::remove_parents(expr * n1) {
|
||||
list<app*> * use_list = 0;
|
||||
m_use_list.find(n1, use_list);
|
||||
while (use_list) {
|
||||
TRACE("semantic_tautology", tout << "removing parent from cg_table:\n" << mk_pp(use_list->head(), m_manager) << "\n";);
|
||||
m_cg_table.erase(use_list->head());
|
||||
use_list = use_list->tail();
|
||||
}
|
||||
}
|
||||
|
||||
void semantic_tautology::restore_parents(expr * n1, expr * n2) {
|
||||
list<app*> * use_list = 0;
|
||||
m_use_list.find(n1, use_list);
|
||||
while (use_list) {
|
||||
app * parent = use_list->head();
|
||||
app * other = 0;
|
||||
if (m_cg_table.find(parent, other)) {
|
||||
TRACE("semantic_tautology", tout << "new congruence:\n" << mk_pp(parent, m_manager) << "\n" << mk_pp(other, m_manager) << "\n";);
|
||||
if (parent != other)
|
||||
m_todo.push_back(expr_pair(parent, other));
|
||||
}
|
||||
else {
|
||||
TRACE("semantic_tautology", tout << "restoring parent to cg_table:\n" << mk_pp(parent, m_manager) << "\n";);
|
||||
m_cg_table.insert(parent);
|
||||
update_use_list(parent, n2);
|
||||
}
|
||||
use_list = use_list->tail();
|
||||
}
|
||||
}
|
||||
|
||||
void semantic_tautology::assert_eq(expr * n1, expr * n2) {
|
||||
n1 = find(n1);
|
||||
n2 = find(n2);
|
||||
if (n1 == n2)
|
||||
return;
|
||||
TRACE("semantic_tautology", tout << "processing equality:\n" << mk_pp(n1, m_manager) << " " << n1->get_id() << "\n" <<
|
||||
mk_pp(n2, m_manager) << " " << n2->get_id() << "\n";);
|
||||
unsigned sz1 = 1;
|
||||
unsigned sz2 = 1;
|
||||
m_size.find(n1, sz1);
|
||||
m_size.find(n2, sz2);
|
||||
if (sz1 > sz2)
|
||||
std::swap(n1, n2);
|
||||
remove_parents(n1);
|
||||
TRACE("semantic_tautology", tout << "merging equivalence classes\n";);
|
||||
m_find.insert(n1, n2);
|
||||
m_size.insert(n2, sz1 + sz2);
|
||||
restore_parents(n1, n2);
|
||||
}
|
||||
|
||||
void semantic_tautology::process_eqs() {
|
||||
while (!m_todo.empty()) {
|
||||
expr_pair const & p = m_todo.back();
|
||||
expr * lhs = p.first;
|
||||
expr * rhs = p.second;
|
||||
m_todo.pop_back();
|
||||
assert_eq(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
bool semantic_tautology::contains_complement(unsigned num_lits, literal * lits, unsigned i, bool sign, expr * atom) {
|
||||
atom = find(atom);
|
||||
for (unsigned j = i + 1; j < num_lits; j++) {
|
||||
literal const & l = lits[j];
|
||||
if (l.sign() != sign && find(l.atom()) == atom)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool semantic_tautology::is_tautology(unsigned num_lits, literal * lits) {
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l = lits[i];
|
||||
expr * atom = l.atom();
|
||||
if (!l.sign() && m_manager.is_eq(atom) && find(to_app(atom)->get_arg(0)) == find(to_app(atom)->get_arg(1)))
|
||||
return true;
|
||||
if (!m_manager.is_eq(atom) && contains_complement(num_lits, lits, i, l.sign(), atom))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool semantic_tautology::operator()(unsigned num_lits, literal * lits) {
|
||||
if (!is_target(num_lits, lits))
|
||||
return false;
|
||||
init(num_lits, lits);
|
||||
process_eqs();
|
||||
bool r = is_tautology(num_lits, lits);
|
||||
TRACE("semantic_tautology", display(tout, num_lits, lits, m_manager); tout << "\nis semantic tautology: " << r << "\n";);
|
||||
return r;
|
||||
}
|
||||
|
||||
};
|
|
@ -1,114 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_semantic_tautology.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Semantic tautology detection
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-11.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_SEMANTIC_TAUTOLOGY_H_
|
||||
#define _SPC_SEMANTIC_TAUTOLOGY_H_
|
||||
|
||||
#include"spc_literal.h"
|
||||
#include"list.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"map.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
typedef obj_map<expr, expr *> expr2expr;
|
||||
|
||||
expr * find(expr2expr & f, expr * e);
|
||||
|
||||
/**
|
||||
\brief Functor for detecting semantic tautology.
|
||||
A clause C is a semantic tautology if it has the following form:
|
||||
|
||||
s_1 != t_1 or ... or s_n != t_n or s = t or R
|
||||
|
||||
sigma(s_1 = t_1), ..., sigma(s_n t_n) |= sigma(s = t)
|
||||
where sigma maps variables to constants.
|
||||
*/
|
||||
class semantic_tautology {
|
||||
typedef std::pair<expr *, expr *> expr_pair;
|
||||
|
||||
typedef obj_hashtable<expr> already_found;
|
||||
typedef expr2expr find_map;
|
||||
typedef obj_map<expr, list<app*> *> use_list;
|
||||
typedef obj_map<expr, unsigned> size_map;
|
||||
|
||||
struct k_hash {
|
||||
unsigned operator()(app * n) const { return n->get_decl()->get_id(); }
|
||||
};
|
||||
|
||||
struct c_hash {
|
||||
find_map & m_find;
|
||||
c_hash(find_map & f):m_find(f) {}
|
||||
unsigned operator()(app * n, unsigned i) const {
|
||||
unsigned id = spc::find(m_find, n->get_arg(i))->get_id();
|
||||
TRACE("semantic_tautology_detail", tout << "child(" << i << ") = #" << id << "\n";);
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
struct cg_hash {
|
||||
ast_manager & m_manager;
|
||||
k_hash m_k_hash;
|
||||
c_hash m_c_hash;
|
||||
cg_hash(ast_manager & m, find_map & f):m_manager(m), m_c_hash(f) {}
|
||||
unsigned operator()(app * n) const;
|
||||
};
|
||||
|
||||
struct cg_eq {
|
||||
find_map & m_find;
|
||||
cg_eq(find_map & f):m_find(f) {}
|
||||
bool operator()(app * n1, app * n2) const;
|
||||
};
|
||||
|
||||
typedef ptr_hashtable<app, cg_hash, cg_eq> cg_table;
|
||||
|
||||
ast_manager & m_manager;
|
||||
region m_region;
|
||||
ptr_vector<app> m_init_todo;
|
||||
svector<expr_pair> m_todo;
|
||||
already_found m_already_found;
|
||||
use_list m_use_list;
|
||||
find_map m_find;
|
||||
size_map m_size;
|
||||
cg_table m_cg_table;
|
||||
|
||||
bool is_target(unsigned num_lits, literal * lits);
|
||||
void reset();
|
||||
void update_use_list(app * parent, expr * child);
|
||||
void push_init_core(expr * n);
|
||||
void push_init(expr * atom);
|
||||
void init_use_list();
|
||||
void init(unsigned num_lits, literal * lits);
|
||||
expr * find(expr * n) { return spc::find(m_find, n); }
|
||||
void remove_parents(expr * n1);
|
||||
void restore_parents(expr * n1, expr * n2);
|
||||
void assert_eq(expr * n1, expr * n2);
|
||||
void process_eqs();
|
||||
bool contains_complement(unsigned num_lits, literal * lits, unsigned i, bool sign, expr * atom);
|
||||
bool is_tautology(unsigned num_lits, literal * lits);
|
||||
|
||||
public:
|
||||
semantic_tautology(ast_manager & m);
|
||||
|
||||
bool operator()(unsigned num_lits, literal * lits);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SPC_SEMANTIC_TAUTOLOGY_H_ */
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_statistics.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-17.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_statistics.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
void statistics::reset() {
|
||||
m_num_mk_clause = 0;
|
||||
m_num_del_clause = 0;
|
||||
m_num_processed = 0;
|
||||
m_num_superposition = 0;
|
||||
m_num_resolution = 0;
|
||||
m_num_eq_factoring = 0;
|
||||
m_num_factoring = 0;
|
||||
m_num_eq_resolution = 0;
|
||||
m_num_trivial = 0;
|
||||
m_num_simplified = 0;
|
||||
m_num_subsumed = 0;
|
||||
m_num_redundant = 0;
|
||||
}
|
||||
|
||||
void statistics::display(std::ostream & out) const {
|
||||
out << "num. mk. clause: " << m_num_mk_clause << "\n";
|
||||
out << "num. del. clause: " << m_num_del_clause << "\n";
|
||||
out << "num. processed: " << m_num_processed << "\n";
|
||||
out << "num. superposition: " << m_num_superposition << "\n";
|
||||
out << "num. resolution: " << m_num_resolution << "\n";
|
||||
out << "num. eq. factoring: " << m_num_eq_factoring << "\n";
|
||||
out << "num. factoring: " << m_num_factoring << "\n";
|
||||
out << "num. eq. resol.: " << m_num_eq_resolution << "\n";
|
||||
out << "num. simplified: " << m_num_simplified << "\n";
|
||||
out << "num. redundant: " << m_num_redundant << "\n";
|
||||
out << " num. trivial: " << m_num_trivial << "\n";
|
||||
out << " num. subsumed: " << m_num_subsumed << "\n";
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_statistics.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-17.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_STATISTICS_H_
|
||||
#define _SPC_STATISTICS_H_
|
||||
|
||||
#include<iostream>
|
||||
|
||||
namespace spc {
|
||||
|
||||
struct statistics {
|
||||
unsigned m_num_mk_clause;
|
||||
unsigned m_num_del_clause;
|
||||
unsigned m_num_processed;
|
||||
unsigned m_num_superposition;
|
||||
unsigned m_num_resolution;
|
||||
unsigned m_num_eq_factoring;
|
||||
unsigned m_num_factoring;
|
||||
unsigned m_num_eq_resolution;
|
||||
unsigned m_num_trivial;
|
||||
unsigned m_num_simplified;
|
||||
unsigned m_num_subsumed;
|
||||
unsigned m_num_redundant;
|
||||
statistics() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset();
|
||||
void display(std::ostream & out) const;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _SPC_STATISTICS_H_ */
|
||||
|
|
@ -1,698 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_subsumption.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-13.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_subsumption.h"
|
||||
#include"fvi_def.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Return true if literal l2 is an instance of l1.
|
||||
|
||||
When ResetSubst == true, m_subst is reset before trying to match l1 and l2.
|
||||
|
||||
When ResetSubst == false, it is assumed that m_subst.push_scope was invoked
|
||||
before invoking match_literal.
|
||||
*/
|
||||
template<bool ResetSubst>
|
||||
bool subsumption::match_literal(literal const & l1, literal const & l2) {
|
||||
if (l1.sign() == l2.sign()) {
|
||||
expr * atom1 = l1.atom();
|
||||
expr * atom2 = l2.atom();
|
||||
bool is_eq1 = m_manager.is_eq(atom1);
|
||||
bool is_eq2 = m_manager.is_eq(atom2);
|
||||
if (is_eq1 && is_eq2) {
|
||||
expr * lhs1 = to_app(atom1)->get_arg(0);
|
||||
expr * rhs1 = to_app(atom1)->get_arg(1);
|
||||
expr * lhs2 = to_app(atom2)->get_arg(0);
|
||||
expr * rhs2 = to_app(atom2)->get_arg(1);
|
||||
if (ResetSubst)
|
||||
m_subst.reset_subst();
|
||||
|
||||
if (m_matcher(lhs1, lhs2, m_subst) && m_matcher(rhs1, rhs2, m_subst))
|
||||
return true;
|
||||
|
||||
if (ResetSubst)
|
||||
m_subst.reset_subst();
|
||||
else {
|
||||
// I'm assuming push_scope was invoked before executing match_literal
|
||||
// So, pop_scope is equivalent to a local reset.
|
||||
m_subst.pop_scope();
|
||||
m_subst.push_scope();
|
||||
}
|
||||
|
||||
return (m_matcher(lhs1, rhs2, m_subst) && m_matcher(rhs1, lhs2, m_subst));
|
||||
}
|
||||
else if (!is_eq1 && !is_eq2) {
|
||||
if (ResetSubst)
|
||||
m_subst.reset_subst();
|
||||
return m_matcher(atom1, atom2, m_subst);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if for every literal l1 in lits1 there is a
|
||||
literal l2 in lits2 such that l2 is an instance of l1.
|
||||
*/
|
||||
bool subsumption::can_subsume(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2) {
|
||||
for (unsigned i = 0; i < num_lits1; i++) {
|
||||
literal const & l1 = lits1[i];
|
||||
unsigned j = 0;
|
||||
for (; j < num_lits2; j++) {
|
||||
literal const & l2 = lits2[j];
|
||||
if (match_literal<true>(l1, l2))
|
||||
break;
|
||||
}
|
||||
if (j == num_lits2)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if cls1 can subsume cls2. It performs a series of quick checks.
|
||||
*/
|
||||
bool subsumption::quick_check(clause * cls1, clause * cls2) {
|
||||
return
|
||||
cls1->get_symbol_count() <= cls2->get_symbol_count() &&
|
||||
cls1->get_const_count() <= cls2->get_const_count() &&
|
||||
cls1->get_depth() <= cls2->get_depth() &&
|
||||
cls1->get_num_pos_literals() <= cls2->get_num_pos_literals() &&
|
||||
cls1->get_num_neg_literals() <= cls2->get_num_neg_literals() &&
|
||||
(!cls1->is_ground() || cls2->is_ground());
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if the set of literals lits1 subsumes the set of literals lits2.
|
||||
*/
|
||||
bool subsumption::subsumes_core(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2) {
|
||||
enum state {
|
||||
INVOKE, DECIDE, BACKTRACK, RETURN
|
||||
};
|
||||
|
||||
if (num_lits1 == 0)
|
||||
return true;
|
||||
|
||||
m_stack.reset();
|
||||
m_subst.reset();
|
||||
|
||||
m_stack.push_back(assoc(0, 0));
|
||||
state st = DECIDE;
|
||||
|
||||
unsigned i;
|
||||
assoc * top;
|
||||
unsigned counter = 0;
|
||||
#ifdef _TRACE
|
||||
unsigned opt = 0;
|
||||
unsigned nopt = 0;
|
||||
#endif
|
||||
while (true && counter < 5000000) {
|
||||
counter++;
|
||||
switch (st) {
|
||||
case INVOKE:
|
||||
SASSERT(!m_stack.empty());
|
||||
i = m_stack.back().first + 1;
|
||||
if (i >= num_lits1) {
|
||||
TRACE("subsumption", tout << "subsumption result: YES.\n";);
|
||||
TRACE_CODE({
|
||||
if (counter > 10000) {
|
||||
TRACE("subsumption_perf",
|
||||
tout << "subsumption succeeded: " << counter << " " << opt << " " << nopt << "\n";
|
||||
tout << "literals1:\n"; display(tout, num_lits1, lits1, m_manager); tout << "\n";
|
||||
tout << "literals2:\n"; display(tout, num_lits2, lits2, m_manager); tout << "\n";);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
m_stack.push_back(assoc(i, 0));
|
||||
st = DECIDE;
|
||||
}
|
||||
break;
|
||||
case DECIDE:
|
||||
top = &(m_stack.back());
|
||||
m_subst.push_scope();
|
||||
if (match_literal<false>(lits1[top->first], lits2[top->second]))
|
||||
st = INVOKE;
|
||||
else
|
||||
st = BACKTRACK;
|
||||
break;
|
||||
case BACKTRACK:
|
||||
top = &(m_stack.back());
|
||||
top->second++;
|
||||
m_subst.pop_scope();
|
||||
if (top->second >= num_lits2)
|
||||
st = RETURN;
|
||||
else
|
||||
st = DECIDE;
|
||||
break;
|
||||
case RETURN:
|
||||
top = &(m_stack.back());
|
||||
m_stack.pop_back();
|
||||
if (m_stack.empty()) {
|
||||
// no more alternatives
|
||||
TRACE("subsumption", tout << "subsumption result: NO\n";);
|
||||
TRACE_CODE({
|
||||
if (counter > 10000) {
|
||||
TRACE("subsumption_perf",
|
||||
tout << "subsumption failed: " << counter << " " << opt << " " << nopt << "\n";
|
||||
tout << "literals1:\n"; display(tout, num_lits1, lits1, m_manager); tout << "\n";
|
||||
tout << "literals2:\n"; display(tout, num_lits2, lits2, m_manager); tout << "\n";);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (m_subst.top_scope_has_bindings()) {
|
||||
TRACE_CODE(nopt++;);
|
||||
st = BACKTRACK;
|
||||
}
|
||||
else {
|
||||
TRACE_CODE(opt++;);
|
||||
#ifdef Z3DEBUG
|
||||
unsigned num_bindings = m_subst.get_num_bindings();
|
||||
#endif
|
||||
m_subst.pop_scope();
|
||||
SASSERT(num_bindings == m_subst.get_num_bindings());
|
||||
st = RETURN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if the set of ground literals lits1 subsumes the set of ground literals lits2.
|
||||
*/
|
||||
bool subsumption::ground_subsumes_core(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2) {
|
||||
for (unsigned i = 0; i < num_lits1; i++) {
|
||||
literal const & l1 = lits1[i];
|
||||
unsigned j = 0;
|
||||
for (; j < num_lits2; j++) {
|
||||
literal const & l2 = lits2[j];
|
||||
if (l1 == l2)
|
||||
break;
|
||||
}
|
||||
if (j == num_lits2)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if the literal l1 subsumes the set of literals lits2.
|
||||
*/
|
||||
bool subsumption::subsumes_core(literal const & l1, unsigned num_lits2, literal * lits2) {
|
||||
for (unsigned i = 0; i < num_lits2; i++) {
|
||||
if (match_literal<true>(l1, lits2[i]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
subsumption::subsumption(ast_manager & m, asserted_literals & al, spc_params & params):
|
||||
m_manager(m),
|
||||
m_params(params),
|
||||
m_asserted_literals(al),
|
||||
m_subst(m),
|
||||
m_matcher(m),
|
||||
m_found_decls(m),
|
||||
m_index(0),
|
||||
m_num_processed_clauses(0),
|
||||
m_opt_threshold(params.m_initial_subsumption_index_opt) {
|
||||
|
||||
m_subst.reserve_offsets(1);
|
||||
|
||||
init_indexes();
|
||||
}
|
||||
|
||||
subsumption::~subsumption() {
|
||||
if (m_index)
|
||||
dealloc(m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if cls1 subsumes cls2
|
||||
*/
|
||||
bool subsumption::operator()(clause * cls1, clause * cls2) {
|
||||
TRACE("subsumption_detail", tout << "checking if:\n"; cls1->display(tout, m_manager); tout << "\nsubsumes\n";
|
||||
cls2->display(tout, m_manager); tout << "\n";);
|
||||
if (!quick_check(cls1, cls2)) {
|
||||
TRACE("subsumption_detail", tout << "failed quick check\n";);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_subst.reserve_vars(std::max(cls1->get_num_vars(), cls2->get_num_vars()));
|
||||
unsigned num_lits1 = cls1->get_num_literals();
|
||||
unsigned num_lits2 = cls2->get_num_literals();
|
||||
literal * lits1 = cls1->get_literals();
|
||||
literal * lits2 = cls2->get_literals();
|
||||
if (cls1->is_ground() && cls2->is_ground())
|
||||
return ground_subsumes_core(num_lits1, lits1, num_lits2, lits2);
|
||||
if (num_lits1 == 1)
|
||||
return subsumes_core(lits1[0], num_lits2, lits2);
|
||||
// TODO: REMOVE true below... using it for debugging purposes.
|
||||
if (true || cls1->get_num_neg_literals() >= 3 || cls1->get_num_pos_literals() >= 3)
|
||||
if (!can_subsume(num_lits1, lits1, num_lits2, lits2)) {
|
||||
TRACE("subsumption_detail", tout << "failed can_subsume\n";);
|
||||
return false;
|
||||
}
|
||||
return subsumes_core(num_lits1, lits1, num_lits2, lits2);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Update the set of function symbols found in the clause being inserted into the index,
|
||||
and the set of clauses found since the index started to be built.
|
||||
|
||||
Return true if the function symbol should be tracked.
|
||||
*/
|
||||
bool subsumption::mark_func_decl(func_decl * f) {
|
||||
if (m_refining_index) {
|
||||
if (!m_cls_found_decl_set.contains(f)) {
|
||||
// update set of func_decls in the curr clause
|
||||
m_cls_found_decl_set.insert(f);
|
||||
m_cls_found_decls.push_back(f);
|
||||
// update global set of founf func_decls
|
||||
unsigned id = f->get_decl_id();
|
||||
m_found_decl_set.reserve(id+1);
|
||||
if (!m_found_decl_set.get(id)) {
|
||||
m_found_decl_set.set(id);
|
||||
m_found_decls.push_back(f);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
unsigned id = f->get_decl_id();
|
||||
// if func_decl was not found yet, then ignore it.
|
||||
if (id < m_found_decl_set.size() && m_found_decl_set.get(id)) {
|
||||
if (!m_cls_found_decl_set.contains(f)) {
|
||||
// update set of func_decls in the curr clause
|
||||
m_cls_found_decl_set.insert(f);
|
||||
m_cls_found_decls.push_back(f);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Increment the number of occurrences of a function symbol in the clause being
|
||||
inserted into the index.
|
||||
*/
|
||||
void subsumption::inc_f_count(func_decl * f, bool neg) {
|
||||
decl2nat & f_count = m_f_count[static_cast<unsigned>(neg)];
|
||||
unsigned val;
|
||||
if (f_count.find(f, val)) {
|
||||
f_count.insert(f, val + 1);
|
||||
}
|
||||
else {
|
||||
f_count.insert(f, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Update the min/max num. of occurrences of func symbol in a clause.
|
||||
*/
|
||||
void subsumption::update_min_max(func_decl * f) {
|
||||
for (unsigned is_neg = 0; is_neg < 1; is_neg++) {
|
||||
decl2nat & f_count = m_f_count[is_neg];
|
||||
decl2nat & f_min = m_f_min[is_neg];
|
||||
decl2nat & f_max = m_f_max[is_neg];
|
||||
unsigned count;
|
||||
if (f_count.find(f, count)) {
|
||||
unsigned old_count;
|
||||
if (!f_min.find(f, old_count) || old_count > count) {
|
||||
f_min.insert(f, count);
|
||||
}
|
||||
if (!f_max.find(f, old_count) || old_count < count) {
|
||||
f_max.insert(f, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Compute the number of occurences of function symbols in
|
||||
a clause.
|
||||
*/
|
||||
void subsumption::update_neg_pos_func_counts(clause * cls) {
|
||||
m_f_count[0].reset();
|
||||
m_f_count[1].reset();
|
||||
m_cls_found_decl_set.reset();
|
||||
m_cls_found_decls.reset();
|
||||
ptr_buffer<expr> todo;
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l = cls->get_literal(i);
|
||||
bool is_neg = l.sign();
|
||||
expr * n = l.atom();
|
||||
todo.push_back(n);
|
||||
while (!todo.empty()) {
|
||||
n = todo.back();
|
||||
todo.pop_back();
|
||||
if (is_app(n)) {
|
||||
func_decl * f = to_app(n)->get_decl();
|
||||
if (fvi_candidate(f) && mark_func_decl(f))
|
||||
inc_f_count(f, is_neg);
|
||||
unsigned num = to_app(n)->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
todo.push_back(to_app(n)->get_arg(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_refining_index) {
|
||||
ptr_vector<func_decl>::iterator it = m_cls_found_decls.begin();
|
||||
ptr_vector<func_decl>::iterator end = m_cls_found_decls.end();
|
||||
for (; it != end; ++it) {
|
||||
func_decl * f = *it;
|
||||
update_min_max(f);
|
||||
unsigned val;
|
||||
if (m_f_freq.find(f, val))
|
||||
m_f_freq.insert(f, val + 1);
|
||||
else
|
||||
m_f_freq.insert(f, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Store in m_feature_vector the value for the features of cls.
|
||||
*/
|
||||
void subsumption::compute_features(clause * cls, unsigned * fvector) {
|
||||
unsigned num = m_features.size();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
feature & f = m_features[i];
|
||||
switch (f.m_kind) {
|
||||
case F_GROUND:
|
||||
fvector[i] = cls->is_ground();
|
||||
break;
|
||||
case F_NUM_POS_LITS:
|
||||
fvector[i] = cls->get_num_pos_literals();
|
||||
break;
|
||||
case F_NUM_NEG_LITS:
|
||||
fvector[i] = cls->get_num_neg_literals();
|
||||
break;
|
||||
case F_DEPTH:
|
||||
fvector[i] = cls->get_depth();
|
||||
break;
|
||||
case F_CONST_COUNT:
|
||||
fvector[i] = cls->get_const_count();
|
||||
break;
|
||||
case F_SYM_COUNT:
|
||||
fvector[i] = cls->get_symbol_count();
|
||||
break;
|
||||
case F_NUM_NEG_FUNCS: {
|
||||
unsigned val;
|
||||
if (m_f_count[1].find(f.m_decl, val))
|
||||
fvector[i] = val;
|
||||
else
|
||||
fvector[i] = 0;
|
||||
break;
|
||||
}
|
||||
case F_NUM_POS_FUNCS: {
|
||||
unsigned val;
|
||||
if (m_f_count[0].find(f.m_decl, val))
|
||||
fvector[i] = val;
|
||||
else
|
||||
fvector[i] = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
TRACE("subsumption_features",
|
||||
tout << "features of: "; cls->display(tout, m_manager); tout << "\n";
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
tout << fvector[i] << " ";
|
||||
}
|
||||
tout << "\n";);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Initialise indexes for forward/backward subsumption.
|
||||
*/
|
||||
void subsumption::init_indexes() {
|
||||
// index for forward/backward subsumption
|
||||
// start with simple set of features
|
||||
m_features.push_back(feature(F_GROUND));
|
||||
m_features.push_back(feature(F_NUM_POS_LITS));
|
||||
m_features.push_back(feature(F_NUM_NEG_LITS));
|
||||
m_features.push_back(feature(F_DEPTH));
|
||||
m_features.push_back(feature(F_CONST_COUNT));
|
||||
m_features.push_back(feature(F_SYM_COUNT));
|
||||
m_index = alloc(index, m_features.size(), to_feature_vector(*this));
|
||||
}
|
||||
|
||||
unsigned subsumption::get_value_range(func_decl * f, bool neg) const {
|
||||
unsigned i = static_cast<unsigned>(neg);
|
||||
unsigned min;
|
||||
unsigned max;
|
||||
if (!m_f_min[i].find(f, min))
|
||||
min = 0;
|
||||
if (!m_f_max[i].find(f, max))
|
||||
max = 0;
|
||||
SASSERT(min <= max);
|
||||
return max - min;
|
||||
}
|
||||
|
||||
inline unsigned subsumption::get_value_range(func_decl * f) const {
|
||||
return std::max(get_value_range(f, false), get_value_range(f, true));
|
||||
}
|
||||
|
||||
bool subsumption::f_lt::operator()(func_decl * f1, func_decl * f2) const {
|
||||
unsigned vrange1 = m_owner.get_value_range(f1);
|
||||
unsigned vrange2 = m_owner.get_value_range(f2);
|
||||
if (vrange1 < vrange2)
|
||||
return true;
|
||||
if (vrange1 == vrange2)
|
||||
return f1->get_id() < f2->get_id();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Optimize the index for (non unit) forward subsumption and
|
||||
backward subsumption.
|
||||
*/
|
||||
void subsumption::optimize_feature_index() {
|
||||
ptr_vector<clause> clauses;
|
||||
m_index->collect(clauses);
|
||||
|
||||
dealloc(m_index);
|
||||
m_features.reset();
|
||||
|
||||
ptr_vector<func_decl> targets;
|
||||
unsigned sz = m_found_decls.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
func_decl * f = m_found_decls.get(i);
|
||||
unsigned val;
|
||||
if (m_f_freq.find(f, val) && val > m_params.m_min_func_freq_subsumption_index && get_value_range(f) > 0)
|
||||
targets.push_back(f);
|
||||
}
|
||||
|
||||
|
||||
f_lt lt(*this);
|
||||
std::sort(targets.begin(), targets.end(), lt);
|
||||
|
||||
m_features.push_back(feature(F_GROUND));
|
||||
m_features.push_back(feature(F_NUM_POS_LITS));
|
||||
m_features.push_back(feature(F_NUM_NEG_LITS));
|
||||
m_features.push_back(feature(F_DEPTH));
|
||||
|
||||
ptr_vector<func_decl>::iterator it = targets.begin();
|
||||
ptr_vector<func_decl>::iterator end = targets.end();
|
||||
for (; it != end; ++it) {
|
||||
func_decl * f = *it;
|
||||
if (get_value_range(f, false) > 1)
|
||||
m_features.push_back(feature(f, false));
|
||||
if (get_value_range(f, true) > 1)
|
||||
m_features.push_back(feature(f, true));
|
||||
if (m_features.size() > m_params.m_max_subsumption_index_features)
|
||||
break;
|
||||
}
|
||||
|
||||
m_features.push_back(feature(F_CONST_COUNT));
|
||||
m_features.push_back(feature(F_SYM_COUNT));
|
||||
m_index = alloc(index, m_features.size(), to_feature_vector(*this));
|
||||
m_num_processed_clauses = 0;
|
||||
unsigned new_threshold = static_cast<unsigned>(m_opt_threshold * m_params.m_factor_subsumption_index_opt);
|
||||
if (new_threshold > m_opt_threshold)
|
||||
m_opt_threshold = new_threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Insert cls into the indexes used for forward/backward subsumption.
|
||||
*/
|
||||
void subsumption::insert(clause * cls) {
|
||||
TRACE("subsumption", tout << "adding clause to subsumption index: " << cls << "\n"; cls->display(tout, m_manager); tout << "\n";);
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
if (num_lits > 1 || m_params.m_backward_subsumption) {
|
||||
m_index->insert(cls);
|
||||
SASSERT(m_index->contains(cls));
|
||||
m_num_processed_clauses++;
|
||||
if (m_num_processed_clauses > m_opt_threshold)
|
||||
optimize_feature_index();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Remove cls from the indexes used for forward/backward subsumption.
|
||||
*/
|
||||
void subsumption::erase(clause * cls) {
|
||||
TRACE("subsumption", tout << "removing clause from subsumption index:" << cls << "\n"; cls->display(tout, m_manager); tout << "\n";
|
||||
tout << "num lits.: " << cls->get_num_literals() << ", backward_sub: " << m_params.m_backward_subsumption << "\n";);
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
if (num_lits > 1 || m_params.m_backward_subsumption)
|
||||
m_index->erase(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Reset the indexes used for forward/backward subsumption.
|
||||
*/
|
||||
void subsumption::reset() {
|
||||
if (m_index)
|
||||
m_index->reset();
|
||||
m_num_processed_clauses = 0;
|
||||
m_opt_threshold = m_params.m_initial_subsumption_index_opt;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return an unit clause C in the index that subsumes cls.
|
||||
Return 0 if such clause does not exist.
|
||||
*/
|
||||
clause * subsumption::unit_forward(clause * cls) {
|
||||
if (!m_asserted_literals.has_literals())
|
||||
return 0;
|
||||
m_asserted_literals.reserve_vars(cls->get_num_vars());
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l = cls->get_literal(i);
|
||||
clause * subsumer = m_asserted_literals.gen(l);
|
||||
if (subsumer)
|
||||
return subsumer;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct non_unit_subsumption_visitor {
|
||||
subsumption & m_owner;
|
||||
clause * m_new_clause;
|
||||
clause * m_subsumer;
|
||||
non_unit_subsumption_visitor(subsumption & owner, clause * new_clause):
|
||||
m_owner(owner),
|
||||
m_new_clause(new_clause),
|
||||
m_subsumer(0) {
|
||||
}
|
||||
bool operator()(clause * candidate) {
|
||||
TRACE("subsumption_index", tout << "considering candidate:\n"; candidate->display(tout, m_owner.get_manager()); tout << "\n";);
|
||||
if (candidate->get_num_literals() > 1 && m_owner(candidate, m_new_clause)) {
|
||||
m_subsumer = candidate;
|
||||
return false; // stop subsumer was found
|
||||
}
|
||||
return true; // continue;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Return a non unit clause C in the index that subsumes cls.
|
||||
Return 0 if such clause does not exist.
|
||||
*/
|
||||
clause * subsumption::non_unit_forward(clause * cls) {
|
||||
non_unit_subsumption_visitor visitor(*this, cls);
|
||||
m_index->visit(cls, visitor, true);
|
||||
return visitor.m_subsumer;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return a unit equality clause (= s t) that (eq) subsumes cls.
|
||||
That is, cls contains a literal (= u[s'] u[t']) and there is
|
||||
a substitution sigma s.t. sigma(s) = s' and sigma(t) = t'.
|
||||
Return 0 if such clause does not exist.
|
||||
*/
|
||||
clause * subsumption::eq_subsumption(clause * cls) {
|
||||
if (!m_asserted_literals.has_pos_literals())
|
||||
return 0;
|
||||
m_asserted_literals.reserve_vars(cls->get_num_vars());
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l = cls->get_literal(i);
|
||||
expr * atom = l.atom();
|
||||
if (!l.sign() && m_manager.is_eq(atom)) {
|
||||
expr * lhs = to_app(atom)->get_arg(0);
|
||||
expr * rhs = to_app(atom)->get_arg(1);
|
||||
clause * subsumer = m_asserted_literals.subsumes(lhs, rhs);
|
||||
if (subsumer) {
|
||||
TRACE("eq_subsumption", tout << "equality subsumption:\n"; cls->display(tout, m_manager);
|
||||
tout << "\nis subsumed by:\n"; subsumer->display(tout, m_manager); tout << "\n";);
|
||||
return subsumer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return a clause C in the index (i.e., insert(C) was invoked) that subsumes cls.
|
||||
Return 0 if such clause does not exist.
|
||||
*/
|
||||
clause * subsumption::forward(clause * cls) {
|
||||
TRACE("subsumption", tout << "trying forward subsumption:\n"; cls->display(tout, m_manager); tout << "\n";);
|
||||
clause * subsumer = unit_forward(cls);
|
||||
if (subsumer)
|
||||
return subsumer;
|
||||
subsumer = non_unit_forward(cls);
|
||||
if (subsumer)
|
||||
return subsumer;
|
||||
if (m_params.m_equality_subsumption)
|
||||
return eq_subsumption(cls);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct backward_subsumption_visitor {
|
||||
subsumption & m_owner;
|
||||
clause * m_new_clause;
|
||||
ptr_buffer<clause> & m_result;
|
||||
backward_subsumption_visitor(subsumption & owner, clause * new_clause, ptr_buffer<clause> & result):
|
||||
m_owner(owner),
|
||||
m_new_clause(new_clause),
|
||||
m_result(result) {
|
||||
}
|
||||
|
||||
bool operator()(clause * candidate) {
|
||||
if (m_owner(m_new_clause, candidate))
|
||||
m_result.push_back(candidate);
|
||||
return true; // always continue in backward subsumption
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Store in result the set of clauses in the index that are subsumes by cls.
|
||||
*/
|
||||
void subsumption::backward(clause * cls, ptr_buffer<clause> & result) {
|
||||
if (m_params.m_backward_subsumption) {
|
||||
backward_subsumption_visitor visitor(*this, cls, result);
|
||||
m_index->visit(cls, visitor, false);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,156 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_subsumption.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-13.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_SUBSUMPTION_H_
|
||||
#define _SPC_SUBSUMPTION_H_
|
||||
|
||||
#include"spc_asserted_literals.h"
|
||||
#include"matcher.h"
|
||||
#include"fvi.h"
|
||||
#include"spc_params.h"
|
||||
#include"obj_hashtable.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
class subsumption {
|
||||
ast_manager & m_manager;
|
||||
spc_params & m_params;
|
||||
asserted_literals & m_asserted_literals;
|
||||
substitution m_subst;
|
||||
matcher m_matcher;
|
||||
|
||||
// A pair representing the association between l1 and l2 where
|
||||
// first is the position of l1 in lits1 and second the position of l2 in
|
||||
// lits2.
|
||||
typedef std::pair<unsigned, unsigned> assoc;
|
||||
typedef vector<assoc> stack;
|
||||
stack m_stack;
|
||||
|
||||
template<bool ResetSubst>
|
||||
bool match_literal(literal const & l1, literal const & l2);
|
||||
|
||||
bool can_subsume(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2);
|
||||
bool quick_check(clause * cls1, clause * cls2);
|
||||
bool subsumes_core(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2);
|
||||
bool subsumes_core(literal const & l1, unsigned num_lits2, literal * lits2);
|
||||
bool ground_subsumes_core(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2);
|
||||
|
||||
enum feature_kind {
|
||||
F_GROUND,
|
||||
F_NUM_POS_LITS,
|
||||
F_NUM_NEG_LITS,
|
||||
F_DEPTH,
|
||||
F_CONST_COUNT,
|
||||
F_SYM_COUNT,
|
||||
F_NUM_NEG_FUNCS,
|
||||
F_NUM_POS_FUNCS
|
||||
};
|
||||
|
||||
struct feature {
|
||||
feature_kind m_kind;
|
||||
func_decl * m_decl;
|
||||
feature(feature_kind k = F_GROUND):m_kind(k) {}
|
||||
feature(func_decl * decl, bool neg):m_kind(neg ? F_NUM_NEG_FUNCS : F_NUM_POS_FUNCS), m_decl(decl) {}
|
||||
};
|
||||
|
||||
vector<feature> m_features;
|
||||
|
||||
bit_vector m_found_decl_set;
|
||||
func_decl_ref_vector m_found_decls; // domain of m_found_decl_set;
|
||||
|
||||
/**
|
||||
\brief Return true if the function symbol is considered for feature vector indexing.
|
||||
*/
|
||||
bool fvi_candidate(func_decl * f) {
|
||||
return f->get_family_id() == null_family_id || f->get_arity() > 0;
|
||||
}
|
||||
|
||||
typedef obj_hashtable<func_decl> found_func_decl_set;
|
||||
found_func_decl_set m_cls_found_decl_set; // temporary set used to track the func_decl's found in a clause
|
||||
ptr_vector<func_decl> m_cls_found_decls;
|
||||
|
||||
bool mark_func_decl(func_decl * f);
|
||||
|
||||
typedef obj_map<func_decl, unsigned> decl2nat;
|
||||
bool m_refining_index; // if true keep collecting data to refine index.
|
||||
decl2nat m_f_count[2]; // temporary field used to track the num. of occurs. of function symbols in neg/pos literals.
|
||||
decl2nat m_f_min[2];
|
||||
decl2nat m_f_max[2];
|
||||
decl2nat m_f_freq;
|
||||
|
||||
void inc_f_count(func_decl * f, bool neg);
|
||||
void update_min_max(func_decl * f);
|
||||
void update_neg_pos_func_counts(clause * cls);
|
||||
|
||||
void compute_features(clause * cls, unsigned * fvector);
|
||||
|
||||
struct to_feature_vector;
|
||||
friend struct to_feature_vector;
|
||||
|
||||
struct to_feature_vector {
|
||||
subsumption & m_owner;
|
||||
to_feature_vector(subsumption & o):m_owner(o) {}
|
||||
void operator()(clause * cls, unsigned * fvector) {
|
||||
m_owner.compute_features(cls, fvector);
|
||||
}
|
||||
};
|
||||
|
||||
typedef fvi<clause, to_feature_vector, obj_ptr_hash<clause>, ptr_eq<clause> > index;
|
||||
index * m_index;
|
||||
unsigned m_num_processed_clauses;
|
||||
unsigned m_opt_threshold;
|
||||
|
||||
void init_indexes();
|
||||
|
||||
struct f_lt;
|
||||
friend struct f_lt;
|
||||
|
||||
unsigned get_value_range(func_decl * f, bool neg) const;
|
||||
unsigned get_value_range(func_decl * f) const;
|
||||
|
||||
struct f_lt {
|
||||
subsumption & m_owner;
|
||||
f_lt(subsumption & o):m_owner(o) {}
|
||||
bool operator()(func_decl * f1, func_decl * f2) const;
|
||||
};
|
||||
|
||||
void optimize_feature_index();
|
||||
|
||||
clause * unit_forward(clause * cls);
|
||||
clause * non_unit_forward(clause * cls);
|
||||
clause * eq_subsumption(expr * lhs, expr * rhs);
|
||||
clause * eq_subsumption(clause * cls);
|
||||
|
||||
public:
|
||||
subsumption(ast_manager & m, asserted_literals & al, spc_params & params);
|
||||
~subsumption();
|
||||
|
||||
bool operator()(clause * cls1, clause * cls2);
|
||||
void insert(clause * cls);
|
||||
void erase(clause * cls);
|
||||
void reset();
|
||||
clause * forward(clause * cls);
|
||||
void backward(clause * cls, ptr_buffer<clause> & result);
|
||||
|
||||
ast_manager & get_manager() { return m_manager; }
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SPC_SUBSUMPTION_H_ */
|
||||
|
|
@ -1,531 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_superposition.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-15.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_superposition.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
superposition::superposition(ast_manager & m, order & o, statistics & s):
|
||||
m_manager(m),
|
||||
m_order(o),
|
||||
m_stats(s),
|
||||
m_subst(m),
|
||||
m_p(m),
|
||||
m_r(m),
|
||||
m_normalize_vars(m),
|
||||
m_spc_fid(m.get_family_id("spc")) {
|
||||
m_subst.reserve_offsets(3);
|
||||
m_deltas[0] = 0;
|
||||
m_deltas[1] = 0;
|
||||
}
|
||||
|
||||
superposition::~superposition() {
|
||||
}
|
||||
|
||||
void superposition::insert_p(clause * cls, expr * lhs, unsigned i) {
|
||||
m_p.insert(lhs);
|
||||
m_subst.reserve_vars(m_p.get_approx_num_regs());
|
||||
m_p2clause_set.insert(clause_pos_pair(cls, i), lhs);
|
||||
}
|
||||
|
||||
void superposition::insert_p(clause * cls, literal & l, unsigned i) {
|
||||
l.set_p_indexed(true);
|
||||
expr * atom = l.atom();
|
||||
if (!m_manager.is_eq(atom))
|
||||
return;
|
||||
if (l.is_oriented())
|
||||
insert_p(cls, l.is_left() ? l.lhs() : l.rhs(), i);
|
||||
else {
|
||||
insert_p(cls, l.lhs(), i);
|
||||
insert_p(cls, l.rhs(), i);
|
||||
}
|
||||
}
|
||||
|
||||
void superposition::insert_r(clause * cls, expr * n, unsigned i, bool lhs) {
|
||||
if (is_app(n)) {
|
||||
unsigned idx = (i << 1) | static_cast<unsigned>(lhs);
|
||||
|
||||
clause_pos_pair new_pair(cls, idx);
|
||||
SASSERT(m_todo.empty());
|
||||
m_todo.push_back(to_app(n));
|
||||
while (!m_todo.empty()) {
|
||||
app * n = m_todo.back();
|
||||
m_todo.pop_back();
|
||||
clause_pos_set * s = m_r2clause_set.get_parents(n);
|
||||
if (s == 0 || !s->contains(new_pair)) {
|
||||
m_r.insert(n);
|
||||
m_r2clause_set.insert(new_pair, n);
|
||||
unsigned num_args = n->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * c = n->get_arg(i);
|
||||
if (is_app(c))
|
||||
m_todo.push_back(to_app(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void superposition::insert_r(clause * cls, literal & l, unsigned i) {
|
||||
l.set_r_indexed(true);
|
||||
expr * atom = l.atom();
|
||||
if (m_manager.is_eq(atom)) {
|
||||
expr * lhs = l.lhs();
|
||||
expr * rhs = l.rhs();
|
||||
if (l.is_oriented()) {
|
||||
bool left = true;
|
||||
if (!l.is_left()) {
|
||||
left = false;
|
||||
std::swap(lhs, rhs);
|
||||
}
|
||||
insert_r(cls, lhs, i, left);
|
||||
}
|
||||
else {
|
||||
insert_r(cls, lhs, i, true);
|
||||
insert_r(cls, rhs, i, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
insert_r(cls, atom, i, false);
|
||||
}
|
||||
m_subst.reserve_vars(m_r.get_approx_num_regs());
|
||||
}
|
||||
|
||||
void superposition::insert(clause * cls) {
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal & l = cls->get_literal(i);
|
||||
if (l.is_p_indexed() || cls->is_eligible_for_paramodulation(m_order, l)) {
|
||||
if (!l.sign() && m_manager.is_eq(l.atom()))
|
||||
insert_p(cls, l, i);
|
||||
insert_r(cls, l, i);
|
||||
}
|
||||
else if (l.is_r_indexed() || cls->is_eligible_for_resolution(m_order, l)) {
|
||||
insert_r(cls, l, i);
|
||||
}
|
||||
}
|
||||
TRACE("superposition_detail",
|
||||
tout << "adding clause: "; cls->display(tout, m_manager); tout << "\n";
|
||||
tout << "p index:\n";
|
||||
m_p.display(tout);
|
||||
tout << "r index:\n";
|
||||
m_r.display(tout););
|
||||
}
|
||||
|
||||
void superposition::erase_p(clause * cls, expr * lhs, unsigned i) {
|
||||
m_p2clause_set.erase(clause_pos_pair(cls, i), lhs);
|
||||
if (m_p2clause_set.empty(lhs))
|
||||
m_p.erase(lhs);
|
||||
}
|
||||
|
||||
void superposition::erase_p(clause * cls, literal & l, unsigned i) {
|
||||
expr * atom = l.atom();
|
||||
if (!m_manager.is_eq(atom))
|
||||
return;
|
||||
if (l.is_oriented())
|
||||
erase_p(cls, l.is_left() ? l.lhs() : l.rhs(), i);
|
||||
else {
|
||||
erase_p(cls, l.lhs(), i);
|
||||
erase_p(cls, l.rhs(), i);
|
||||
}
|
||||
}
|
||||
|
||||
void superposition::erase_r(clause * cls, literal & l, unsigned i) {
|
||||
clause_pos_pair pair(cls, i);
|
||||
|
||||
expr * atom = l.atom();
|
||||
SASSERT(is_app(atom));
|
||||
SASSERT(m_todo.empty());
|
||||
m_todo.push_back(to_app(atom));
|
||||
|
||||
while (!m_todo.empty()) {
|
||||
app * n = m_todo.back();
|
||||
m_todo.pop_back();
|
||||
switch (m_r2clause_set.erase(pair, n)) {
|
||||
case 0: // pair is not a parent of n
|
||||
break;
|
||||
case 1: // pair is the last parent of n
|
||||
m_r.erase(n);
|
||||
default:
|
||||
unsigned num_args = n->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * c = n->get_arg(i);
|
||||
if (is_app(c))
|
||||
m_todo.push_back(to_app(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void superposition::erase(clause * cls) {
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal & l = cls->get_literal(i);
|
||||
if (l.is_p_indexed())
|
||||
erase_p(cls, l, i);
|
||||
if (l.is_r_indexed())
|
||||
erase_r(cls, l, i);
|
||||
}
|
||||
}
|
||||
|
||||
void superposition::reset() {
|
||||
m_p.reset();
|
||||
m_p2clause_set.reset();
|
||||
m_r.reset();
|
||||
m_r2clause_set.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Copy to result the literals of s except literal at position idx. Apply the substitution m_subst,
|
||||
assuming that the variables of s are in the variable bank offset. The deltas for each bank are
|
||||
stored in m_deltas.
|
||||
*/
|
||||
void superposition::copy_literals(clause * s, unsigned idx, unsigned offset, literal_buffer & result) {
|
||||
unsigned num_lits = s->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++)
|
||||
if (i != idx) {
|
||||
literal const & l = s->get_literal(i);
|
||||
expr_ref new_atom(m_manager);
|
||||
m_subst.apply(2, m_deltas, expr_offset(l.atom(), offset), new_atom);
|
||||
TRACE("superposition_copy", tout << "i: " << i << ", idx: " << idx << ", offset: " << offset << "\natom:\n";
|
||||
tout << mk_pp(l.atom(), m_manager) << "\nnew_atom:\n" << mk_pp(new_atom, m_manager) << "\n";);
|
||||
result.push_back(literal(new_atom, l.sign()));
|
||||
}
|
||||
}
|
||||
|
||||
void superposition::normalize_literals(unsigned num_lits, literal * lits, literal_buffer & result) {
|
||||
m_normalize_vars.reset();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal const & l = lits[i];
|
||||
result.push_back(literal(m_normalize_vars(l.atom()), l.sign()));
|
||||
}
|
||||
}
|
||||
|
||||
void superposition::mk_sp_clause(unsigned num_lits, literal * lits, justification * p1, justification * p2) {
|
||||
literal_buffer new_literals(m_manager);
|
||||
normalize_literals(num_lits, lits, new_literals);
|
||||
justification * js = mk_superposition_justification(m_manager, m_spc_fid, p1, p2,
|
||||
new_literals.size(), new_literals.c_ptr(),
|
||||
m_normalize_vars.get_num_vars(), m_normalize_vars.get_vars());
|
||||
clause * new_cls = clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), js, 0);
|
||||
m_new_clauses->push_back(new_cls);
|
||||
TRACE("superposition", tout << "new superposition clause:\n"; new_cls->display(tout, m_manager); tout << "\n";);
|
||||
m_stats.m_num_superposition++;
|
||||
}
|
||||
|
||||
void superposition::mk_res_clause(unsigned num_lits, literal * lits, justification * p1, justification * p2) {
|
||||
literal_buffer new_literals(m_manager);
|
||||
normalize_literals(num_lits, lits, new_literals);
|
||||
justification * js = mk_resolution_justification(m_manager, m_spc_fid, p1, p2,
|
||||
new_literals.size(), new_literals.c_ptr(),
|
||||
m_normalize_vars.get_num_vars(), m_normalize_vars.get_vars());
|
||||
clause * new_cls = clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), js, 0);
|
||||
m_new_clauses->push_back(new_cls);
|
||||
TRACE("superposition", tout << "new resolution clause:\n"; new_cls->display(tout, m_manager); tout << "\n";);
|
||||
m_stats.m_num_resolution++;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Given the equation (= lhs rhs) of the clause being
|
||||
added, try to apply resolution where the clause being added
|
||||
is the main clause in the superposition rule.
|
||||
*/
|
||||
void superposition::try_superposition_main(expr * lhs, expr * rhs) {
|
||||
m_lhs = lhs;
|
||||
m_rhs = rhs;
|
||||
m_subst.reset_subst();
|
||||
TRACE("spc_superposition", tout << "try_superposition_main, lhs:\n" << mk_pp(m_lhs, m_manager) << "\nrhs:\n" << mk_pp(m_rhs, m_manager) << "\n";
|
||||
tout << "substitution:\n"; m_subst.display(tout););
|
||||
r_visitor v(*this, m_subst);
|
||||
m_r.unify(lhs, v);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Try to apply superposition rule using the clause
|
||||
being added (m_clause) as main clause, and its literal m_lit
|
||||
as the equation.
|
||||
*/
|
||||
void superposition::try_superposition_main() {
|
||||
expr * lhs = m_lit->lhs();
|
||||
expr * rhs = m_lit->rhs();
|
||||
TRACE("spc_superposition", tout << "trying superposition:\n" << mk_pp(lhs, m_manager) << "\n" << mk_pp(rhs, m_manager) << "\nis_oriented: " << m_lit->is_oriented() << "\n";);
|
||||
if (m_lit->is_oriented()) {
|
||||
if (!m_lit->is_left())
|
||||
std::swap(lhs, rhs);
|
||||
try_superposition_main(lhs, rhs);
|
||||
}
|
||||
else {
|
||||
try_superposition_main(lhs, rhs);
|
||||
try_superposition_main(rhs, lhs);
|
||||
}
|
||||
}
|
||||
|
||||
void superposition::found_r(expr * r) {
|
||||
TRACE("spc_superposition", tout << "found_r:\n" << mk_pp(r, m_manager) << "\n";
|
||||
tout << "substitution:\n"; m_subst.display(tout););
|
||||
if (m_r2clause_set.empty(r))
|
||||
return;
|
||||
TRACE("spc_superposition", tout << "r2clause is not empty.\n";);
|
||||
if (!m_lit->is_oriented() && m_order.greater(m_rhs, m_lhs, &m_subst))
|
||||
return;
|
||||
TRACE("spc_superposition", tout << "order restriction was met.\n";);
|
||||
if (!m_clause->is_eligible_for_paramodulation(m_order, *m_lit, 0, &m_subst))
|
||||
return;
|
||||
TRACE("spc_superposition", tout << "literal is eligible for paramodulation.\n";);
|
||||
r2clause_set::iterator it = m_r2clause_set.begin(r);
|
||||
r2clause_set::iterator end = m_r2clause_set.end(r);
|
||||
for (; it != end; ++it) {
|
||||
clause_pos_pair & p = *it;
|
||||
clause * aux_cls = p.first;
|
||||
unsigned aux_idx = p.second >> 1;
|
||||
//
|
||||
// The following optimization is incorrect (if statement).
|
||||
// For example, it prevents the Z3 from proving the trivial benchmark
|
||||
// c = X,
|
||||
// a != b
|
||||
// using the order a < b < c
|
||||
//
|
||||
// To prove, this example we need to generate the clause Y = X by applying superposition of c = X on itself.
|
||||
// We can see that by renaming the first clause to c = Y, and then, substituting c in the original by Y.
|
||||
//
|
||||
// Actually, this optimization is correct when the set of variables in m_lhs is a superset of the set of variables in m_rhs,
|
||||
// because in this case, the new literal will be equivalent to true. In the example above, this is not the case,
|
||||
// since m_lhs does not contain any variable, and m_rhs contains one.
|
||||
//
|
||||
|
||||
//
|
||||
// if (r == m_lhs && m_clause == aux_cls && m_idx == aux_idx)
|
||||
// continue;
|
||||
//
|
||||
bool in_lhs = (p.second & 1) != 0;
|
||||
TRACE("spc_superposition", tout << "aux_cls:\n"; aux_cls->display(tout, m_manager); tout << "\naux_idx: " << aux_cls << ", in_lhs: " << in_lhs << "\n";);
|
||||
literal & aux_lit = aux_cls->get_literal(aux_idx);
|
||||
if (!aux_cls->is_eligible_for_resolution(m_order, aux_lit, 1, &m_subst))
|
||||
continue;
|
||||
literal_buffer new_literals(m_manager);
|
||||
m_subst.reset_cache();
|
||||
if (m_manager.is_eq(aux_lit.atom())) {
|
||||
expr * lhs = aux_lit.lhs();
|
||||
expr * rhs = aux_lit.rhs();
|
||||
TRACE("spc_superposition", tout << "aux_lit lhs:\n" << mk_pp(lhs, m_manager) << "\nrhs:\n" << mk_pp(rhs, m_manager) << "\n";);
|
||||
if (!in_lhs)
|
||||
std::swap(lhs, rhs);
|
||||
if (!aux_lit.is_oriented() && m_order.greater(rhs, lhs, 1, &m_subst)) {
|
||||
TRACE("spc_superposition", tout << "failed order constraint.\n";);
|
||||
continue;
|
||||
}
|
||||
expr_ref new_lhs(m_manager), new_rhs(m_manager);
|
||||
m_subst.apply(2, m_deltas, expr_offset(lhs, 1), expr_offset(r, 1), expr_offset(m_rhs, 0), new_lhs);
|
||||
m_subst.apply(2, m_deltas, expr_offset(rhs, 1), new_rhs);
|
||||
TRACE("spc_superposition", tout << "aux_lit new_lhs:\n" << mk_pp(new_lhs, m_manager) << "\nnew_rhs:\n" << mk_pp(new_rhs, m_manager) << "\n";);
|
||||
expr * new_eq = m_manager.mk_eq(new_lhs, new_rhs);
|
||||
new_literals.push_back(literal(new_eq, aux_lit.sign()));
|
||||
}
|
||||
else {
|
||||
expr_ref new_atom(m_manager);
|
||||
m_subst.apply(2, m_deltas, expr_offset(aux_lit.atom(), 1), new_atom);
|
||||
new_literals.push_back(literal(new_atom, aux_lit.sign()));
|
||||
}
|
||||
copy_literals(m_clause, m_idx, 0, new_literals);
|
||||
copy_literals(aux_cls, aux_idx, 1, new_literals);
|
||||
TRACE("superposition", tout << "found r target: " << mk_pp(r, m_manager) << " for \n" <<
|
||||
mk_pp(m_lhs, m_manager) << "\nmain clause: "; m_clause->display(tout, m_manager);
|
||||
tout << "\naux clause: "; aux_cls->display(tout, m_manager); tout << "\nat pos: " <<
|
||||
aux_idx << "\n";);
|
||||
mk_sp_clause(new_literals.size(), new_literals.c_ptr(), m_clause->get_justification(), aux_cls->get_justification());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Try to apply superposition rule using the clause
|
||||
being added (m_clause) as the aux clause, and its literal m_lit
|
||||
as the target.
|
||||
*/
|
||||
void superposition::try_superposition_aux() {
|
||||
TRACE("superposition_aux", tout << "superposition aux:\n"; m_clause->display(tout, m_manager);
|
||||
tout << "\nusing literal: " << m_idx << "\n";);
|
||||
if (m_manager.is_eq(m_lit->atom())) {
|
||||
expr * lhs = m_lit->lhs();
|
||||
expr * rhs = m_lit->rhs();
|
||||
if (m_lit->is_oriented()) {
|
||||
if (!m_lit->is_left())
|
||||
std::swap(lhs, rhs);
|
||||
try_superposition_aux(lhs, rhs);
|
||||
}
|
||||
else {
|
||||
try_superposition_aux(lhs, rhs);
|
||||
try_superposition_aux(rhs, lhs);
|
||||
}
|
||||
}
|
||||
else {
|
||||
try_superposition_aux(m_lit->atom(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Use the clause being added as the auxiliary clause in the superposition rule.
|
||||
*/
|
||||
void superposition::try_superposition_aux(expr * lhs, expr * rhs) {
|
||||
TRACE("superposition_aux", tout << "try_superposition_aux\n" << mk_pp(lhs, m_manager) << "\n" << mk_pp(rhs, m_manager) << "\n";);
|
||||
if (is_var(lhs))
|
||||
return;
|
||||
m_lhs = lhs;
|
||||
m_rhs = rhs;
|
||||
SASSERT(m_todo.empty());
|
||||
m_todo.push_back(to_app(lhs));
|
||||
while (!m_todo.empty()) {
|
||||
m_target = m_todo.back();
|
||||
m_todo.pop_back();
|
||||
m_subst.reset_subst();
|
||||
p_visitor v(*this, m_subst);
|
||||
TRACE("superposition_aux", tout << "trying to find unifier for:\n" << mk_pp(m_target, m_manager) << "\n";);
|
||||
m_p.unify(m_target, v);
|
||||
unsigned j = m_target->get_num_args();
|
||||
while (j > 0) {
|
||||
--j;
|
||||
expr * arg = m_target->get_arg(j);
|
||||
if (is_app(arg))
|
||||
m_todo.push_back(to_app(arg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void superposition::found_p(expr * p) {
|
||||
TRACE("superposition_found_p", tout << "found p:\n" << mk_pp(p, m_manager) << "\n";);
|
||||
if (m_p2clause_set.empty(p)) {
|
||||
TRACE("superposition_found_p", tout << "clause set is empty.\n";);
|
||||
return;
|
||||
}
|
||||
if (m_rhs && !m_lit->is_oriented() && m_order.greater(m_rhs, m_lhs, &m_subst)) {
|
||||
TRACE("superposition_found_p", tout << "aux clause failed not rhs > lhs constraint.\n";);
|
||||
return;
|
||||
}
|
||||
if (!m_clause->is_eligible_for_resolution(m_order, *m_lit, 0, &m_subst)) {
|
||||
TRACE("superposition_found_p", tout << "aux literal is not eligible for resolution.\n";);
|
||||
return;
|
||||
}
|
||||
p2clause_set::iterator it = m_p2clause_set.begin(p);
|
||||
p2clause_set::iterator end = m_p2clause_set.end(p);
|
||||
for (; it != end; ++it) {
|
||||
clause_pos_pair & pair = *it;
|
||||
clause * main_cls = pair.first;
|
||||
TRACE("superposition_found_p", tout << "p clause:\n"; main_cls->display(tout, m_manager); tout << "\n";);
|
||||
unsigned lit_idx = pair.second;
|
||||
if (p == m_lhs && m_clause == main_cls && m_idx == lit_idx)
|
||||
continue;
|
||||
literal const & main_lit = main_cls->get_literal(lit_idx);
|
||||
SASSERT(m_manager.is_eq(main_lit.atom()));
|
||||
expr * lhs = main_lit.lhs();
|
||||
expr * rhs = main_lit.rhs();
|
||||
if (rhs == p)
|
||||
std::swap(lhs, rhs);
|
||||
SASSERT(lhs == p);
|
||||
TRACE("superposition_found_p", tout << "lhs: " << mk_pp(lhs, m_manager) << "\nrhs: " << mk_pp(rhs, m_manager) << "\n";);
|
||||
if (!main_lit.is_oriented() && m_order.greater(rhs, lhs, 1, &m_subst))
|
||||
continue;
|
||||
if (!main_cls->is_eligible_for_paramodulation(m_order, main_lit, 1, &m_subst))
|
||||
continue;
|
||||
literal_buffer new_literals(m_manager);
|
||||
m_subst.reset_cache();
|
||||
TRACE("superposition_found_p", tout << "creating new_lhs\n";);
|
||||
expr_ref new_lhs(m_manager);
|
||||
m_subst.apply(2, m_deltas, expr_offset(m_lhs, 0), expr_offset(m_target, 0), expr_offset(rhs, 1), new_lhs);
|
||||
// FIX: m_subst.reset_cache();
|
||||
TRACE("superposition_found_p", tout << "new_lhs: " << mk_pp(new_lhs, m_manager) << "\n";
|
||||
m_subst.display(tout););
|
||||
expr * new_atom = 0;
|
||||
if (m_rhs) {
|
||||
TRACE("superposition_found_p", tout << "creating new_rhs\n";);
|
||||
expr_ref new_rhs(m_manager);
|
||||
m_subst.apply(2, m_deltas, expr_offset(m_rhs, 0), new_rhs);
|
||||
TRACE("superposition_found_p", tout << "new_rhs: " << mk_pp(new_rhs, m_manager) << "\n";);
|
||||
new_atom = m_manager.mk_eq(new_lhs, new_rhs);
|
||||
}
|
||||
else
|
||||
new_atom = new_lhs;
|
||||
TRACE("superposition_found_p", tout << "new_atom: " << mk_pp(new_atom, m_manager) << "\n"; m_subst.display(tout););
|
||||
new_literals.push_back(literal(new_atom, m_lit->sign()));
|
||||
TRACE("superposition_found_p", tout << "copying literals\n";);
|
||||
copy_literals(main_cls, lit_idx, 1, new_literals);
|
||||
copy_literals(m_clause, m_idx, 0, new_literals);
|
||||
TRACE("superposition", tout << "found p target: " << mk_pp(p, m_manager) << " for \n" <<
|
||||
mk_pp(m_lhs, m_manager) << "\nmain clause: "; main_cls->display(tout, m_manager);
|
||||
tout << "\naux clause: "; m_clause->display(tout, m_manager); tout << "\n";);
|
||||
mk_sp_clause(new_literals.size(), new_literals.c_ptr(), main_cls->get_justification(), m_clause->get_justification());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Try to apply resolution rule using the clause being added (m_clause).
|
||||
*/
|
||||
void superposition::try_resolution() {
|
||||
m_subst.reset_subst();
|
||||
res_visitor v(*this, m_subst);
|
||||
m_r.unify(m_lit->atom(), v);
|
||||
}
|
||||
|
||||
void superposition::found_res(expr * r) {
|
||||
if (m_r2clause_set.empty(r))
|
||||
return;
|
||||
if (!m_clause->is_eligible_for_resolution(m_order, *m_lit, 0, &m_subst))
|
||||
return;
|
||||
r2clause_set::iterator it = m_r2clause_set.begin(r);
|
||||
r2clause_set::iterator end = m_r2clause_set.end(r);
|
||||
for (; it != end; ++it) {
|
||||
clause_pos_pair & pair = *it;
|
||||
clause * aux_cls = pair.first;
|
||||
unsigned aux_idx = pair.second >> 1;
|
||||
literal const & aux_lit = aux_cls->get_literal(aux_idx);
|
||||
if (aux_lit.sign() == m_lit->sign())
|
||||
continue;
|
||||
if (aux_lit.atom() != r)
|
||||
continue;
|
||||
if (!aux_cls->is_eligible_for_resolution(m_order, aux_lit, 1, &m_subst))
|
||||
continue;
|
||||
literal_buffer new_literals(m_manager);
|
||||
m_subst.reset_cache();
|
||||
copy_literals(m_clause, m_idx, 0, new_literals);
|
||||
copy_literals(aux_cls, aux_idx, 1, new_literals);
|
||||
mk_res_clause(new_literals.size(), new_literals.c_ptr(), m_clause->get_justification(), aux_cls->get_justification());
|
||||
}
|
||||
}
|
||||
|
||||
void superposition::operator()(clause * cls, ptr_vector<clause> & new_clauses) {
|
||||
m_subst.reserve_vars(cls->get_num_vars());
|
||||
m_clause = cls;
|
||||
m_new_clauses = &new_clauses;
|
||||
SASSERT(m_deltas[0] == 0);
|
||||
m_deltas[1] = m_clause->get_num_vars();
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (m_idx = 0; m_idx < num_lits; m_idx++) {
|
||||
m_lit = &(cls->get_literal(m_idx));
|
||||
bool is_eq = m_manager.is_eq(m_lit->atom());
|
||||
if (!m_lit->sign() && m_lit->is_p_indexed() && is_eq)
|
||||
try_superposition_main();
|
||||
if (m_lit->is_r_indexed()) {
|
||||
try_superposition_aux();
|
||||
if (!is_eq)
|
||||
try_resolution();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_superposition.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-15.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_SUPERPOSITION_H_
|
||||
#define _SPC_SUPERPOSITION_H_
|
||||
|
||||
#include"spc_clause.h"
|
||||
#include"spc_clause_pos_set.h"
|
||||
#include"substitution_tree.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"sparse_use_list.h"
|
||||
#include"normalize_vars.h"
|
||||
#include"spc_statistics.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Functor for applying the superposition right/left rules.
|
||||
|
||||
- Superposition Left
|
||||
s = t or S, u != v or R
|
||||
==>
|
||||
sigma(u[p<-t] != v or S or R)
|
||||
|
||||
sigma is the mgu(u|p, s)
|
||||
sigma(s) not greater than sigma(t)
|
||||
sigma(u) not greater than sigma(v)
|
||||
sigma(s = t) is eligible for paramodulation
|
||||
sigma(u != v) is eligible for resolution
|
||||
u|p is not a variable
|
||||
|
||||
|
||||
- Superposition Right
|
||||
s = t or S, u = v or R
|
||||
==>
|
||||
sigma(u[p<-t] != v or S or R)
|
||||
|
||||
Same restrictions of Superposition Left
|
||||
|
||||
This functor also applied binary resolution rule.
|
||||
|
||||
We say the left clause is the main clause in the superposition.
|
||||
*/
|
||||
class superposition {
|
||||
ast_manager & m_manager;
|
||||
order & m_order;
|
||||
statistics & m_stats;
|
||||
substitution m_subst;
|
||||
|
||||
// indexes for left clause
|
||||
substitution_tree m_p; // potential left hand sides for superposition
|
||||
typedef sparse_use_list<expr, svector<clause_pos_pair> > p2clause_set;
|
||||
p2clause_set m_p2clause_set;
|
||||
|
||||
void insert_p(clause * cls, expr * lhs, unsigned i);
|
||||
void insert_p(clause * cls, literal & l, unsigned i);
|
||||
|
||||
void erase_p(clause * cls, expr * lhs, unsigned i);
|
||||
void erase_p(clause * cls, literal & l, unsigned i);
|
||||
|
||||
// indexes for right clause
|
||||
substitution_tree m_r; // potential targets for superposition
|
||||
typedef sparse_use_list<expr, clause_pos_set> r2clause_set;
|
||||
r2clause_set m_r2clause_set;
|
||||
ptr_vector<app> m_todo;
|
||||
|
||||
void insert_r(clause * cls, expr * n, unsigned i, bool lhs);
|
||||
void insert_r(clause * cls, literal & l, unsigned i);
|
||||
void erase_r(clause * cls, literal & l, unsigned i);
|
||||
|
||||
normalize_vars m_normalize_vars;
|
||||
|
||||
// temporary fields...
|
||||
ptr_vector<clause> * m_new_clauses;
|
||||
clause * m_clause;
|
||||
literal * m_lit;
|
||||
expr * m_lhs;
|
||||
expr * m_rhs;
|
||||
app * m_target;
|
||||
unsigned m_idx;
|
||||
unsigned m_deltas[2];
|
||||
family_id m_spc_fid;
|
||||
|
||||
void normalize_literals(unsigned num_lits, literal * lits, literal_buffer & result);
|
||||
void copy_literals(clause * s, unsigned idx, unsigned offset, literal_buffer & result);
|
||||
void mk_sp_clause(unsigned num_lits, literal * lits, justification * p1, justification * p2);
|
||||
void mk_res_clause(unsigned num_lits, literal * lits, justification * p1, justification * p2);
|
||||
void try_superposition_main(expr * lhs, expr * rhs);
|
||||
void try_superposition_main();
|
||||
void found_r(expr * r);
|
||||
void try_superposition_aux(expr * lhs, expr * rhs);
|
||||
void try_superposition_aux();
|
||||
void found_p(expr * p);
|
||||
void try_resolution();
|
||||
void found_res(expr * r);
|
||||
|
||||
friend struct r_visitor;
|
||||
struct r_visitor : public st_visitor {
|
||||
superposition & m_owner;
|
||||
r_visitor(superposition & o, substitution & s):st_visitor(s), m_owner(o) {}
|
||||
virtual bool operator()(expr * e) { m_owner.found_r(e); return true; /* continue */ }
|
||||
};
|
||||
|
||||
friend struct p_visitor;
|
||||
struct p_visitor : public st_visitor {
|
||||
superposition & m_owner;
|
||||
p_visitor(superposition & o, substitution & s):st_visitor(s), m_owner(o) {}
|
||||
virtual bool operator()(expr * e) { m_owner.found_p(e); return true; /* continue */ }
|
||||
};
|
||||
|
||||
friend struct res_visitor;
|
||||
struct res_visitor : public st_visitor {
|
||||
superposition & m_owner;
|
||||
res_visitor(superposition & o, substitution & s):st_visitor(s), m_owner(o) {}
|
||||
virtual bool operator()(expr * e) { m_owner.found_res(e); return true; /* continue */ }
|
||||
};
|
||||
|
||||
public:
|
||||
superposition(ast_manager & m, order & o, statistics & stats);
|
||||
~superposition();
|
||||
|
||||
void insert(clause * cls);
|
||||
void erase(clause * cls);
|
||||
void reset();
|
||||
|
||||
void operator()(clause * cls, ptr_vector<clause> & new_clauses);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SPC_SUPERPOSITION_H_ */
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_unary_inference.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-14.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_unary_inference.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
unary_inference::unary_inference(ast_manager & m, order & ord):
|
||||
m_manager(m),
|
||||
m_order(ord),
|
||||
m_subst(m),
|
||||
m_unifier(m) {
|
||||
m_subst.reserve_offsets(1);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create the result clause. The literal at position j of \c cls in removed,
|
||||
and the substitution m_subst is applied to the resultant clause.
|
||||
*/
|
||||
clause * unary_inference::mk_result(clause * cls, unsigned j) {
|
||||
sbuffer<literal> new_literals;
|
||||
unsigned num = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (i != j) {
|
||||
literal const & l = cls->get_literal(i);
|
||||
expr_ref new_atom(m_manager);
|
||||
m_subst.apply(l.atom(), new_atom);
|
||||
new_literals.push_back(literal(new_atom, l.sign()));
|
||||
}
|
||||
}
|
||||
|
||||
justification * js = mk_justification(cls->get_justification(), new_literals.size(), new_literals.c_ptr());
|
||||
clause * new_cls = clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), js, cls->get_scope_lvl());
|
||||
return new_cls;
|
||||
}
|
||||
|
||||
};
|
|
@ -1,48 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_unary_inference.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-14.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPC_UNARY_INFERENCE_H_
|
||||
#define _SPC_UNARY_INFERENCE_H_
|
||||
|
||||
#include"spc_clause.h"
|
||||
#include"unifier.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
/**
|
||||
\brief Superclass for eq_resolution and factoring.
|
||||
*/
|
||||
class unary_inference {
|
||||
protected:
|
||||
ast_manager & m_manager;
|
||||
order & m_order;
|
||||
substitution m_subst;
|
||||
unifier m_unifier;
|
||||
|
||||
clause * mk_result(clause * cls, unsigned j);
|
||||
virtual justification * mk_justification(justification * parent, unsigned num_lits, literal * new_lits) = 0;
|
||||
public:
|
||||
unary_inference(ast_manager & m, order & ord);
|
||||
virtual ~unary_inference() {}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* _SPC_UNARY_INFERENCE_H_ */
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
splay_tree.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Splay trees
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-31.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPLAY_TREE_H_
|
||||
#define _SPLAY_TREE_H_
|
||||
|
||||
#include"util.h"
|
||||
#include"buffer.h"
|
||||
|
||||
template<typename Key, typename Compare>
|
||||
class splay_tree : private Compare {
|
||||
struct cell {
|
||||
Key m_key;
|
||||
cell * m_left;
|
||||
cell * m_right;
|
||||
|
||||
cell():m_left(0), m_right(0) {}
|
||||
cell(Key const & k, cell * l = 0, cell * r = 0):
|
||||
m_key(k), m_left(l), m_right(r) {}
|
||||
};
|
||||
|
||||
cell * m_root;
|
||||
int compare(Key const & k1, Key const & k2) const { return Compare::operator()(k1, k2); }
|
||||
cell * splay(cell * c, Key const & k);
|
||||
|
||||
void display_core(std::ostream & out, cell * c) const {
|
||||
if (c) {
|
||||
out << "(" << c->m_key << " ";
|
||||
display_core(out, c->m_left);
|
||||
out << " ";
|
||||
display_core(out, c->m_right);
|
||||
out << ")";
|
||||
}
|
||||
else
|
||||
out << "null";
|
||||
}
|
||||
|
||||
public:
|
||||
splay_tree(Compare const & c = Compare()):
|
||||
Compare(c),
|
||||
m_root(0) {}
|
||||
|
||||
~splay_tree() {
|
||||
m_root = 0;
|
||||
}
|
||||
|
||||
void insert(Key const & k);
|
||||
|
||||
bool find(Key const & k, Key & r) const;
|
||||
|
||||
void erase(Key const & k);
|
||||
|
||||
void reset();
|
||||
|
||||
bool empty() const { return m_root == 0; }
|
||||
|
||||
bool singleton() const { return m_root != 0 && m_root->m_left == 0 && m_root->m_right == 0; }
|
||||
|
||||
/**
|
||||
\brief Visit nodes in the splay tree in ascending order.
|
||||
The Visitor functor should provide the following methods:
|
||||
|
||||
- bool visit_left(Key const & k)
|
||||
return true if the left child should be visited
|
||||
|
||||
- bool visit_right(Key const & k)
|
||||
return true if the right child should be visited
|
||||
|
||||
- void operator()(Key const & k)
|
||||
do something with the key.
|
||||
*/
|
||||
template<typename Visitor>
|
||||
void visit_core(Visitor & v) {
|
||||
typedef std::pair<cell *, bool> entry;
|
||||
if (m_root) {
|
||||
buffer<entry> todo;
|
||||
todo.push_back(entry(m_root, false));
|
||||
while (!todo.empty()) {
|
||||
entry & curr = todo.back();
|
||||
cell * c = curr.first;
|
||||
if (!curr.second) {
|
||||
curr.second = true;
|
||||
if (c->m_left && v.visit_left(c->m_key))
|
||||
todo.push_back(entry(c->m_left, false));
|
||||
}
|
||||
else {
|
||||
v(c->m_key);
|
||||
todo.pop_back();
|
||||
if (c->m_right && v.visit_right(c->m_key))
|
||||
todo.push_back(entry(c->m_right, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
struct all_visitor_wrapper {
|
||||
Visitor & m_visitor;
|
||||
all_visitor_wrapper(Visitor & v):m_visitor(v) {}
|
||||
bool visit_right(Key const & k) { return true; }
|
||||
bool visit_left(Key const & k) { return true; }
|
||||
void operator()(Key const & k) { m_visitor.operator()(k); }
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Visit all nodes in the splay tree in ascending order.
|
||||
|
||||
- void operator()(Key const & k)
|
||||
do something with the key pair.
|
||||
*/
|
||||
template<typename Visitor>
|
||||
void visit(Visitor & v) {
|
||||
all_visitor_wrapper<Visitor> w(v);
|
||||
visit_core(w);
|
||||
}
|
||||
|
||||
template<typename Visitor, bool LE>
|
||||
struct visitor_wrapper {
|
||||
Visitor & m_visitor;
|
||||
splay_tree & m_tree;
|
||||
Key m_key;
|
||||
visitor_wrapper(Visitor & v, splay_tree & t, Key const & k):m_visitor(v), m_tree(t), m_key(k) {}
|
||||
bool visit_left(Key const & k) {
|
||||
return LE || m_tree.compare(k, m_key) > 0;
|
||||
}
|
||||
bool visit_right(Key const & k) {
|
||||
return !LE || m_tree.compare(k, m_key) < 0;
|
||||
}
|
||||
void operator()(Key const & k) {
|
||||
if ((LE && m_tree.compare(k, m_key) <= 0) ||
|
||||
(!LE && m_tree.compare(k, m_key) >= 0))
|
||||
m_visitor.operator()(k);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Visit all nodes with keys less than or equal to k.
|
||||
|
||||
- void operator()(Key const & k)
|
||||
do something with the key.
|
||||
*/
|
||||
template<typename Visitor>
|
||||
void visit_le(Visitor & v, Key const & k) {
|
||||
visitor_wrapper<Visitor, true> w(v, *this, k);
|
||||
visit_core(w);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Visit all nodes with keys greater than or equal to k.
|
||||
|
||||
- void operator()(Key const & k)
|
||||
do something with the key.
|
||||
*/
|
||||
template<typename Visitor>
|
||||
void visit_ge(Visitor & v, Key const & k) {
|
||||
visitor_wrapper<Visitor, false> w(v, *this, k);
|
||||
visit_core(w);
|
||||
}
|
||||
|
||||
void display(std::ostream & out) const {
|
||||
display_core(out, m_root);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,152 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
splay_tree_def.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Splay trees
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-31.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPLAY_TREE_DEF_H_
|
||||
#define _SPLAY_TREE_DEF_H_
|
||||
|
||||
#include"splay_tree.h"
|
||||
|
||||
template<typename Key, typename Compare>
|
||||
typename splay_tree<Key, Compare>::cell * splay_tree<Key, Compare>::splay(cell * root, Key const & k) {
|
||||
if (!root)
|
||||
return 0;
|
||||
|
||||
cell aux;
|
||||
cell * tmp;
|
||||
cell * left = &aux;
|
||||
cell * right = &aux;
|
||||
cell * t = root;
|
||||
|
||||
while (true) {
|
||||
int r = compare(k, t->m_key);
|
||||
if (r < 0) {
|
||||
if (!t->m_left)
|
||||
break;
|
||||
if (compare(k, t->m_left->m_key) < 0) {
|
||||
tmp = t->m_left;
|
||||
t->m_left = tmp->m_right;
|
||||
tmp->m_right = t;
|
||||
t = tmp;
|
||||
if (!t->m_left)
|
||||
break;
|
||||
}
|
||||
right->m_left = t;
|
||||
right = t;
|
||||
t = t->m_left;
|
||||
}
|
||||
else if (r > 0) {
|
||||
if (!t->m_right)
|
||||
break;
|
||||
if (compare(k, t->m_right->m_key) > 0) {
|
||||
tmp = t->m_right;
|
||||
t->m_right = tmp->m_left;
|
||||
tmp->m_left = t;
|
||||
t = tmp;
|
||||
if (!t->m_right)
|
||||
break;
|
||||
|
||||
}
|
||||
left->m_right = t;
|
||||
left = t;
|
||||
t = t->m_right;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
left->m_right = t->m_left;
|
||||
right->m_left = t->m_right;
|
||||
t->m_left = aux.m_right;
|
||||
t->m_right = aux.m_left;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename Key, typename Compare>
|
||||
void splay_tree<Key, Compare>::insert(Key const & k) {
|
||||
if (!m_root)
|
||||
m_root = alloc(cell, k);
|
||||
else {
|
||||
m_root = splay(m_root, k);
|
||||
int r = compare(k, m_root->m_key);
|
||||
if (r < 0) {
|
||||
cell * new_cell = alloc(cell, k, m_root->m_left, m_root);
|
||||
m_root->m_left = 0;
|
||||
m_root = new_cell;
|
||||
}
|
||||
else if (r > 0) {
|
||||
cell * new_cell = alloc(cell, k, m_root, m_root->m_right);
|
||||
m_root->m_right = 0;
|
||||
m_root = new_cell;
|
||||
}
|
||||
else
|
||||
m_root->m_key = k;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Key, typename Compare>
|
||||
bool splay_tree<Key, Compare>::find(Key const & k, Key & r) const {
|
||||
if (m_root) {
|
||||
splay_tree<Key, Compare> * _this = const_cast<splay_tree<Key, Compare> *>(this);
|
||||
_this->m_root = _this->splay(m_root, k);
|
||||
if (compare(k, m_root->m_key) == 0) {
|
||||
r = m_root->m_key;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Key, typename Compare>
|
||||
void splay_tree<Key, Compare>::erase(Key const & k) {
|
||||
if (m_root) {
|
||||
m_root = splay(m_root, k);
|
||||
if (compare(k, m_root->m_key) == 0) {
|
||||
cell * to_delete = m_root;
|
||||
if (m_root->m_left) {
|
||||
cell * aux = splay(m_root->m_left, k);
|
||||
SASSERT(!aux->m_right);
|
||||
aux->m_right = m_root->m_right;
|
||||
m_root = aux;
|
||||
}
|
||||
else
|
||||
m_root = m_root->m_right;
|
||||
|
||||
dealloc(to_delete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Key, typename Compare>
|
||||
void splay_tree<Key, Compare>::reset() {
|
||||
ptr_buffer<cell> todo;
|
||||
if (m_root)
|
||||
todo.push_back(m_root);
|
||||
while (!todo.empty()) {
|
||||
cell * c = todo.back();
|
||||
todo.pop_back();
|
||||
if (c->m_left)
|
||||
todo.push_back(c->m_left);
|
||||
if (c->m_right)
|
||||
todo.push_back(c->m_right);
|
||||
dealloc(c);
|
||||
}
|
||||
m_root = 0;
|
||||
}
|
||||
|
||||
#endif /* _SPLAY_TREE_DEF_H_ */
|
|
@ -1,114 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
splay_tree_map.h
|
||||
|
||||
Abstract:
|
||||
|
||||
A mapping as a splay tree.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SPLAY_TREE_MAP_H_
|
||||
#define _SPLAY_TREE_MAP_H_
|
||||
|
||||
#include"splay_tree.h"
|
||||
|
||||
template<typename Key, typename Data, typename Compare>
|
||||
class splay_tree_map {
|
||||
typedef std::pair<Key, Data> entry;
|
||||
|
||||
struct entry_compare : private Compare {
|
||||
entry_compare(Compare const & c):Compare(c) {}
|
||||
int operator()(entry const & e1, entry const & e2) const {
|
||||
return Compare::operator()(e1.first, e2.first);
|
||||
}
|
||||
};
|
||||
|
||||
typedef splay_tree<entry, entry_compare> tree;
|
||||
|
||||
tree m_tree;
|
||||
|
||||
template<typename Visitor>
|
||||
struct core_visitor_wrapper {
|
||||
Visitor & m_visitor;
|
||||
core_visitor_wrapper(Visitor & v):m_visitor(v) {}
|
||||
bool visit_right(entry const & k) { return m_visitor.visit_right(k.first); }
|
||||
bool visit_left(entry const & k) { return m_visitor.visit_left(k.first); }
|
||||
void operator()(entry const & k) { m_visitor.operator()(k.first, k.second); }
|
||||
};
|
||||
|
||||
template<typename Visitor>
|
||||
struct visitor_wrapper {
|
||||
Visitor & m_visitor;
|
||||
visitor_wrapper(Visitor & v):m_visitor(v) {}
|
||||
void operator()(entry const & k) { m_visitor.operator()(k.first, k.second); }
|
||||
};
|
||||
|
||||
public:
|
||||
splay_tree_map(Compare const & c = Compare()):
|
||||
m_tree(entry_compare(c)) {}
|
||||
|
||||
void insert(Key const & k, Data const & d) {
|
||||
m_tree.insert(entry(k, d));
|
||||
}
|
||||
|
||||
bool find(Key const & k, Data & r) const {
|
||||
entry e(k, r);
|
||||
if (m_tree.find(e, e)) {
|
||||
r = e.second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void erase(Key const & k) {
|
||||
entry e;
|
||||
e.first = k;
|
||||
m_tree.erase(e);
|
||||
}
|
||||
|
||||
void reset() { m_tree.reset(); }
|
||||
|
||||
bool empty() const { return m_tree.empty(); }
|
||||
|
||||
void display(std::ostream & out) const { m_tree.display(out); }
|
||||
|
||||
template<typename Visitor>
|
||||
void visit_core(Visitor & v) {
|
||||
core_visitor_wrapper<Visitor> w(v);
|
||||
m_tree.visit_core(w);
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
void visit(Visitor & v) {
|
||||
visitor_wrapper<Visitor> w(v);
|
||||
m_tree.visit(w);
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
void visit_le(Visitor & v, Key const & k) {
|
||||
visitor_wrapper<Visitor> w(v);
|
||||
entry e;
|
||||
e.first = k;
|
||||
m_tree.visit_le(w, e);
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
void visit_ge(Visitor & v, Key const & k) {
|
||||
visitor_wrapper<Visitor> w(v);
|
||||
entry e;
|
||||
e.first = k;
|
||||
m_tree.visit_ge(w, e);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _SPLAY_TREE_MAP_H_ */
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
use_list.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Use list term index.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-04.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"use_list.h"
|
||||
|
||||
void app_use_list::inc_ref(app * n) {
|
||||
if (n->get_num_args() == 0)
|
||||
return; // ignore constants
|
||||
unsigned id = n->get_id();
|
||||
unsigned c = m_ref_counter.get(id, 0);
|
||||
m_ref_counter.setx(id, c+1, 0);
|
||||
if (c == 0)
|
||||
m_todo.push_back(n);
|
||||
}
|
||||
|
||||
void app_use_list::dec_ref(app * n) {
|
||||
if (n->get_num_args() == 0)
|
||||
return; // ignore constants
|
||||
unsigned id = n->get_id();
|
||||
SASSERT(m_ref_counter[id] > 0);
|
||||
m_ref_counter[id]--;
|
||||
if (m_ref_counter[id] == 0)
|
||||
m_todo.push_back(n);
|
||||
}
|
||||
|
||||
void app_use_list::insert(expr * n) {
|
||||
if (is_var(n))
|
||||
return; // nothing to index
|
||||
SASSERT(m_todo.empty());
|
||||
inc_ref(to_app(n));
|
||||
while (!m_todo.empty()) {
|
||||
app * n = m_todo.back();
|
||||
unsigned num_args = n->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * c = n->get_arg(i);
|
||||
if (is_var(c)) {
|
||||
if (!m_ignore_vars)
|
||||
use_list<app*>::insert(n, c);
|
||||
}
|
||||
else {
|
||||
SASSERT(is_app(c));
|
||||
use_list<app*>::insert(n, c);
|
||||
inc_ref(to_app(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void app_use_list::erase(expr * n) {
|
||||
if (is_var(n))
|
||||
return; // nothing to index
|
||||
SASSERT(m_todo.empty());
|
||||
dec_ref(to_app(n));
|
||||
while (!m_todo.empty()) {
|
||||
app * n = m_todo.back();
|
||||
unsigned num_args = n->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * c = n->get_arg(i);
|
||||
if (is_var(c)) {
|
||||
if (!m_ignore_vars)
|
||||
use_list<app*>::erase(n, c);
|
||||
}
|
||||
else {
|
||||
SASSERT(is_app(c));
|
||||
use_list<app*>::erase(n, c);
|
||||
dec_ref(to_app(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void app_use_list::reset() {
|
||||
use_list<app*>::reset();
|
||||
m_ref_counter.reset();
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
use_list.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Use list expression index.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-04.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _USE_LIST_H_
|
||||
#define _USE_LIST_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"vector.h"
|
||||
|
||||
/**
|
||||
\brief Generic use-list data-structure.
|
||||
*/
|
||||
template<typename T>
|
||||
class use_list {
|
||||
typedef vector<T> set;
|
||||
vector<set> m_use_list;
|
||||
public:
|
||||
typedef typename set::const_iterator iterator;
|
||||
use_list() {}
|
||||
|
||||
void insert(T const & parent, expr * child) {
|
||||
unsigned id = child->get_id();
|
||||
if (id >= m_use_list.size())
|
||||
m_use_list.resize(id+1, set());
|
||||
set & s = m_use_list[id];
|
||||
s.push_back(parent);
|
||||
}
|
||||
|
||||
void erase(T const & parent, expr * child) {
|
||||
unsigned id = child->get_id();
|
||||
if (id >= m_use_list.size())
|
||||
return;
|
||||
set & s = m_use_list[id];
|
||||
s.erase(parent);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_use_list.reset();
|
||||
}
|
||||
|
||||
iterator begin(expr * e) const {
|
||||
unsigned id = e->get_id();
|
||||
if (id >= m_use_list.size())
|
||||
return 0;
|
||||
return m_use_list[id].begin();
|
||||
}
|
||||
|
||||
iterator end(expr * e) const {
|
||||
unsigned id = e->get_id();
|
||||
if (id >= m_use_list.size())
|
||||
return 0;
|
||||
return m_use_list[id].end();
|
||||
}
|
||||
|
||||
bool empty(expr * e) const {
|
||||
unsigned id = e->get_id();
|
||||
if (id >= m_use_list.size())
|
||||
return true;
|
||||
return m_use_list[id].empty();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Index for tracking the uses of an expression. It is a
|
||||
mapping from expressions to expressions. For example, consider the
|
||||
term (f a (g a)), the constant a is used by f and g applications.
|
||||
|
||||
\remark The expressions inserted in this index should not contain
|
||||
quantifiers.
|
||||
|
||||
\warning This index will not increase the reference counter of the
|
||||
indexed expressions.
|
||||
*/
|
||||
class app_use_list : use_list<app*> {
|
||||
|
||||
bool m_ignore_vars; //!< when true, variables are not indexed
|
||||
unsigned_vector m_ref_counter;
|
||||
ptr_vector<app> m_todo;
|
||||
|
||||
void inc_ref(app * n);
|
||||
void dec_ref(app * n);
|
||||
|
||||
public:
|
||||
/**
|
||||
\brief If ignore_vars = true, then the index will not track
|
||||
the use of variables.
|
||||
*/
|
||||
app_use_list(bool ignore_vars = true):
|
||||
m_ignore_vars(ignore_vars) {
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Update the use list of all direct/indirect children of n.
|
||||
*/
|
||||
void insert(expr * n);
|
||||
|
||||
/**
|
||||
\brief Remove n (and its unreachable direct/indirect children) from the index.
|
||||
*/
|
||||
void erase(expr * n);
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
#endif /* _USE_LIST_H_ */
|
|
@ -1,26 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
st_cmds.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Commands for testing strategies.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-04-27
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ST_CMD_H_
|
||||
#define _ST_CMD_H_
|
||||
|
||||
class cmd_context;
|
||||
|
||||
void install_st_cmds(cmd_context & ctx);
|
||||
|
||||
#endif
|
|
@ -1,46 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
value_compiler_extension.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Compiler extension for creating values (i.e., "interpreted" constants that
|
||||
are different any other constant).
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2006-10-31.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _VALUE_COMPILER_EXTENSION_H_
|
||||
#define _VALUE_COMPILER_EXTENSION_H_
|
||||
|
||||
#include"ast_compiler.h"
|
||||
|
||||
class value_compiler_extension : public ast_compiler_plugin {
|
||||
context & m_context;
|
||||
public:
|
||||
value_compiler_extension(ast_manager & m, context & ctx):
|
||||
ast_compiler_plugin(m.get_family_id(symbol("interpreted_value"))),
|
||||
m_context(ctx) {
|
||||
ctx.register_plugin(this);
|
||||
}
|
||||
|
||||
virtual ~value_compiler_extension() {
|
||||
}
|
||||
|
||||
virtual bool compile_term(ast_compiler & c, const_ast * a, enode * & r) {
|
||||
SASSERT(a->get_decl()->get_family_id() == m_fid);
|
||||
const_decl_ast * d = a->get_decl();
|
||||
r = m_context.mk_interpreted_const(d);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _VALUE_COMPILER_EXTENSION_H_ */
|
||||
|
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