Skip to content

Commit

Permalink
amr-errors in dev interface, more amr check criteria (#4451)
Browse files Browse the repository at this point in the history
  • Loading branch information
mwdchang authored Aug 14, 2024
1 parent 8b6fe87 commit 82b567a
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 67 deletions.
28 changes: 28 additions & 0 deletions packages/client/hmi-client/src/model-representation/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,14 @@ export function checkPetrinetAMR(amr: Model) {
const numInitials = ode?.initials?.length || 0;
const numRates = ode?.rates?.length || 0;

if (numStates === 0) {
results.push({ type: 'warn', content: 'zero states' });
}

if (numTransitions === 0) {
results.push({ type: 'warn', content: 'zero transitions' });
}

if (numStates !== numInitials) {
results.push({ type: 'error', content: 'states need to match initials' });
}
Expand All @@ -292,6 +300,8 @@ export function checkPetrinetAMR(amr: Model) {
});

// Check state
const stateSet = new Set<string>();
const initialSet = new Set<string>();
model.states.forEach((state) => {
const initial = initialMap.get(state.id);
if (!initial) {
Expand All @@ -303,9 +313,19 @@ export function checkPetrinetAMR(amr: Model) {
if (!isASCII(initial?.expression as string)) {
results.push({ type: 'warn', content: `${state.id} has non-ascii expression` });
}
if (stateSet.has(state.id)) {
results.push({ type: 'error', content: `state (${state.id}) has duplicate` });
}
if (initialSet.has(initial?.target as string)) {
results.push({ type: 'error', content: `initial (${initial?.target}) has duplicate` });
}
stateSet.add(state.id);
initialSet.add(initial?.target as string);
});

// Check transitions
const transitionSet = new Set<string>();
const rateSet = new Set<string>();
model.transitions.forEach((transition) => {
const rate = rateMap.get(transition.id);
if (!rate) {
Expand All @@ -317,6 +337,14 @@ export function checkPetrinetAMR(amr: Model) {
if (!isASCII(rate?.expression as string)) {
results.push({ type: 'warn', content: `${transition.id} has non-ascii expression` });
}
if (transitionSet.has(transition.id)) {
results.push({ type: 'error', content: `transition (${transition.id}) has duplicate` });
}
if (rateSet.has(rate?.target as string)) {
results.push({ type: 'error', content: `rate (${rate?.target}) has duplicate` });
}
transitionSet.add(transition.id);
rateSet.add(rate?.target as string);
});

return results;
Expand Down
105 changes: 38 additions & 67 deletions packages/client/hmi-client/src/temp/AMRPetriTest.vue
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@
<template>
<div style="display: flex; flex-direction: row; padding: 1rem">
<div style="display: flex; flex-direction: column">
<textarea style="width: 550px; height: 550px; margin: 0 10px" v-model="jsonStr"> </textarea>
<textarea style="width: 600px; height: 425px; margin: 0 10px" v-model="jsonStr"> </textarea>
<div style="height: 150px; max-height: 150px; overflow-y: scroll; border: 1px solid #bbb; margin: 0.5rem">
<table style="width: 100%">
<tr v-for="(log, idx) in errors" :key="idx" style="border: 1px solid #ddd">
<td :class="[log.type]" style="width: 6rem">{{ log.type }}</td>
<td>{{ log.content }}</td>
</tr>
</table>
<div v-if="errors.length === 0">No problems found</div>
</div>
<div>
<button style="width: 10rem; margin: 3px; font-size: 125%" @click="isCollapsed = true">Collapse</button>
<button style="width: 10rem; margin: 3px; font-size: 125%" @click="isCollapsed = false">Expand</button>
<button style="width: 10rem; margin: 3px; font-size: 100%" @click="isCollapsed = true">Collapse</button>
<button style="width: 10rem; margin: 3px; font-size: 100%" @click="isCollapsed = false">Expand</button>
</div>
</div>
<div>
<div style="position: fixed; padding: 2px">
{{ strataType === null ? 'No strata' : strataType }}
</div>
<div ref="graphElement" class="canvas" style="height: 600px; width: 900px"></div>
<div ref="graphElement" class="canvas" style="height: 600px; width: 750px"></div>
</div>
</div>
</template>

<script setup lang="ts">
import _ from 'lodash';
import { getModelRenderer } from '@/model-representation/service';
import { checkPetrinetAMR, getModelRenderer } from '@/model-representation/service';
import { getMMT } from '@/services/model';
import { onMounted, ref, watch } from 'vue';
import * as mmtExample from '@/examples/mira-petri.json';
import { convertToIGraph, collapseParameters, createParameterMatrix } from '@/model-representation/mira/mira';
import { convertToIGraph } from '@/model-representation/mira/mira';
const graphElement = ref<HTMLDivElement | null>(null);
const jsonStr = ref('');
const strataType = ref<string | null>(null);
const isCollapsed = ref(true);
const errors = ref<any[]>([]);
onMounted(async () => {
jsonStr.value = JSON.stringify(mmtExample, null, 2);
Expand All @@ -37,69 +43,15 @@ onMounted(async () => {
() => [jsonStr.value, isCollapsed.value],
async () => {
const jsonData = JSON.parse(jsonStr.value);
errors.value = checkPetrinetAMR(jsonData);
const mmtR = await getMMT(jsonData);
const mmt = mmtR.mmt;
const template_params = mmtR.template_params;
const observable_summary = mmtR.observable_summary;
const renderer = getModelRenderer(mmt, graphElement.value as HTMLDivElement, false);
const renderer = getModelRenderer(mmt, graphElement.value as HTMLDivElement, true);
const graphData = convertToIGraph(mmt, observable_summary, isCollapsed.value);
// Create all possible matrices
const rootParams = collapseParameters(mmt, template_params);
const rootParamKeys = [...rootParams.keys()];
const lines: any[] = [];
rootParamKeys.forEach((key) => {
const matrices = createParameterMatrix(mmt, template_params, key);
let header = '';
const subjectOutcome = matrices.subjectOutcome;
const subjectControllers = matrices.subjectControllers;
const outcomeControllers = matrices.outcomeControllers;
if (subjectOutcome.matrix.length > 0) {
lines.push(`subject-outcome of ${key}`);
header = ',' + subjectOutcome.rowNames.join(',');
lines.push('');
lines.push(header);
subjectOutcome.matrix.forEach((r, idx) => {
const rowStr = subjectOutcome.colNames[idx] + r.map((d) => d.content.id).join(',');
lines.push(rowStr);
});
lines.push('');
lines.push('');
}
if (subjectControllers.matrix.length > 0) {
lines.push(`subject-controllers of ${key}`);
header = ',' + subjectControllers.rowNames.join(',');
lines.push('');
lines.push(header);
subjectControllers.matrix.forEach((r, idx) => {
const rowStr = subjectControllers.colNames[idx] + ',' + r.map((d) => d.content.id).join(',');
lines.push(rowStr);
});
lines.push('');
lines.push('');
}
if (outcomeControllers.matrix.length > 0) {
lines.push(`outcome-controllers of ${key}`);
header = ',' + outcomeControllers.rowNames.join(',');
lines.push('');
lines.push(header);
outcomeControllers.matrix.forEach((r, idx) => {
const rowStr = outcomeControllers.colNames[idx] + ',' + r.map((d) => d.content.id).join(',');
lines.push(rowStr);
});
lines.push('');
lines.push('');
}
});
console.log(lines.join('\n'));
await renderer.setData(graphData);
renderer.isGraphDirty = true;
renderer.render();
Expand All @@ -108,3 +60,22 @@ onMounted(async () => {
);
});
</script>

<style scoped>
table {
border-collapse: collapse;
}
td {
padding: 2px;
}
td.error {
background: #f20;
text-align: center;
}
td.warn {
background: #f80;
text-align: center;
}
</style>

0 comments on commit 82b567a

Please sign in to comment.