# Pkg.clone("https://github.com/QuantEcon/Games.jl") using Games matching_pennies_bimatrix = Array{Float64}(2, 2, 2) matching_pennies_bimatrix[1, 1, :] = [1, -1] # payoff profile for action profile (1, 1) matching_pennies_bimatrix[1, 2, :] = [-1, 1] matching_pennies_bimatrix[2, 1, :] = [-1, 1] matching_pennies_bimatrix[2, 2, :] = [1, -1] g_MP = NormalFormGame(matching_pennies_bimatrix) g_MP.players[1] # Player instance for player 1 g_MP.players[2] # Player instance for player 2 g_MP.players[1].payoff_array # Player 1's payoff array g_MP.players[2].payoff_array # Player 2's payoff array g_MP[1, 1] # payoff profile for action profile (1, 1) coordination_game_matrix = [4 0; 3 2] # square matrix g_Coo = NormalFormGame(coordination_game_matrix) g_Coo.players[1].payoff_array # Player 1's payoff array g_Coo.players[2].payoff_array # Player 2's payoff array RPS_matrix = [0 -1 1; 1 0 -1; -1 1 0] g_RPS = NormalFormGame(RPS_matrix) g_PD = NormalFormGame((2, 2)) # There are 2 players, each of whom has 2 actions g_PD[1, 1] = [1, 1] g_PD[1, 2] = [-2, 3] g_PD[2, 1] = [3, -2] g_PD[2, 2] = [0, 0]; g_PD g_PD.players[1].payoff_array player1 = Player([3 1; 0 2]) player2 = Player([2 0; 1 3]); player1.payoff_array player2.payoff_array g_BoS = NormalFormGame((player1, player2)) function cournot(a::Real, c::Real, ::Val{N}, q_grid::Vector{T}) where {N,T<:Real} nums_actions = ntuple(x->length(q_grid), Val(N)) S = promote_type(typeof(a), typeof(c), T) payoff_array= Array{S}(nums_actions) for I in CartesianRange(nums_actions) Q = zero(S) for i in 1:N Q += q_grid[I[i]] end payoff_array[I] = (a - c - Q) * q_grid[I[1]] end players = ntuple(x->Player(payoff_array), Val(N)) return NormalFormGame(players) end a, c = 80, 20 N = 3 q_grid = [10, 15] # [1/3 of Monopoly quantity, Nash equilibrium quantity] g_Cou = cournot(a, c, Val(N), q_grid) g_Cou.players[1] g_Cou.nums_actions best_response(g_MP.players[1], 2) # By default, returns the best response action with the smallest index best_response(g_MP.players[1], [0.5, 0.5]) # With tie_breaking='random', returns randomly one of the best responses best_response(g_MP.players[1], [0.5, 0.5], tie_breaking="random") # Try several times best_responses(g_MP.players[1], [0.5, 0.5]) is_nash(g_MP, ([0.5, 0.5], [0.5, 0.5])) is_nash(g_MP, (1, 1)) is_nash(g_MP, ([1., 0.], [0.5, 0.5])) function print_pure_nash_brute(g::NormalFormGame) NEs = pure_nash(g) num_NEs = length(NEs) if num_NEs == 0 msg = "no pure Nash equilibrium" elseif num_NEs == 1 msg = "1 pure Nash equilibrium:\n$(NEs[1])" else msg = "$num_NEs pure Nash equilibria:\n" for (i, NE) in enumerate(NEs) i < num_NEs ? msg *= "$NE," : msg *= "$NE" end end println(join(["The game has ", msg])) end print_pure_nash_brute(g_MP) print_pure_nash_brute(g_Coo) print_pure_nash_brute(g_RPS) print_pure_nash_brute(g_BoS) print_pure_nash_brute(g_PD) print_pure_nash_brute(g_Cou) function sequential_best_response(g::NormalFormGame; init_actions::Union{Vector{Int},Void}=nothing, tie_breaking="smallest", verbose=true) N = num_players(g) a = Array{Int}(N) if init_actions == nothing init_actions = ones(Int, N) end copy!(a, init_actions) if verbose println("init_actions: $a") end new_a = Array{Int}(N) max_iter = prod(g.nums_actions) for t in 1:max_iter copy!(new_a, a) for (i, player) in enumerate(g.players) if N == 2 a_except_i = new_a[3-i] else a_except_i = (new_a[i+1:N]..., new_a[1:i-1]...) end new_a[i] = best_response(player, a_except_i, tie_breaking=tie_breaking) if verbose println("player $i: $new_a") end end if new_a == a return a else copy!(a, new_a) end end println("No pure Nash equilibrium found") return a end a, c = 80, 20 N = 3 q_grid = collect(linspace(0, a-c, 13)) # [0, 5, 10, ..., 60] g_Cou = cournot(a, c, Val(N), q_grid) a_star = sequential_best_response(g_Cou) # By default, start with (1, 1, 1) println("Nash equilibrium indices: $a_star") println("Nash equilibrium quantities: $(q_grid[a_star])") # Start with the largest actions (13, 13, 13) sequential_best_response(g_Cou, init_actions=[13, 13, 13]) is_nash(g_Cou, tuple(a_star...)) print_pure_nash_brute(g_Cou) N = 4 q_grid = collect(linspace(0, a-c, 61)) # [0, 1, 2, ..., 60] g_Cou = cournot(a, c, Val(N), q_grid) sequential_best_response(g_Cou) sequential_best_response(g_Cou, init_actions=[1, 1, 1, 31]) print(g_MP) # Matching Pennies sequential_best_response(g_MP) support_enumeration(g_MP) support_enumeration(g_Coo) support_enumeration(g_RPS) player1 = Player( [ 9504 -660 19976 -20526 1776 -8976; -111771 31680 -130944 168124 -8514 52764; 397584 -113850 451176 -586476 29216 -178761; 171204 -45936 208626 -263076 14124 -84436; 1303104 -453420 1227336 -1718376 72336 -461736; 737154 -227040 774576 -1039236 48081 -300036] ) player2 = Player( [ 72336 -461736 1227336 -1718376 1303104 -453420; 48081 -300036 774576 -1039236 737154 -227040; 29216 -178761 451176 -586476 397584 -113850; 14124 -84436 208626 -263076 171204 -45936; 1776 -8976 19976 -20526 9504 -660; -8514 52764 -130944 168124 -111771 31680] ) g_vonStengel = NormalFormGame(player1, player2); length(support_enumeration(g_vonStengel)) function all_pay_auction(r::T, c::Integer, ::Val{N}; dissipation::Bool=true) where {N,T<:Real} nums_actions = ntuple(x->c+1, Val(N)) S = typeof(zero(T)/one(T)) payoff_array= Array{S}(nums_actions) num_ties = 0 for bids in CartesianRange(nums_actions) payoff_array[bids] = -(bids[1]-1) num_ties = 1 for j in 2:N if bids[j] > bids[1] num_ties = 0 break elseif bids[j] == bids[1] if dissipation num_ties = 0 break else num_ties += 1 end end end if num_ties > 0 payoff_array[bids] += r / num_ties end end players = ntuple(x->Player(payoff_array), Val(N)) return NormalFormGame(players) end N = 2 c = 5 # odd r = 8; g_APA_odd = all_pay_auction(r, c, Val(N)) g_APA_odd.players[1] pure_nash(g_APA_odd) support_enumeration(g_APA_odd) c = 6 # even g_APA_even = all_pay_auction(r, c, Val(N)) support_enumeration(g_APA_even)