Skip to content

Instantly share code, notes, and snippets.

@jindraivanek
Last active January 17, 2021 19:52
Show Gist options
  • Save jindraivanek/4109e0f979701d0eafe518496820ebde to your computer and use it in GitHub Desktop.
Save jindraivanek/4109e0f979701d0eafe518496820ebde to your computer and use it in GitHub Desktop.
#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