Source code for pygplib.baserelst
"""Base Class of Relational Structure over a single domain of discourse"""
from .name import NameMgr
from .be import Be
[docs]
class BaseRelSt(Be):
"""Base class of relational structure.
This class assumes the followings:
There is no function symbol.
A first-order variable runs over a single domain of discourse.
A first-order variable is encoded with a sequence of Boolean variables of
fixed-length.
Each object in domain has unique code, represented
by a tuple of integers.
"""
def __init__(self, \
objects: tuple[int], codes: tuple[tuple[int]], length: int,\
msg: str = ""):
"""Initializes an object of BaseRelSt class."""
self.domain = objects
"""tuple of objects (constant symbol indices)"""
self._codes = codes
"""tuple of codes"""
self._pos = {}
"""dictionary to find the position of an object or its code"""
for pos, obj in enumerate(self.domain):
self._pos[obj] = pos
for pos, tup in enumerate(self._codes):
if tup in self._pos:
raise Exception(f"the codes of position {self._pos[tup]} "\
+f"and {pos} coincides: {self._codes}: "+msg)
self._pos[tup] = pos
super().__init__(length)
def _object_to_pos(self, obj: int) -> int:
"""Finds the position of an object."""
return self._pos[obj]
def _pos_to_object(self, pos: int) -> int:
"""Finds the object of a position."""
return self.domain[pos]
[docs]
def decode_assignment(self, assign: tuple[int]) -> dict[int, int]:
"""Decodes truth assignment of Boolean variables.
Args:
assign: truth assignment of Boolean variables
Returns:
dict: assignment of first-order variables to objects
Note:
element index ranges from 0 to number of codes minus 1
"""
var_symb_set = {
self.get_variable_position_pair(abs(x))[0] \
for x in assign if self.is_decodable_boolean_var(abs(x))\
}
dic = {} # dic to find set of code pos of value 1 from symbol index
for x in var_symb_set:
for px in self.get_boolean_var_list(x):
if (px in assign) and (-px in assign):
raise Exception(f"Conflicting assign w.r.t {px}")
if px in assign:
if x not in dic:
dic[x] = set()
pos = self.get_variable_position_pair(px)[1]
dic[x].add(pos+1)
continue
if -px in assign:
continue
raise Exception(f"Incomplete assign w.r.t {px}: {NameMgr.lookup_name(x)}")
result = {}
for x in var_symb_set:
if x not in dic:
dic[x] = set()
code = tuple(sorted(dic[x]))
if code not in self._pos:
raise Exception("No matching element")
result[x] = self._pos_to_object(self._pos[code])
return result
[docs]
def get_code(self, obj: int) -> tuple:
"""Returns the code of an object (a constant symbol index).
Args:
obj: constant symbol index
"""
if not NameMgr.has_name(obj):
raise ValueError(f"{obj} has no name")
if not NameMgr.is_constant(obj):
raise ValueError(\
f"{NameMgr.lookup_name(obj)} is not constant symbol")
return self._codes[self._object_to_pos(obj)]