Skip to content

Commit df39303

Browse files
committed
Make parser.parse_and read a single AND gate also in binary format
1 parent 31379b7 commit df39303

File tree

1 file changed

+35
-23
lines changed

1 file changed

+35
-23
lines changed

aiger/parser.py

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ class Latch:
3939
init: bool = attr.ib(converter=bool)
4040

4141

42+
@attr.s(auto_attribs=True, frozen=True)
43+
class And:
44+
lhs: int
45+
rhs0: int
46+
rhs1: int
47+
48+
4249
@attr.s(auto_attribs=True, frozen=True)
4350
class Symbol:
4451
kind: str
@@ -60,9 +67,10 @@ class SymbolTable:
6067
@attr.s(auto_attribs=True)
6168
class State:
6269
header: Optional[Header] = None
63-
inputs: List[str] = attr.ib(factory=list)
64-
outputs: List[str] = attr.ib(factory=list)
65-
latches: List[str] = attr.ib(factory=list)
70+
inputs: List[int] = attr.ib(factory=list)
71+
outputs: List[int] = attr.ib(factory=list)
72+
latches: List[Latch] = attr.ib(factory=list)
73+
ands: List[And] = attr.ib(factory=list)
6674
symbols: SymbolTable = attr.ib(factory=SymbolTable)
6775
comments: Optional[List[str]] = None
6876
nodes: SortedDict = attr.ib(factory=SortedDict)
@@ -79,6 +87,10 @@ def remaining_outputs(self):
7987
def remaining_inputs(self):
8088
return self.header.num_inputs - len(self.inputs)
8189

90+
@property
91+
def remaining_ands(self):
92+
return self.header.num_ands - len(self.ands)
93+
8294

8395
def _consume_stream(stream, delim) -> str:
8496
line = bytearray()
@@ -225,40 +237,38 @@ def _read_delta(data):
225237

226238

227239
def _add_and(state, elems):
228-
elems = fn.lmap(int, elems)
229-
state.header.num_ands -= 1
230-
deps = set(elems[1:])
231-
state.nodes[elems[0]] = deps
240+
lhs, rhs0, rhs1 = fn.lmap(int, elems)
241+
state.ands.append(And(lhs, rhs0, rhs1))
242+
deps = {rhs0, rhs1}
243+
state.nodes[lhs] = deps
232244
for dep in deps:
233245
if dep & 1:
234246
state.nodes[dep] = {dep ^ 1}
235247

236248

237249
def parse_and(state, stream) -> bool:
238-
if state.header.num_ands <= 0:
250+
if state.remaining_ands <= 0:
239251
return False
240252

241253
if state.header.binary_mode:
242-
lhs = 2 * (state.header.num_inputs + state.header.num_latches)
243-
for i in range(state.header.num_ands):
244-
lhs += 2
245-
delta = _read_delta(stream)
246-
if delta > lhs:
247-
raise ValueError(f"Invalid lhs {lhs} or delta {delta}")
248-
rhs0 = lhs - delta
249-
delta = _read_delta(stream)
250-
if delta > rhs0:
251-
raise ValueError(f"Invalid rhs0 {rhs0} or delta {delta}")
252-
rhs1 = rhs0 - delta
253-
_add_and(state, (lhs, rhs0, rhs1))
254-
254+
idx = state.header.num_inputs + state.header.num_latches + len(state.ands) + 1
255+
lhs = 2 * idx
256+
delta = _read_delta(stream)
257+
if delta > lhs:
258+
raise ValueError(f"Invalid lhs {lhs} or delta {delta}")
259+
rhs0 = lhs - delta
260+
delta = _read_delta(stream)
261+
if delta > rhs0:
262+
raise ValueError(f"Invalid rhs0 {rhs0} or delta {delta}")
263+
rhs1 = rhs0 - delta
255264
else:
256265
line = _consume_stream(stream, '\n')
257266
match = AND_PATTERN.match(line)
258267
if match is None:
259268
raise ValueError(f"Expecting an and: {line}")
269+
lhs, rhs0, rhs1 = match.groups()
260270

261-
_add_and(state, match.groups())
271+
_add_and(state, (lhs, rhs0, rhs1))
262272
return True
263273

264274

@@ -334,7 +344,7 @@ def parse(stream):
334344
if parser not in (parse_header, parse_output, parse_comment, parse_symbol):
335345
raise ValueError(DONE_PARSING_ERROR.format(state))
336346

337-
assert state.header.num_ands == 0
347+
assert state.remaining_ands == 0
338348
assert state.remaining_inputs == 0
339349
assert state.remaining_outputs == 0
340350
assert state.remaining_latches == 0
@@ -349,6 +359,7 @@ def parse(stream):
349359

350360
# Create expression DAG.
351361
latch_ids = {latch.id: name for name, latch in latches.items()}
362+
and_ids = {and_.lhs: and_ for and_ in state.ands}
352363
lit2expr = {0: A.aig.ConstFalse()}
353364
for lit in toposort_flatten(state.nodes):
354365
if lit == 0:
@@ -361,6 +372,7 @@ def parse(stream):
361372
elif lit & 1:
362373
lit2expr[lit] = A.aig.Inverter(lit2expr[lit & -2])
363374
else:
375+
assert lit in and_ids
364376
nodes = [lit2expr[lit2] for lit2 in state.nodes[lit]]
365377
lit2expr[lit] = reduce(A.aig.AndGate, nodes)
366378

0 commit comments

Comments
 (0)