remove F# support
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Google.OrTools.FSharp
|
||||
|
||||
module Program =
|
||||
[<EntryPoint>]
|
||||
let main _ =
|
||||
printfn "Google.OrTools.FSharp Tests"
|
||||
0
|
||||
@@ -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)
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user