From a69862500211dc06f4cf37ee3dd4600af3fdcd23 Mon Sep 17 00:00:00 2001 From: Zejin Shi Date: Mon, 20 Mar 2017 15:53:17 +0900 Subject: [PATCH] Update docstrings, indentations,, and type assertion. --- src/support_enumeration.jl | 69 ++++++++++++++++++++++++-------- test/test_support_enumeration.jl | 10 ++--- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/support_enumeration.jl b/src/support_enumeration.jl index 7c5cf066..8bb1f0f5 100644 --- a/src/support_enumeration.jl +++ b/src/support_enumeration.jl @@ -2,6 +2,10 @@ Compute all mixed Nash equilibria of a 2-player (non-degenerate) normal form game by support enumeration. +Julia version of QuantEcon.py/support_enumeration.py + +Authors: Daisuke Oyama, Zejin Shi + References ---------- B. von Stengel, "Equilibrium Computation for Two-Player Games in @@ -21,16 +25,17 @@ players have the same number n of actions, there are 2n choose n minus 1 such pairs. This should thus be used only for small games. # Arguments + * `g::NormalFormGame`: NormalFormGame instance. # Returns + * `::Vector{Tuple{Vector{Float64},Vector{Float64}}}`: Mixed-action - Nash equilibria that are found. + Nash equilibria that are found. """ function support_enumeration(g::NormalFormGame) task = support_enumeration_task(g) - NEs = Tuple{Vector{Float64},Vector{Float64}}[NE for NE in task] return NEs @@ -43,40 +48,41 @@ end Task version of `support_enumeration`. # Arguments + * `g::NormalFormGame`: NormalFormGame instance. # Returns + * `::Task`: runnable task for generating Nash equilibria. """ -function support_enumeration_task(g::NormalFormGame) - - N = length(g.nums_actions) - if N != 2 - throw(ArgumentError("Implemented only for 2-player games")) - end +function support_enumeration_task(g::NormalFormGame{2}) - task = Task(() -> _support_enumeration_task(g.players[1].payoff_array, - g.players[2].payoff_array)) + task = Task( + () -> _support_enumeration_producer(g.players[1].payoff_array, + g.players[2].payoff_array) + ) return task end """ - _support_enumeration_task{T<:Real}(payoff_matrix1::Matrix{T}, - payoff_matrix2::Matrix{T}) + _support_enumeration_producer{T<:Real}(payoff_matrix1::Matrix{T}, + payoff_matrix2::Matrix{T}) Main body of `support_enumeration_task`. # Arguments + * `payoff_matrix1::Matrix{T}`: Payoff matrix of player 1. * `payoff_matrix2::Matrix{T}`: Payoff matrix of player 2. # Produces + * `Tuple{Vector{Float64},Vector{Float64}}`: Tuple of Nash equilibrium - mixed actions. + mixed actions. """ -function _support_enumeration_task{T<:Real}(payoff_matrix1::Matrix{T}, - payoff_matrix2::Matrix{T}) +function _support_enumeration_producer{T<:Real}(payoff_matrix1::Matrix{T}, + payoff_matrix2::Matrix{T}) nums_actions = size(payoff_matrix1, 1), size(payoff_matrix2, 1) n_min = min(nums_actions...) @@ -132,15 +138,17 @@ best responses to it, in which case the outcome is stored in `out`; steps. # Arguments + * `A::Matrix{T}`: Matrix used in intermediate steps. * `out::Vector{Float64}`: Vector to store the nonzero values of the - desired mixed action. + desired mixed action. * `b::Vector{T}`: Vector used in intermediate steps. * `payoff_matrix::Matrix{T}`: The player's payoff matrix. * `own_supp::Vector{Int}`: Vector containing the player's action indices. * `opp_supp::Vector{Int}`: Vector containing the opponent's action indices. # Returns + * `::Bool`: `true` if a desired mixed action exists and `false` otherwise. """ function _indiff_mixed_action!{T<:Real}(A::Matrix{T}, out::Vector{Float64}, @@ -197,9 +205,11 @@ representation with the k set bits, by "Gosper's hack". Copy-paste from en.wikipedia.org/wiki/Combinatorial_number_system # Arguments + * `x::Int`: Integer with k set bits. # Returns + * `::Int`: Smallest integer > x with k set bits. """ function _next_k_combination(x::Int) @@ -218,10 +228,35 @@ next k-array in lexicographic ordering of the descending sequences of the elements. `a` is modified in place. # Arguments + * `a::Vector{Int}`: Array of length k. # Returns -* `:::Vector{Int}`: View of `a`. + +* `:::Vector{Int}`: Next k-array of `a`. + +# Examples + +```julia +julia> n, k = 4, 2 +(4,2) + +julia> a = collect(1:k) +2-element Array{Int64,1}: + 1 + 2 + +julia> while a[end] < n + 1 + @show a + _next_k_array!(a) + end +a = [1,2] +a = [1,3] +a = [2,3] +a = [1,4] +a = [2,4] +a = [3,4] +``` """ function _next_k_array!(a::Vector{Int}) diff --git a/test/test_support_enumeration.jl b/test/test_support_enumeration.jl index 0b785eb1..c2d3a7a8 100644 --- a/test/test_support_enumeration.jl +++ b/test/test_support_enumeration.jl @@ -2,10 +2,10 @@ @testset "test 3 by 2 non-degenerate normal form game" begin g = NormalFormGame(Player([3 3; 2 5; 0 6]), - Player([3 2 3; 2 6 1])) + Player([3 2 3; 2 6 1])) NEs = [([1.0, 0.0, 0.0], [1.0, 0.0]), - ([0.8, 0.2, 0.0], [2/3, 1/3]), - ([0.0, 1/3, 2/3], [1/3, 2/3])] + ([0.8, 0.2, 0.0], [2/3, 1/3]), + ([0.0, 1/3, 2/3], [1/3, 2/3])] for (actions_computed, actions) in zip(NEs, support_enumeration(g)) for (action_computed, action) in zip(actions_computed, actions) @@ -17,9 +17,9 @@ @testset "test 3 by 2 degenerate normal form game" begin g = NormalFormGame(Player([1 -1; -1 1; 0 0]), - Player([1 0 0; 0 0 0])) + Player([1 0 0; 0 0 0])) NEs = [([1.0, 0.0, 0.0], [1.0, 0.0]), - ([0.0, 1.0, 0.0], [0.0, 1.0])] + ([0.0, 1.0, 0.0], [0.0, 1.0])] for (actions_computed, actions) in zip(NEs, support_enumeration(g)) for (action_computed, action) in zip(actions_computed, actions)