Skip to content

Commit a7740fb

Browse files
committed
relocate shared network functions in a separate file
1 parent 0ba8fcc commit a7740fb

File tree

4 files changed

+187
-154
lines changed

4 files changed

+187
-154
lines changed

src/OperationsResearchModels.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ include("transportation.jl")
1919
include("assignment.jl")
2020
include("shortestpath.jl")
2121
include("maximumflow.jl")
22+
include("minimumcostflow.jl")
2223
include("game.jl")
2324
include("mst.jl")
2425
include("pmedian.jl")
@@ -35,6 +36,7 @@ import .Transportation
3536
import .Assignment
3637
import .ShortestPath
3738
import .MaximumFlow
39+
import .MinimumCostFlow
3840
import .Game
3941
import .MinimumSpanningTree
4042
import .PMedian
@@ -59,7 +61,7 @@ import .ShortestPath: ShortestPathResult, ShortestPathProblem
5961

6062
import .Network: Connection, nodes
6163
import .MaximumFlow: MaximumFlowResult, MaximumFlowProblem
62-
import .MaximumFlow: MinimumCostFlowProblem, MinimumCostFlowResult
64+
import .MinimumCostFlow: MinimumCostFlowProblem, MinimumCostFlowResult
6365
import .Assignment: AssignmentProblem, AssignmentResult
6466
import .Game: game, GameResult, game_solver
6567
import .MinimumSpanningTree: hasloop, MstResult, MstProblem

src/maximumflow.jl

Lines changed: 2 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
module MaximumFlow
22

3-
using ..Network
3+
import ..Network: Connection, nodes, start, finish, hassameorder, leftexpressions, rightexpressions
44

55
using JuMP, HiGHS
66
import ..OperationsResearchModels: solve
77

88

99
export MaximumFlowProblem, MaximumFlowResult
10-
export MinimumCostFlowProblem, MinimumCostFlowResult
10+
1111

1212

1313
struct MaximumFlowResult
@@ -19,66 +19,10 @@ struct MaximumFlowProblem
1919
connections::Vector{Connection}
2020
end
2121

22-
struct MinimumCostFlowProblem
23-
connections::Vector{Connection}
24-
costs::Vector{Connection}
25-
end
2622

27-
struct MinimumCostFlowResult
28-
path::Vector{Connection}
29-
cost::Float64
30-
end
3123

3224

33-
function leftexpressions(x::Matrix{JuMP.VariableRef}, node::Int64, nodes::Vector{Connection}, model)
34-
lst = []
35-
for conn in nodes
36-
if conn.to == node
37-
push!(lst, conn)
38-
end
39-
end
40-
if length(lst) == 0
41-
return :f
42-
end
43-
expr = @expression(model, 0)
44-
for i = eachindex(lst)
45-
expr += x[lst[i].from, lst[i].to]
46-
end
47-
return expr
48-
end
4925

50-
function rightexpressions(x::Matrix{JuMP.VariableRef}, node::Int64, nodes::Vector{Connection}, model)
51-
lst = []
52-
for conn in nodes
53-
if conn.from == node
54-
push!(lst, conn)
55-
end
56-
end
57-
if length(lst) == 0
58-
return :f
59-
end
60-
expr = @expression(model, 0)
61-
for i = eachindex(lst)
62-
expr += x[lst[i].from, lst[i].to]
63-
end
64-
return expr
65-
end
66-
67-
68-
function hassameorder(a::Vector{Connection}, b::Vector{Connection})::Bool
69-
70-
if length(a) != length(b)
71-
return false
72-
end
73-
74-
for i = 1:length(a)
75-
if a[i].from != b[i].from || a[i].to != b[i].to
76-
return false
77-
end
78-
end
79-
80-
return true
81-
end
8226

