### A Pluto.jl notebook ### # v0.14.5 using Markdown using InteractiveUtils # ╔═╡ 22e21588-1464-432f-b32e-0791e8f96417 begin import Pkg Pkg.activate(mktempdir()) Pkg.add([ Pkg.PackageSpec(name="InteractiveUtils"), Pkg.PackageSpec(name="JuMP"), Pkg.PackageSpec(name="GLPK"), Pkg.PackageSpec(name="VegaLite"), Pkg.PackageSpec(name="DataFrames") ]) using InteractiveUtils, JuMP, GLPK, VegaLite, DataFrames end # ╔═╡ 4e79e380-69ff-11eb-1b7e-6fb10ea2f115 md"## Optimization for the critical path calculation" # ╔═╡ 232168d0-6959-11eb-0d6f-110d35b9e301 md""" Problem formulation $\min X_{N+1} - X_1,$ $\text{subject to}$ $X_i + t_i \leq X_j\quad\forall (i,j) \in A,$ $X_i \geq 0\quad\forall i \in \{1, \ldots, N+1\}.$ Read [the article ] (https://www.moodle.aau.dk/pluginfile.php/2225893/mod_resource/content/1/Linear%20programming%20formation%20for%20Critical%20Path%20Method.pdf) for the linear programming formulation for critical path calculation. --------------- ##### Example problem data for the critical path method Activity | Duration | Predcessor :------- | :---------------: | --------: 1 | 10 | - 2 | 14 | 1,3 3 | 3 | 1 4 | 5 | 3 5 | 8 | 2,4 6 | 3 | 4 """ # ╔═╡ 9cad36f0-695b-11eb-0314-df6f87e48bba md" #### Build an optimization model" # ╔═╡ 404b0f52-69ff-11eb-0c54-2b13258a2bb5 md" ##### Import useful packages for this example including opt. solver" # ╔═╡ a0788070-6a03-11eb-05da-b3a77d5fb3c4 # otherwise use the code below for packages to install and import #begin # import Pkg # Pkg.add("GLPK") #end # ╔═╡ 901f3d52-6962-11eb-241d-c7938c265e66 md""" !!! correct "Note" Since commercial solvers often require additional installation for their binaries and obtaining licenses, in this lecture, we will use GLPK, an open source optimization solver mixed integer linear programming. Please check the [list of supported solvers for JuMP](https://jump.dev/JuMP.jl/stable/installation/#Installing-a-solver) for more information. """ # ╔═╡ 75788b25-c804-46c5-87fc-5c7224a68b11 md"##### Generate variables for data" # ╔═╡ 3b60eb80-695b-11eb-1bef-b551f510e246 begin # Activity duration durations = [10, 14, 3, 5, 8, 3, 0] # Set for precedence relationship A = [[1,2], [3,2], [1,3],[3,4], [2,5], [4,5], [4,6], [5,7], [6,7]] end # ╔═╡ 4d53561e-6a05-11eb-066c-7d60e519b6b6 begin # In other julia IDEs... model_0= Model() TotalActivity = length(durations) # = dummy activity index @variable(model_0, 0 <= X[i in 1:length(durations)]) @objective(model_0, Min, X[TotalActivity] - X[1]) for pred in A # pred = (i,j) in A @constraint(model_0, X[pred[1]]+durations[pred[1]] <= X[pred[2]]) set_optimizer(model_0, GLPK.Optimizer) optimize!(model_0) end end # ╔═╡ 4e536cce-f8de-4fea-a7c9-3a27909e69e2 md""" !!! correct "Note" Codes above will not work in Pluto environment as Pluto cannot understand the macros (e.g. @variable, @objective, etc), so we need to tweak the approach a bit """ # ╔═╡ acc6c420-695b-11eb-3f7c-df48c793397a begin function CriticalPath(durations, Pred_A) # Build a model model= Model() TotalActivity = length(durations) # = dummy activity index @variable(model, 0 <= X[i in 1:TotalActivity]) @objective(model, Min, X[TotalActivity] - X[1]) for pred in Pred_A # pred = (i,j) in A @constraint(model, X[pred[1]]+durations[pred[1]] <= X[pred[2]]) end # Solve the model set_optimizer(model, GLPK.Optimizer) # To apply other optimization solvers, simply change the name of the optimizer # for example, # set_optimizer(CLPEX.Optimizer) or set_optimizer(model, Ipopt.Optimizer) return model end model = CriticalPath(durations, A) optimize!(model) end # ╔═╡ 87ebc0c0-6a04-11eb-1c5e-3fdf3c7cb3f1 md""" Revisit the problem formulation $\min X_{N+1} - X_1,$ $\text{subject to}$ $X_i + t_i \leq X_j\quad\forall (i,j) \in A,$ $X_i \geq 0\quad\forall i \in \{1, \ldots, N+1\}.$ """ # ╔═╡ d06737ab-3b1f-4162-86c1-048ff9b79d01 md"##### Query output of optimization solving" # ╔═╡ 15a1ad30-6a05-11eb-3805-bb901a4abb65 status = termination_status(model) # ╔═╡ 1b7e5360-6961-11eb-13d1-11d8d03a78c2 project_duration = objective_value(model) # ╔═╡ 1d4afd12-6961-11eb-1281-3f0de6fcaecb value.(model[:X]) # ╔═╡ 349a828e-69f4-11eb-0702-67b05d97c94d md"#### Display the result" # ╔═╡ af6d75b0-6a01-11eb-38b7-9b689cd4224a md" [VegaLite.jl](https://www.queryverse.org/VegaLite.jl/stable/) : A plotting package for Julia [DataFrames.jl](https://dataframes.juliadata.org/stable/) : A tabular data handling package (similar to pandas in Python and data.frame/dplyr in R) " # ╔═╡ 1eb7a2a0-69f4-11eb-348a-4739efaf6d47 begin GanttChart_df = DataFrame(Activity = Int64[], Start = Float64[], End = Float64[]) for i in 1:length(durations)-1 tStart = value(model[:X][i]) tEnd = tStart + durations[i] push!(GanttChart_df, [i, tStart, tEnd]) end GanttChart_df end # ╔═╡ 3eb8ecb0-69f6-11eb-2739-0fba2651c751 begin function showGanttChart(df) df |> @vlplot( :bar, y = {:Activity, type = "ordinal"}, x = {:Start, type = "quantitative"}, x2 = :End ) end showGanttChart(GanttChart_df) end # ╔═╡ 0638af80-69fe-11eb-1064-d706b4b9d9cc md""" !!! correct "Note" Visit [JuMP tutorial] (https://github.com/jump-dev/JuMPTutorials.jl) for more in-depth tutorial for JuMP and optimization model examples. """ # ╔═╡ Cell order: # ╟─4e79e380-69ff-11eb-1b7e-6fb10ea2f115 # ╟─232168d0-6959-11eb-0d6f-110d35b9e301 # ╟─9cad36f0-695b-11eb-0314-df6f87e48bba # ╟─404b0f52-69ff-11eb-0c54-2b13258a2bb5 # ╠═22e21588-1464-432f-b32e-0791e8f96417 # ╠═a0788070-6a03-11eb-05da-b3a77d5fb3c4 # ╟─901f3d52-6962-11eb-241d-c7938c265e66 # ╟─75788b25-c804-46c5-87fc-5c7224a68b11 # ╠═3b60eb80-695b-11eb-1bef-b551f510e246 # ╠═4d53561e-6a05-11eb-066c-7d60e519b6b6 # ╟─4e536cce-f8de-4fea-a7c9-3a27909e69e2 # ╠═acc6c420-695b-11eb-3f7c-df48c793397a # ╟─87ebc0c0-6a04-11eb-1c5e-3fdf3c7cb3f1 # ╟─d06737ab-3b1f-4162-86c1-048ff9b79d01 # ╠═15a1ad30-6a05-11eb-3805-bb901a4abb65 # ╠═1b7e5360-6961-11eb-13d1-11d8d03a78c2 # ╠═1d4afd12-6961-11eb-1281-3f0de6fcaecb # ╟─349a828e-69f4-11eb-0702-67b05d97c94d # ╟─af6d75b0-6a01-11eb-38b7-9b689cd4224a # ╠═1eb7a2a0-69f4-11eb-348a-4739efaf6d47 # ╠═3eb8ecb0-69f6-11eb-2739-0fba2651c751 # ╟─0638af80-69fe-11eb-1064-d706b4b9d9cc