Skip to content
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ sample-data/*.json
# Keep repository sample graphs
!sample-data/example.json
!sample-data/rg_imaging.json
!sample-data/synthetic.json


# PyInstaller output, to be enabled later
Expand Down
60 changes: 57 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,63 @@ All notable changes to LTSVisualizer are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased](https://github.com/dbera/LTSVisualizer)
## [Unreleased](https://github.com/dbera/LTSVisualizer/compare/v0.4.0...HEAD)

## [0.4.0](https://github.com/dbera/LTSVisualizer) - 2026-08-06
### Added

- Added an on-demand **Analysis** tab alongside the Inspector.
- Added terminal-state detection for states without outgoing transitions.
- Added iterative strongly connected component computation without recursive graph traversal.
- Added cyclic-component classification for multi-state SCCs and singleton states with self-loops.
- Added inline Web Worker execution so graph analysis does not block the main browser interface.
- Added analysis cancellation, stale-result protection, worker error handling, rerun support, and automatic reset when another graph is loaded.
- Added terminal-state filtering, pagination with at most 100 results per page, and state navigation using the current neighborhood depth.
- Added cyclic-component minimum-size filtering, pagination with at most 100 results per page, and component-only graph views.
- Added user-facing sequential cyclic-component numbering independent of internal SCC identifiers.
- Added large synthetic tests for long acyclic graphs and large strongly connected components.
- Added worker-controller tests for success, failure, cancellation, reruns, stale responses, malformed responses, reset, and disposal.
- Added `sample-data/synthetic.json` with known terminal-state and SCC results for manual verification.
- Added a **Paths** tab for a user-defined number of shortest paths between source and target states.
- Added configurable maximum visits per state; `1` produces loopless paths and higher values permit bounded revisits.
- Added equal-source-and-target support, including zero-transition paths and bounded returning cycles.
- Added edge-ID-sequence uniqueness so parallel transitions produce distinct alternatives.
- Added deterministic shortest-first ordering by transition count.
- Added reverse-distance-guided search to prioritize reachable alternatives and prune states that cannot reach the target.
- Added internal candidate safeguards with partial-result reporting when additional paths may exist.
- Added an inline path-search Web Worker with cancellation, stale-response protection, reruns, errors, reset, and disposal.
- Added path-search and worker-controller tests covering ordering, revisits, self-loops, parallel edges, equal endpoints, safeguards, cancellation, long paths, reverse-distance pruning, and lifecycle behavior.
- Added computed-path navigation using existing visualization and JSON and PlantUML exports.
- Added expandable transition details with names, source and target states, and exact edge IDs.
- Added clickable result details that center and select graph edges or states while keeping the Paths tab open.
- Added graph-view snapshots and **Return to graph view** restoration for visible elements, positions, zoom, pan, focus, neighborhood depth, and layout.
- Added separate curved rendering for parallel transitions.

### Changed

- Kept graph analysis explicitly user-triggered instead of running automatically when a graph is loaded or when the Analysis tab is opened.
- Limited worker input to node IDs and edge topology instead of transferring markings, labels, inputs, outputs, or other semantic data.
- Kept terminal-state terminology separate from deadlock classification because successful completion and unintended deadlock cannot be distinguished from topology alone.
- Updated path selection to leave a component-only graph view before path construction begins.
- Preserved analysis results while switching between Inspector and Analysis tabs or navigating individual results.
- Preserved path-search results while switching among Inspector, Analysis, and Paths.
- Kept computed-path inspection non-disruptive by pinning Inspector data without switching tabs automatically.
- Reused the selected-path representation so computed paths retain ordered edge IDs, loops, repeated traversals, parallel-edge identity, semantic data, and export behavior.
- Kept computed-path viewport fitting separate from layout so selecting a result does not rearrange states.
- Reserved the path-search model for future ordered transition constraints and partial transition-data matching.

### Fixed

- Fixed selected SCC views retaining states and transitions from the previously visible graph.
- Fixed cyclic components being displayed with confusing internal SCC IDs instead of sequential user-facing numbers.
- Fixed stale worker responses being able to affect a newer analysis request.
- Fixed worker cleanup during cancellation, reset, rerun, and component unmounting.
- Fixed dense searches wasting candidate capacity on branches that cannot reach the target by adding reverse-distance pruning.
- Fixed long-path candidate construction repeatedly copying complete path data by using parent-linked candidates and reconstructing edge IDs only for completed paths.
- Fixed computed paths being difficult to locate by fitting the viewport without changing node positions.
- Fixed leaving a computed-path view requiring manual graph reconstruction by restoring the saved graph view explicitly.
- Fixed edge-unique paths with identical state sequences being visually indistinguishable by separating parallel curves and exposing exact transition details.

## [0.4.0](https://github.com/dbera/LTSVisualizer/compare/v0.3.0...v0.4.0) - 2026-08-06

### Added

Expand Down Expand Up @@ -221,7 +275,7 @@ When preparing a release:
Example:

```markdown
## [0.4.0] - 2026-08-06
## [0.5.0] - YYYY-MM-DD
```

## Versioning guidance
Expand Down
113 changes: 100 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,48 @@ LTSVisualizer does not import PlantUML files. PlantUML remains available only as
- Pin inspector content while continuing to explore the graph.
- Clear pinned inspector content without clearing a selected path.

### Graph analysis

- Open the **Analysis** tab without affecting the Inspector.
- Run analysis explicitly with **Run analysis**. Analysis is never started automatically when a graph is loaded.
- Detect terminal states, defined as states with no outgoing transitions.
- Compute strongly connected components using an iterative graph traversal that avoids recursive call-stack limits.
- Classify an SCC as cyclic when it contains more than one state or when a singleton state has a self-loop.
- Run graph analysis in an inline Web Worker so the browser interface remains responsive.
- Cancel an analysis while it is running.
- Ignore stale worker results after cancellation, reruns, or loading another graph.
- Filter terminal states by state ID and browse large result sets in pages of 100.
- Select a terminal state to open its current neighborhood view.
- Filter cyclic components by minimum component size and browse results in pages of 100.
- Select one cyclic component to display only its member states and internal transitions.
- Clear a component-only view and return to normal neighborhood exploration.
- Use the same analysis functionality in the hosted application and the offline `file:///` build.

A terminal state is not automatically an error. Whether a terminal state represents successful completion or an unintended deadlock depends on the model. LTSVisualizer reports terminal states and does not attempt to classify their business meaning.

Analysis results are held in browser memory for the currently loaded graph. They are reset when another graph is opened and are not added to graph or selected-path exports.

### Bounded alternative path search

- Open the **Paths** tab to compute up to a user-defined number of shortest paths between two states.
- Set **Visits per state** to `1` for loopless paths or to a higher value to allow bounded revisits.
- Support equal source and target states. The zero-transition path is returned first, and returning cycles may follow when the visit bound permits them.
- Treat paths as unique by ordered edge-ID sequence, so parallel transitions remain distinct even when they connect the same states.
- Order results by increasing transition count, with deterministic ordering for equal-length alternatives.
- Use reverse shortest-distance guidance from the target to prioritize reachable alternatives and prune states that cannot reach the target.
- Run searches in an inline Web Worker with cancellation, stale-result protection, errors, reruns, and reset when another graph is loaded.
- Stop safely at internal candidate safeguards and report partial results without claiming that no additional paths exist.
- Select a result to reuse existing path visualization and JSON and PlantUML exports.
- Separate parallel transitions visually and expose transition names, source and target states, and exact edge IDs.
- Select transition or state details to center and select the corresponding graph element without leaving the **Paths** tab.
- Pin clicked transition or state data for later viewing in Inspector without switching tabs automatically.
- Preserve search results while switching among Inspector, Analysis, and Paths.
- Fit the viewport around a computed path without changing node positions.
- Use **Return to graph view** to restore visible elements, positions, zoom, pan, focus, neighborhood depth, and layout while retaining results.
- Use the same functionality in hosted and offline `file:///` builds.

Path-search results are kept in browser memory for the currently loaded graph and are reset when another graph is opened.

### Manual path selection

- Start a path from the currently focused state.
Expand All @@ -105,6 +147,19 @@ The repository includes:

- `sample-data/example.json`: a small graph for quick checks.
- `sample-data/rg_imaging.json`: a larger, realistic reachability graph.
- `sample-data/synthetic.json`: a synthetic graph for terminal-state and strongly connected component analysis.

The expected analysis for `synthetic.json` is:

```text
States: 32
Transitions: 41
Terminal states: 4
Cyclic components: 5
States in cyclic components: 19
Largest cyclic component: 8
Cyclic component sizes: 8, 5, 3, 2, 1
```

## JSON input format

Expand Down Expand Up @@ -337,6 +392,34 @@ Graph data remains in the browser and is not uploaded to a server.

For very large graphs, neighborhood exploration is recommended instead of displaying every state and transition simultaneously.

### Analyze a graph

1. Open the **Analysis** tab in the right-hand panel.
2. Select **Run analysis**. Loading a graph or opening the tab does not start computation.
3. Select **Cancel** if the analysis should be stopped.
4. Review the terminal-state and cyclic-component summary.
5. Expand **Terminal states** to filter and select a terminal state.
6. Expand **Cyclic components** to filter by minimum size and select a component.
7. Select **Clear component view** to return to normal neighborhood exploration.
8. Select **Run again** to recompute the results for the current graph.

For large graphs, worker execution prevents the analysis algorithm from blocking the main browser interface. Preparing and transferring graph topology still consumes browser memory, so analysis remains an explicit user action.

### Find alternative paths

1. Open the **Paths** tab.
2. Enter source and target state IDs.
3. Choose the requested number of paths.
4. Set **Visits per state** to `1` for loopless paths or higher for bounded revisits.
5. Select **Find paths**. During a running search, the action changes to **Cancel**.
6. Select a result to display it without relaying out its states.
7. Expand **Show transition details** to compare transition names, state pairs, and edge IDs.
8. Select a transition name or edge ID to center and select its edge, or select a state ID to center and select its state.
9. Use **Export .puml** or **Export .json** to export the displayed computed path.
10. Select **Return to graph view** to restore the prior graph context without clearing results.

Paths are ordered by transition count and are unique by ordered edge IDs. If source and target are equal, the zero-transition path is valid.

### Select a path

1. Search for or focus the desired starting state.
Expand Down Expand Up @@ -438,6 +521,10 @@ React and TypeScript application
|-- Cytoscape.js visualization
|-- Search and neighborhood exploration
|-- Structured semantic-data inspection
|-- On-demand terminal-state and SCC analysis
| `-- Inline Web Worker with cancellation
|-- Bounded alternative path search
| `-- Reverse-distance-guided inline Web Worker with cancellation
|-- Manual path selection
|-- Complete-graph JSON export
|-- Selected-path JSON export
Expand Down Expand Up @@ -480,6 +567,7 @@ LTSVisualizer/
| |-- src/
| | |-- components/
| | |-- graph/
| | |-- workers/
| | |-- App.css
| | |-- App.tsx
| | |-- index.css
Expand All @@ -491,7 +579,8 @@ LTSVisualizer/
| `-- vite.offline.config.ts
|-- sample-data/
| |-- example.json
| `-- rg_imaging.json
| |-- rg_imaging.json
| `-- synthetic.json
|-- CHANGELOG.md
|-- CONTRIBUTING.md
|-- LICENSE
Expand Down Expand Up @@ -543,7 +632,7 @@ npm run build
npm run build:offline
```

The current test suite covers JSON validation and round trips, graph serialization, complete-graph export, path selection, loops, repeated states, parallel edges, selected-path export, semantic data, and PlantUML path export.
The current test suite covers JSON validation and round trips, graph serialization, complete-graph export, manual and computed path selection, loops, repeated states, bounded revisits, source-equals-target paths, self-loops, parallel edges, deterministic shortest-first ordering, reverse-distance pruning, resource safeguards, selected-path export, semantic data, PlantUML path export, terminal-state detection, iterative SCC computation, large synthetic graph topologies, and worker-controller lifecycle behavior.

## Build targets

Expand Down Expand Up @@ -633,30 +722,28 @@ The tag triggers the offline HTML release workflow and publishes `LTSVisualizer.
- PlantUML is an export-only format.
- Extremely large full-graph views can be visually dense even when rendering remains responsive.
- Global force-directed layouts are intentionally avoided because they can be computationally expensive in the browser.
- Terminal states are reported topologically and are not classified as successful completions or definite deadlocks.
- Graph analysis uses a worker and is user-triggered, but very large graphs still require additional browser memory for topology transfer and analysis results.
- Bounded path search is user-triggered and uses a worker, but highly connected graphs can still reach internal candidate safeguards before every requested alternative is found. Partial results are reported and additional valid paths may exist.
- Cancelling path search terminates its worker immediately; partial paths found before cancellation are not retained.
- The offline release depends on browser support for local `file:///` applications and file selection.
- GitHub Pages availability depends on successful processing by GitHub's deployment service.

## Roadmap

Planned priorities:
Planned priority:

1. Refactor graph loading, shared graph types, Cytoscape integration, and visualization logic.
2. Experiment with constrained graph search.
1. Extend bounded alternative path search with transition constraints.

The constrained graph-search experiment may support:
The future constrained-search extension may support:

- Start and optional target states
- Required transitions in order
- Required transitions matched by transition name and specific or partial structured input and output data
- Forbidden transitions
- Maximum path length
- Shortest matching paths
- Loops and parallel transitions
- Reuse of the existing path visualization and export functionality
- Additional constraint combinations while preserving bounded revisits, parallel-edge identity, shortest-first results, and existing visualization and export functionality

Additional potential improvements include:

- Deadlock-state detection
- Strongly connected component analysis
- State-to-state marking differences
- Token-journey visualization
- Transition-frequency analytics
Expand Down
Loading
Loading