diff --git a/src/Games.jl b/src/Games.jl index 640228a8..685e274a 100644 --- a/src/Games.jl +++ b/src/Games.jl @@ -1,10 +1,32 @@ module Games +# Packages + +# Type aliases # +typealias PureAction Integer +typealias MixedAction{T<:Real} Vector{T} +typealias Action{T<:Real} Union{PureAction,MixedAction{T}} +typealias ActionProfile{T<:Real,N} NTuple{N,Action{T}} +typealias PureActionProfile{N,T<:PureAction} NTuple{N, T} + # package code goes here include("normal_form_game.jl") +include("nash_equilibrium.jl") + + +export Player, NormalFormGame, # Types -export Player, NormalFormGame, + # Type aliases + Action, MixedAction, PureAction, ActionProfile, + + # Normal form game functions best_response, best_responses, is_best_response, payoff_vector, - is_nash, pure2mixed, num_players, num_actions, num_opponents + is_nash, pure2mixed, pure_strategy_NE, + + # General functions + num_players, num_actions, num_opponents, + + # Nash Equilibrium + pure_nash end # module diff --git a/src/normal_form_game.jl b/src/normal_form_game.jl index 4f5164c1..b9cc60ad 100644 --- a/src/normal_form_game.jl +++ b/src/normal_form_game.jl @@ -5,13 +5,6 @@ Authors: Daisuke Oyama =# -# Type aliases # - -typealias PureAction Integer -typealias MixedAction{T<:Real} Vector{T} -typealias Action{T<:Real} Union{PureAction,MixedAction{T}} -typealias ActionProfile{T<:Real,N} NTuple{N,Action{T}} - const opponents_actions_docstring = """ `opponents_actions::Union{Action,ActionProfile,Void}` : Profile of N-1 opponents' actions. If N=2, then it must be a vector of reals (in which case @@ -594,3 +587,4 @@ function pure2mixed(num_actions::Integer, action::PureAction) mixed_action[action] = 1 return mixed_action end + diff --git a/src/pure_nash.jl b/src/pure_nash.jl new file mode 100644 index 00000000..fde4d806 --- /dev/null +++ b/src/pure_nash.jl @@ -0,0 +1,26 @@ +""" +Finds all pure action Nash equilibria for a normal form +game. It returns an empty array if there is no pure +action Nash. + +Currently uses a brute force algorithm, but that hopefully +will change in the future. +""" +function pure_nash(nfg::NormalFormGame) + # Get number of players and their actions + np = num_players(nfg) + na = nfg.nums_actions + + # Holder for all NE + ne = Array(PureActionProfile{np,Int}, 0) + + # For each action profile check whether it is NE + as = CartesianRange(na) + for a in as + _a = a.I + is_nash(nfg, _a) ? push!(ne, _a) : nothing + end + + return ne +end + diff --git a/test/runtests.jl b/test/runtests.jl index 6bf5928e..9c7b3e16 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,3 +8,5 @@ else end include("test_normal_form_game.jl") +include("test_pure_nash.jl") + diff --git a/test/test_pure_nash.jl b/test/test_pure_nash.jl new file mode 100644 index 00000000..9f90a6fa --- /dev/null +++ b/test/test_pure_nash.jl @@ -0,0 +1,17 @@ +@testset "Testing Pure Nash Equilibrium Routines" begin + + # Pure strategy Nash equilibrium + @testset "2x2 Pure strategy Nash equilibrium" begin + A = [9.0 1.0 + 10.0 3.0] + p1 = Player(A) + p2 = Player(A) + + nfg = NormalFormGame(p1, p2) + psne = pure_nash(nfg) + + @test psne == [(2, 2)] + end + +end +