Skip to content
Merged
28 changes: 13 additions & 15 deletions src/fictplay.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,23 +63,23 @@ end
"""
FictitiousPlay(g[, gain=DecreasingGain()])

Construct a `FictitiousPlay` instance from `NormalFormGame`.
Construct a `FictitiousPlay` instance from a normal form game.

# Arguments

- `g::NormalFormGame` : `NormalFormGame` instance.
- `g::AbstractNormalFormGame` : N-player normal form game.
- `gain::AbstractGain` : Argument to specify the gain or step size;
`DecreasingGain()` or `ConstantGain(size)`.

# Returns

- `::FictitiousPlay` : The fictitious play model.
"""
FictitiousPlay(g::NormalFormGame, gain::AbstractGain=DecreasingGain()) =
FictitiousPlay(g.players, g.nums_actions, gain)

FictitiousPlay(g::AbstractNormalFormGame, gain::AbstractGain=DecreasingGain()) =
FictitiousPlay(convert(NormalFormGame, g), gain)
function FictitiousPlay(g::AbstractNormalFormGame,
gain::AbstractGain=DecreasingGain())
g = convert(NormalFormGame, g)
return FictitiousPlay(g.players, g.nums_actions, gain)
end

"""
FictitiousPlay(fp[, gain=fp.gain])
Expand Down Expand Up @@ -127,7 +127,7 @@ Construct a `StochasticFictitiousPlay` instance.

# Arguments

- `g::NormalFormGame` : `NormalFormGame` instance.
- `g::AbstractNormalFormGame` : N-player normal form game.
- `d::Distributions.Distribution` : `Distribution` instance from which payoff
perturbations are drawn.
- `gain::AbstractGain` : Argument to specify the gain or step size;
Expand All @@ -137,13 +137,11 @@ Construct a `StochasticFictitiousPlay` instance.

- `::StochasticFictitiousPlay` : The stochastic fictitious play model.
"""
StochasticFictitiousPlay(g::NormalFormGame, d::Distribution,
gain::AbstractGain=DecreasingGain()) =
StochasticFictitiousPlay(g.players, g.nums_actions, d, gain)

StochasticFictitiousPlay(g::AbstractNormalFormGame, d::Distribution,
gain::AbstractGain=DecreasingGain()) =
StochasticFictitiousPlay(convert(NormalFormGame, g), d, gain)
function StochasticFictitiousPlay(g::AbstractNormalFormGame, d::Distribution,
gain::AbstractGain=DecreasingGain())
g = convert(NormalFormGame, g)
return StochasticFictitiousPlay(g.players, g.nums_actions, d, gain)
end

"""
StochasticFictitiousPlay(fp[, d=fp.d, gain=fp.gain])
Expand Down
11 changes: 5 additions & 6 deletions src/homotopy_continuation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ typically much faster.

# Arguments

- `g::NormalFormGame`: N-player NormalFormGame instance.
- `g::AbstractNormalFormGame`: N-player normal form game.
- `ntofind=Inf`: Maximal number of Nash equilibria to find.
- `options...`: Optional arguments to pass to `HomotopyContinuation.solve`. For
example, the option `seed::UInt32` can set the random seed used during the
Expand Down Expand Up @@ -72,10 +72,9 @@ julia> all([is_nash(g, NE) for NE in NEs])
true
```
"""
hc_solve(g::AbstractNormalFormGame; ntofind=Inf, options...) =
hc_solve(convert(NormalFormGame, g); ntofind=ntofind, options...)

function hc_solve(g::NormalFormGame{N}; ntofind=Inf, options...) where N
function hc_solve(g::AbstractNormalFormGame{N};
ntofind=Inf, options...) where N
g = convert(NormalFormGame, g)
ntofind <= 0 && return NTuple{N,Vector{Float64}}[]

# Do not let HomotopyContinuation.solve reseed the global RNG by default
Expand All @@ -97,7 +96,7 @@ function hc_solve(g::NormalFormGame{N}; ntofind=Inf, options...) where N
return NEs
end

function hc_solve(g::NormalFormGame{1}; args...)
function hc_solve(g::AbstractNormalFormGame{1}; args...)
throw(ArgumentError("not implemented for 1-player games"))
end

Expand Down
8 changes: 3 additions & 5 deletions src/lemke_howson.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ the Lemke–Howson algorithm (Lemke and Howson, 1964), implemented with

# Arguments

