Skip to content

Commit

Permalink
Migrate action and infoset to pure-python cython.
Browse files Browse the repository at this point in the history
  • Loading branch information
tturocy committed Sep 1, 2023
1 parent bc95936 commit dcc665e
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 53 deletions.
40 changes: 14 additions & 26 deletions src/pygambit/core/action.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
import typing

from libcpp.string cimport string

cdef class Action:
@cython.cclass
class Action:
"""A choice available at an information set."""
cdef c_GameAction action
action = cython.declare(c_GameAction)

def __repr__(self):
return (
Expand All @@ -35,21 +33,15 @@ cdef class Action:
f"in game '{self.infoset.game.title}'>"
)

def __richcmp__(self, other, whichop) -> bool:
def __eq__(self, other: typing.Any) -> bool:
if isinstance(other, Action):
if whichop == 2:
return self.action.deref() == (<Action>other).action.deref()
elif whichop == 3:
return self.action.deref() != (<Action>other).action.deref()
else:
raise NotImplementedError
else:
if whichop == 2:
return False
elif whichop == 3:
return True
else:
raise NotImplementedError
return self.action.deref() == (<Action> other).action.deref()
return False

def __ne__(self, other: typing.Any) -> bool:
if isinstance(other, Action):
return self.action.deref() != (<Action> other).action.deref()
return True

def __hash__(self) -> long:
return long(<long>self.action.deref())
Expand Down Expand Up @@ -103,13 +95,9 @@ cdef class Action:
def prob(self) -> typing.Union[decimal.Decimal, Rational]:
"""
Get or set the probability a chance action is played.

Parameters
----------
value : Any
The probability the action is played. This can be any numeric type, or any object that
has a string representation which can be interpreted as an integer,
decimal, or rational number.
When setting the probability, the value can be any numeric type, or any object that
has a string representation which can be interpreted as an integer,
decimal, or rational number.

Raises
------
Expand Down
53 changes: 26 additions & 27 deletions src/pygambit/core/infoset.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,14 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#

cdef class Members(Collection):

@cython.cclass
class Members(Collection):
"""The set of nodes which are members of an information set."""
cdef c_GameInfoset infoset
infoset = cython.declare(c_GameInfoset)

def __init__(self, infoset: Infoset):
self.infoset = infoset.infoset

def __len__(self):
return self.infoset.deref().NumMembers()
Expand All @@ -36,9 +41,10 @@ cdef class Members(Collection):
return n


cdef class Actions(Collection):
@cython.cclass
class Actions(Collection):
"""The set of actions which are available at an information set."""
cdef c_GameInfoset infoset
infoset = cython.declare(c_GameInfoset)

def add(self, action=None):
"""Add an action at the information set. If `action` is not null, the new action
Expand All @@ -60,36 +66,32 @@ cdef class Actions(Collection):
def __getitem__(self, act):
if not isinstance(act, int):
return Collection.__getitem__(self, act)
cdef Action a
a = cython.declare(Action)
a = Action()
a.action = self.infoset.deref().GetAction(act+1)
return a

cdef class Infoset:

@cython.cclass
class Infoset:
"""Represents an information set in a :py:class:`Game`."""
cdef c_GameInfoset infoset
infoset = cython.declare(c_GameInfoset)

def __repr__(self) -> str:
return (
f"<Infoset [{self.infoset.deref().GetNumber()-1}] '{self.label}' "
f"for player '{self.player.label}' in game '{self.game.title}'>"
)
def __richcmp__(Infoset self, other, whichop) -> bool:

def __eq__(self, other: typing.Any) -> bool:
if isinstance(other, Infoset):
if whichop == 2:
return self.infoset.deref() == (<Infoset>other).infoset.deref()
elif whichop == 3:
return self.infoset.deref() != (<Infoset>other).infoset.deref()
else:
raise NotImplementedError
else:
if whichop == 2:
return False
elif whichop == 3:
return True
else:
raise NotImplementedError
return self.infoset.deref() == (<Infoset> other).infoset.deref()
return False

def __ne__(self, other: typing.Any) -> bool:
if isinstance(other, Infoset):
return self.infoset.deref() != (<Infoset> other).infoset.deref()
return True

def __hash__(self) -> long:
return long(<long>self.infoset.deref())
Expand Down Expand Up @@ -155,18 +157,15 @@ cdef class Infoset:
@property
def actions(self) -> Actions:
"""Returns the set of actions at the information set."""
cdef Actions a
a = cython.declare(Actions)
a = Actions()
a.infoset = self.infoset
return a

@property
def members(self) -> Members:
"""Returns the set of nodes which are members of the information set."""
cdef Members m
m = Members()
m.infoset = self.infoset
return m
return Members(self)

@property
def player(self) -> Player:
Expand Down
1 change: 1 addition & 0 deletions src/pygambit/gambit.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import fractions
import warnings
import typing

import cython
from libcpp cimport bool
from libcpp.string cimport string
import typing
Expand Down

0 comments on commit dcc665e

Please sign in to comment.