44Examples
55--------
66
7- Create a QuantEcon NormalFormGame from a gam file storing
7+ Create a QuantEcon NormalFormGame from a . gam file storing
88a 3-player Minimum Effort Game
99
1010>>> import os
2727 [[-19., -19., 1.], [ -8., -8., 2.], [ 3., 3., 3.]]]]
2828
2929"""
30+ import numbers
3031import numpy as np
3132from .normal_form_game import Player , NormalFormGame
3233
3334
35+ class GamPayoffVector :
36+ """
37+ Internal intermediate representation that stores payoffs in a single
38+ flat 1-dim array.
39+
40+ Payoff values are ordered as in the GameTracer .gam format:
41+ 1. Player-major blocks: player 0, ..., player N-1.
42+ 2. Within each block, action profiles are ordered with player 0
43+ varying fastest, then player 1, ..., player N-1 (i.e.,
44+ Fortran/column-major order).
45+
46+ Attributes
47+ ----------
48+ N : scalar(int)
49+ Number of players.
50+
51+ nums_actions : tuple(int)
52+ Tuple of the numbers of actions, one for each player.
53+
54+ payoffs : ndarray(ndim=1)
55+ Array storing payoffs in .gam order.
56+
57+ """
58+ def __init__ (self , nums_actions , payoffs ):
59+ nums_actions = tuple (nums_actions )
60+ if len (nums_actions ) == 0 :
61+ raise ValueError ('nums_actions must be a non-empty iterable ' +
62+ 'of positive integers' )
63+
64+ for n in nums_actions :
65+ if not isinstance (n , numbers .Integral ):
66+ raise TypeError ('nums_actions must contain only integers' )
67+ if n <= 0 :
68+ raise ValueError ('all nums_actions must be positive' )
69+
70+ self .nums_actions = tuple (int (n ) for n in nums_actions )
71+ self .N = len (self .nums_actions )
72+
73+ payoffs = np .ascontiguousarray (payoffs )
74+ if payoffs .ndim != 1 :
75+ raise ValueError ('payoffs must be a 1-dim array_like' )
76+
77+ expected = np .prod (self .nums_actions ) * self .N
78+ if payoffs .size != expected :
79+ raise ValueError (
80+ f'payoffs length mismatch: expected { expected } , ' +
81+ f'got { payoffs .size } '
82+ )
83+
84+ self .payoffs = payoffs
85+
86+ @classmethod
87+ def from_nfg (cls , g , dtype = None ):
88+ """
89+ Construct a GamPayoffVector from a NormalFormGame `g`.
90+
91+ Examples
92+ --------
93+ >>> player0 = Player([[0, 3], [1, 4], [2, 5]])
94+ >>> player1 = Player([[6, 7, 8], [9, 10, 11]])
95+ >>> g = NormalFormGame((player0, player1))
96+ >>> print(g)
97+ 2-player NormalFormGame with payoff profile array:
98+ [[[ 0, 6], [ 3, 9]],
99+ [[ 1, 7], [ 4, 10]],
100+ [[ 2, 8], [ 5, 11]]]
101+ >>> p = GamPayoffVector.from_nfg(g)
102+ >>> p.payoffs
103+ array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
104+
105+ """
106+ N = g .N
107+ nums_actions = g .nums_actions
108+ if dtype is None :
109+ dtype = g .dtype
110+
111+ na = np .prod (nums_actions )
112+ payoffs = np .empty (na * N , dtype = dtype )
113+
114+ for i , player in enumerate (g .players ):
115+ payoffs [na * i :na * (i + 1 )].reshape (nums_actions , order = 'F' )[:] = \
116+ player .payoff_array .transpose (
117+ (* range (N - i , g .N ), * range (N - i ))
118+ )
119+
120+ return cls (nums_actions , payoffs )
121+
122+ def to_nfg (self , dtype = None ):
123+ """
124+ Construct a NormalFormGame from self.
125+
126+ Examples
127+ --------
128+ >>> nums_actions = (3, 2)
129+ >>> payoffs = np.arange(12)
130+ >>> p = GamPayoffVector(nums_actions, payoffs)
131+ >>> g = p.to_nfg()
132+ >>> print(g)
133+ 2-player NormalFormGame with payoff profile array:
134+ [[[ 0, 6], [ 3, 9]],
135+ [[ 1, 7], [ 4, 10]],
136+ [[ 2, 8], [ 5, 11]]]
137+
138+ """
139+ N = self .N
140+ nums_actions = self .nums_actions
141+
142+ na = np .prod (nums_actions )
143+ payoffs2d = self .payoffs .reshape ((na , N ), order = 'F' )
144+ players = tuple (
145+ Player (
146+ np .asarray (
147+ payoffs2d [:, i ].reshape (nums_actions , order = 'F' ).transpose (
148+ (* range (i , N ), * range (i ))
149+ ), dtype = dtype , order = 'C'
150+ )
151+ ) for i in range (N )
152+ )
153+
154+ return NormalFormGame (players )
155+
156+
34157def _str2num (s ):
35158 """
36159 Convert string to appropriate numeric type.
@@ -52,27 +175,27 @@ def _str2num(s):
52175
53176class GAMReader :
54177 """
55- Reader object that converts a game in GameTracer gam format into
178+ Reader object that converts a game in GameTracer . gam format into
56179 a NormalFormGame.
57180
58181 """
59182 @classmethod
60183 def from_file (cls , file_path ):
61184 """
62- Read from a gam format file.
185+ Read from a . gam format file.
63186
64187 Parameters
65188 ----------
66189 file_path : str
67- Path to gam file.
190+ Path to . gam file.
68191
69192 Returns
70193 -------
71194 NormalFormGame
72195
73196 Examples
74197 --------
75- Save a gam format string in a temporary file:
198+ Save a . gam format string in a temporary file:
76199
77200 >>> import tempfile
78201 >>> fname = tempfile.mkstemp()[1]
@@ -111,12 +234,12 @@ def from_url(cls, url):
111234 @classmethod
112235 def from_string (cls , string ):
113236 """
114- Read from a gam format string.
237+ Read from a . gam format string.
115238
116239 Parameters
117240 ----------
118241 string : str
119- String in gam format.
242+ String in . gam format.
120243
121244 Returns
122245 -------
@@ -163,13 +286,13 @@ def _parse(string):
163286class GAMWriter :
164287 """
165288 Writer object that converts a NormalFormgame into a game in
166- GameTracer gam format.
289+ GameTracer . gam format.
167290
168291 """
169292 @classmethod
170293 def to_file (cls , g , file_path ):
171294 """
172- Save the GameTracer gam format string representation of the
295+ Save the GameTracer . gam format string representation of the
173296 NormalFormGame `g` to a file.
174297
175298 Parameters
@@ -186,7 +309,7 @@ def to_file(cls, g, file_path):
186309 @classmethod
187310 def to_string (cls , g ):
188311 """
189- Return a GameTracer gam format string representing the
312+ Return a GameTracer . gam format string representing the
190313 NormalFormGame `g`.
191314
192315 Parameters
@@ -196,7 +319,7 @@ def to_string(cls, g):
196319 Returns
197320 -------
198321 str
199- String representation in gam format.
322+ String representation in . gam format.
200323
201324 """
202325 return cls ._dump (g )
@@ -218,19 +341,19 @@ def _dump(g):
218341
219342def from_gam (filename : str ) -> NormalFormGame :
220343 """
221- Makes a QuantEcon Normal Form Game from a gam file.
344+ Makes a QuantEcon Normal Form Game from a . gam file.
222345
223346 Gam files are described by GameTracer [1]_.
224347
225348 Parameters
226349 ----------
227350 filename : str
228- path to gam file.
351+ path to . gam file.
229352
230353 Returns
231354 -------
232355 NormalFormGame
233- The QuantEcon Normal Form Game described by the gam file.
356+ The QuantEcon Normal Form Game described by the . gam file.
234357
235358 References
236359 ----------
@@ -243,7 +366,7 @@ def from_gam(filename: str) -> NormalFormGame:
243366
244367def to_gam (g , file_path = None ):
245368 """
246- Write a NormalFormGame to a file in gam format.
369+ Write a NormalFormGame to a file in . gam format.
247370
248371 Parameters
249372 ----------
0 commit comments