Skip to content

Commit

Permalink
FEAT: Add is_dominated
Browse files Browse the repository at this point in the history
  • Loading branch information
QBatista committed Oct 29, 2018
1 parent 86750aa commit d2bb525
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/Games.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export
# Normal form game functions
best_response, best_responses, is_best_response, payoff_vector,
is_nash, pure2mixed, pure_strategy_NE, is_pareto_efficient,
is_pareto_dominant,
is_pareto_dominant, is_dominated,

# General functions
num_players, num_actions, num_opponents,
Expand Down
72 changes: 72 additions & 0 deletions src/normal_form_game.jl
Original file line number Diff line number Diff line change
Expand Up @@ -691,3 +691,75 @@ Return true if `action_profile` is Pareto dominant for game `g`.
* `::Bool`
""" is_pareto_dominant

# is_dominated

"""
is_domiated(player, action[, tol=1e-8, method=0])
Determine whether `action` is strictly dominated by some mixed
action.
# Arguments
- `player::Player` : Player instance.
- `action::PureAction` : Integer representing a pure action.
- `tol::Float64` : Tolerance to be used.
- `lp_solver::AbstractMathProgSolver` : Allows users to choose a particular
solver for linear programming problems. Options include ClpSolver(),
CbcSolver(), GLPKSolverLP() and GurobiSolver(). By default, it choooses
ClpSolver().
# Returns
- `::Bool` : True if `action` is strictly dominated by some mixed action;
False otherwise.
"""
function is_dominated(player::Player, action::PureAction;
tol::Float64=1e-8, lp_solver=ClpSolver())
payoff_array = player.payoff_array

if num_opponents(player) == 0
return maximum(payoff_array) > payoff_array[action] + tol
end

ind = trues(num_actions(player))
ind[action] = false
D = copy(selectdim(payoff_array, 1, ind))
D .-= selectdim(payoff_array, 1, action:action)

if num_opponents(player) >= 2
D = reshape(D, (size(D)[1], prod(size(D)[2:end])))
end

m, n = size(D)

A = Array{Float64}(undef, n+2, m+1)
A[1:n, 1:m] = -transpose(D)
A[1:n, end] .= 1.
A[n+1, 1:m] .= 1.
A[n+2, 1:m] .= -1.
A[n+1:end, end] .= 0.

b = Array{Float64}(undef, n+2)
b[1:n] .= 0.
b[n+1] .= 1.
b[n+2] .= -1.

c = zeros(m+1)
c[end] = -1.

res = linprog(c, A, '<', b, lp_solver)

if res.status == :Optimal
return res.sol[end] > tol
elseif res.status == :Infeasible
return false
else
throw(ErrorException("Error: solution status $(res.status)"))
end
end
41 changes: 41 additions & 0 deletions test/test_normal_form_game.jl
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@
@test @inferred(payoff_vector(player, nothing)) == [0, 1]
@test @inferred is_best_response(player, 2, nothing)
@test @inferred(best_response(player, nothing)) == 2
@test is_dominated(player, 1) == true
@test is_dominated(player, 2) == false
end

@testset "NormalFormGame with 1 player" begin
Expand Down Expand Up @@ -260,6 +262,45 @@
end
end
end

@testset "Test is_dominated" begin
coordination_game_matrix = [4 0; 3 2]
player = Player(coordination_game_matrix)
for action = 1:num_actions(player)
@test is_dominated(player, action) == false
end

payoffs_2opponents = Array{Int64}(undef, 2, 2, 2)
payoffs_2opponents[:, 1, 1] = [3, 1]
payoffs_2opponents[:, 1, 2] = [6, 0]
payoffs_2opponents[:, 2, 1] = [4, 5]
payoffs_2opponents[:, 2, 2] = [2, 7]
player = Player(payoffs_2opponents)

for i = 1:num_actions(player)
@test is_dominated(player, i) == false
end

end

@testset "Test player corner cases" begin
n, m = 3, 4
player = Player(zeros((n, m)))
for action = 1:n
@test is_best_response(player, action, ones(m) * 1/m) == true
@test is_dominated(player, action) == false
end

e = 1e-8
player = Player([-e -e;
1 -1;
-1 1])
action = 1
@test is_best_response(player, action, [1/2, 1/2], tol=e) == true
@test is_best_response(player, action, [1/2, 1/2], tol=e/2) == false
@test is_dominated(player, action, tol=e) == false
@test is_dominated(player, action, tol=e/2) == true
end
end

end

0 comments on commit d2bb525

Please sign in to comment.