Skip to content

Commit 13e975b

Browse files
committed
check canonicity in integration tests
* make sure that automata are not only equivalent but also minimal * for the state local input ITs this requires an additional minimization step before computing the enabled symbols
1 parent 9d40f13 commit 13e975b

3 files changed

Lines changed: 29 additions & 23 deletions

File tree

test-support/learner-it-support/src/main/java/de/learnlib/testsupport/it/learner/LearnerVariantITCase.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@ public void testLearning() {
5252
LearningAlgorithm<? extends M, I, D> learner = variant.getLearner();
5353

5454
Alphabet<I> alphabet = example.getAlphabet();
55+
M reference = example.getReferenceAutomaton();
5556

5657
int maxRounds = variant.getMaxRounds();
5758
if (maxRounds < 0) {
58-
maxRounds = example.getReferenceAutomaton().size();
59+
maxRounds = reference.size();
5960
}
6061

6162
long start = System.nanoTime();
@@ -75,9 +76,10 @@ public void testLearning() {
7576
Assert.assertTrue(refined, "Real counterexample " + ceQuery.getInput() + " did not refine hypothesis");
7677
}
7778

78-
Assert.assertNull(Automata.findSeparatingWord(example.getReferenceAutomaton(),
79-
learner.getHypothesisModel(),
80-
alphabet), "Final hypothesis does not match reference automaton");
79+
M hypothesis = learner.getHypothesisModel();
80+
Assert.assertEquals(hypothesis.size(), reference.size());
81+
Assert.assertNull(Automata.findSeparatingWord(reference, hypothesis, alphabet),
82+
"Final hypothesis does not match reference automaton");
8183

8284
long duration = (System.nanoTime() - start) / NANOS_PER_MILLISECOND;
8385
LOGGER.info("Passed learner integration test {} ... took [{}]",

test-support/learner-it-support/src/main/java/de/learnlib/testsupport/it/learner/VPDALearnerITCase.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ public void testLearning() {
6262
Assert.assertTrue(refined, "Real counterexample " + ceQuery.getInput() + " did not refine hypothesis");
6363
}
6464

65-
Assert.assertTrue(Automata.testEquivalence(reference, learner.getHypothesisModel(), alphabet),
65+
OneSEVPA<?, I> hypothesis = learner.getHypothesisModel();
66+
Assert.assertEquals(hypothesis.size(), reference.size());
67+
Assert.assertTrue(Automata.testEquivalence(reference, hypothesis, alphabet),
6668
"Final hypothesis does not match reference automaton");
6769

6870
long duration = (System.nanoTime() - start) / NANOS_PER_MILLISECOND;

test-support/learning-examples/src/main/java/de/learnlib/examples/mealy/ExampleRandomStateLocalInputMealy.java

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@
1717

1818
import java.util.Arrays;
1919
import java.util.Collection;
20-
import java.util.Collections;
2120
import java.util.HashSet;
21+
import java.util.Objects;
2222
import java.util.Random;
23-
import java.util.Set;
2423

2524
import de.learnlib.examples.LearningExample.StateLocalInputMealyLearningExample;
2625
import net.automatalib.automata.transducers.MealyMachine;
@@ -29,6 +28,7 @@
2928
import net.automatalib.commons.util.mappings.Mapping;
3029
import net.automatalib.commons.util.mappings.MutableMapping;
3130
import net.automatalib.commons.util.random.RandomUtil;
31+
import net.automatalib.util.automata.Automata;
3232
import net.automatalib.util.automata.random.RandomAutomata;
3333
import net.automatalib.words.Alphabet;
3434
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -56,38 +56,40 @@ public ExampleRandomStateLocalInputMealy(Random random,
5656

5757
this.alphabet = alphabet;
5858
this.undefinedOutput = undefinedOutput;
59-
CompactMealy<I, O> source = RandomAutomata.randomDeterministic(random,
60-
size,
61-
alphabet,
62-
Collections.emptyList(),
63-
Arrays.asList(outputs),
64-
new CompactMealy<>(alphabet));
59+
CompactMealy<I, O> source = RandomAutomata.randomMealy(random, size, alphabet, Arrays.asList(outputs));
6560

6661
final int alphabetSize = alphabet.size();
6762

6863
final Collection<Integer> oldStates = source.getStates();
6964
final Integer sink = source.addState();
70-
final MutableMapping<Integer, Collection<I>> enabledInputs = source.createDynamicStateMapping();
7165

7266
for (final Integer s : oldStates) {
73-
74-
final Set<I> stateInputs = new HashSet<>(alphabet);
7567
// randomly remove (redirect to sink) transitions
7668
for (int idx : RandomUtil.distinctIntegers(random.nextInt(alphabetSize), alphabetSize, random)) {
77-
final I sym = alphabet.getSymbol(idx);
78-
stateInputs.remove(sym);
79-
source.setTransition(s, sym, sink, undefinedOutput);
69+
source.setTransition(s, idx, sink, undefinedOutput);
8070
}
81-
enabledInputs.put(s, stateInputs);
8271
}
83-
8472
// configure sink
8573
for (final I i : alphabet) {
8674
source.addTransition(sink, i, sink, undefinedOutput);
8775
}
88-
enabledInputs.put(sink, Collections.emptyList());
8976

90-
this.referenceAutomaton = new MockedSLIMealy<>(source, enabledInputs);
77+
final CompactMealy<I, O> minimized = Automata.invasiveMinimize(source, alphabet);
78+
final MutableMapping<Integer, Collection<I>> enabledInputs = source.createStaticStateMapping();
79+
80+
for (Integer s : minimized) {
81+
final Collection<I> stateInputs = new HashSet<>(alphabet);
82+
83+
for (I i : alphabet) {
84+
if (Objects.equals(undefinedOutput, minimized.getOutput(s, i))) {
85+
stateInputs.remove(i);
86+
}
87+
}
88+
89+
enabledInputs.put(s, stateInputs);
90+
}
91+
92+
this.referenceAutomaton = new MockedSLIMealy<>(minimized, enabledInputs);
9193
}
9294

9395
@SafeVarargs

0 commit comments

Comments
 (0)