1
Fork 0
mirror of https://github.com/Jaxan/satuio.git synced 2025-04-27 14:47:46 +02:00

Some more cleanup

This commit is contained in:
Joshua Moerman 2022-02-02 12:47:25 +01:00
parent be13bc3dbe
commit f6c1024b30
5 changed files with 81 additions and 78 deletions

View file

@ -22,19 +22,10 @@ from pysat.card import CardEnc, EncType
from argparse import ArgumentParser # Command line options from argparse import ArgumentParser # Command line options
from rich.console import Console # Import colorized output from rich.console import Console # Import colorized output
from time import time # Time for rough timing measurements
from tqdm import tqdm # Import fancy progress bars from tqdm import tqdm # Import fancy progress bars
from parser import read_machine from utils.parser import read_machine
from utils.utils import *
# function for some time logging
start = time()
start_total = start
def measure_time(*str):
global start
now = time()
print('***', *str, "in %.3f seconds" % (now - start))
start = now
# ***************** # *****************
@ -45,8 +36,8 @@ def measure_time(*str):
parser = ArgumentParser() parser = ArgumentParser()
parser.add_argument('filename', help='File of the mealy machine (dot format)') parser.add_argument('filename', help='File of the mealy machine (dot format)')
parser.add_argument('length', help='Length of the ADS', type=int) parser.add_argument('length', help='Length of the ADS', type=int)
parser.add_argument('-v', '--verbose', help="Show more output", action='store_true') parser.add_argument('-v', '--verbose', help='Show more output', action='store_true')
parser.add_argument('--show-differences', help="Show even more output", action='store_true') parser.add_argument('--show-differences', help='Show even more output', action='store_true')
parser.add_argument('--solver', help='Which solver to use (default g3)', default='g3') parser.add_argument('--solver', help='Which solver to use (default g3)', default='g3')
parser.add_argument('--states', help='For which states to compute an ADS', nargs='+') parser.add_argument('--states', help='For which states to compute an ADS', nargs='+')
args = parser.parse_args() args = parser.parse_args()
@ -259,15 +250,11 @@ measure_time('Solver finished')
# are no assumptions used in our encoding. # are no assumptions used in our encoding.
if not solution: if not solution:
console.print('! no ADS of length', length, style='bold red') console.print('! no ADS of length', length, style='bold red')
measure_total_time('Done')
exit() exit()
# We get the model, and store all true variables # Get the set of true variables
# in a set, for easy lookup. truth = get_truth(solver)
m = solver.get_model()
truth = set()
for l in m:
if l > 0:
truth.add(l)
# (If verbose) For each state, we print the paths and output. # (If verbose) For each state, we print the paths and output.
# We mark the differences red (there can be differences not # We mark the differences red (there can be differences not
@ -325,12 +312,6 @@ if args.show_differences:
console.print('') console.print('')
# Get some element from a set, doesn't matter which
def some_elem(collection):
for x in collection:
return x
# Now we will extract the tree from the solution above. # Now we will extract the tree from the solution above.
# The initial_set indicates which states we possibly started at, # The initial_set indicates which states we possibly started at,
# and the level is the current depth of the tree. # and the level is the current depth of the tree.
@ -365,7 +346,8 @@ def extract_tree(initial_set, level):
return { 'split_symbol': split_symbol, 'subtree': sub_trees } return { 'split_symbol': split_symbol, 'subtree': sub_trees }
# Pretty (and compactly) printing the tree # Pretty (and compactly) printing the tree. As before, we color code
# the output: green for inputs, red for outputs, and blue for states
def print_tree(console, tree, left=''): def print_tree(console, tree, left=''):
# The leaf is inlined in the printing # The leaf is inlined in the printing
if 'leaf' in tree: if 'leaf' in tree:
@ -394,14 +376,13 @@ def print_tree(console, tree, left=''):
print_tree(console, subtree, left + str_pad) print_tree(console, subtree, left + str_pad)
# Output the full tree # Output the distinguishing tree
print_tree(console, extract_tree(states, 0)) print_tree(console, extract_tree(states, 0))
print('')
# Report some final stats # Report some final stats
start = start_total measure_total_time('Done')
print('')
measure_time("Done with total time")
# TODO: we know that dvar(s, t, i) is an equivalence relation for # TODO: we know that dvar(s, t, i) is an equivalence relation for
# each i. Do we help the solver when asserting that? Or will that # each i. Do we help the solver when asserting that? Or will that

View file

@ -22,23 +22,15 @@ from pysat.card import CardEnc, EncType
from argparse import ArgumentParser # Command line options from argparse import ArgumentParser # Command line options
from rich.console import Console # Import colorized output from rich.console import Console # Import colorized output
from time import time # Time for rough timing measurements
from tqdm import tqdm # Import fancy progress bars from tqdm import tqdm # Import fancy progress bars
from parser import read_machine from utils.parser import read_machine
from utils.utils import *
# We set up some things for nice output # We set up some things for nice output
console = Console(markup=False, highlight=False) console = Console(markup=False, highlight=False)
# function for some time logging
start = time()
start_total = start
def measure_time(*str):
global start
now = time()
print('***', *str, "in %.3f seconds" % (now - start))
start = now
# ***************** # *****************
# Reading the input # Reading the input
@ -355,13 +347,8 @@ for length in range(2, bound + 1):
if not b: if not b:
continue continue
# We get the model, and store all true variables # Get the set of true variables
# in a set, for easy lookup. truth = get_truth(solver)
m = solver.get_model()
truth = set()
for l in m:
if l > 0:
truth.add(l)
# We extract the word # We extract the word
uio = [] uio = []
@ -381,9 +368,9 @@ for length in range(2, bound + 1):
for (s, uio) in uios.items(): for (s, uio) in uios.items():
console.print(s, style='bold black', end=' => ') console.print(s, style='bold black', end=' => ')
console.print(uio, style='bold green') console.print(uio, style='bold green')
print('')
# Report some final stats # Report some final stats
start = start_total measure_total_time('\nDone')
measure_time("Done with total time")
print('With UIO:', len(uios)) print('With UIO:', len(uios))
print('without: ', len(states) - len(uios)) print('without: ', len(states) - len(uios))

