After asking here, OP is interested in listing all of the unique 2x2 games. The games here are game theory games in which there are two players and two strategies. Therefore, there are four possible results (see. Diagram). These results come with "wins" for each player. Payoff “pairs” are two wins for each player from certain combinations of strategies. Payments are given in whole numbers and cannot exceed 4.
For example, consider the following example of a 2x2 game (with a pair of wins it is written in brackets, and P1 and P2 denote players 1 and 2, respectively):
P2
Right Left
Up (2,2) (3,4)
P1
Down (1,1) (4,3)
Here the winnings take the values [(2,2), (3,4) | (1.1), (4.3)].
Now, obviously, many other games are possible (i.e., unique payoff matrices). If the gain for each player is set to 1,2,3,4 (which we can rearrange in 4! = 24 ways), then 24 * 24 games are possible. OP is interested in listing all of these games.
Here comes the thin part: two unique payoff matrices can, nevertheless, represent games, if they can be obtained from another using
i) column exchange (i.e. relabel Player A strategies)
ii) swap strings (i.e. iterate over player B's strategies)
iii) Player exchange (i.e. exchange of payout pairs and mirroring the matrix along the first diagonal)
OP posted the following code that correctly lists all 78 possible games in which there can be winnings for each (1,2,3,4).
, , : .. (1,2,3,3) 1 (1,2,3,4) 2. 4!/2! (1,2,3,3) , , .
#!/usr/bin/groovy
class Tuple {
final int a,b
Tuple(int a,int b) {
assert 1 <= a && a <= 4
assert 1 <= b && b <= 4
this.a = a
this.b = b
}
#!/usr/bin/groovy
class Tuple {
final int a,b
Tuple(int a,int b) {
assert 1 <= a && a <= 4
assert 1 <= b && b <= 4
this.a = a
this.b = b
}
boolean equals(def o) {
if (!(o && o instanceof Tuple)) {
return false
}
return a == o.a && b == o.b
}
int hashCode() {
return (a-1) * 4 + (b-1)
}
String toString() {
return "($a,$b)"
}
Tuple flip() {
return new Tuple(b,a)
}
}
class GameMatrix {
final Tuple tl, tr, bl, br
GameMatrix(Tuple tl,tr,bl,br) {
assert tl && tr && bl && br
this.tl = tl; this.tr = tr
this.bl = bl; this.br = br
}
GameMatrix colExchange() {
return new GameMatrix(tr,tl,br,bl)
}
GameMatrix rowExchange() {
return new GameMatrix(bl,br,tl,tr)
}
GameMatrix playerExchange() {
return new GameMatrix(tl.flip(),bl.flip(),tr.flip(),br.flip())
}
GameMatrix mirror() {
return new GameMatrix(br,bl,tr,tl)
}
String toString() {
return "[ ${tl},${tr} | ${bl},${br} ]"
}
boolean equals(def o) {
if (!(o && o instanceof GameMatrix)) {
return false
}
return tl == o.tl && tr == o.tr && bl == o.bl && br == o.br
}
int hashCode() {
return (( tl.hashCode() * 16 + tr.hashCode() ) * 16 + bl.hashCode() ) * 16 + br.hashCode()
}
}
static dupCheck(GameMatrix gm, Map canonicals) {
def q = gm.playerExchange()
def chain = "player"
if (q.tl.a == 4) {
}
else if (q.tr.a == 4) {
q = q.colExchange(); chain = "column ∘ ${chain}"
}
else if (q.bl.a == 4) {
q = q.rowExchange(); chain = "row ∘ ${chain}"
}
else if (q.br.a == 4) {
q = q.mirror(); chain = "mirror ∘ ${chain}"
}
else {
assert false : "Can't happen"
}
assert q.tl.a == 4
return (canonicals[q]) ? [ canonicals[q], chain ] : [ null, null ]
}
static main(String[] argv) {
def canonicals = [:]
def i = 1
[3,2,1].permutations { payoffs_playerA ->
[4,3,2,1].permutations { payoffs_playerB ->
def gm = new GameMatrix(
new Tuple(4, payoffs_playerB[0]),
new Tuple(payoffs_playerA[0], payoffs_playerB[1]),
new Tuple(payoffs_playerA[1], payoffs_playerB[2]),
new Tuple(payoffs_playerA[2], payoffs_playerB[3])
)
def ( c, chain ) = dupCheck(gm,canonicals)
if (c) {
System.out << "${gm} equivalent to ${c} via ${chain}\n"
}
else {
System.out << "${gm} accepted as canonical entry ${i}\n"
canonicals[gm] = gm
i++
}
}
}
}
"assert 1 <= a && a <= 4", " 1 <= a && a <= 3", 4 a 3 . .
, , "int hashCode() {return (a-1) * 4 + (b-1)" if "(q.tl.a == 4) {
} else if (q.tr.a == 4) {" , .
, , , , , ( 1,2,3,4 1,2,3,3).
, .
