Skip to content

Commit 56c95f8

Browse files
Cdstp 113 data loss in subgraph creation (#97)
* CDSTP-113 Created functions to get a map of overlapping out events from a DiGraph of Event * CDSTP-113 update calculate loop components to always consider any nodes that break the loop as break points (unless they have a path to an in node to exit point) or unless they are part of an eventset from a break out node that contains an event in the loop * CDSTP-113 Adds functionality to filter and replace break nodes with a connection to end events of a loop with a dummy break event type. * CDSTP-113 Added updated functionality into detect loops * CDSTP-113 Updated functionality to remove dummy break events and restructure nested PUML Graphs so that PUML can be ingested by plu2json * CDSTP-113 Updated pv_to_puml_file function to use v2 with revised loop detection and use removal of dummy break events * CDSTP-113 updated tests to account for updated methodology for break events * CDSTP-113 updated mypy errors file * CDSTP-113 Added extra tests and docs * CDSTP-113 Updated test outcomes graphs * CDSTP-113 Fixed docstrings * CDSTP-113 test for pm4py * CDSTP-113 try fixing setuptools to olde version * CDSTP-113 attempt to fix workflow * CDSTP-113 update github actions yaml * CDSTP-113 update env * CDSTP-113 update workflow * CDSTP-113 update linting workflow
1 parent d7bfad1 commit 56c95f8

17 files changed

+830
-141
lines changed

.github/workflows/PythonLinting.yml

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: run-tests
2+
on: [workflow_call]
3+
jobs:
4+
run-tests:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- name: Setup Actions
8+
uses: actions/checkout@v4
9+
10+
- name: Setup Python
11+
uses: actions/setup-python@v5
12+
with:
13+
python-version: '3.11'
14+
15+
- name: Install Python Dependencies
16+
run: |
17+
export PIP_CONSTRAINT='pip_constraint.txt'
18+
pip install --upgrade pip
19+
20+
pip install flake8
21+
flake8 --version
22+
pip install pylint
23+
pylint --version
24+
pip install mypy
25+
mypy --version
26+
27+
pip install -r requirements.txt
28+
29+
- name: Flake8
30+
if: '!cancelled()'
31+
run: |
32+
PY_FILES=$(git ls-files '*.py')
33+
34+
if [ -z "$PY_FILES" ]
35+
then
36+
echo "No files to check!"
37+
else
38+
flake8 $PY_FILES
39+
fi
40+
41+
- name: Pylint
42+
if: '!cancelled()'
43+
run: |
44+
PY_FILES=$(git ls-files '*.py')
45+
46+
if [ -z "$PY_FILES" ]
47+
then
48+
echo "No files to check!"
49+
else
50+
pylint $PY_FILES
51+
fi
52+
53+
- name: MyPy
54+
if: '!cancelled()'
55+
run: |
56+
PY_FILES=$(git ls-files '*.py')
57+
58+
if [ -z "$PY_FILES" ]
59+
then
60+
echo "No files to check!"
61+
else
62+
mypy --strict --explicit-package-bases --namespace-packages .
63+
fi

.github/workflows/test-workflow.yml

+13-10
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ on:
99
push:
1010
branches:
1111
main
12+
13+
1214
jobs:
1315
sast:
1416
uses: SmartDCSITlimited/actions-store/.github/workflows/SAST.yml@main
1517
secret-detection:
1618
uses: SmartDCSITlimited/actions-store/.github/workflows/SecretDetection.yml@main
1719
python-linting:
18-
uses: SmartDCSITlimited/actions-store/.github/workflows/PythonLinting.yml@main
20+
uses: ./.github/workflows/PythonLinting.yml
1921

2022
run-tests:
2123
runs-on: ubuntu-latest
@@ -49,15 +51,6 @@ jobs:
4951
conda install -y -c conda-forge cvxopt
5052
conda install -y -c conda-forge pygraphviz
5153
52-
- name: Install Requirements
53-
run: |
54-
pip install --upgrade pip
55-
56-
pip install pytest
57-
pytest --version
58-
59-
pip install -r requirements.txt
60-
6154
- name: Install Requirements (test-event-generator)
6255
run: |
6356
cd test-event-generator
@@ -77,6 +70,16 @@ jobs:
7770
pip install .
7871
cd ..
7972
rm -rf test-harness
73+
74+
- name: Install Requirements
75+
run: |
76+
export PIP_CONSTRAINT='pip_constraint.txt'
77+
pip install --upgrade pip
78+
79+
pip install pytest
80+
pytest --version
81+
82+
pip install -r requirements.txt
8083
8184
- name: Run Tests
8285
run: |

mypy_errors.txt

+60-60
Large diffs are not rendered by default.

pip_constraint.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
setuptools<72

tel2puml/events.py

+88-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from pm4py import ( # type: ignore[import-untyped]
1010
ProcessTree,
1111
)
12-
from networkx import DiGraph
12+
from networkx import DiGraph, Graph, connected_components
1313
from test_event_generator.solutions.graph_solution import ( # type: ignore[import-untyped] # noqa: E501
1414
GraphSolution,
1515
)
@@ -455,7 +455,7 @@ def get_reduced_event_set(event_sets: set[EventSet]) -> set[frozenset[str]]:
455455
"""This function reduces a set of event sets to a set of unique events.
456456
457457
:return: The reduced event set.
458-
:rtype: `set`[:class:`frozenset`[`str`]]
458+
:rtype: `set`[`frozenset`[`str`]]
459459
"""
460460
return {event_set.to_frozenset() for event_set in event_sets}
461461

@@ -474,3 +474,89 @@ def get_event_set_counts(event_sets: set[EventSet]) -> dict[str, set[int]]:
474474
else:
475475
event_set_counts[event] = {count}
476476
return event_set_counts
477+
478+
479+
def get_overlapping_event_types(
480+
event_sets: set[EventSet],
481+
) -> set[frozenset[str]]:
482+
"""This function gets the overlapping events from a set of event sets.
483+
484+
:param event_sets: The event sets.
485+
:type event_sets: `set`[:class:`EventSet`]
486+
:return: The overlapping events.
487+
:rtype: `set`[`frozenset`[`str`]]
488+
"""
489+
graph: "Graph[str]" = Graph()
490+
for event_set in event_sets:
491+
if len(event_set) > 1:
492+
graph.add_edges_from(
493+
{
494+
(event1, event2)
495+
for event1 in event_set
496+
for event2 in event_set
497+
}
498+
)
499+
return {frozenset(component) for component in connected_components(graph)}
500+
501+
502+
def get_overlapping_events_from_event_sets_and_connected_events(
503+
event_sets: set[EventSet], connected_events: set[Event]
504+
) -> list[set[Event]]:
505+
"""This function gets the overlapping events from a set of event sets.
506+
507+
:param event_sets: The event sets.
508+
:type event_sets: `set`[:class:`EventSet`]
509+
:param connected_events: The connected events.
510+
:type connected_events: `set`[:class:`Event`]
511+
:return: The overlapping events.
512+
:rtype: `set`[`frozenset`[:class:`str`]]
513+
"""
514+
overlapping_event_types = get_overlapping_event_types(event_sets)
515+
return [
516+
{
517+
event
518+
for event in connected_events
519+
if event.event_type in over_lapping_event_types_set
520+
}
521+
for over_lapping_event_types_set in overlapping_event_types
522+
]
523+
524+
525+
def get_overlapping_events_from_event_and_graph(
526+
event: Event, graph: "DiGraph[Event]"
527+
) -> list[set[Event]]:
528+
"""This function gets the overlapping events from a set of event sets.
529+
530+
:param event: The event.
531+
:type event: :class:`Event`
532+
:param graph: The graph.
533+
:type graph: :class:`DiGraph`[:class:`Event`]
534+
:return: The overlapping events.
535+
:rtype: `set`[`frozenset`[`str`]]
536+
"""
537+
return get_overlapping_events_from_event_sets_and_connected_events(
538+
event.event_sets, set(
539+
edge[1] for edge in graph.out_edges(event)
540+
)
541+
)
542+
543+
544+
def get_event_to_over_lapping_events_map(
545+
graph: "DiGraph[Event]",
546+
) -> dict[Event, list[set[Event]]]:
547+
"""This function gets the event to overlapping events mapping from the
548+
graph.
549+
550+
:param graph: The graph.
551+
:type graph: :class:`DiGraph`[:class:`Event`]
552+
:return: The event to overlapping events mapping.
553+
:rtype: `dict`[:class:`Event`, `list`[`set`[:class:`Event`]]]
554+
"""
555+
event_to_overlapping_events_map: dict[Event, list[set[Event]]] = {}
556+
for event in graph.nodes:
557+
over_lapping_events = get_overlapping_events_from_event_and_graph(
558+
event, graph
559+
)
560+
if over_lapping_events:
561+
event_to_overlapping_events_map[event] = over_lapping_events
562+
return event_to_overlapping_events_map

0 commit comments

Comments
 (0)