def _encode_table(self): self._encoded_table = [] for indices, conditions in self.table: # Encode the mask. mask_code = long(0) for idx in indices: mask_code += 2**long(idx) # Low order, low index. # Encode each condition of truth table. encoded_sub_table = set() for condition in conditions: encoded_condition = long(0) for idx, state in zip(indices, condition): encoded_condition += 2**long(idx) if int(state) else 0 encoded_sub_table.add(encoded_condition) self._encoded_table.append((mask_code, encoded_sub_table))
def __init__(self, table, reduced=False, names=None, metadata=None): if not isinstance(table, (list, tuple)): raise TypeError("table must be a list or tuple") super(LogicNetwork, self).__init__(size=len(table), names=names, metadata=metadata) # Store positive truth table for human reader. self.table = [] for row in table: # Validate incoming indices. if not (isinstance(row, (list, tuple)) and len(row) == 2): raise TypeError("Invalid table format") for idx in row[0]: if idx >= self.size: raise IndexError("mask index out of range") # Validate truth table of the sub net. if not isinstance(row[1], (list, tuple, set)): raise TypeError("Invalid table format") conditions = set() for condition in row[1]: conditions.add(''.join([str(long(s)) for s in condition])) self.table.append((row[0], conditions)) if reduced: self.reduce_table() # Encode truth table for faster computation. self._encode_table()
def test_init_long(self): table = [((), set()) for _ in range(65)] table[0] = ((np.int64(64), ), set('1')) mask = long(2)**64 net = LogicNetwork(table) self.assertEqual(net.table, table) self.assertEqual(net._encoded_table[0], (mask, set([mask])))
def is_dependent(self, target, source): """ Is the ``target`` node dependent on the state of ``source``? .. doctest:: logicnetwork >>> net = LogicNetwork([((1, 2), {'01', '10'}), ... ((0, 2), {'01', '10', '11'}), ... ((0, 1), {'11'})]) >>> net.is_dependent(0, 0) False >>> net.is_dependent(0, 2) True :param target: index of the target node :type target: int :param source: index of the source node :type source: int :return: whether the target node is dependent on the source """ sub_table = self.table[target] if source not in sub_table[0]: # No explicit dependency. return False # Determine implicit dependency. i = sub_table[0].index(source) counter = {} for state in sub_table[1]: # State excluding source. state_sans_source = state[:i] + state[i + 1:] if long(state[i]) == 1: counter[state_sans_source] = counter.get(state_sans_source, 0) + 1 else: counter[state_sans_source] = counter.get(state_sans_source, 0) - 1 if any(counter.values()): # States uneven. return True return False
def __init__(self, table, names=None, reduced=False): """ Construct a network from a logic truth table. A truth table stores a list of tuples, one for each node in order. A tuple of the form `(A, {C1, C2, ...})` at index `i` provides the activation conditions for the node of index `i`. `A` is a tuple marking the indices of the nodes which influence the state of node `i` via logic relations. `{C1, C2, ...}` is a set, each element of which is the collection of binary states of these influencing nodes that would activate node `i`, setting it to `1`. Any other collection of states of nodes in `A` are assumed to deactivate node `i`, setting it to `0`. `C1`, `C2`, etc. are sequences (`tuple` or `str`) of binary digits, each being the binary state of corresponding node in `A`. .. rubric:: Examples .. doctest:: logicnetwork >>> net = LogicNetwork([((0,), {'0'})]) >>> net.size 1 >>> net.table [((0,), {'0'})] .. doctest:: logicnetwork >>> net = LogicNetwork([((1,), {'0', '1'}), ((0,), {'1'})]) >>> net.size 2 >>> net.table == [((1,), {'0', '1'}), ((0,), {'1'})] True .. doctest:: logicnetwork >>> net = LogicNetwork([((1, 2), {'01', '10'}), ... ((0, 2), ((0, 1), '10', [1, 1])), ... ((0, 1), {'11'})], ['A', 'B', 'C']) >>> net.size 3 >>> net.names ['A', 'B', 'C'] >>> net.table == [((1, 2), {'01', '10'}), ... ((0, 2), {'01', '11', '10'}), ((0, 1), {'11'})] True :param table: the logic table :param names: names of nodes, default None """ if not isinstance(table, (list, tuple)): raise TypeError("table must be a list or tuple") self.__size = len(table) if names: if not isinstance(names, (list, tuple)): raise TypeError("names must be a list or tuple") elif len(names) != self.__size: raise ValueError("number of names must match network size") else: self.names = list(names) # Store positive truth table for human reader. self.table = [] for row in table: # Validate incoming indices. if not (isinstance(row, (list, tuple)) and len(row) == 2): raise ValueError("Invalid table format") for idx in row[0]: if idx >= self.__size: raise IndexError("mask index out of range") # Validate truth table of the sub net. if not isinstance(row[1], (list, tuple, set)): raise ValueError("Invalid table format") conditions = set() for condition in row[1]: conditions.add(''.join([str(long(s)) for s in condition])) self.table.append((row[0], conditions)) if reduced: self.reduce_table() self._state_space = StateSpace(self.__size, base=2) # Encode truth table for faster computation. self._encode_table() self.metadata = {}
def _unsafe_encode(self, state): encoded, place = long(0), long(1) for x in state: encoded += place * long(x) place <<= 1 return encoded