-
Notifications
You must be signed in to change notification settings - Fork 1
[Stepper] Add Enhanced Table View with Matrix Display for Subformula Satisfaction #102
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
Changes from 10 commits
9bcc776
a619dc2
b5dbc3f
c04dc33
940bac2
07bc78f
9047c52
c473ef9
d82b29e
4f87e64
429715c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -71,6 +71,13 @@ def formattedTraceAssignment(self): | |
| asStr = asStr.replace('!', '¬') | ||
| return asStr | ||
|
|
||
| def getAllSubformulae(self): | ||
| """Extract all subformulae from this node and its children recursively.""" | ||
| result = [(self.formula, self.satisfied)] | ||
| for child in self.children: | ||
| result.extend(child.getAllSubformulae()) | ||
| return result | ||
|
|
||
| def __formula_to__mermaid_inner__(self): | ||
| edges = [] | ||
| if self.satisfied: | ||
|
|
@@ -173,6 +180,43 @@ def to_dict(self): | |
| "prefix_states": self.prefix_states, | ||
| "cycle_states": self.cycle_states | ||
| } | ||
|
|
||
| def getMatrixView(self): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 0s and 1s are not visible in the matrix view. We should also make the cycle obvious with a header like we do in the Table view. Don't worry about highlighting cells red or green, make the actual TEXT color for 0 or 1 these colors. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed the Matrix View visibility issues:
See commit 07bc78f and screenshot: https://github.com/user-attachments/assets/a160c974-96b5-4c40-b534-761b8d5b746d |
||
| """Generate matrix view data for table display.""" | ||
| all_states = self.prefix_states + self.cycle_states | ||
|
|
||
| if not all_states: | ||
| return {"subformulae": [], "matrix": [], "rows": []} | ||
|
|
||
| # Collect all unique subformulae across all states | ||
| all_subformulae_set = set() | ||
| for state in all_states: | ||
| subformulae = state.getAllSubformulae() | ||
| for formula, _ in subformulae: | ||
| all_subformulae_set.add(formula) | ||
|
|
||
| # Sort subformulae for consistent ordering (simple ones first, complex ones last) | ||
| all_subformulae = sorted(list(all_subformulae_set), key=lambda x: (len(x), x)) | ||
|
|
||
| # Build matrix: rows are subformulae, columns are time steps | ||
| matrix = [] | ||
| rows = [] # Combined data for easier template iteration | ||
| for subformula in all_subformulae: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dont think this is being correctly populated with 0s and 1s There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in commit c473ef9. The issue was that the Matrix View template was dependent on |
||
| row = [] | ||
| for state in all_states: | ||
| # Find this subformula in the current state | ||
| subformulae = state.getAllSubformulae() | ||
| subformula_dict = {f: s for f, s in subformulae} | ||
| satisfaction = subformula_dict.get(subformula, False) | ||
| row.append(1 if satisfaction else 0) | ||
| matrix.append(row) | ||
| rows.append({"subformula": subformula, "values": row}) | ||
|
|
||
| return { | ||
| "subformulae": all_subformulae, | ||
| "matrix": matrix, | ||
| "rows": rows | ||
| } | ||
|
|
||
| def __repr__(self): | ||
| return f"TraceSatisfactionResult(prefix_states={self.prefix_states}, cycle_states={self.cycle_states})" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,14 +68,25 @@ | |
| display: inline-block; | ||
| } | ||
|
|
||
| .unsatformula { | ||
|
|
||
| border: 2px solid #dc3545; | ||
| /* red solid border */ | ||
| border-radius: 6px; | ||
| padding: 4px 8px; | ||
|
|
||
| display: inline-block; | ||
| .unsatformula { | ||
|
|
||
| border: 2px solid #dc3545; | ||
| /* red solid border */ | ||
| border-radius: 6px; | ||
| padding: 4px 8px; | ||
|
|
||
| display: inline-block; | ||
| } | ||
|
|
||
| /* Matrix view text colors */ | ||
| .matrix-satisfied { | ||
| color: #28a745 !important; | ||
| font-weight: bold; | ||
| } | ||
|
|
||
| .matrix-unsatisfied { | ||
| color: #dc3545 !important; | ||
| font-weight: bold; | ||
| } | ||
| </style> | ||
|
|
||
|
|
@@ -131,18 +142,24 @@ <h5 class="modal-title" id="exampleModalLabel">Load Stepper with a new LTL Formu | |
| </div> | ||
|
|
||
|
|
||
| <ul class="nav nav-tabs mb-3 mt-4" id="stepperTabs" role="tablist"> | ||
| <li class="nav-item"> | ||
| <a class="nav-link active" id="stepper-tab" data-toggle="tab" href="#stepper-view" role="tab">Stepper | ||
| View</a> | ||
| </li> | ||
| <li class="nav-item"> | ||
| <a class="nav-link" id="table-tab" data-toggle="tab" href="#table-view" role="tab">Table View<sup>Beta</sup></a> | ||
| </li> | ||
| <ul class="nav nav-tabs mb-3 mt-4" id="stepperTabs" role="tablist"> | ||
| <li class="nav-item"> | ||
| <a class="nav-link active" id="stepper-tab" data-toggle="tab" href="#stepper-view" role="tab">Stepper | ||
| View</a> | ||
| </li> | ||
| <li class="nav-item"> | ||
| <a class="nav-link" id="table-tab" data-toggle="tab" href="#table-view" role="tab">Table View<sup>Beta</sup></a> | ||
| </li> | ||
| <li class="nav-item"> | ||
| <a class="nav-link" id="matrix-tab" data-toggle="tab" href="#matrix-view" role="tab">Matrix View<sup>Alpha</sup></a> | ||
| </li> | ||
| </ul> | ||
|
|
||
| <div class="tab-content"> | ||
| <div class="tab-pane fade show active" id="stepper-view" role="tabpanel"> | ||
| <div class="tab-content"> | ||
| <!-- ================================ --> | ||
| <!-- STEPPER VIEW - Interactive stepping through formula satisfaction --> | ||
| <!-- ================================ --> | ||
| <div class="tab-pane fade show active" id="stepper-view" role="tabpanel"> | ||
| <!-- Stepper view lets you see the entire trace at once, and each tree state one by one. --> | ||
|
|
||
| <div id="statecontainer"> | ||
|
|
@@ -180,59 +197,111 @@ <h4><span class="help float-right"> By clicking the <code>Previous State</code> | |
| </div> | ||
| </div> | ||
| {% endfor %} | ||
| </div> | ||
| </div> | ||
| <!-- This view lets you look at multiple tree views at once, for state by state. --> | ||
| <div class="tab-pane fade" id="table-view" role="tabpanel"> | ||
|
|
||
|
|
||
| <p> | ||
| Sub-formulae are demarcated by their bounding boxes, which | ||
| indicate whether they are <span class="satformula">satisfied</span> or | ||
| <span class="unsatformula">unsatisfied</span>. | ||
|
|
||
| </p> | ||
| <!-- Table view goes here --> | ||
| <table class="table table-bordered" id="stateTable"> | ||
| <thead> | ||
| <tr> | ||
| <th class="w-auto"></th> | ||
| {% for ps in prefixstates %} | ||
| <th></th> | ||
| {% endfor %} | ||
| {% if cyclestates %} | ||
| <th class="cycle-state-col" colspan="{{ cyclestates|length }}">Cycle</th> | ||
| {% endif %} | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr> | ||
| <th class="w-auto">Trace State</th> | ||
| {% for ps in prefixstates %} | ||
| <td><pre>{{ ps.formattedTraceAssignment }}</pre></td> | ||
| {% endfor %} | ||
| {% for ps in cyclestates %} | ||
| <td class="cycle-state-col"><pre>{{ ps.formattedTraceAssignment }}</pre></td> | ||
| {% endfor %} | ||
| </tr> | ||
| <tr> | ||
| <th class="w-auto"> | ||
| Formula | ||
| </span> | ||
| </th> | ||
| {% for ps in prefixstates %} | ||
| <td> | ||
| {{ ps.formulaAsHTML | safe }} | ||
| </td> | ||
| {% endfor %} | ||
| {% for ps in cyclestates %} | ||
| <td class="cycle-state-col"> | ||
| {{ ps.formulaAsHTML | safe }} | ||
| </td> | ||
| {% endfor %} | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
| </div> | ||
| </div> | ||
| <!-- ================================ --> | ||
| <!-- TABLE VIEW - Detailed formula view with satisfaction highlighting --> | ||
| <!-- ================================ --> | ||
| <div class="tab-pane fade" id="table-view" role="tabpanel"> | ||
| {% if matrix_data.subformulae %} | ||
| <p> | ||
| Sub-formulae are demarcated by their bounding boxes, which | ||
| indicate whether they are <span class="satformula">satisfied</span> or | ||
| <span class="unsatformula">unsatisfied</span>. | ||
| </p> | ||
| <!-- Detailed table view --> | ||
| <table class="table table-bordered" id="stateTable"> | ||
| <thead> | ||
| <tr> | ||
| <th class="w-auto"></th> | ||
| {% for ps in prefixstates %} | ||
| <th></th> | ||
| {% endfor %} | ||
| {% if cyclestates %} | ||
| <th class="cycle-state-col" colspan="{{ cyclestates|length }}">Cycle</th> | ||
| {% endif %} | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr> | ||
| <th class="w-auto">Trace State</th> | ||
| {% for ps in prefixstates %} | ||
| <td><pre>{{ ps.formattedTraceAssignment }}</pre></td> | ||
| {% endfor %} | ||
| {% for ps in cyclestates %} | ||
| <td class="cycle-state-col"><pre>{{ ps.formattedTraceAssignment }}</pre></td> | ||
| {% endfor %} | ||
| </tr> | ||
| <tr> | ||
| <th class="w-auto"> | ||
| Formula | ||
| </span> | ||
| </th> | ||
| {% for ps in prefixstates %} | ||
| <td> | ||
| {{ ps.formulaAsHTML | safe }} | ||
| </td> | ||
| {% endfor %} | ||
| {% for ps in cyclestates %} | ||
| <td class="cycle-state-col"> | ||
| {{ ps.formulaAsHTML | safe }} | ||
| </td> | ||
| {% endfor %} | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
| {% else %} | ||
| <div class="alert alert-info"> | ||
| <p><strong>No formula loaded.</strong></p> | ||
| <p>Please enter an LTL formula and trace to see the table view.</p> | ||
| </div> | ||
| {% endif %} | ||
| </div> | ||
| <!-- ================================ --> | ||
| <!-- MATRIX VIEW - Binary matrix display of subformula satisfaction over time --> | ||
| <!-- ================================ --> | ||
| <div class="tab-pane fade" id="matrix-view" role="tabpanel"> | ||
| <p> | ||
| This matrix view shows how each subformula's satisfaction evolves over time. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Almost there! We need to visually indicate the cycle in the trace There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed! Added cycle indication to the Matrix View with dual-header layout and proper cycle styling. The Matrix View now shows:
See commit 429715c. |
||
| Each row represents a subformula, and each column represents a time step. | ||
| Values are shown as <strong class="matrix-satisfied">1</strong> (satisfied) or <strong class="matrix-unsatisfied">0</strong> (unsatisfied). | ||
| </p> | ||
|
|
||
| {% if matrix_data.subformulae %} | ||
| <!-- Matrix view table --> | ||
| <table class="table table-bordered table-sm" id="matrixTable"> | ||
| <thead> | ||
| <tr> | ||
| <th class="w-auto">Subformula</th> | ||
| {% if matrix_data.rows and matrix_data.rows|length > 0 and matrix_data.rows[0] and 'values' in matrix_data.rows[0] %} | ||
| {% set num_columns = matrix_data.rows[0]['values']|length %} | ||
| {% for i in range(num_columns) %} | ||
| <th class="text-center">{{ i }}</th> | ||
| {% endfor %} | ||
| {% endif %} | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| {% for row_data in matrix_data.rows %} | ||
| {% if row_data and 'subformula' in row_data and 'values' in row_data %} | ||
| <tr> | ||
| <td class="font-monospace"><code>{{ row_data['subformula'] }}</code></td> | ||
| {% for value in row_data['values'] %} | ||
| <td class="text-center"> | ||
| <span class="{% if value == 1 %}matrix-satisfied{% else %}matrix-unsatisfied{% endif %}">{{ value }}</span> | ||
| </td> | ||
| {% endfor %} | ||
| </tr> | ||
| {% endif %} | ||
| {% endfor %} | ||
| </tbody> | ||
| </table> | ||
| {% else %} | ||
| <div class="alert alert-info"> | ||
| <p><strong>No formula loaded.</strong></p> | ||
| <p>Please enter an LTL formula and trace to see the matrix view.</p> | ||
| </div> | ||
| {% endif %} | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.