mirror of
https://github.com/Jaxan/satuio.git
synced 2025-04-27 22:57:45 +02:00
Pretty printing the ADS
This commit is contained in:
parent
7ddb1bb45c
commit
be13bc3dbe
1 changed files with 124 additions and 48 deletions
100
satuio/ads.py
100
satuio/ads.py
|
@ -254,7 +254,13 @@ max_state_length = max([len(str) for str in states])
|
||||||
solution = solver.solve()
|
solution = solver.solve()
|
||||||
measure_time('Solver finished')
|
measure_time('Solver finished')
|
||||||
|
|
||||||
if solution:
|
# If there is no solution, we can exit. As far as I know
|
||||||
|
# there is no relevant information in the "core", as there
|
||||||
|
# are no assumptions used in our encoding.
|
||||||
|
if not solution:
|
||||||
|
console.print('! no ADS of length', length, style='bold red')
|
||||||
|
exit()
|
||||||
|
|
||||||
# We get the model, and store all true variables
|
# We get the model, and store all true variables
|
||||||
# in a set, for easy lookup.
|
# in a set, for easy lookup.
|
||||||
m = solver.get_model()
|
m = solver.get_model()
|
||||||
|
@ -263,21 +269,24 @@ if solution:
|
||||||
if l > 0:
|
if l > 0:
|
||||||
truth.add(l)
|
truth.add(l)
|
||||||
|
|
||||||
|
# (If verbose) For each state, we print the paths and output.
|
||||||
|
# We mark the differences red (there can be differences not
|
||||||
|
# marked, these are the differences decided in the solving).
|
||||||
|
if args.verbose:
|
||||||
console.print('! words:')
|
console.print('! words:')
|
||||||
|
|
||||||
|
# Print the words for each state. Note that these are
|
||||||
|
# also UIO sequenes for that state.
|
||||||
for s in states:
|
for s in states:
|
||||||
console.print(s.rjust(max_state_length, ' '), end=': ', style='bold black')
|
console.print(s.rjust(max_state_length, ' '), end=': ', style='bold black')
|
||||||
|
|
||||||
# We print the word
|
|
||||||
for i in range(length):
|
for i in range(length):
|
||||||
for a in alphabet:
|
for a in alphabet:
|
||||||
if avar(s, i, a) in truth:
|
if avar(s, i, a) in truth:
|
||||||
console.print(a, end=' ', style='bold green')
|
console.print(a, end=' ', style='bold green')
|
||||||
console.print('')
|
console.print('')
|
||||||
|
|
||||||
# (If verbose) For each state, we print the paths and output.
|
# Print the complete path of each state
|
||||||
# We mark the differences red (there can be differences not
|
|
||||||
# marked, these are the differences decided in the solving).
|
|
||||||
if args.verbose:
|
|
||||||
console.print('! paths')
|
console.print('! paths')
|
||||||
for s in states:
|
for s in states:
|
||||||
console.print(s.rjust(max_state_length, ' '), end=': ', style='bold black')
|
console.print(s.rjust(max_state_length, ' '), end=': ', style='bold black')
|
||||||
|
@ -296,6 +305,7 @@ if solution:
|
||||||
|
|
||||||
console.print('')
|
console.print('')
|
||||||
|
|
||||||
|
# Print even more debugging info (not recommended)
|
||||||
if args.show_differences:
|
if args.show_differences:
|
||||||
console.print('! differences')
|
console.print('! differences')
|
||||||
for s in states:
|
for s in states:
|
||||||
|
@ -313,10 +323,79 @@ if solution:
|
||||||
console.print('_', end=' ')
|
console.print('_', end=' ')
|
||||||
|
|
||||||
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.
|
||||||
|
# The initial_set indicates which states we possibly started at,
|
||||||
|
# and the level is the current depth of the tree.
|
||||||
|
def extract_tree(initial_set, level):
|
||||||
|
global truth, possible_outputs
|
||||||
|
|
||||||
|
some_state = some_elem(initial_set)
|
||||||
|
|
||||||
|
# If there is only one state left, we can stop the tree here
|
||||||
|
if len(initial_set) == 1:
|
||||||
|
return { 'leaf': some_state }
|
||||||
|
|
||||||
|
# Get the (single) input which makes the split
|
||||||
|
split_symbol = some_elem([a for a in alphabet if avar(some_state, level, a) in truth])
|
||||||
|
|
||||||
|
# Collect the different outputs, put them in buckets
|
||||||
|
split_outputs = {}
|
||||||
|
for s in initial_set:
|
||||||
|
for o in possible_outputs[(s, level)]:
|
||||||
|
if ovar(s, level, o) in truth:
|
||||||
|
if o not in split_outputs:
|
||||||
|
split_outputs[o] = []
|
||||||
|
split_outputs[o].append(s)
|
||||||
|
break
|
||||||
|
|
||||||
|
# For each bucket, recursively create the tree
|
||||||
|
sub_trees = {}
|
||||||
|
for (o, xs) in split_outputs.items():
|
||||||
|
sub_trees[o] = extract_tree(xs, level + 1)
|
||||||
|
|
||||||
|
# Return a node
|
||||||
|
return { 'split_symbol': split_symbol, 'subtree': sub_trees }
|
||||||
|
|
||||||
|
|
||||||
|
# Pretty (and compactly) printing the tree
|
||||||
|
def print_tree(console, tree, left=''):
|
||||||
|
# The leaf is inlined in the printing
|
||||||
|
if 'leaf' in tree:
|
||||||
|
console.print('> state', end=' ')
|
||||||
|
console.print(tree['leaf'], style='bold blue')
|
||||||
else:
|
else:
|
||||||
console.print('! no ADS of length', length, style='bold red')
|
# The next input symbol is also inlined
|
||||||
# The core returned by the solver is not interesting:
|
console.print('> ', end='')
|
||||||
# It is only the assumption (i.e. bvar).
|
console.print(tree['split_symbol'], end='', style='bold green')
|
||||||
|
# We contract single-successor paths in the tree
|
||||||
|
while len(tree['subtree']) == 1:
|
||||||
|
tree = some_elem(tree['subtree'].values())
|
||||||
|
console.print(' - ', end='')
|
||||||
|
console.print(tree['split_symbol'], end='', style='bold green')
|
||||||
|
else:
|
||||||
|
console.print()
|
||||||
|
counter = len(tree['subtree'])
|
||||||
|
# Each possible output gets a new line, and we recurse
|
||||||
|
for (o, subtree) in tree['subtree'].items():
|
||||||
|
str_elm, str_pad = '├─ ', '│ '
|
||||||
|
counter -= 1
|
||||||
|
if counter == 0:
|
||||||
|
str_elm, str_pad = '└─ ', ' '
|
||||||
|
console.print(left, str_elm, end='', sep='')
|
||||||
|
console.print(o, end=' ', style='bold red')
|
||||||
|
print_tree(console, subtree, left + str_pad)
|
||||||
|
|
||||||
|
|
||||||
|
# Output the full tree
|
||||||
|
print_tree(console, extract_tree(states, 0))
|
||||||
|
|
||||||
|
|
||||||
# Report some final stats
|
# Report some final stats
|
||||||
|
@ -336,6 +415,3 @@ measure_time("Done with total time")
|
||||||
|
|
||||||
# TODO: the same for difference -> dvar. We only do one implication,
|
# TODO: the same for difference -> dvar. We only do one implication,
|
||||||
# and perhaps adding the other makes it faster.
|
# and perhaps adding the other makes it faster.
|
||||||
|
|
||||||
# TODO: prune the tree in the end. (Some states will have shorter
|
|
||||||
# words than others.)
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue