ag_gen/tools/path_walk.py
2022-03-29 14:53:12 -05:00

136 lines
5.2 KiB
Python

#!/usr/bin/env python4
import re
import argparse
import io
import os
from sys import argv, exit
parser = argparse.ArgumentParser()
parser.add_argument("-m", "--manual", dest = "manual", default = None, help="Manual Mode {node #}")
parser.add_argument("-s", "--state_info", dest="state_info", help="State Info File")
parser.add_argument("-i", "--input", dest = "input_d", help="Input Dot File")
parser.add_argument("-o", "--output", dest = "output_d", help="Output Dot File.")
parser.add_argument("-q", "--quality", dest = "quality", help="Quality to Search for in Auto Mode")
args=parser.parse_args()
#if len(argv) != 4:
# print("Usage: %s [node ID to path walk from] [input DOT file] [output DOT file]" %argv[0])
# exit(1)
if (args.manual == "0"):
print("This is the root!")
exit(1)
crit_nodes = []
if(args.manual !=None):
crit_nodes.append(args.manual)
else:
with open(args.state_info, 'r') as myfile:
text = myfile.read()
splits = text.split("ID:")
states = len(splits) -1
for i in range(states):
if "is_critical=true" in splits[i] or (args.quality !=None and args.quality in splits[i]):
crit_nodes.append(str(i-1))
print(str(i-1))
for crits in crit_nodes:
with open(args.input_d, 'r') as in_file:
text=in_file.read()
in_file.close()
# Splits input file line by line, except for first and last line
line_splits = text.split(";")
total_lines = len(line_splits)
# The first part of the file - contains the declaration of each state and any coloring
state_info = text.split("->")[0][:-2].strip('\n')
num_states=len((state_info.split(";")))-1
# The last part of the file - contains all of the edge info
path_info = text.split("->",1)[0]
# Delete all of the state_info except for the first from_node, edge text, then add the path info back
path_info = path_info[(len(path_info)-2):].strip('\n') +"->" + (text.split("->",1)[1])
# declare and init the array - num_states x num_states is probably overkill. Init with -1 since we know that will never be a valid value
node_paths = [ [-1]*num_states for i in range(num_states)]
# length * 3 since it splits into 3 parts: first part is the from_node
# second part is the to_node
# third part is the edge label. Delete the trailing '}' and new line character. i+=3 to jump to the next line
for i in range(0,(3*len(path_info.split(";")))-3,3):
# iterate through node_paths[0] to node_paths[num_states] and append the to node and label each time
# Since it could be out of order, it can't be 0 through num_states - each line you have to check what the from_node actually is, and access that node_paths[#]
node_paths[int(path_info.replace('->',' ').replace(';',' ').split()[i])].append((path_info.replace('->',' ').replace(';',' ').split()[i+1])+' ' +(path_info.replace('->',' ').replace(';',' ').split()[i+2]))
# Remove all the initialized -1's from the array
for i in range(num_states):
while -1 in node_paths[i]:
node_paths[i].remove(-1)
#node_paths[x] contains the nodes that x goes to, plus the edge label.
curr_node=crits
next_nodes = []
parsed_nodes = []
remove_nodes = []
with open("temp.dot", 'w') as tmpDOT:
tmpDOT.write(state_info+"\n")
while True:
for i in range(num_states):
#if curr_node is the to_node, log the from_node
# if (re.sub(r'^.*?', curr_node+" ", curr_node+" ")) in repr(node_paths[i]):
if (str(curr_node) + " ") in repr(node_paths[i]):
from_node=i
index =[j for j, s in enumerate(node_paths[i]) if (str(curr_node)+" ") in s]
if (node_paths[i][index[0]].index(str(curr_node) + " ")) != 0:
continue
if from_node not in next_nodes:
next_nodes.append(from_node)
tmpDOT.write(str(from_node)+"->"+node_paths[i][index[0]]+";"+"\n")
if len(next_nodes)>0:
next_nodes.sort()
parsed_nodes.append(str(curr_node))
curr_node=next_nodes.pop()
else:
break
tmpDOT.write("\n")
parsed_nodes.append('0')
tmpDOT.close()
# Delete the unused states from the dot file so there aren't floating nodes
for i in range(num_states):
if repr(i) not in parsed_nodes:
remove_nodes.append(i)
# Count -1 for the new line char, written to make sure there's not a leading new line in the file
count = -1
written=0
pwd=os.getcwd()
# Remove all duplicate lines
#with open(args.output_d, 'w') as outDOT:
with io.open(pwd +'/path_walk/' + "node_" + str(crits)+".dot", 'w', encoding='utf-8') as outDOT:
lines_seen = set()
for line in open("temp.dot", 'r'):
if count not in remove_nodes:
if line not in lines_seen:
if written == 0:
outDOT.write(line.strip('\n'))
written=1
else:
outDOT.write('\n'+ line.strip('\n'))
lines_seen.add(line)
count+=1
outDOT.write("}")
outDOT.close()