- `g::NormalFormGame{2,T}`: 2-player NormalFormGame instance.
- `g::AbstractNormalFormGame{2,T}`: 2-player normal form game.
- `init_pivot::Int`: Initial pivot, an integer `k` such that `1 <= k <= m+n`,
where integers `1, ..., m`, and `m+1, ..., m+n` correspond to the actions
of players 1 and 2, respectively.
Expand Down Expand Up @@ -143,14 +143,12 @@ julia> res.num_iter # Number of pivoting steps performed
and Extensive Form," Chapter 3, N. Nisan, T. Roughgarden, E. Tardos, and
V. Vazirani eds., Algorithmic Game Theory, 2007.
"""
lemke_howson(g::AbstractNormalFormGame{2}; kwargs...) =
lemke_howson(convert(NormalFormGame, g); kwargs...)

function lemke_howson(g::NormalFormGame{2,T};
function lemke_howson(g::AbstractNormalFormGame{2,T};
init_pivot::Int=1,
max_iter::Int=10^6,
capping::Union{Int,Nothing} = nothing,
full_output::Union{Val{true},Val{false}}=Val(false)) where T
g = convert(NormalFormGame, g)
nums_actions = g.nums_actions
total_num = sum(nums_actions)
_check_init_pivot(init_pivot, total_num)
Expand Down
10 changes: 3 additions & 7 deletions src/localint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Construct a `LocalInteraction` instance.

# Arguments

- `g::NormalFormGame` : The game used in the model.
- `g::AbstractNormalFormGame{2}` : The 2-player game used in the model.
- `adj_matrix::AbstractMatrix` : Adjacency matrix of the graph in the model.
- `revision::AbstractRevision` : Arguments to specify the revision method;
`SimultaneousRevision()` or `AsynchronousRevision()`.
Expand All @@ -67,15 +67,11 @@ Construct a `LocalInteraction` instance.

- `::LocalInteraction` : The local interaction model.
"""
LocalInteraction(g::AbstractNormalFormGame{2},
adj_matrix::AbstractMatrix{<:Real},
revision::AbstractRevision=SimultaneousRevision()) =
LocalInteraction(convert(NormalFormGame, g), adj_matrix, revision)

