Skip to content

Commit

Permalink
make cpm and pert solve() compatible.
Browse files Browse the repository at this point in the history
  • Loading branch information
jbytecode committed May 6, 2024
1 parent 76647c3 commit e832353
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 22 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
- Iterations for single `solve()` method for many problems to provide a uniform way, e.g., `solve(p)` and `solve(r)` should work at the same time where `p` and `r` would be `TransportationProblem`, `AssignmentProblem`, `ShortestPathProblem`, `MaximumFlowProblem`, `MstProblem`, `KnapsackProblem`, etc.

- In the release iterations, some of the methods will be removed so this release is planned to be a breaking one.

- Make `cpm` and `pert` solvable using `solve(::CpmProblem)` and `solve(::PertProblem)`.


### 0.1.8
Expand Down
10 changes: 8 additions & 2 deletions docs/src/algorithms.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,18 @@ OperationsResearchModels.pmedian_with_distances

## CPM (Critical Path Method)
```@docs
OperationsResearchModels.cpm
OperationsResearchModels.solve(problem::CpmProblem)
```

### CPM Activity
```@docs
OperationsResearchModels.CpmActivity
```


## PERT (Project Evalutation and Review Technique)
```@docs
OperationsResearchModels.pert
OperationsResearchModels.solve(problem::PertProblem)
```

## Knapsack
Expand Down
8 changes: 4 additions & 4 deletions src/OperationsResearchModels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ import .Assignment: AssignmentProblem, AssignmentResult
import .Game: game, GameResult
import .MinimumSpanningTree: hasloop, MstResult, MstProblem
import .PMedian: pmedian, pmedian_with_distances, PMedianResult
import .CPM: cpm, CpmActivity, earliestfinishtime, longestactivity, CpmResult
import .CPM: pert, PertActivity, PertResult
import .CPM: CpmActivity, earliestfinishtime, longestactivity, CpmProblem, CpmResult
import .CPM: PertActivity, PertProblem, PertResult
import .Knapsack: KnapsackResult, KnapsackProblem
import .Latex: latex

Expand All @@ -60,8 +60,8 @@ export AssignmentProblem, AssignmentResult
export game, GameResult
export hasloop, MstResult, MstProblem
export pmedian, pmedian_with_distances, PMedianResult
export cpm, CpmActivity, earliestfinishtime, longestactivity, CpmResult
export pert, PertActivity, PertResult
export CpmActivity, earliestfinishtime, longestactivity, CpmProblem, CpmResult
export PertActivity, PertProblem, PertResult
export KnapsackResult, KnapsackProblem
export Simplex
export Utility
Expand Down
72 changes: 62 additions & 10 deletions src/cpm.jl
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
module CPM

export cpm
import ..OperationsResearchModels: solve

export CpmActivity
export CpmProblem
export CpmResult
export earliestfinishtime
export longestactivity
export PertActivity
export PertProblem
export PertResult
export pert


"""
CpmActivity(name::String, time::Float64, dependencies)
# Description
The object that represents an activity in CPM (Critical Path Method).
# Arguments
- `name::String`: The name of the activity.
- `time::Float64`: The time of the activity.
- `dependencies`: The dependencies of the activity in type of `Vector{CpmActivity}`.
# Example
```julia
julia> A = CpmActivity("A", 2, []);
julia> B = CpmActivity("B", 3, []);
julia> C = CpmActivity("C", 2, [A, B]);
"""
struct CpmActivity
name::String
time::Float64
dependencies::Vector{CpmActivity}
end

struct CpmProblem
activities::Vector{CpmActivity}
end

struct CpmResult
pathstr::Vector{String}
path::Vector{CpmActivity}
Expand All @@ -28,6 +54,10 @@ struct PertActivity
dependencies::Vector{PertActivity}
end

struct PertProblem
activities::Vector{PertActivity}
end

struct PertResult
path::Vector{PertActivity}
mean::Float64
Expand Down Expand Up @@ -86,18 +116,22 @@ function pathtostring(activities::Vector{CpmActivity})::Vector{String}
end

"""
cpm(activities)
solve(problem)
# Arguments
- `activities::Vector{CpmActivity}`
- `problem::CpmProblem`: The problem in type of CpmProblem.
# Output
- `::CpmResult`: The object holds the results
# Description
Calculates CPM (Critical Path Method) and reports the critical path for a given set of activities.
# Example
```julia
julia> A = CpmActivity("A", 2);
julia> B = CpmActivity("B", 3);
Expand All @@ -112,7 +146,9 @@ julia> J = CpmActivity("J", 2, [C, D]);
julia> activities = [A, B, C, D, E, F, G, H, I, J];
julia> result = cpm(activities);
julia> problem = CpmProblem(activities);
julia> result = solve(problem);
julia> result.pathstr
4-element Vector{String}:
Expand All @@ -125,7 +161,10 @@ julia> result.pathstr
true
```
"""
function cpm(activities::Vector{CpmActivity})::CpmResult
function solve(problem::CpmProblem)::CpmResult

activities = problem.activities

path = CpmActivity[]

while true
Expand Down Expand Up @@ -178,12 +217,13 @@ end


"""
pert(activities)
solve(problem::PertProblem)::PertResult
# Arguments
- `activities::Vector{PertActivity}`: Vector of Pert Activities.
- `problem::PertProblem`: The problem in type of PertProblem.
# Example
```julia
julia> A = PertActivity("A", 1, 2, 3)
PertActivity("A", 1.0, 2.0, 3.0, PertActivity[])
Expand All @@ -200,6 +240,8 @@ julia> activities = [A, B, C]
PertActivity("B", 3.0, 3.0, 3.0, PertActivity[])
PertActivity("C", 5.0, 5.0, 5.0, PertActivity[PertActivity("A", 1.0, 2.0, 3.0, PertActivity[]), PertActivity("B", 3.0, 3.0, 3.0, PertActivity[])])
julia> problem = PertProblem(activities);
julia> result = pert(activities)
PertResult(PertActivity[PertActivity("B", 3.0, 3.0, 3.0, PertActivity[]), PertActivity("C", 5.0, 5.0, 5.0, PertActivity[PertActivity("A", 1.0, 2.0, 3.0, PertActivity[]), PertActivity("B", 3.0, 3.0, 3.0, PertActivity[])])], 8.0, 0.0)
Expand All @@ -210,19 +252,29 @@ julia> result.stddev
0.0
```
"""
function pert(activities::Vector{PertActivity})
function solve(problem::PertProblem)::PertResult

activities = problem.activities

L = length(activities)

cpmactivities = Array{CpmActivity,1}(undef, L)

for i = 1:L
current::PertActivity = activities[i]
cpmactivity =
CpmActivity(current.name, mean(current), perttocpm.(current.dependencies))
cpmactivities[i] = cpmactivity
end
cpmresult = cpm(cpmactivities)

cpmresult = solve(CpmProblem(cpmactivities))

pertpath = cpmresult.path

pertactivities = findpertactivities(pertpath, activities)

pertmean = sum(pertpath)

stddev = sqrt(var(pertactivities))

return PertResult(pertactivities, pertmean, stddev)
Expand Down
11 changes: 9 additions & 2 deletions test/testcpm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@

activities = CpmActivity[A, B, C, D, E, F]

result = cpm(activities)

problem = CpmProblem(activities)


result = solve(problem)

@test result isa CpmResult

Expand All @@ -52,7 +56,10 @@
J = CpmActivity("J", 2, [C, D])

activities = [A, B, C, D, E, F, G, H, I, J]
result = cpm(activities)

problem = CpmProblem(activities)

result = solve(problem)

@test result.pathstr == ["B", "E", "G", "I"]
@test result.path == [B, E, G, I]
Expand Down
13 changes: 10 additions & 3 deletions test/testpert.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

activities = [A, B, C]

result::PertResult = pert(activities)
problem = PertProblem(activities)

result::PertResult = solve(problem)

@test result.mean == 8.0
@test result.stddev == 0.0
Expand All @@ -23,7 +25,9 @@

activities = [A, B, C]

result::PertResult = pert(activities)
problem = PertProblem(activities)

result::PertResult = solve(problem)

@test result.mean == 10.0
@test isapprox(result.stddev, 0.4714045207910317, atol = epsilon)
Expand All @@ -49,7 +53,10 @@

activities = [A, B, C, D, E, F, G, H, I, J, K, L]

result = pert(activities)

problem = PertProblem(activities)

result = solve(problem)

@test result isa PertResult
@test result.mean == 22.5
Expand Down

0 comments on commit e832353

Please sign in to comment.