View file

@ -4,7 +4,7 @@ Script for finding UIO sequences in a Mealy machine. Uses SAT solvers
but you can specify multiple (or all) states for which an UIO is but you can specify multiple (or all) states for which an UIO is
desired. When an UIO (of specified length) does not exist, the solver desired. When an UIO (of specified length) does not exist, the solver
returns UNSAT. For the usage, please run returns UNSAT. For the usage, please run
python3 uio.py --help python3 uio.py --help
© Joshua Moerman, Open Universiteit, 2022 © Joshua Moerman, Open Universiteit, 2022
@ -17,19 +17,10 @@ from pysat.card import CardEnc, EncType
from argparse import ArgumentParser # Command line options from argparse import ArgumentParser # Command line options
from rich.console import Console # Import colorized output from rich.console import Console # Import colorized output
from time import time # Time for rough timing measurements
from tqdm import tqdm # Import fancy progress bars from tqdm import tqdm # Import fancy progress bars
from parser import read_machine from utils.parser import read_machine
from utils.utils import *
# function for some time logging
start = time()
start_total = start
def measure_time(*str):
global start
now = time()
print('***', *str, "in %.3f seconds" % (now - start))
start = now
# ***************** # *****************
@ -40,7 +31,7 @@ def measure_time(*str):
parser = ArgumentParser() parser = ArgumentParser()
parser.add_argument('filename', help='File of the mealy machine (dot format)') parser.add_argument('filename', help='File of the mealy machine (dot format)')
parser.add_argument('length', help='Length of the UIO', type=int) parser.add_argument('length', help='Length of the UIO', type=int)
parser.add_argument('-v', '--verbose', help="Show more output", action='store_true') parser.add_argument('-v', '--verbose', help='Show more output', action='store_true')
parser.add_argument('--solver', help='Which solver to use (default g3)', default='g3') parser.add_argument('--solver', help='Which solver to use (default g3)', default='g3')
parser.add_argument('--bases', help='For which states to compute an UIO (leave empty for all states)', nargs='*') parser.add_argument('--bases', help='For which states to compute an UIO (leave empty for all states)', nargs='*')
args = parser.parse_args() args = parser.parse_args()
@ -171,7 +162,7 @@ for s in tqdm(states, desc="CNF paths"):
# x_('s', s, i, t) /\ x_('in', i, a) => x_('s', s, i+1, delta(t, a)) # x_('s', s, i, t) /\ x_('in', i, a) => x_('s', s, i+1, delta(t, a))
# == -x_('s', s, i, t) \/ -x_('in', i, a) \/ x_('s', s, i+1, delta(t, a)) # == -x_('s', s, i, t) \/ -x_('in', i, a) \/ x_('s', s, i+1, delta(t, a))
solver.add_clause([-sv, -av, svar(s, i+1, next_t)]) solver.add_clause([-sv, -av, svar(s, i+1, next_t)])
# Only one output should be enabled # Only one output should be enabled
unique([ovar(s, i, o) for o in possible_outputs[(s, i)]]) unique([ovar(s, i, o) for o in possible_outputs[(s, i)]])
@ -243,14 +234,9 @@ for base in bases:
measure_time('Solver finished') measure_time('Solver finished')
if b: if b:
# We get the model, and store all true variables # Get the set of true variables
# in a set, for easy lookup. truth = get_truth(solver)
m = solver.get_model()
truth = set()
for l in m:
if l > 0:
truth.add(l)
# We print the word # We print the word
console.print('! UIO of length', length, style='bold green') console.print('! UIO of length', length, style='bold green')
for i in range(length): for i in range(length):
@ -278,7 +264,7 @@ for base in bases:
style = 'bold green' style = 'bold green'
elif evar(s, i) in truth: elif evar(s, i) in truth:
style = 'bold red' style = 'bold red'
console.print(o, end=', ', style=style) console.print(o, end=', ', style=style)
console.print('') console.print('')
@ -287,10 +273,9 @@ for base in bases:
# The core returned by the solver is not interesting: # The core returned by the solver is not interesting:
# It is only the assumption (i.e. bvar). # It is only the assumption (i.e. bvar).
print('')
# Report some final stats # Report some final stats
start = start_total measure_total_time('\nDone')
print('')
measure_time("Done with total time")
print('With UIO:', num_uios[True]) print('With UIO:', num_uios[True])
print('without: ', num_uios[False]) print('without: ', num_uios[False])

50
satuio/utils/utils.py Normal file
View file

@ -0,0 +1,50 @@
"""
Functions to measure time and print stuff nicely, etc
© Joshua Moerman, Open Universiteit, 2022
"""
from time import time
# *******************************
# Functions for some time logging
# *******************************
start = time()
start_total = start
def measure_time(*str):
global start
now = time()
print('***', *str, "in %.3f seconds" % (now - start))
start = now
def measure_total_time(*str):
global start_total
now = time()
print('***', *str, ": total time = %.3f seconds" % (now - start_total))
# ****************************
# Functions related to solving
# ****************************
# This stores all true variables in a set, for easy lookup
def get_truth(solver):
m = solver.get_model()
truth = set()
for l in m:
if l > 0:
truth.add(l)
return truth
# *****************
# General functions
# *****************
# Get some element from a set, doesn't matter which.
# (I could not find this in the standard library.)
def some_elem(collection):
for x in collection:
return x