Last active
January 17, 2021 19:52
-
-
Save jindraivanek/4109e0f979701d0eafe518496820ebde to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#r "nuget: Flips" | |
type Cut = Cut of float | |
type Plan = Plan of Map<Cut, int> | |
module Cut = | |
/// Take a Cut and return the length as a float | |
let length (Cut length) = | |
length | |
module Plan = | |
/// Give me a Plan with no cuts | |
let empty : Plan = | |
Plan Map.empty | |
/// Give me the total length of cuts in the plan | |
let length (Plan plan) = | |
plan | |
|> Seq.sumBy (fun (KeyValue(Cut cut, count)) -> cut * float count) | |
/// Add a Cut to a Plan and return a new Plan | |
let addCut (cut: Cut) (Plan plan) = | |
match Map.tryFind cut plan with | |
| Some count -> Plan (Map.add cut (count + 1) plan) | |
| None -> Plan (Map.add cut 1 plan) | |
/// Give me the count of each distinct cut in a given Plan | |
let cutCounts (Plan plan) = | |
plan | |
|> Seq.map (fun (KeyValue(cut, count)) -> cut, count) | |
// let plans = generatePlans 2.0 3.0 cuts | |
fsi.ShowDeclarationValues <- false | |
let cuts = | |
[ | |
1380.0 | |
1520.0 | |
1560.0 | |
1710.0 | |
1820.0 | |
1880.0 | |
1930.0 | |
2000.0 | |
2050.0 | |
2100.0 | |
2140.0 | |
2150.0 | |
2200.0 | |
] |> List.map Cut | |
let cutRequirements = | |
[ | |
Cut 1380.0 , 22.0 | |
Cut 1520.0 , 25.0 | |
Cut 1560.0 , 12.0 | |
Cut 1710.0 , 14.0 | |
Cut 1820.0 , 18.0 | |
Cut 1880.0 , 18.0 | |
Cut 1930.0 , 20.0 | |
Cut 2000.0 , 10.0 | |
Cut 2050.0 , 12.0 | |
Cut 2100.0 , 14.0 | |
Cut 2140.0 , 16.0 | |
Cut 2150.0 , 18.0 | |
Cut 2200.0 , 20.0 | |
] |> Map | |
let C = Map.toList cutRequirements |> List.length | |
let totalItems = Map.toList cutRequirements |> List.sumBy snd |> int | |
let stockLength = 56000.0 | |
open Flips | |
open Flips.Types | |
open Flips.SliceMap | |
let M = | |
DecisionBuilder "PlanMatrix" { | |
for _ in [1..totalItems] do | |
for _ in cuts -> | |
Integer (0.0, infinity) | |
} |> SMap2 | |
let plan = | |
DecisionBuilder "PlanUsed" { | |
for _ in [1..totalItems] -> | |
Boolean | |
} |> SMap | |
let planUsedConstraints = | |
ConstraintBuilder "PlanUsed" { | |
for i in [1..totalItems] -> | |
sum (M.[i, All]) <== float C * plan.[i] | |
} | |
let cutRequirementConstraints = | |
ConstraintBuilder "CutRequirements" { | |
for cut in cuts -> | |
sum (M.[All, cut]) >== cutRequirements.[cut] | |
} | |
let planConstraints = | |
let cutVals = cuts |> List.map (fun ((Cut x) as c) -> c, x) |> SMap | |
ConstraintBuilder "PlanRequirements" { | |
for i in [1..totalItems] -> | |
sum (cutVals .* M.[i, All]) <== stockLength | |
} | |
let objective = Objective.create "MinRolls" Minimize (sum plan) | |
let model = | |
Model.create objective | |
|> Model.addConstraints planUsedConstraints | |
|> Model.addConstraints cutRequirementConstraints | |
|> Model.addConstraints planConstraints | |
let settings = | |
Settings.basic | |
|> Settings.setMaxDuration 60_000L | |
//|> Settings.setSolverType SolverType.Gurobi900 | |
|> Settings.setLPFile "model.lp" | |
let result = Solver.solve settings model | |
match result with | |
| Optimal solution -> | |
let values = | |
Solution.getValues solution M | |
|> Map.filter (fun _ quantity -> quantity > 0.0001) | |
let totalNumberOfRolls = | |
Solution.getValues solution plan | |
|> Map.filter (fun _ quantity -> quantity > 0.0001) | |
|> Seq.length | |
printfn "Quantity | (Plan number, Cut)" | |
for KeyValue(plan, quantity) in values do | |
printfn $"%f{quantity} | {plan}" | |
printfn "==========================================" | |
printfn $"Total Number of Rolls: {totalNumberOfRolls}" | |
printfn "==========================================" | |
| x -> | |
failwithf "Unable to solve: %A" x |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment