Skip to content

Commit aea4ae1

Browse files
committed
Export lower and upper bounds of the game and strategy type (Pure or Mixed) in Game solver.
1 parent fd83df7 commit aea4ae1

5 files changed

Lines changed: 102 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
### 0.2.13 (Upcoming Release)
22

33
- Minimum Spanning Tree accepts distance matrix encapsulated by MstProblem as input.
4+
- Export lower and upper bounds of the game and strategy type (Pure or Mixed) in Game solver.
45

56
### 0.2.12
67

docs/src/game.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Zero-Sum Games
22

3+
## Strategy Type
4+
5+
```@docs
6+
OperationsResearchModels.StrategyType
7+
```
38

49
## Game Problem
510

src/OperationsResearchModels.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ import .Network: Connection, nodes
8989
import .MaximumFlow: MaximumFlowResult, MaximumFlowProblem
9090
import .MinimumCostFlow: MinimumCostFlowProblem, MinimumCostFlowResult
9191
import .Assignment: AssignmentProblem, AssignmentResult, isbalanced, balance
92-
import .Game: GameProblem, GameResult
92+
import .Game: GameProblem, GameResult, StrategyType, alpha, beta, strategytype, Pure, Mixed
9393
import .MinimumSpanningTree: hasloop, MstResult, MstProblem
9494
import .PMedian: pmedian, pmedian_with_distances, PMedianResult
9595
import .CPM: CpmActivity, earliestfinishtime, longestactivity, CpmProblem, CpmResult
@@ -109,7 +109,7 @@ export TransportationProblem,
109109
export Connection, ShortestPathResult, MaximumFlowResult, MinimumCostFlowResult, nodes
110110
export ShortestPathProblem, MaximumFlowProblem, MinimumCostFlowProblem
111111
export AssignmentProblem, AssignmentResult, isbalanced, balance
112-
export GameProblem, GameResult
112+
export GameProblem, GameResult, StrategyType, alpha, beta, strategytype, Pure, Mixed
113113
export hasloop, MstResult, MstProblem
114114
export pmedian, pmedian_with_distances, PMedianResult
115115
export CpmActivity, earliestfinishtime, longestactivity, CpmProblem, CpmResult

src/game.jl

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,25 @@ using JuMP, HiGHS
55

66
import ..OperationsResearchModels: solve
77

8+
export GameProblem
9+
export GameResult
10+
export StrategyType
11+
12+
"""
13+
StrategyType
14+
15+
# Description
16+
17+
An enumeration to represent the type of strategy in a game.
18+
19+
- `Pure`: Indicates that the optimal strategy is pure, meaning that the player should choose one strategy with probability 1.
20+
- `Mixed`: Indicates that the optimal strategy is mixed, meaning that the player should randomize between multiple strategies with certain probabilities.
21+
"""
22+
@enum StrategyType begin
23+
Pure
24+
Mixed
25+
end
26+
827

928
"""
1029
GameProblem
@@ -34,12 +53,18 @@ A structure to hold the result of a game.
3453
- `probabilities`: Probabilities of the strategies
3554
- `value`: Value of the game
3655
- `model::JuMP.Model`: The JuMP model used to solve the game.
56+
- `alpha::Float64`: The lower bound of the game value (maximin).
57+
- `beta::Float64`: The upper bound of the game value (minimax).
58+
- `strategytype::StrategyType`: Indicates whether the optimal strategy is pure or mixed.
3759
3860
"""
3961
struct GameResult
4062
probabilities::Any
4163
value::Any
4264
model::JuMP.Model
65+
alpha::Float64
66+
beta::Float64
67+
strategytype::StrategyType
4368
end
4469

4570

@@ -134,10 +159,40 @@ function game_solver(gamematrix::Matrix{<:Real}; verbose::Bool = false)::GameRes
134159

135160
gamevalue = JuMP.value(g) #objective_value(model)
136161

137-
result = GameResult(values, gamevalue, model)
162+
a = alpha(GameProblem(gamematrix))
163+
b = beta(GameProblem(gamematrix))
164+
stype = strategytype(GameProblem(gamematrix))
165+
166+
result = GameResult(
167+
values,
168+
gamevalue,
169+
model,
170+
a,
171+
b,
172+
stype)
138173

139174
return result
140175

141176
end
142177

178+
function alpha(problem::GameProblem)::Float64
179+
return maximum(minimum.(eachrow(problem.decisionMatrix)))
180+
end
181+
182+
function beta(problem::GameProblem)::Float64
183+
return minimum(maximum.(eachcol(problem.decisionMatrix)))
184+
end
185+
186+
function strategytype(problem::GameProblem)::StrategyType
187+
a = alpha(problem)
188+
b = beta(problem)
189+
if a == b
190+
return Pure
191+
else
192+
return Mixed
193+
end
194+
end
195+
196+
197+
143198
end # end of module

test/testgame.jl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
[0.4666667, 0.5333333, 0.0000000],
2323
atol = tol,
2424
)
25+
26+
@test result[1].strategytype == Mixed
2527
end
2628

2729
@testset "Game - Rock & Paper & Scissors" begin
@@ -49,6 +51,10 @@
4951

5052
@test isapprox(result[2].probabilities, [0.333333, 0.333333, 0.33333], atol = tol)
5153

54+
@test result[1].alpha == -1.0
55+
56+
@test result[1].beta == 1.0
57+
5258
end
5359

5460
@testset "Simple Game" begin
@@ -74,4 +80,36 @@
7480

7581
@test isapprox(result[2].probabilities, [0.6, 0.4], atol = 0.00001)
7682
end
83+
84+
85+
@testset "Pure Strategy Game" begin
86+
87+
mat = [
88+
2 5
89+
1 1
90+
]
91+
92+
problem = GameProblem(mat)
93+
94+
result = solve(problem)
95+
96+
@test isa(result, Vector{GameResult})
97+
98+
@test length(result) == 2
99+
100+
@test result[1].value == 2.0
101+
102+
# Best option is R1 - C1
103+
104+
@test isapprox(result[1].probabilities, [1.0, 0.0], atol = 0.00001)
105+
106+
@test isapprox(result[2].probabilities, [1.0, 0.0], atol = 0.00001)
107+
108+
@test result[1].strategytype == Pure
109+
110+
@test result[1].alpha == 2.0
111+
112+
@test result[1].beta == 2.0
113+
114+
end
77115
end

0 commit comments

Comments
 (0)