function LocalInteraction(g::NormalFormGame{2,T},
function LocalInteraction(g::AbstractNormalFormGame{2,T},
adj_matrix::AbstractMatrix{S},
revision::AbstractRevision=SimultaneousRevision()
) where {T<:Real,S<:Real}
g = convert(NormalFormGame, g)
if size(adj_matrix, 1) != size(adj_matrix, 2)
throw(ArgumentError("Adjacency matrix must be square"))
end
Expand Down
8 changes: 3 additions & 5 deletions src/lrsnash.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function calls the Nash equilibrium computation routine in `lrslib`

# Arguments

- `g::NormalFormGame{2,<:RatOrInt}`: 2-player NormalFormGame instance
- `g::AbstractNormalFormGame{2,<:RatOrInt}`: 2-player normal form game
with Integer or Rational payoffs.

# Returns
Expand Down Expand Up @@ -51,10 +51,8 @@ two outputs.
- D. Avis, G. Rosenberg, R. Savani, and B. von Stengel, "Enumeration of
Nash Equilibria for Two-Player Games," Economic Theory (2010), 9-37.
"""
lrsnash(g::AbstractNormalFormGame{2,<:RatOrInt}) =
lrsnash(convert(NormalFormGame, g))

function lrsnash(g::NormalFormGame{2,<:RatOrInt})
function lrsnash(g::AbstractNormalFormGame{2,<:RatOrInt})
g = convert(NormalFormGame, g)
hrs = [buildrep(i, g.players[3-i].payoff_array) for i in 1:2]
NEs = solve_nash(hrs...)
return NEs
Expand Down
21 changes: 8 additions & 13 deletions src/pure_nash.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ will change in the future.

# Arguments

- `nfg::NormalFormGame`: Instance of N-player NormalFormGame.
- `ntofind::Inf`: Maximal number of pure action Nash equilibria to be
found; default is `prod(nfg.nums_actions)`.
- `nfg::AbstractNormalFormGame`: N-player normal form game.
- `ntofind`: Maximal number of pure action Nash equilibria to be
found; default is the number of all action profiles.
- `tol::Real` : Tolerance to be used to determine best response actions.

# Returns
Expand Down Expand Up @@ -59,18 +59,13 @@ julia> pure_nash(g)
(2, 2, 2, 2)
```
"""
pure_nash(nfg::AbstractNormalFormGame; ntofind=prod(nums_actions(nfg)),
tol::Real=1e-8) =
pure_nash(convert(NormalFormGame, nfg), ntofind=ntofind, tol=tol)

function pure_nash(nfg::NormalFormGame; ntofind=prod(nfg.nums_actions),
tol::Real=1e-8)
# Get number of players and their actions
np = num_players(nfg)
na = nfg.nums_actions
function pure_nash(nfg::AbstractNormalFormGame{N};
ntofind=prod(nums_actions(nfg)), tol::Real=1e-8) where {N}
nfg = convert(NormalFormGame, nfg)
na = nums_actions(nfg)

# Holder for all NE
ne = Array{PureActionProfile{np,Int}}(undef, 0)
ne = Array{PureActionProfile{N,Int}}(undef, 0)

# Create counter for how many to find
nfound = 0
Expand Down
30 changes: 22 additions & 8 deletions src/repeated_game.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,33 @@ Type representing an N-player repeated game.
# Fields

- `sg::NormalFormGame{N, T}` : The stage game used to create the repeated game.
- `delta::TD` : The common discount rate at which all players discount the
future.
- `delta::TD` : The common discount factor at which all players discount the
future, where `TD<:Real`.
"""
struct RepeatedGame{N, T<:Real, TD<:Real}
sg::NormalFormGame{N, T}
delta::TD
end

"""
RepeatedGame(g, delta)

Construct a `RepeatedGame` instance from a normal form game.

# Arguments

- `g::AbstractNormalFormGame` : N-player normal form game.
- `delta::TD` : The common discount factor at which all players discount the
future.

# Returns

- `::RepeatedGame` : The repeated game.

"""
RepeatedGame(g::AbstractNormalFormGame{N,T}, delta::TD) where {N,T,TD<:Real} =
RepeatedGame{N,T,TD}(convert(NormalFormGame, g), delta)

# Type alias for 2 player game
"""
RepGame2
Expand All @@ -46,7 +65,7 @@ Helper constructor that builds a repeated game for two players.

- `p1::Player` : The first player.
- `p2::Player` : The second player.
- `delta::TD` : The common discount rate at which all players discount the
- `delta::TD` : The common discount factor at which all players discount the
future.

# Returns
Expand All @@ -56,11 +75,6 @@ Helper constructor that builds a repeated game for two players.
RepeatedGame(p1::Player, p2::Player, delta::TD) where TD =
RepeatedGame(NormalFormGame((p1, p2)), delta)

# `delta::Real` as in the struct, so that an invalid `delta` is a MethodError
# rather than a recursion through `convert` on the NormalFormGame
RepeatedGame(g::AbstractNormalFormGame, delta::Real) =
RepeatedGame(convert(NormalFormGame, g), delta)

"""
unpack(rpd)

Expand Down
17 changes: 5 additions & 12 deletions src/vertex_enumeration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ to find a completely labeled pair.

# Arguments

- `g::NormalFormGame{2,T}`: 2-player NormalFormGame instance.
- `g::AbstractNormalFormGame{2,T}`: 2-player normal form game.
- `plib::Polyhedra.Library`: Allows to choose a particular package for
polyhedral computation.

Expand Down Expand Up @@ -159,11 +159,7 @@ julia> vertex_enumeration(g)
([0.0, 0.333333, 0.666667], [0.333333, 0.666667])
```
"""
vertex_enumeration(g::AbstractNormalFormGame{2};
plib::Polyhedra.Library=CDDLib.Library()) =
vertex_enumeration(convert(NormalFormGame, g), plib=plib)

function vertex_enumeration(g::NormalFormGame{2,T};
function vertex_enumeration(g::AbstractNormalFormGame{2,T};
plib::Polyhedra.Library=CDDLib.Library()) where T
S = _coeftype(T)
c = Channel{Tuple{Vector{S},Vector{S}}}(0)
Expand All @@ -184,7 +180,7 @@ Task version of `vertex_enumeration`.
# Arguments

- `c::Channel`: Channel to be bound to the vertex enumeration task.
- `g::NormalFormGame{2}`: 2-player NormalFormGame instance.
- `g::AbstractNormalFormGame{2}`: 2-player normal form game.
- `plib::Polyhedra.Library`: Allows to choose a particular package for
polyhedral computation.

Expand Down Expand Up @@ -221,13 +217,10 @@ julia> for NE in c
([0.0, 0.333333, 0.666667], [0.333333, 0.666667])
```
"""
vertex_enumeration_task(c::Channel, g::AbstractNormalFormGame{2};
plib::Polyhedra.Library=CDDLib.Library()) =
vertex_enumeration_task(c, convert(NormalFormGame, g), plib=plib)

function vertex_enumeration_task(c::Channel,
g::NormalFormGame{2};
g::AbstractNormalFormGame{2};
plib::Polyhedra.Library=CDDLib.Library())
g = convert(NormalFormGame, g)
brps = ntuple(
i -> BestResponsePolytope(g.players[3-i], idx=i, plib=plib), 2
)
Expand Down
Loading