8327
"""
8428
@@ -182,101 +126,6 @@ end
182126

183127

184128

185-
"""
186-
solve(problem, flow)
187-
188-
# Description
189-
190-
This function solves the Minimum Cost Flow problem given a flow value.
191-
192-
# Arguments
193-
194-
- `problem::MinimumCostFlowProblem`: The problem in type of MinimumCostFlowProblem
195-
- `flow::Float64`: The flow value to be used in the problem.
196-
197-
198-
"""
199-
function solve(problem::MinimumCostFlowProblem, flow::Float64)::MinimumCostFlowResult
200-
cns = problem.connections
201-
costs = problem.costs
202-
203-
if !hassameorder(cns, costs)
204-
throw(ArgumentError("Connections and costs must have the same order."))
205-
end
206-
207-
model = Model(HiGHS.Optimizer)
208-
MOI.set(model, MOI.Silent(), true)
209-
210-
mynodes = nodes(cns)
211-
n = length(mynodes)
212-
213-
startnode = start(cns)
214-
finishnode = finish(cns)
215-
216-
# Variables
217-
@variable(model, x[1:n, 1:n] .>= 0)
218-
219-
# Objective Function
220-
@objective(model, Min, sum(x[conn.from, conn.to] * conn.value for conn in costs))
221-
222-
# Constraints
223-
for nextnode in mynodes
224-
leftexpr = leftexpressions(x, nextnode, cns, model)
225-
rightexpr = rightexpressions(x, nextnode, cns, model)
226-
if leftexpr == :f
227-
@constraint(model, rightexpr == flow)
228-
elseif rightexpr == :f
229-
@constraint(model, leftexpr == flow)
230-
else
231-
@constraint(model, leftexpr - rightexpr == 0)
232-
end
233-
end
234-
235-
for nd in cns
236-
@constraint(model, x[nd.from, nd.to] <= nd.value)
237-
end
238-
239-
optimize!(model)
240-
241-
xs = value.(x)
242-
cost = JuMP.objective_value(model)
243-
solutionnodes = []
244-
for i = 1:n
245-
for j = 1:n
246-
if xs[i, j] > 0
247-
push!(solutionnodes, Connection(i, j, xs[i, j]))
248-
end
249-
end
250-
end
251-
252-
return MinimumCostFlowResult(solutionnodes, cost)
253-
end
254-
255-
256-
"""
257-
solve(problem)
258-
259-
# Description
260-
261-
This function solves the Minimum Cost Flow problem by first solving the Maximum Flow problem and
262-
then using the flow value to solve the Minimum Cost Flow problem.
263-
264-
# Arguments
265-
266-
- `problem::MinimumCostFlowProblem`: The problem in type of MinimumCostFlowProblem
267-
268-
"""
269-
function solve(problem::MinimumCostFlowProblem)::MinimumCostFlowResult
270-
271-
maximumflowproblem = MaximumFlowProblem(problem.connections)
272-
273-
maximumflowresult = solve(maximumflowproblem)
274-
275-
f = maximumflowresult.flow
276129

277-
result::MinimumCostFlowResult = solve(problem, f)
278-
279-
return result
280-
end
281130

282131
end # end of module

src/minimumcostflow.jl

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
module MinimumCostFlow
2+
3+
using JuMP, HiGHS
4+
import ..OperationsResearchModels: solve
5+
6+
import ..Network: Connection, nodes, start, finish, hassameorder, leftexpressions, rightexpressions
7+
import ..MaximumFlow: MaximumFlowProblem, MaximumFlowResult
8+
9+
export MinimumCostFlowProblem, MinimumCostFlowResult
10+
11+
struct MinimumCostFlowProblem
12+
connections::Vector{Connection}
13+
costs::Vector{Connection}
14+
end
15+
16+
struct MinimumCostFlowResult
17+
path::Vector{Connection}
18+
cost::Float64
19+
end
20+
21+
22+
23+
"""
24+
solve(problem, flow)
25+
26+
# Description
27+
28+
This function solves the Minimum Cost Flow problem given a flow value.
29+
30+
# Arguments
31+
32+
- `problem::MinimumCostFlowProblem`: The problem in type of MinimumCostFlowProblem
33+
- `flow::Float64`: The flow value to be used in the problem.
34+
35+
36+
"""
37+
function solve(problem::MinimumCostFlowProblem, flow::Float64)::MinimumCostFlowResult
38+
cns = problem.connections
39+
costs = problem.costs
40+
41+
if !hassameorder(cns, costs)
42+
throw(ArgumentError("Connections and costs must have the same order."))
43+
end
44+
45+
model = Model(HiGHS.Optimizer)
46+
MOI.set(model, MOI.Silent(), true)
47+
48+
mynodes = nodes(cns)
49+
n = length(mynodes)
50+
51+
startnode = start(cns)
52+
finishnode = finish(cns)
53+
54+
# Variables
55+
@variable(model, x[1:n, 1:n] .>= 0)
56+
57+
# Objective Function
58+
@objective(model, Min, sum(x[conn.from, conn.to] * conn.value for conn in costs))
59+
60+
# Constraints
61+
for nextnode in mynodes
62+
leftexpr = leftexpressions(x, nextnode, cns, model)
63+
rightexpr = rightexpressions(x, nextnode, cns, model)
64+
if leftexpr == :f
65+
@constraint(model, rightexpr == flow)
66+
elseif rightexpr == :f
67+
@constraint(model, leftexpr == flow)
68+
else
69+
@constraint(model, leftexpr - rightexpr == 0)
70+
end
71+
end
72+
73+
for nd in cns
74+
@constraint(model, x[nd.from, nd.to] <= nd.value)
75+
end
76+
77+
optimize!(model)
78+
79+
xs = value.(x)
80+
cost = JuMP.objective_value(model)
81+
solutionnodes = []
82+
for i = 1:n
83+
for j = 1:n
84+
if xs[i, j] > 0
85+
push!(solutionnodes, Connection(i, j, xs[i, j]))
86+
end
87+
end
88+
end
89+
90+
return MinimumCostFlowResult(solutionnodes, cost)
91+
end
92+
93+
94+
"""
95+
solve(problem)
96+
97+
# Description
98+
99+
This function solves the Minimum Cost Flow problem by first solving the Maximum Flow problem and
100+
then using the flow value to solve the Minimum Cost Flow problem.
101+
102+
# Arguments
103+
104+
- `problem::MinimumCostFlowProblem`: The problem in type of MinimumCostFlowProblem
105+
106+
"""
107+
function solve(problem::MinimumCostFlowProblem)::MinimumCostFlowResult
108+
109+
maximumflowproblem = MaximumFlowProblem(problem.connections)
110+
111+
maximumflowresult = solve(maximumflowproblem)
112+
113+
f = maximumflowresult.flow
114+
115+
result::MinimumCostFlowResult = solve(problem, f)
116+
117+
return result
118+
end
119+
120+
121+
end # end of module MinimumCostFlow

0 commit comments

Comments
 (0)