mirror of
https://github.com/Z3Prover/z3
synced 2025-04-27 02:45:51 +00:00
Add MSF plugins
This commit is contained in:
parent
58f8181a74
commit
5cc4cc8226
24 changed files with 2683 additions and 0 deletions
230
examples/msf/SolverFoundation.Plugin.Z3/Z3MILPSolver.cs
Normal file
230
examples/msf/SolverFoundation.Plugin.Z3/Z3MILPSolver.cs
Normal file
|
@ -0,0 +1,230 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
|
||||
using Microsoft.Z3;
|
||||
using Microsoft.SolverFoundation.Common;
|
||||
using Microsoft.SolverFoundation.Services;
|
||||
using Microsoft.SolverFoundation.Plugin;
|
||||
|
||||
namespace Microsoft.SolverFoundation.Plugin.Z3
|
||||
{
|
||||
/// <summary>
|
||||
/// The class is implementation of the MSF mixed linear programming solver
|
||||
/// using the Microsoft Z3 solver as the backend.
|
||||
/// </summary>
|
||||
public class Z3MILPSolver : LinearModel, ILinearSolver, ILinearSolution, IReportProvider
|
||||
{
|
||||
#region Private members
|
||||
|
||||
private LinearResult _result;
|
||||
private LinearSolutionQuality _solutionQuality;
|
||||
private Z3BaseSolver _solver;
|
||||
|
||||
#endregion Private members
|
||||
|
||||
#region Solver construction and destruction
|
||||
|
||||
/// <summary>Constructor that initializes the base clases</summary>
|
||||
public Z3MILPSolver() : base(null)
|
||||
{
|
||||
_result = LinearResult.Feasible;
|
||||
_solver = new Z3BaseSolver(this);
|
||||
}
|
||||
|
||||
/// <summary>Constructor that initializes the base clases</summary>
|
||||
public Z3MILPSolver(ISolverEnvironment context) : this() { }
|
||||
|
||||
/// <summary>
|
||||
/// Shutdown can be called when when the solver is not active, i.e.
|
||||
/// when it is done with Solve() or it has gracefully returns from Solve()
|
||||
/// after an abort.
|
||||
/// </summary>
|
||||
public void Shutdown() { _solver.DestructSolver(true); }
|
||||
|
||||
#endregion Solver construction and destruction
|
||||
|
||||
#region Obtaining information about the solution
|
||||
|
||||
public ILinearSolverReport GetReport(LinearSolverReportType reportType)
|
||||
{
|
||||
// We don't support sensitivity report
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion Obtaining information about the solution
|
||||
|
||||
#region Construction of the problem
|
||||
|
||||
/// <summary>
|
||||
/// Get corresponding Z3 formula of a MSF row.
|
||||
/// </summary>
|
||||
/// <param name="rid">The MSF row id</param>
|
||||
private ArithExpr MkGoalRow(int rid)
|
||||
{
|
||||
// Start with the 0 term
|
||||
List<ArithExpr> row = new List<ArithExpr>();
|
||||
|
||||
// Now, add all the entries of this row
|
||||
foreach (LinearEntry entry in GetRowEntries(rid))
|
||||
{
|
||||
// Get the variable and constant in the row
|
||||
ArithExpr e = _solver.GetVariable(entry.Index);
|
||||
if (!entry.Value.IsOne)
|
||||
{
|
||||
e = _solver.Context.MkMul(_solver.GetNumeral(entry.Value, e.Sort), e);
|
||||
}
|
||||
row.Add(e);
|
||||
}
|
||||
switch (row.Count)
|
||||
{
|
||||
case 0: return _solver.GetNumeral(new Rational());
|
||||
case 1: return row[0];
|
||||
default: return _solver.Context.MkAdd(row.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a MSF row to the Z3 assertions.
|
||||
/// </summary>
|
||||
/// <param name="rid">The MSF row id</param>
|
||||
private void AddRow(int rid)
|
||||
{
|
||||
// Start with the 0 term
|
||||
ArithExpr row = MkGoalRow(rid);
|
||||
_solver.AssertArith(rid, row);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set results based on internal solver status
|
||||
/// </summary>
|
||||
private void SetResult(Z3Result status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case Z3Result.Optimal:
|
||||
_result = LinearResult.Optimal;
|
||||
_solutionQuality = LinearSolutionQuality.Exact;
|
||||
break;
|
||||
case Z3Result.LocalOptimal:
|
||||
_result = LinearResult.Feasible;
|
||||
_solutionQuality = LinearSolutionQuality.Approximate;
|
||||
break;
|
||||
case Z3Result.Feasible:
|
||||
_result = LinearResult.Feasible;
|
||||
_solutionQuality = LinearSolutionQuality.Exact;
|
||||
break;
|
||||
case Z3Result.Infeasible:
|
||||
_result = LinearResult.InfeasiblePrimal;
|
||||
_solutionQuality = LinearSolutionQuality.None;
|
||||
break;
|
||||
case Z3Result.Interrupted:
|
||||
_result = LinearResult.Interrupted;
|
||||
_solutionQuality = LinearSolutionQuality.None;
|
||||
break;
|
||||
default:
|
||||
Debug.Assert(false, "Unrecognized Z3 Result");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Construction of the problem
|
||||
|
||||
#region Solving the problem
|
||||
|
||||
/// <summary>
|
||||
/// Starts solving the problem using the Z3 solver.
|
||||
/// </summary>
|
||||
/// <param name="parameters">Parameters to the solver</param>
|
||||
/// <returns>The solution to the problem</returns>
|
||||
public ILinearSolution Solve(ISolverParameters parameters)
|
||||
{
|
||||
// Get the Z3 parameters
|
||||
var z3Params = parameters as Z3BaseParams;
|
||||
Debug.Assert(z3Params != null, "Parameters should be an instance of Z3BaseParams.");
|
||||
|
||||
_solver.Solve(z3Params, Goals, AddRow, MkGoalRow, SetResult);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion Solving the problem
|
||||
|
||||
#region ILinearSolution Members
|
||||
|
||||
public Rational GetSolutionValue(int goalIndex)
|
||||
{
|
||||
var goal = Goals.ElementAt(goalIndex);
|
||||
Debug.Assert(goal != null, "Goal should be an element of the goal list.");
|
||||
return GetValue(goal.Index);
|
||||
}
|
||||
|
||||
public void GetSolvedGoal(int goalIndex, out object key, out int vid, out bool minimize, out bool optimal)
|
||||
{
|
||||
var goal = Goals.ElementAt(goalIndex);
|
||||
Debug.Assert(goal != null, "Goal should be an element of the goal list.");
|
||||
key = goal.Key;
|
||||
vid = goal.Index;
|
||||
minimize = goal.Minimize;
|
||||
optimal = _result == LinearResult.Optimal;
|
||||
}
|
||||
|
||||
// LpResult is LP relaxation assignment.
|
||||
|
||||
public LinearResult LpResult
|
||||
{
|
||||
get { return _result; }
|
||||
}
|
||||
|
||||
public Rational MipBestBound
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(GoalCount > 0, "MipBestBound is only applicable for optimization instances.");
|
||||
return GetSolutionValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
public LinearResult MipResult
|
||||
{
|
||||
get { return _result; }
|
||||
}
|
||||
|
||||
public LinearResult Result
|
||||
{
|
||||
get { return _result; }
|
||||
}
|
||||
|
||||
public LinearSolutionQuality SolutionQuality
|
||||
{
|
||||
get { return _solutionQuality; }
|
||||
}
|
||||
|
||||
public int SolvedGoalCount
|
||||
{
|
||||
get { return GoalCount; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public Report GetReport(SolverContext context, Solution solution, SolutionMapping solutionMapping)
|
||||
{
|
||||
LinearSolutionMapping lpSolutionMapping = solutionMapping as LinearSolutionMapping;
|
||||
if (lpSolutionMapping == null && solutionMapping != null)
|
||||
throw new ArgumentException("solutionMapping is not a LinearSolutionMapping", "solutionMapping");
|
||||
return new Z3LinearSolverReport(context, this, solution, lpSolutionMapping);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class implementing the LinearReport.
|
||||
/// </summary>
|
||||
public class Z3LinearSolverReport : LinearReport
|
||||
{
|
||||
public Z3LinearSolverReport(SolverContext context, ISolver solver, Solution solution, LinearSolutionMapping solutionMapping)
|
||||
: base(context, solver, solution, solutionMapping) {
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue