Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolves #4 #13 #14

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/actions/spelling/allow.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ graphviz
https
ispell
levelname
maxnode
maxtransition
nsew
padx
pady
println
pycairo
pylib
scrollregion
snd
xdg
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- markdownlint-disable MD033 MD041 -->
<!-- markdownlint-disable MD033 MD040 MD041 MD053 -->
<a name="readme-top"></a>

<!-- PROJECT LOGO -->
Expand Down Expand Up @@ -65,7 +65,7 @@ If you are having trouble installing the required Python3 Libraries see [here][p
or Download and save locally
2. Install [Cairosvg][cairosvg-package]
```sh
pip install cairosvg
pip install cairosvg
```
3. Install [Graphviz-pylib][graphviz-package]
```sh
Expand Down
2 changes: 2 additions & 0 deletions src/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
loaded_svg_content = None
MIN_WIDTH = 1
MIN_HEIGHT = 1
MAXIMUM_RECURSION_DEPTH = 15
current_image = None
transition_trace: list[str] = []
graph_states: list[str] = []
state_stack: list[str] = []
is_svg_updated = False
hints_visible = False
Expand Down
80 changes: 80 additions & 0 deletions src/graph_analysis.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from tkinter import messagebox

import globals

current_best_node = []
current_best_path = []


def perform_reachability_analysis(transitions, initial_state):
visited = set()
Expand All @@ -12,6 +17,7 @@ def perform_reachability_analysis(transitions, initial_state):
for next_state in transitions.get(state, {}):
stack.append(next_state)

globals.graph_states = visited
unreachable_states = set(transitions.keys()) - visited
return visited, unreachable_states

Expand All @@ -34,6 +40,78 @@ def on_reachability_analysis(transitions, initial_state_key, show_results):
show_results("Reachability Analysis:", results)


def decide_graph_analysis(mode, transitions, initial_state_key, show_results):
if len(globals.graph_states) <= 15:
perform_euler_hamilton_walk(mode, transitions, initial_state_key, show_results)
else:
messagebox.showinfo(
"UML Diagram has too many States",
"Performing longest Path analysis instead",
)
if mode == "node":
perform_longest_path_analysis(transitions, initial_state_key, show_results)
else:
perform_max_transition_path_analysis(
transitions, initial_state_key, show_results
)


def perform_euler_hamilton_walk(mode, transitions, initial_state_key, show_results):
global current_best_node
global current_best_path
current_best_node = []
current_best_path = []

def find_longest_paths(
current_state,
path,
visited,
recursion_depth,
):
global current_best_node
global current_best_path
visited.append(current_state)

if mode == "node":
if len(set(visited)) > len(set(current_best_node)):
current_best_node = visited
current_best_path = path
elif len(set(visited)) == len(set(current_best_node)):
if len(path) < len(current_best_path):
current_best_node = visited
current_best_path = path
elif mode == "transition":
if len(set(path)) > len(set(current_best_path)):
current_best_node = visited
current_best_path = path
elif len(set(path)) == len(set(current_best_path)):
if len(path) < len(current_best_path):
current_best_node = visited
current_best_path = path

if recursion_depth < globals.MAXIMUM_RECURSION_DEPTH:
for next_state, labels in transitions.get(current_state, {}).items():
for label in labels:
new_path = path + [(current_state, next_state, label)]
find_longest_paths(
next_state,
new_path,
visited.copy(),
recursion_depth + 1,
)

find_longest_paths(initial_state_key, [], [], 0)

transition_sequences = []
for path in current_best_path:
transition_sequences.append(path[2])

show_results(
"Maximum " + mode + " analysis:",
"\n" + " ".join(current_best_node) + "\n" + "->".join(transition_sequences),
)


def perform_longest_path_analysis(transitions, initial_state_key, show_results):
def find_longest_paths(current_state, path, visited):
visited.add(current_state)
Expand Down Expand Up @@ -75,10 +153,12 @@ def find_max_transition_path(transitions, current_state, path, visited_transitio
)
if len(result_path) > len(max_path):
max_path = result_path
print(len(max_path))
return max_path


def perform_max_transition_path_analysis(transitions, initial_state_key, show_results):
print("reached1")
max_transition_path = find_max_transition_path(
transitions, initial_state_key, [], set()
)
Expand Down
13 changes: 7 additions & 6 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
TRANSITION_TRACE_TITLE_BG,
)
from graph_analysis import (
decide_graph_analysis,
on_reachability_analysis,
perform_longest_path_analysis,
perform_max_transition_path_analysis,
perform_reachability_analysis,
)
from graph_visualization import show_state_diagram_graph
from GUI import (
Expand Down Expand Up @@ -95,6 +95,7 @@ def on_file_loaded():
initial_state_key = globals.initial_state_key
globals.analysis_results_text.pack_forget()
globals.analysis_results_visible = False
perform_reachability_analysis(current_transitions, initial_state_key)

def update_text_width():
canvas_width = canvas.winfo_width()
Expand Down Expand Up @@ -254,17 +255,17 @@ def show_analysis_results(title, content):
left_button_frame,
text="Max Nodes Analysis",
state="disabled",
command=lambda: perform_longest_path_analysis(
current_transitions, initial_state_key, show_analysis_results
command=lambda: decide_graph_analysis(
"node", current_transitions, initial_state_key, show_analysis_results
),
)

max_transition_path = tk.Button(
left_button_frame,
text="Max transitions Analysis",
state="disabled",
command=lambda: perform_max_transition_path_analysis(
current_transitions, initial_state_key, show_analysis_results
command=lambda: decide_graph_analysis(
"transition", current_transitions, initial_state_key, show_analysis_results
),
)

Expand Down
Loading