From b3a5138b2ebbb0bd10f7725ec94ff64bd2caead0 Mon Sep 17 00:00:00 2001 From: dgelessus <dgelessus@users.noreply.github.com> Date: Mon, 28 Feb 2022 19:11:28 +0100 Subject: [PATCH] Use new getters for properties/invariant/assertions in :check --- CHANGELOG.md | 1 + build.gradle | 2 +- notebooks/tests/check.ipynb | 222 ++++++++++++++++++ .../prob2/jupyter/commands/CheckCommand.java | 70 +++--- 4 files changed, 259 insertions(+), 36 deletions(-) create mode 100644 notebooks/tests/check.ipynb diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d415eb..b8922b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [(next version)](https://gitlab.cs.uni-duesseldorf.de/api/v4/projects/848/jobs/artifacts/master/raw/build/libs/prob2-jupyter-kernel-1.3.1-SNAPSHOT-all.jar?job=test) +* Updated ProB 2 to version 4.0.0-SNAPSHOT. * Disabled LaTeX formatting inside `:check` tables as well, because of the layout issues mentioned below. ## [1.3.0](https://www3.hhu.de/stups/downloads/prob2-jupyter/prob2-jupyter-kernel-1.3.0-all.jar) diff --git a/build.gradle b/build.gradle index 11c6368..3ddc233 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,7 @@ dependencies { implementation(group: "ch.qos.logback", name: "logback-classic", version: "1.2.10") implementation(group: "com.google.code.gson", name: "gson", version: "2.8.9") implementation(group: "com.google.guava", name: "guava", version: "31.0.1-jre") - implementation(group: "de.hhu.stups", name: "de.prob2.kernel", version: "3.15.0") + implementation(group: "de.hhu.stups", name: "de.prob2.kernel", version: "4.0.0-SNAPSHOT") implementation(group: "io.github.spencerpark", name: "jupyter-jvm-basekernel", version: "2.3.0") implementation(group: "org.jetbrains", name: "annotations", version: "23.0.0") implementation(group: "se.sawano.java", name: "alphanumeric-comparator", version: "1.4.1") diff --git a/notebooks/tests/check.ipynb b/notebooks/tests/check.ipynb new file mode 100644 index 0000000..d8a288f --- /dev/null +++ b/notebooks/tests/check.ipynb @@ -0,0 +1,222 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "36c2fbc3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```\n", + ":check WHAT\n", + "```\n", + "\n", + "Check the machine's properties, invariant, or assertions in the current state.\n", + "\n", + "The properties/invariant/assertions are checked and displayed in table form. Each row corresponds to a part of the properties/invariant conjunction, or to an assertion." + ], + "text/plain": [ + ":check WHAT\n", + "Check the machine's properties, invariant, or assertions in the current state.\n", + "\n", + "The properties/invariant/assertions are checked and displayed in table form. Each row corresponds to a part of the properties/invariant conjunction, or to an assertion." + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + ":help :check" + ] + }, + { + "cell_type": "markdown", + "id": "69f51548", + "metadata": {}, + "source": [ + "`:check` works for classical B machines." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "daa741b3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Loaded machine: CheckTest" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "MACHINE CheckTest\n", + "CONSTANTS x, y\n", + "PROPERTIES x : {1, 2} & y : {3, 4}\n", + "VARIABLES a, b\n", + "INVARIANT a : 0..x & b : 1..y\n", + "INITIALISATION a := x; b := y\n", + "ASSERTIONS a <= x; b <= y\n", + "END" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0f0f8bc9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Executed operation: SETUP_CONSTANTS()" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + ":constants" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "ca180263", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Executed operation: INITIALISATION()" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + ":init" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a4901fab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "|Predicate|Value|\n", + "|---|---|\n", + "|x∈{1,2}|TRUE|\n", + "|y∈{3,4}|TRUE|" + ], + "text/plain": [ + "x:{1,2} = TRUE\n", + "y:{3,4} = TRUE" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + ":check properties" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "62fe69ce", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "|Predicate|Value|\n", + "|---|---|\n", + "|a∈0‥x|TRUE|\n", + "|b∈1‥y|TRUE|" + ], + "text/plain": [ + "a:0..x = TRUE\n", + "b:1..y = TRUE" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + ":check invariant" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "d2054303", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "|Predicate|Value|\n", + "|---|---|\n", + "|a≤x|TRUE|\n", + "|b≤y|TRUE|" + ], + "text/plain": [ + "a<=x = TRUE\n", + "b<=y = TRUE" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + ":check assertions" + ] + }, + { + "cell_type": "markdown", + "id": "72e11ab6", + "metadata": {}, + "source": [ + "TODO: Test for Event-B" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "ProB 2", + "language": "prob", + "name": "prob2" + }, + "language_info": { + "codemirror_mode": "prob2_jupyter_repl", + "file_extension": ".prob", + "mimetype": "text/x-prob2-jupyter-repl", + "name": "prob" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/main/java/de/prob2/jupyter/commands/CheckCommand.java b/src/main/java/de/prob2/jupyter/commands/CheckCommand.java index 8fd4fd5..db72f85 100644 --- a/src/main/java/de/prob2/jupyter/commands/CheckCommand.java +++ b/src/main/java/de/prob2/jupyter/commands/CheckCommand.java @@ -1,22 +1,20 @@ package de.prob2.jupyter.commands; -import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.StringJoiner; import java.util.stream.Collectors; +import java.util.stream.Stream; import com.google.inject.Inject; import de.prob.animator.domainobjects.AbstractEvalResult; import de.prob.animator.domainobjects.IEvalElement; -import de.prob.model.classicalb.Assertion; +import de.prob.model.classicalb.ClassicalBMachine; +import de.prob.model.representation.AbstractElement; import de.prob.model.representation.AbstractFormulaElement; -import de.prob.model.representation.AbstractTheoremElement; -import de.prob.model.representation.Axiom; -import de.prob.model.representation.Invariant; +import de.prob.model.representation.ConstantsComponent; +import de.prob.model.representation.Machine; import de.prob.statespace.AnimationSelector; import de.prob.statespace.Trace; import de.prob.unicode.UnicodeTranslator; @@ -37,15 +35,6 @@ import org.jetbrains.annotations.NotNull; public final class CheckCommand implements Command { private static final @NotNull Parameter.RequiredSingle WHAT_PARAM = Parameter.required("what"); - private static final @NotNull Map<@NotNull String, @NotNull Class<? extends AbstractTheoremElement>> CHILDREN_BASE_CLASS_MAP; - static { - final Map<String, Class<? extends AbstractTheoremElement>> childrenBaseClassMap = new HashMap<>(); - childrenBaseClassMap.put("properties", Axiom.class); - childrenBaseClassMap.put("invariant", Invariant.class); - childrenBaseClassMap.put("assertions", Assertion.class); - CHILDREN_BASE_CLASS_MAP = Collections.unmodifiableMap(childrenBaseClassMap); - } - private final @NotNull AnimationSelector animationSelector; @Inject @@ -83,27 +72,39 @@ public final class CheckCommand implements Command { @Override public @NotNull DisplayData run(final @NotNull ParsedArguments args) { final String what = args.get(WHAT_PARAM); - if (!CHILDREN_BASE_CLASS_MAP.containsKey(what)) { - throw new UserErrorException("Don't know how to check " + what); - } - final Class<? extends AbstractTheoremElement> childrenBaseClass = CHILDREN_BASE_CLASS_MAP.get(what); final Trace trace = this.animationSelector.getCurrentTrace(); - // Find all children of a subclass of childrenBaseClass. - // This needs to be done manually, because getChildrenOfType only returns children whose class *exactly* matches the given class. - // For example, getChildrenOfType(Axiom.class) doesn't return children of class Property (which is a subclass of Axiom). - final List<IEvalElement> formulas = new ArrayList<>(); - trace.getStateSpace().getMainComponent().getChildren().forEach((clazz, children) -> { - if (childrenBaseClass.isAssignableFrom(clazz)) { - children.stream() - .map(childrenBaseClass::cast) - .map(AbstractFormulaElement::getFormula) - .collect(Collectors.toCollection(() -> formulas)); - } - }); + final AbstractElement mainComponent = trace.getStateSpace().getMainComponent(); + final List<? extends AbstractFormulaElement> elements; + switch (what) { + case "properties": + if (!(mainComponent instanceof ConstantsComponent)) { + throw new UserErrorException("Checking " + what + " is only supported for classical B machines or Event-B contexts"); + } + elements = ((ConstantsComponent)mainComponent).getAxioms(); + break; + + case "invariant": + if (!(mainComponent instanceof Machine)) { + throw new UserErrorException("Checking " + what + " is only supported for classical B or Event-B machines"); + } + elements = ((Machine)mainComponent).getInvariants(); + break; + + case "assertions": + if (!(mainComponent instanceof ClassicalBMachine)) { + throw new UserErrorException("Checking " + what + " is only supported for classical B machines"); + } + elements = ((ClassicalBMachine)mainComponent).getAssertions(); + break; + + default: + throw new UserErrorException("Don't know how to check " + what); + } final StringJoiner sjPlain = new StringJoiner("\n"); final StringJoiner sjMarkdown = new StringJoiner("\n", "|Predicate|Value|\n|---|---|\n", ""); - for (final IEvalElement f : formulas) { + for (final AbstractFormulaElement element : elements) { + final IEvalElement f = element.getFormula(); final AbstractEvalResult result = trace.evalCurrent(f); sjPlain.add(f.getCode() + " = " + CommandUtils.inlinePlainTextForEvalResult(result)); sjMarkdown.add("|" + UnicodeTranslator.toUnicode(f.getCode()) + "|" + CommandUtils.inlineMarkdownForEvalResult(result) + '|'); @@ -123,8 +124,7 @@ public final class CheckCommand implements Command { return new ParameterCompleters(Collections.singletonMap( WHAT_PARAM, (argString, at) -> { final String prefix = argString.substring(0, at); - return new ReplacementOptions(CHILDREN_BASE_CLASS_MAP.keySet() - .stream() + return new ReplacementOptions(Stream.of("properties", "invariant", "assertions") .filter(s -> s.startsWith(prefix)) .collect(Collectors.toList()), 0, argString.length()); } -- GitLab