1
Fork 0
mirror of https://git.cs.ou.nl/joshua.moerman/mealy-decompose.git synced 2025-04-30 02:07:44 +02:00

installed a linter and formatter for python

This commit is contained in:
Joshua Moerman 2024-06-14 14:00:25 +02:00
parent cf63613836
commit 353d191c0c

View file

@ -1,7 +1,6 @@
from pysat.solvers import Solver from pysat.solvers import Solver
from pysat.card import ITotalizer from pysat.card import ITotalizer
from pysat.formula import IDPool from pysat.formula import IDPool
from pysat.formula import CNF
import signal import signal
import math import math
@ -13,14 +12,15 @@ import argparse
keep_log = True keep_log = True
def main(): def main():
record_file = './results/log.txt' if keep_log else None record_file = './results/log.txt' if keep_log else None
parser = argparse.ArgumentParser(description="Decomposes a FSM into smaller components by remapping its outputs. Uses a SAT solver.") parser = argparse.ArgumentParser(description='Decomposes a FSM into smaller components by remapping its outputs. Uses a SAT solver.')
parser.add_argument('-c', '--components', type=int, default=2, help='number of components') parser.add_argument('-c', '--components', type=int, default=2, help='number of components')
parser.add_argument('-w', '--weak', default=False, action="store_true", help='look for weak decomposition') parser.add_argument('-w', '--weak', default=False, action='store_true', help='look for weak decomposition')
parser.add_argument('--add-state-trans', default=False, action="store_true", help='adds state transitivity constraints') parser.add_argument('--add-state-trans', default=False, action='store_true', help='adds state transitivity constraints')
parser.add_argument('-v', '--verbose', default=False, action="store_true", help='prints more info') parser.add_argument('-v', '--verbose', default=False, action='store_true', help='prints more info')
parser.add_argument('-t', '--timeout', type=int, default=None, help='timeout (in seconds)') parser.add_argument('-t', '--timeout', type=int, default=None, help='timeout (in seconds)')
parser.add_argument('filename', help='path to .dot file') parser.add_argument('filename', help='path to .dot file')
args = parser.parse_args() args = parser.parse_args()
@ -36,7 +36,8 @@ def main():
print(f'Input FSM: {len(machine.states)} states, {len(machine.inputs)} inputs, and {len(machine.outputs)} outputs') print(f'Input FSM: {len(machine.states)} states, {len(machine.inputs)} inputs, and {len(machine.outputs)} outputs')
if args.timeout != None: if args.timeout:
def timeout_handler(*_): def timeout_handler(*_):
with open(record_file, 'a') as file: with open(record_file, 'a') as file:
last_two_comps = '/'.join(args.filename.split('/')[-2:]) last_two_comps = '/'.join(args.filename.split('/')[-2:])
@ -71,6 +72,7 @@ class FSM:
def output(self, s, a): def output(self, s, a):
return self.output_map[(s, a)] return self.output_map[(s, a)]
def parse_dot_file(lines): def parse_dot_file(lines):
def parse_transition(line): def parse_transition(line):
(l, _, r) = line.partition('->') (l, _, r) = line.partition('->')
@ -126,6 +128,7 @@ def print_table(cell, rs, cs):
print(cell(r, c).rjust(col_size), end='') print(cell(r, c).rjust(col_size), end='')
print('') print('')
def print_eqrel(rel, xs): def print_eqrel(rel, xs):
print_table(lambda r, c: 'Y' if rel(r, c) else '·', xs, xs) print_table(lambda r, c: 'Y' if rel(r, c) else '·', xs, xs)
@ -179,7 +182,7 @@ class Encoder:
# Een hulp variabele voor False en True, maakt de andere variabelen eenvoudiger # Een hulp variabele voor False en True, maakt de andere variabelen eenvoudiger
def var_const(self, b): def var_const(self, b):
return(self.vpool.id(('const', b))) return self.vpool.id(('const', b))
# Voor elke relatie en elke twee elementen o1 en o2, is er een variabele die # Voor elke relatie en elke twee elementen o1 en o2, is er een variabele die
# aangeeft of o1 en o2 gerelateerd zijn. Er is 1 variabele voor xRy en yRx, dus # aangeeft of o1 en o2 gerelateerd zijn. Er is 1 variabele voor xRy en yRx, dus
@ -236,7 +239,7 @@ class Encoder:
# (Aka: the bijbehorende quotienten zijn joint-injective.) # (Aka: the bijbehorende quotienten zijn joint-injective.)
self.progress.reset('injectivity', guess=len(self.os) * (len(self.os) - 1) / 2) self.progress.reset('injectivity', guess=len(self.os) * (len(self.os) - 1) / 2)
for xi, xo in enumerate(self.os): for xi, xo in enumerate(self.os):
for yo in self.os[xi+1:]: for yo in self.os[xi + 1 :]:
# Tenminste een rid moet een verschil maken # Tenminste een rid moet een verschil maken
self.add_clause([-self.var_rel(rid, xo, yo) for rid in self.rids]) self.add_clause([-self.var_rel(rid, xo, yo) for rid in self.rids])
self.progress.add() self.progress.add()
@ -268,7 +271,7 @@ class Encoder:
# Belangrijkste: een element is een representant, of equivalent met een # Belangrijkste: een element is een representant, of equivalent met een
# eerder element. We forceren hiermee dat de solver representanten moet # eerder element. We forceren hiermee dat de solver representanten moet
# kiezen (voor aan de lijst). # kiezen (voor aan de lijst).
self.add_clause([self.var_state_rep(rid, sx)] + [self.var_state_rel(rid, sx, sy) for sy in states[:ix]] ) self.add_clause([self.var_state_rep(rid, sx)] + [self.var_state_rel(rid, sx, sy) for sy in states[:ix]])
for sy in states[:ix]: for sy in states[:ix]:
# rx en ry kunnen niet beide een representant zijn, tenzij ze # rx en ry kunnen niet beide een representant zijn, tenzij ze
@ -281,7 +284,7 @@ class Encoder:
# formule. We gaan een binaire zoek doen met incremental sat solving. # formule. We gaan een binaire zoek doen met incremental sat solving.
self.rhs = None self.rhs = None
if self.args.weak: if self.args.weak:
self.lower_bound = int(math.floor((self.N-1)**(1/self.c))) self.lower_bound = int(math.floor((self.N - 1) ** (1 / self.c)))
self.upper_bound = int(self.N) self.upper_bound = int(self.N)
print(f'weak size constraints {self.lower_bound} {self.upper_bound}') print(f'weak size constraints {self.lower_bound} {self.upper_bound}')
self.rhs = [] self.rhs = []
@ -292,7 +295,7 @@ class Encoder:
self.add_clauses(cnf_optim.cnf.clauses) self.add_clauses(cnf_optim.cnf.clauses)
self.rhs.append(cnf_optim.rhs) self.rhs.append(cnf_optim.rhs)
else: else:
self.lower_bound = int(math.floor(self.c * (self.N-1)**(1/self.c))) self.lower_bound = int(math.floor(self.c * (self.N - 1) ** (1 / self.c)))
self.upper_bound = int(self.N + self.c - 1) self.upper_bound = int(self.N + self.c - 1)
print(f'size constraints {self.lower_bound} {self.upper_bound}') print(f'size constraints {self.lower_bound} {self.upper_bound}')
with ITotalizer([self.var_state_rep(rid, sx) for rid in self.rids for sx in self.machine.states], ubound=self.upper_bound, top_id=self.vpool.top) as cnf_optim: with ITotalizer([self.var_state_rep(rid, sx) for rid in self.rids for sx in self.machine.states], ubound=self.upper_bound, top_id=self.vpool.top) as cnf_optim:
@ -334,8 +337,7 @@ class Encoder:
m = self.solver.get_model() m = self.solver.get_model()
model = {} model = {}
for l in m: for l in m:
if l < 0: model[-l] = False model[abs(l)] = l > 0
else: model[l] = True
if self.args.verbose: if self.args.verbose:
for rid in self.rids: for rid in self.rids:
@ -359,7 +361,7 @@ class Encoder:
counts.append(count) counts.append(count)
print(f'Reduced sizes = {counts} = {sum(counts)}') print(f'Reduced sizes = {counts} = {sum(counts)}')
if self.record_file != None: if self.record_file:
with open(self.record_file, 'a') as file: with open(self.record_file, 'a') as file:
last_two_comps = '/'.join(self.args.filename.split('/')[-2:]) last_two_comps = '/'.join(self.args.filename.split('/')[-2:])
file.write(f'{last_two_comps}\t{self.N}\t{len(self.machine.inputs)}\t{len(self.machine.outputs)}\t{self.args.weak}\t{self.c}\t{sum(counts)}\t{sorted(counts, reverse=True)}\n') file.write(f'{last_two_comps}\t{self.N}\t{len(self.machine.inputs)}\t{len(self.machine.outputs)}\t{self.args.weak}\t{self.c}\t{sum(counts)}\t{sorted(counts, reverse=True)}\n')
@ -396,5 +398,5 @@ class Encoder:
################################### ###################################
# Run script # Run script
if __name__ == "__main__": if __name__ == '__main__':
main() main()