remove F# support

This commit is contained in:
Laurent Perron
2022-02-24 10:34:49 +01:00
parent 3375871fe5
commit 4237f386a6
8 changed files with 1 additions and 648 deletions

View File

@@ -57,49 +57,6 @@ run_test: build
cd $(SOURCE_PROJECT_PATH) && "$(DOTNET_BIN)" test --no-build -c Release $(ARGS)
endif
# .Net F#
ifeq ($(SOURCE_SUFFIX),.fs) # Those rules will be used if SOURCE contain a .cs file
SOURCE_PROJECT_DIR := $(SOURCE)
SOURCE_PROJECT_DIR := $(subst /$(SOURCE_NAME).fs,, $(SOURCE_PROJECT_DIR))
SOURCE_PROJECT_PATH = $(subst /,$S,$(SOURCE_PROJECT_DIR))
.PHONY: build # Build a .Net F# program (using 'dotnet test').
build: $(SOURCE) $(SOURCE)proj $(FSHARP_ORTOOLS_NUPKG)
cd $(SOURCE_PROJECT_PATH) && "$(DOTNET_BIN)" build -c Release
cd $(SOURCE_PROJECT_PATH) && "$(DOTNET_BIN)" pack -c Release
.PHONY: run # Run a .Net F# program (using 'dotnet test').
run: build
cd $(SOURCE_PROJECT_PATH) && "$(DOTNET_BIN)" run --no-build -c Release $(ARGS)
endif
$(TEMP_DOTNET_DIR):
$(MKDIR) $(TEMP_DOTNET_DIR)
# create test fsproj
$(TEMP_DOTNET_DIR)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME): | $(TEMP_DOTNET_DIR)
$(MKDIR_P) $(TEMP_DOTNET_DIR)$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)
$(TEMP_DOTNET_DIR)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)/%.fs: \
$(SRC_DIR)/ortools/dotnet/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)/%.fs | $(TEMP_DOTNET_DIR)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)
$(COPY) $(SRC_DIR)$Sortools$Sdotnet$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)$S$*.fs $(TEMP_DOTNET_DIR)$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)$S$*.fs
$(TEMP_DOTNET_DIR)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME).fsproj: \
ortools/dotnet/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME).fsproj.in | $(TEMP_DOTNET_DIR)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)
$(SED) -e "s/@PROJECT_VERSION@/$(OR_TOOLS_VERSION)/" \
ortools$Sdotnet$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME).fsproj.in > \
$(TEMP_DOTNET_DIR)$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME).fsproj
$(SED) -i -e 's/@DOTNET_PACKAGES_DIR@/..\/packages/' \
$(TEMP_DOTNET_DIR)$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME).fsproj
.PHONY: test_dotnet_fsharp # Run F# OrTools Tests
test_dotnet_fsharp: $(FSHARP_ORTOOLS_NUPKG) \
$(TEMP_DOTNET_DIR)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME).fsproj \
$(TEMP_DOTNET_DIR)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)/Program.fs \
$(TEMP_DOTNET_DIR)/$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)/Tests.fs
"$(DOTNET_BIN)" build $(DOTNET_BUILD_ARGS) $(TEMP_DOTNET_DIR)$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME).fsproj
"$(DOTNET_BIN)" test $(DOTNET_BUILD_ARGS) $(TEMP_DOTNET_DIR)$S$(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)
#############################
## .NET Examples/Samples ##
#############################
@@ -248,52 +205,6 @@ rdotnet_%: \
cd $(TEMP_DOTNET_DIR)$Stests$S$* && "$(DOTNET_BIN)" build -c Release
cd $(TEMP_DOTNET_DIR)$Stests$S$* && "$(DOTNET_BIN)" test --no-build -c Release $(ARGS)
DOTNET_FS_EXAMPLES := contrib dotnet
define dotnet-fs-example-target =
$$(TEMP_DOTNET_DIR)/$1/%: \
$$(SRC_DIR)/examples/$1/%.fs \
| $$(TEMP_DOTNET_DIR)/$1
-$$(MKDIR) $$(TEMP_DOTNET_DIR)$$S$1$$S$$*
$$(TEMP_DOTNET_DIR)/$1/%/%.fsproj: \
$${SRC_DIR}/ortools/dotnet/Sample.fsproj.in \
| $$(TEMP_DOTNET_DIR)/$1/%
$$(SED) -e "s/@DOTNET_PACKAGES_DIR@/..\/..\/..\/dependencies\/dotnet\/packages/" \
ortools$$Sdotnet$$SSample.fsproj.in \
> $$(TEMP_DOTNET_DIR)$$S$1$$S$$*$$S$$*.fsproj
$$(SED) -i -e 's/@DOTNET_PROJECT@/$$(DOTNET_ORTOOLS_ASSEMBLY_NAME)/' \
$$(TEMP_DOTNET_DIR)$$S$1$$S$$*$$S$$*.fsproj
$$(SED) -i -e 's/@SAMPLE_NAME@/$$*/' \
$$(TEMP_DOTNET_DIR)$$S$1$$S$$*$$S$$*.fsproj
$$(SED) -i -e 's/@PROJECT_VERSION@/$$(OR_TOOLS_VERSION)/' \
$$(TEMP_DOTNET_DIR)$$S$1$$S$$*$$S$$*.fsproj
$$(SED) -i -e 's/@PROJECT_VERSION_MAJOR@/$$(OR_TOOLS_MAJOR)/' \
$$(TEMP_DOTNET_DIR)$$S$1$$S$$*$$S$$*.fsproj
$$(SED) -i -e 's/@PROJECT_VERSION_MINOR@/$$(OR_TOOLS_MINOR)/' \
$$(TEMP_DOTNET_DIR)$$S$1$$S$$*$$S$$*.fsproj
$$(SED) -i -e 's/@PROJECT_VERSION_PATCH@/$$(GIT_REVISION)/' \
$$(TEMP_DOTNET_DIR)$$S$1$$S$$*$$S$$*.fsproj
$$(SED) -i -e 's/@FILE_NAME@/$$*.fs/' \
$$(TEMP_DOTNET_DIR)$$S$1$$S$$*$$S$$*.fsproj
$$(TEMP_DOTNET_DIR)/$1/%/%.fs: \
$$(SRC_DIR)/examples/$1/%.fs \
| $$(TEMP_DOTNET_DIR)/$1/%
$$(COPY) $$(SRC_DIR)$$Sexamples$$S$1$$S$$*.fs \
$$(TEMP_DOTNET_DIR)$$S$1$$S$$*
rdotnet_%: \
$(FSHARP_ORTOOLS_NUPKG) \
$$(TEMP_DOTNET_DIR)/$1/%/%.fsproj \
$$(TEMP_DOTNET_DIR)/$1/%/%.fs \
FORCE
cd $$(TEMP_DOTNET_DIR)$$S$1$$S$$* && "$$(DOTNET_BIN)" build -c Release
cd $$(TEMP_DOTNET_DIR)$$S$1$$S$$* && "$$(DOTNET_BIN)" run --no-build --framework net6.0 -c Release $$(ARGS)
endef
$(foreach example,$(DOTNET_FS_EXAMPLES),$(eval $(call dotnet-fs-example-target,$(example))))
#############################
## .NET Examples/Samples ##
#############################
@@ -492,23 +403,7 @@ test_dotnet_contrib: \
rdotnet_who_killed_agatha \
rdotnet_xkcd \
rdotnet_young_tableaux \
rdotnet_zebra \
rdotnet_fsdiet \
rdotnet_fsequality-inequality \
rdotnet_fsequality \
rdotnet_fsinteger-linear-program \
rdotnet_fsintegerprogramming \
rdotnet_fsknapsack \
rdotnet_fslinearprogramming \
rdotnet_fsnetwork-max-flow-lpSolve \
rdotnet_fsnetwork-max-flow \
rdotnet_fsnetwork-min-cost-flow \
rdotnet_fsProgram \
rdotnet_fsrabbit-pheasant \
rdotnet_fsvolsay \
rdotnet_fsvolsay3-lpSolve \
rdotnet_fsvolsay3 \
rdotnet_SimpleProgramFSharp
rdotnet_zebra
# rdotnet_coins_grid ARGS="5 2" \
# rdotnet_nontransitive_dice \ # too long
# rdotnet_partition \ # too long
@@ -659,9 +554,6 @@ nuget_archive: dotnet | $(TEMP_DOTNET_DIR)
"$(DOTNET_BIN)" publish $(DOTNET_BUILD_ARGS) --no-build --no-dependencies --no-restore -f net6.0 \
-o "..$S..$S..$S$(TEMP_DOTNET_DIR)" \
ortools$Sdotnet$S$(DOTNET_ORTOOLS_ASSEMBLY_NAME)$S$(DOTNET_ORTOOLS_ASSEMBLY_NAME).csproj
"$(DOTNET_BIN)" publish $(DOTNET_BUILD_ARGS) --no-build --no-dependencies --no-restore -f net6.0 \
-o "..$S..$S..$S$(TEMP_DOTNET_DIR)" \
ortools$Sdotnet$S$(FSHARP_ORTOOLS_ASSEMBLY_NAME)$S$(FSHARP_ORTOOLS_ASSEMBLY_NAME).fsproj
"$(DOTNET_BIN)" pack -c Release $(NUGET_PACK_ARGS) --no-build \
-o "..$S..$S..$S$(BIN_DIR)" \
ortools$Sdotnet
@@ -699,7 +591,6 @@ clean_dotnet:
-$(DEL) $(OBJ_DIR)$Sswig$S*_csharp_wrap.$O
# -$(DEL) $(LIB_DIR)$S$(DOTNET_ORTOOLS_NATIVE).*
# -$(DEL) $(BIN_DIR)$S$(DOTNET_ORTOOLS_ASSEMBLY_NAME).*
# -$(DEL) $(BIN_DIR)$S$(FSHARP_ORTOOLS_ASSEMBLY_NAME).*
-$(DELREC) $(DOTNET_EX_PATH)$Sbin
-$(DELREC) $(DOTNET_EX_PATH)$Sobj
-$(DELREC) $(CONTRIB_EX_PATH)$Sbin
@@ -737,9 +628,6 @@ detect_dotnet:
@echo DOTNET_ORTOOLS_RUNTIME_NUPKG = $(DOTNET_ORTOOLS_RUNTIME_NUPKG)
@echo DOTNET_ORTOOLS_ASSEMBLY_NAME = $(DOTNET_ORTOOLS_ASSEMBLY_NAME)
@echo DOTNET_ORTOOLS_NUPKG = $(DOTNET_ORTOOLS_NUPKG)
@echo FSHARP_ORTOOLS_ASSEMBLY_NAME = $(FSHARP_ORTOOLS_ASSEMBLY_NAME)
@echo FSHARP_ORTOOLS_NUPKG = $(FSHARP_ORTOOLS_NUPKG)
@echo FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME = $(FSHARP_ORTOOLS_TESTS_ASSEMBLY_NAME)
ifeq ($(SYSTEM),win)
@echo off & echo(
else

View File

@@ -1,32 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<!-- see https://github.com/dotnet/docs/issues/12237 -->
<RollForward>LatestMajor</RollForward>
<AssemblyName>Google.OrTools.FSharp.Tests</AssemblyName>
<IsPackable>false</IsPackable>
<RestoreSources>@DOTNET_PACKAGES_DIR@;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
</PropertyGroup>
<ItemGroup>
<Compile Include="Tests.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Google.OrTools.FSharp" Version="@PROJECT_VERSION@" />
</ItemGroup>
</Project>

View File

@@ -1,7 +0,0 @@
namespace Google.OrTools.FSharp
module Program =
[<EntryPoint>]
let main _ =
printfn "Google.OrTools.FSharp Tests"
0

View File

@@ -1,54 +0,0 @@
namespace Google.OrTools.FSharp
module Tests =
open System
open Xunit
open Google.OrTools.LinearSolver
open Google.OrTools.FSharp
[<Fact>]
let ``Equality Matrix cannot be empty`` () =
try
let opts = SolverOpts.Default.Name("Equality Constraints").Goal(Minimize).Objective([2.0;1.0;0.0;0.0;0.0]).Algorithm(LP CLP)
opts |> lpSolve |> SolverSummary |> ignore
with
| Failure msg ->
Assert.Equal("Must provide at least one Matrix/Vector pair for inequality/equality contraints", msg)
[<Fact>]
let ``Linear Solver with GLOP Solver`` () =
let svr = Solver.CreateSolver("GLOP")
// x1, x2 are continuous non-negative variables.
let x1 = svr.MakeNumVar(Double.NegativeInfinity, Double.PositiveInfinity, "x1")
let x2 = svr.MakeNumVar(Double.NegativeInfinity, Double.PositiveInfinity, "x2")
// Maximize 8 * x1 + 4 * x2
let objective = svr.Objective()
objective.SetCoefficient(x1, 8.0)
objective.SetCoefficient(x2, 4.0)
objective.SetMaximization()
// x1 + x2 <= 10.
let c0 = svr.MakeConstraint(Double.NegativeInfinity, 10.0)
c0.SetCoefficient(x1, 1.0)
c0.SetCoefficient(x2, 1.0)
// 5 * x1 + x2 <= 15.
let c1 = svr.MakeConstraint(Double.NegativeInfinity, 15.0)
c1.SetCoefficient(x1, 5.0)
c1.SetCoefficient(x2, 1.0)
Assert.Equal(svr.NumVariables(), 2)
Assert.Equal(svr.NumConstraints(), 2)
let resultStatus = svr.Solve()
Assert.Equal(resultStatus, Solver.ResultStatus.OPTIMAL)
Assert.Equal(svr.Objective().Value(), 45.0)
Assert.Equal(x1.SolutionValue(), 5.0/4.0)
Assert.Equal(x2.SolutionValue(), 35.0/4.0)

View File

@@ -1,40 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworks>netcoreapp3.1;net6.0</TargetFrameworks>
<AssemblyName>Google.OrTools.FSharp</AssemblyName>
<Version>@PROJECT_VERSION@</Version>
<!-- Nuget Properties -->
<Description>.NET F# wrapper for the Operations Research Tools project</Description>
<!-- Pack Option -->
<Title>Google.OrTools.FSharp v@PROJECT_VERSION@</Title>
<PackageId>Google.OrTools.FSharp</PackageId>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<!-- Signing -->
<AssemblyKeyFileAttribute>../or-tools.snk</AssemblyKeyFileAttribute>
<SignAssembly>true</SignAssembly>
<PublicSign>false</PublicSign>
<DelaySign>false</DelaySign>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<GenerateTailCalls>true</GenerateTailCalls>
</PropertyGroup>
<ItemGroup>
<Compile Include="OrTools.fs"/>
</ItemGroup>
<PropertyGroup>
<RestoreSources>@DOTNET_PACKAGES_DIR@;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.OrTools" Version="@PROJECT_VERSION@" />
</ItemGroup>
</Project>

View File

@@ -1,354 +0,0 @@
namespace Google.OrTools
module FSharp =
open System
open Google.OrTools.Algorithms
open Google.OrTools.Graph
open Google.OrTools.LinearSolver
type Goal =
/// Maximize the Objective Function
| Maximize
/// Minimize the Objective Function
| Minimize
/// Linear Programming Algorithms
type LinearProgramming =
/// Coin-Or (Recommended default)
| CLP
/// GNU Linear Programming Kit
| GLPK
/// Google Linear Optimization
| GLOP
/// Gurobi Optimizer
| GUROBI
/// IBM CPLEX
| CPLEX
/// Solver Name
override this.ToString() =
match this with
| CLP -> "CLP_LINEAR_PROGRAMMING"
| GLPK -> "GLPK_LINEAR_PROGRAMMING"
| GLOP -> "GLOP_LINEAR_PROGRAMMING"
| GUROBI -> "GUROBI_LINEAR_PROGRAMMING"
| CPLEX -> "CPLEX_LINEAR_PROGRAMMING"
/// Solver Id
member this.Id =
match this with
| CLP -> 0
| GLPK -> 1
| GLOP -> 2
| GUROBI -> 6
| CPLEX -> 10
/// Integer Programming Algorithms
type IntegerProgramming =
/// Solving Constraint Integer Programs (Recommended default)
| SCIP
/// GNU Linear Programming Kit
| GLPK
/// Coin-Or Branch and Cut
| CBC
/// Gurobi Optimizer
| GUROBI
/// IBM CPLEX
| CPLEX
/// Binary Optimizer
| BOP
/// Solver Name
override this.ToString() =
match this with
| SCIP -> "SCIP_MIXED_INTEGER_PROGRAMMING"
| GLPK -> "GLPK_MIXED_INTEGER_PROGRAMMING"
| CBC -> "CBC_MIXED_INTEGER_PROGRAMMING"
| GUROBI -> "GUROBI_MIXED_INTEGER_PROGRAMMING"
| CPLEX -> "CPLEX_MIXED_INTEGER_PROGRAMMING"
| BOP -> "BOP_INTEGER_PROGRAMMING"
/// Solver Id
member this.Id =
match this with
| SCIP -> 3
| GLPK -> 4
| CBC -> 5
| GUROBI -> 7
| CPLEX -> 11
| BOP -> 12
type LinearSolverAlgorithm =
| LP of LinearProgramming
| IP of IntegerProgramming
/// Max Flow Solver Result
type MaximumFlowResult =
| Optimal
| IntegerOverflow
| BadInput
| BadResult
member this.Id =
match this with
| Optimal -> MaxFlow.Status.OPTIMAL
| IntegerOverflow -> MaxFlow.Status.POSSIBLE_OVERFLOW
| BadInput -> MaxFlow.Status.BAD_INPUT
| BadResult -> MaxFlow.Status.BAD_RESULT
/// Minimum Cost Flow Result
type MinimumCostFlowResult =
| NotSolved
| Optimal
| Feasible
| Infeasible
| Unbalanced
| BadResult
| BadCostRange
member this.Id =
match this with
| NotSolved -> MinCostFlowBase.Status.NOT_SOLVED
| Optimal -> MinCostFlowBase.Status.OPTIMAL
| Feasible -> MinCostFlowBase.Status.FEASIBLE
| Infeasible -> MinCostFlowBase.Status.INFEASIBLE
| Unbalanced -> MinCostFlowBase.Status.UNBALANCED
| BadResult -> MinCostFlowBase.Status.BAD_RESULT
| BadCostRange -> MinCostFlowBase.Status.BAD_COST_RANGE
/// Knapsack Solver Algorithm
type KnapsackSolverAlgorithm =
| BruteForce
| SixtyFourItems
| DynamicProgramming
| MultidimensionCBC
| MultidimensionGLPK
| MultidimensionBranchAndBound
| MultidimensionSCIP
/// Solver Id
member this.Id =
match this with
| BruteForce -> 0
| SixtyFourItems -> 1
| DynamicProgramming -> 2
| MultidimensionCBC -> 3
| MultidimensionGLPK -> 4
| MultidimensionBranchAndBound -> 5
| MultidimensionSCIP -> 6
let knapsackSolve (name: string) (solverAlgorithm:KnapsackSolverAlgorithm) (profits:int64 list) (weights:int64 [,]) (capacities:int64 list) =
// extract the specific algorithm so its Id can be used to create solver
let algorithm =
match solverAlgorithm with
| MultidimensionBranchAndBound ->
MultidimensionBranchAndBound.Id
| BruteForce ->
BruteForce.Id
| SixtyFourItems ->
SixtyFourItems.Id
| DynamicProgramming ->
DynamicProgramming.Id
| MultidimensionCBC ->
MultidimensionCBC.Id
| MultidimensionGLPK ->
MultidimensionGLPK.Id
| MultidimensionSCIP ->
MultidimensionSCIP.Id
let solver = new KnapsackSolver(enum<KnapsackSolver.SolverType>(algorithm), name)
// transform lists to compatible structures for C++ Solver
let profit_array = List.toArray profits
let capacity_array = List.toArray capacities
solver.Init(profit_array, weights, capacity_array)
solver
type SolverOpts = {
/// Name of the solver
SolverName: string;
/// Linear objective function vector
ObjectiveFunction: float list;
/// Matrix for linear inequality constraints
ConstraintMatrix: float list list option;
/// Upper Bound vector for linear inequality constraints
ConstraintVectorUpperBound: float list option;
/// Lower Bound vector for linear inequality constraints
ConstraintVectorLowerBound: float list option;
/// Vector of variable upper bounds
VariableUpperBound: float list;
/// Vector of variable lower bounds
VariableLowerBound: float list;
/// Matrix for linear equality constraints
ConstraintMatrixEq: float list list option;
/// Vector for linear equality constraints
ConstraintVectorEq: float list option;
/// Solver Algorithm to use
SolverAlgorithm: LinearSolverAlgorithm;
/// Solver Goal (Minimize/Maximize)
SolverGoal: Goal
} with
member this.Name(nm:string)=
{this with SolverName = nm}
member this.Objective(objVector:float list) =
{this with ObjectiveFunction = objVector}
member this.Matrix(mat:float list list) =
{this with ConstraintMatrix = Some(mat)}
member this.VectorUpperBound(vec:float list) =
{this with ConstraintVectorUpperBound = Some(vec)}
member this.VectorLowerBound(vec:float list) =
{this with ConstraintVectorLowerBound = Some(vec)}
member this.MatrixEq(mat:float list list) =
{this with ConstraintMatrixEq = Some(mat)}
member this.VectorEq(vec:float list) =
{this with ConstraintVectorEq = Some(vec)}
member this.VarUpperBound(ub:float list) =
{this with VariableUpperBound = ub}
member this.VarLowerBound(lb:float list) =
{this with VariableLowerBound = lb}
member this.Algorithm(algo:LinearSolverAlgorithm) =
{this with SolverAlgorithm = algo}
member this.Goal(goal:Goal) =
{this with SolverGoal = goal}
static member Default =
{
SolverName = "Solver";
ObjectiveFunction = [];
ConstraintMatrix = None;
ConstraintVectorUpperBound = None;
ConstraintVectorLowerBound = None;
VariableUpperBound = [];
VariableLowerBound = [];
ConstraintMatrixEq = None;
ConstraintVectorEq = None;
SolverAlgorithm = LP CLP
SolverGoal = Maximize
}
let lpSolve (solverOptions:SolverOpts) =
// extract the specific algorithm so its Id can be used to create solver
let algorithm =
match solverOptions.SolverAlgorithm with
| LP lp -> lp.Id
| IP ip -> ip.Id
let solverType = enum<Solver.OptimizationProblemType>(algorithm)
let solver = new Solver(solverOptions.SolverName, solverType)
// Detect errors on required parameters
if (solverOptions.ConstraintMatrix.IsNone && solverOptions.ConstraintVectorUpperBound.IsNone && solverOptions.ConstraintVectorLowerBound.IsNone)
&& (solverOptions.ConstraintMatrixEq.IsNone && solverOptions.ConstraintVectorEq.IsNone) then
failwith "Must provide at least one Matrix/Vector pair for inequality/equality contraints"
if solverOptions.ObjectiveFunction.IsEmpty then
failwith "Objective function cannot be empty"
if solverOptions.VariableUpperBound.IsEmpty then
failwith "Variable upper bound values cannot be empty"
if solverOptions.VariableLowerBound.IsEmpty then
failwith "Variable lower bound values cannot be empty"
// check inequality matrix dimensions against bounds
match (solverOptions.ConstraintMatrix, solverOptions.ConstraintVectorLowerBound, solverOptions.ConstraintVectorUpperBound) with
| _, Some lb, Some ub when lb.Length <> ub.Length ->
failwithf "Constraint vector dimensions should be equal.\nLower Bound Length: %i\nUpper Bound Length: %i" lb.Length ub.Length
| _ -> ()
// Check Objective function dimensions with variable bounds dimensions
match (solverOptions.ObjectiveFunction.Length, solverOptions.VariableLowerBound.Length, solverOptions.VariableUpperBound.Length) with
| _ , lb, ub when lb <> ub ->
failwithf "Variable vector dimensions should be equal.\nLower Bound Length: %i\nUpper Bound Length: %i" lb ub
| obj, _ , ub when obj <> ub ->
failwithf "Variable vector dimensions should be equal.\nUpper Bound Length: %i\nObjective Function Length: %i" ub obj
| obj, lb, _ when obj <> lb ->
failwithf "Variable vector dimensions should be equal.\nLower Bound Length: %i\nObjective Function Length: %i" lb obj
| _ -> ()
// Variables
let vars =
match solverOptions.SolverAlgorithm with
| LP lp ->
[ for i in 0 .. (solverOptions.VariableLowerBound.Length-1) -> solver.MakeNumVar(solverOptions.VariableLowerBound.[i], solverOptions.VariableUpperBound.[i], (sprintf "var[%i]" i ) ) ]
| IP ip ->
[ for i in 0 .. (solverOptions.VariableLowerBound.Length-1) -> solver.MakeIntVar(solverOptions.VariableLowerBound.[i], solverOptions.VariableUpperBound.[i], (sprintf "var[%i]" i ) ) ]
// Constraints
let cols = [ for i in 0 .. (solverOptions.VariableLowerBound.Length-1) -> i ] // generate column index selectors
// Inequality Constraints
match (solverOptions.ConstraintMatrix, solverOptions.ConstraintVectorLowerBound, solverOptions.ConstraintVectorUpperBound) with
| (None, Some lb, Some ub) ->
failwithf "Matrix for Equality Constraints undefined."
| (Some mat, None, Some ub) ->
for row = 0 to (ub.Length-1) do
// generate constraint operands based on indices
let constraintOperands = List.map (fun c -> vars.[c] * mat.[c].[row]) cols
let linearExp = List.reduce (+) constraintOperands
// create the constraint
let rangeConstraint = RangeConstraint(linearExp, Double.NegativeInfinity, ub.[row])
solver.Add(rangeConstraint) |> ignore
| (Some mat, Some lb, None) ->
for row = 0 to (lb.Length-1) do
// generate constraint operands based on indices
let constraintOperands = List.map (fun c -> vars.[c] * mat.[c].[row]) cols
let linearExp = List.reduce (+) constraintOperands
// create the constraint
let rangeConstraint = RangeConstraint(linearExp, lb.[row], Double.PositiveInfinity)
solver.Add(rangeConstraint) |> ignore
| (Some mat, Some lb, Some ub) ->
for row = 0 to (ub.Length-1) do
// generate constraint operands based on indices
let constraintOperands = List.map (fun c -> vars.[c] * mat.[c].[row]) cols
let linearExp = List.reduce (+) constraintOperands
// create the constraint
let rangeConstraint = RangeConstraint(linearExp, lb.[row], ub.[row])
solver.Add(rangeConstraint) |> ignore
| _ -> ()
// Equality Constraints
match (solverOptions.ConstraintMatrixEq, solverOptions.ConstraintVectorEq) with
| (None, Some b) ->
failwithf "Matrix for Equality Constraints undefined."
| (Some mat, Some vec) ->
for row = 0 to (vec.Length-1) do
// generate constraint operands based on indices
let constraintOperands = List.map (fun c -> vars.[c] * mat.[c].[row]) cols
let linearExp = List.reduce (+) constraintOperands
// create the constraint
let equalityConstraint = RangeConstraint(linearExp, vec.[row], vec.[row])
solver.Add(equalityConstraint) |> ignore
| _ -> ()
// Objective
let objectiveOperands = List.map (fun c -> solverOptions.ObjectiveFunction.[c] * vars.[c]) cols
let objectiveExp = List.reduce (+) objectiveOperands
match solverOptions.SolverGoal with
| Minimize ->
solver.Minimize(objectiveExp)
| Maximize ->
solver.Maximize(objectiveExp)
solver
/// Solves the optimization problem and prints the results to console
let SolverSummary (solver:Solver) =
let resultStatus = solver.Solve();
match resultStatus with
| status when status <> Solver.ResultStatus.OPTIMAL ->
printfn "The problem does not have an optimal solution!"
exit 0
| _ ->
printfn "\nProblem solved in %d milliseconds" (solver.WallTime())
printfn "Iterations: %i\n" (solver.Iterations())
printfn "Objective: %f" (solver.Objective().Value())
for i in 0 .. (solver.NumVariables()-1) do
printfn "%-10s: %f " (sprintf "var[%i]" i) ((solver.LookupVariableOrNull(sprintf "var[%i]" i)).SolutionValue())
solver

View File

@@ -7,8 +7,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.OrTools.runtime.linu
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.OrTools.runtime.osx-x64", "Google.OrTools.runtime.osx-x64\Google.OrTools.runtime.osx-x64.csproj", "{FC646C34-8541-427D-B9F6-1247798F4574}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.OrTools.runtime.win-x64", "Google.OrTools.runtime.win-x64\Google.OrTools.runtime.win-x64.csproj", "{FC646C34-8541-427D-B9F6-1247798F4574}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.OrTools", "Google.OrTools\Google.OrTools.csproj", "{FC646C34-8541-427D-B9F6-1247798F4574}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.OrTools.FSharp", "Google.OrTools.FSharp\Google.OrTools.FSharp.fsproj", "{FC646C34-8541-427D-B9F6-1247798F4574}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.OrTools.FSharp.Tests", "Google.OrTools.FSharp.Tests\Google.OrTools.FSharp.Tests.fsproj", "{FC646C34-8541-427D-B9F6-1247798F4574}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@@ -1,46 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<LangVersion>6.0</LangVersion>
<TargetFrameworks>net6.0</TargetFrameworks>
<EnableDefaultItems>false</EnableDefaultItems>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<!-- see https://github.com/dotnet/docs/issues/12237 -->
<RollForward>LatestMajor</RollForward>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AssemblyName>@DOTNET_PROJECT@.FSharp.@SAMPLE_NAME@</AssemblyName>
<Version>@PROJECT_VERSION@</Version>
<!-- Nuget Properties -->
<Description>Simple App consuming @DOTNET_PROJECT@.FSharp package</Description>
<!-- Pack Option -->
<IsPackable>true</IsPackable>
<Title>@DOTNET_PROJECT@.FSharp.@SAMPLE_NAME@ v@PROJECT_VERSION@</Title>
<PackageId>@DOTNET_PROJECT@.FSharp.@SAMPLE_NAME@</PackageId>
<PackageTags>sample</PackageTags>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<!-- Signing -->
<SignAssembly>false</SignAssembly>
<PublicSign>false</PublicSign>
<DelaySign>false</DelaySign>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<GenerateTailCalls>true</GenerateTailCalls>
</PropertyGroup>
<!-- Dependencies -->
<PropertyGroup>
<RestoreSources>@DOTNET_PACKAGES_DIR@;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
</PropertyGroup>
<ItemGroup>
<Compile Include="@FILE_NAME@" />
<PackageReference Include="@DOTNET_PROJECT@.FSharp" Version="@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.*" />
</ItemGroup>
</Project>