Skip to content

Instantly share code, notes, and snippets.

@IltaySaeedi
Created May 6, 2021 14:08
Show Gist options
  • Save IltaySaeedi/4c3b5553333cad0a8aeb1656c494ecf7 to your computer and use it in GitHub Desktop.
Save IltaySaeedi/4c3b5553333cad0a8aeb1656c494ecf7 to your computer and use it in GitHub Desktop.
This is my first exprience with Linear Programming, I tried to solve a transportation problem by using Flips package.
#r "nuget: Flips, 2.4.5"
open Flips
open Flips.Types
// مساله حمل و نقل
// مساله: 2 کارخانه با ظرفیت های تولید کالای معین به 3 انبار کالاهای
// خود را ارسال می کنند تا تقاضای انبارها تامین شود نه بیشتر نه کمتر
// با توجه به هزینه هایی که رفت آمد در پی دارد بیابید که
// هر کارخانه به چه مقدار و به کدام انبار اجناس خود را ارسال کند
// تا کمترین هزینه ی رفت و آمد را داشته باشیم
// Transportation problem
// m Factories should send goods to n Storages based on
// demands of the storages no more, no less
// by considernig cost of eavh transport between factories and storages
// find best solution to minimize the cost of transportation
// ظرفیت کارخانه ها
// Capacity of each factory
let factory1Capacity = 240.0
let factory2Capacity = 350.0
// نیاز هر انبار
// Demand of each storage
let storage1Demand = 210.0
let storage2Demand = 240.0
let storage3Demand = 130.0
// هزینه حمل و نقل از کارخانه به انبار
// Cost of transport from factories to storages
let costF1ToS1 = 14.0
let costF1ToS2 = 17.0
let costF1ToS3 = 13.0
let costF2ToS1 = 10.0
let costF2ToS2 = 16.0
let costF2ToS3 = 14.0
// تعداد جنس ارسال شده به هر انبار
// مینیمم صفر است و ماکسیمم به تقاضای هر انبار بستگی دارد
// number of supplies that factories send to each storage
// minimun is zero and maximum is demand of storage
let suppliesF1ToS1 =
Decision.createInteger
"Number of supplies from factory1 to storage1" 0.0 storage1Demand
let suppliesF1ToS2 =
Decision.createInteger
"Number of supplies from factory1 to storage2" 0.0 storage2Demand
let suppliesF1ToS3 =
Decision.createInteger
"Number of supplies from factory1 to storage3" 0.0 storage3Demand
let suppliesF2ToS1 =
Decision.createInteger
"Number of supplies from factory2 to storage1" 0.0 storage1Demand
let suppliesF2ToS2 =
Decision.createInteger
"Number of supplies from factory2 to storage2" 0.0 storage2Demand
let suppliesF2ToS3 =
Decision.createInteger
"Number of supplies from factory2 to storage3" 0.0 storage3Demand
// مجموع هزینه های حمل و نقل
// Total cost of Transports
let objectiveExpression =
costF1ToS1 * suppliesF1ToS1
+ costF2ToS1 * suppliesF2ToS1
+ costF1ToS2 * suppliesF1ToS2
+ costF2ToS2 * suppliesF2ToS2
+ costF1ToS3 * suppliesF1ToS3
+ costF2ToS3 * suppliesF2ToS3
// مینیمم کردن هزینه ها برای رسیدن به هدف
// Minimizing of total cost
let objective =
Objective.create "Minimize Cost" Minimize objectiveExpression
// محدودیت کارخانه ها در تولید
// Constraint of factories in production
let SentFromFactory1 =
Constraint.create
"Sent from factory1"
(suppliesF1ToS1 + suppliesF1ToS2 + suppliesF1ToS3
<== factory1Capacity)
let SentFromFactory2 =
Constraint.create
"Sent from factory2"
(suppliesF2ToS1 + suppliesF2ToS2 + suppliesF2ToS3
<== factory2Capacity)
// تامین نیاز انبارها
// Supplying demands of storages
let deliveredToStorage1 =
Constraint.create
"Delivered to storage1"
(suppliesF1ToS1 + suppliesF2ToS1
== storage1Demand)
let deliveredToStorage2 =
Constraint.create
"Delivered to storage2"
(suppliesF1ToS2 + suppliesF2ToS2
== storage2Demand)
let deliveredToStorage3 =
Constraint.create
"Delivered to storage3"
(suppliesF1ToS3 + suppliesF2ToS3
== storage3Demand)
// ایجاد مدل
// Creating model
let model =
Model.create objective
|> Model.addConstraint SentFromFactory1
|> Model.addConstraint SentFromFactory2
|> Model.addConstraint deliveredToStorage1
|> Model.addConstraint deliveredToStorage2
|> Model.addConstraint deliveredToStorage3
// تنظیمات
// Settings of solver
let settings =
{ SolverType = CBC
MaxDuration = 10_000L
WriteLPFile = None
WriteMPSFile = None }
// حل کردن
// Solving
let solutionOpt =
match Solver.solve settings model with
| Optimal s -> Some s
| Infeasible _
| Unbounded _
| Unknown _ -> None
// شاید مساله را پاسخ داشته باشد
// Maybe we found minimized cost
let minimizedCost solutionOpt objectiveExpr =
Option.map
(fun solution -> Solution.evaluate solution objectiveExpr)
solutionOpt
// این ماژول برای گزارش انتقال ها می باشد
// This module is for printing transport reports
module Functions =
// تمام تصمیم ها
// All the decisions
let allDecisions =
[ suppliesF1ToS1
suppliesF1ToS2
suppliesF1ToS3
suppliesF2ToS1
suppliesF2ToS2
suppliesF2ToS3 ]
// فیلتر کردن مسیرهای بدون عبور
// filter the ways without transport
let filterNoneOrZero (allDeciscions: Decision list)
(deciscionsResult: Map<Decision, float>) =
allDeciscions
|> List.choose
(fun d ->
let r = deciscionsResult.TryFind d
match r with
| Some 0.0
| None -> None
| Some r -> Some(d, r))
// گزارش کردن هر ارسال
// print each report
let decisionsToString (decisions: (Decision * float) list) =
decisions
|> List.map
(fun (d, r) ->
let (DecisionName name) = d.Name
$"{name}: {r}\n")
|> List.reduce (fun s acc -> acc + s)
// گزارش حمل و نقل ها
// print the report
match minimizedCost solutionOpt objectiveExpression with
| Some minimum ->
printfn "Objective result: %f" minimum
let solution = solutionOpt |> Option.get
Functions.filterNoneOrZero Functions.allDecisions solution.DecisionResults
|> Functions.decisionsToString
|> printfn "%s"
| _ ->
()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment