Skip to content

Commit a5efeab

Browse files
mohbayrammtf90
andauthored
add Moore variants of L*, DT and TTT algorithms (#87)
* add Moore variant to LStar, DiscriminationTree and TTT algorithms * cleanup * add additional tests + more fixes/cleanups * cleanup Moore-specific counter oracles Co-authored-by: Markus Frohme <markus.frohme@udo.edu>
1 parent 426dd1a commit a5efeab

File tree

70 files changed

+2323
-59
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2323
-59
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1111
* Added the OSTIA passive learning algorithm, thanks to [Aleksander Mendoza-Drosik](https://github.com/aleksander-mendoza).
1212
* Added the OML (optimal-MAT-learner) active learning algorithm, thanks to [Falk Howar](https://github.com/fhowar).
1313
* Added a new learning algorithm for systems of procedural automata (SPAs).
14+
* Added Moore versions of the learners `DT`, `TTT`, `LStar`, thanks to [Mohamad Bayram](https://github.com/mohbayram).
1415

1516
### Changed
1617

@@ -21,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2122
* The `ADT` class is no longer initialized with a `leafSplitter` but the `extendLeaf` and `splitLeaf` methods take an additional argument. This allows for a more customizable behavior.
2223
* The `{DFA,Mealy}CacheOracle`s and the `SULCache` are no longer thread-safe because the intended pipeline of a parallel setup (as suggested by the LearnLib factory methods) consists of a single-threaded cache that delegates to parallel (non-cached) oracles. Here, the synchronization logic only adds unnecessary overhead. In case you want a shared, thread-safe cache (which was currently not conveniently possible to setup) the `learnlib-parallelism` module now contains the `ThreadSafe{DFA,Mealy,SUL}Caches` factories which allow one to construct parallel oracles (whose parameters and return types are tailored towards using our `ParallelOracleBuilders` factory) with a shared cache. See the in-tree `ParallelismExample2` for reference.
2324
* `SymbolQueryCache` now needs to be created via the `MealyCaches` factory.
25+
* `AbstractTTTHypothesis` has received an additional type parameter for its state type.
2426

2527

2628
### Removed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ While certain features have been stripped for improved modularity, development h
1717
Currently, the following learning algorithms with respective target models are supported:
1818

1919

20-
Algorithm (active) | Target models || Algorithm (passive) | Models
20+
Algorithm (active) | Target models || Algorithm (passive) | Models
2121
--- | --- | --- | --- | ---
22-
ADT | `Mealy` || OSTIA | `SST`
23-
DHC | `Mealy` || RPNI | `DFA` `Mealy`
24-
Discrimination Tree | `DFA` `Mealy` `VPDA` || RPNI (EDSM) | `DFA`
25-
Kearns & Vazirani | `DFA` `Mealy` || RPNI (MDL) | `DFA`
26-
L* (incl. variants) | `DFA` `Mealy`
22+
ADT | `Mealy` || OSTIA | `SST`
23+
DHC | `Mealy` || RPNI | `DFA` `Mealy`
24+
Discrimination Tree | `DFA` `Mealy` `Moore` `VPDA` || RPNI (EDSM) | `DFA`
25+
Kearns & Vazirani | `DFA` `Mealy` || RPNI (MDL) | `DFA`
26+
L* (incl. variants) | `DFA` `Mealy` `Moore`
2727
NL* | `NFA`
2828
OML | `DFA` `Mealy`
2929
SPA | `SPA`
30-
TTT | `DFA` `Mealy` `VPDA`
30+
TTT | `DFA` `Mealy` `Moore` `VPDA`
3131

3232

3333
Additionally, LearnLib offers a variety of tools to ease the practical application of automata learning on real-world systems.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/* Copyright (C) 2013-2022 TU Dortmund
2+
* This file is part of LearnLib, http://www.learnlib.de/.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package de.learnlib.algorithms.discriminationtree.moore;
17+
18+
import com.github.misberner.buildergen.annotations.GenerateBuilder;
19+
import de.learnlib.algorithms.discriminationtree.AbstractDTLearner;
20+
import de.learnlib.algorithms.discriminationtree.DTLearnerState;
21+
import de.learnlib.algorithms.discriminationtree.hypothesis.HState;
22+
import de.learnlib.algorithms.discriminationtree.hypothesis.HTransition;
23+
import de.learnlib.api.algorithm.LearningAlgorithm.MooreLearner;
24+
import de.learnlib.api.oracle.MembershipOracle;
25+
import de.learnlib.api.query.AbstractQuery;
26+
import de.learnlib.api.query.Query;
27+
import de.learnlib.counterexamples.LocalSuffixFinder;
28+
import de.learnlib.datastructure.discriminationtree.MultiDTree;
29+
import net.automatalib.automata.transducers.MooreMachine;
30+
import net.automatalib.words.Alphabet;
31+
import net.automatalib.words.Word;
32+
import org.checkerframework.checker.nullness.qual.Nullable;
33+
34+
/**
35+
* A {@link MooreMachine}-based specialization of the DT learner.
36+
*
37+
* @param <I>
38+
* input symbol type
39+
* @param <O>
40+
* output symbol type
41+
*
42+
* @author bayram
43+
* @author frohme
44+
*/
45+
public class DTLearnerMoore<I, O> extends AbstractDTLearner<MooreMachine<?, I, ?, O>, I, Word<O>, O, Void>
46+
implements MooreLearner<I, O> {
47+
48+
private HypothesisWrapperMoore<I, O> hypWrapper;
49+
50+
@GenerateBuilder(defaults = AbstractDTLearner.BuilderDefaults.class)
51+
public DTLearnerMoore(Alphabet<I> alphabet,
52+
MembershipOracle<I, Word<O>> oracle,
53+
LocalSuffixFinder<? super I, ? super Word<O>> suffixFinder,
54+
boolean repeatedCounterexampleEvaluation) {
55+
56+
super(alphabet, oracle, suffixFinder, repeatedCounterexampleEvaluation, new MultiDTree<>(oracle));
57+
this.hypWrapper = new HypothesisWrapperMoore<>(getHypothesisDS());
58+
59+
}
60+
61+
@Override
62+
protected @Nullable Query<I, Word<O>> spQuery(HState<I, Word<O>, O, Void> state) {
63+
return new AbstractQuery<I, Word<O>>(state.getAccessSequence(), Word.epsilon()) {
64+
65+
@Override
66+
public void answer(Word<O> output) {
67+
state.setProperty(output.firstSymbol());
68+
}
69+
};
70+
}
71+
72+
@Override
73+
protected @Nullable Query<I, Word<O>> tpQuery(HTransition<I, Word<O>, O, Void> transition) {
74+
return null;
75+
}
76+
77+
@Override
78+
public MooreMachine<?, I, ?, O> getHypothesisModel() {
79+
return hypWrapper;
80+
}
81+
82+
@Override
83+
public void resume(DTLearnerState<I, Word<O>, O, Void> state) {
84+
super.resume(state);
85+
this.hypWrapper = new HypothesisWrapperMoore<>(getHypothesisDS());
86+
}
87+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/* Copyright (C) 2013-2022 TU Dortmund
2+
* This file is part of LearnLib, http://www.learnlib.de/.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package de.learnlib.algorithms.discriminationtree.moore;
17+
18+
import java.util.Collection;
19+
20+
import de.learnlib.algorithms.discriminationtree.hypothesis.DTLearnerHypothesis;
21+
import de.learnlib.algorithms.discriminationtree.hypothesis.HState;
22+
import de.learnlib.algorithms.discriminationtree.hypothesis.HTransition;
23+
import net.automatalib.automata.transducers.MooreMachine;
24+
import net.automatalib.words.Word;
25+
import org.checkerframework.checker.nullness.qual.Nullable;
26+
27+
/**
28+
* A {@link MooreMachine}-based specialization of the DT learner hypothesis.
29+
*
30+
* @param <I>
31+
* input symbol type
32+
* @param <O>
33+
* output symbol type
34+
*
35+
* @author bayram
36+
* @author frohme
37+
*/
38+
public class HypothesisWrapperMoore<I, O>
39+
implements MooreMachine<HState<I, Word<O>, O, Void>, I, HTransition<I, Word<O>, O, Void>, O> {
40+
41+
private final DTLearnerHypothesis<I, Word<O>, O, Void> dtHypothesis;
42+
43+
HypothesisWrapperMoore(DTLearnerHypothesis<I, Word<O>, O, Void> dtHypothesis) {
44+
this.dtHypothesis = dtHypothesis;
45+
}
46+
47+
@Override
48+
public O getStateOutput(HState<I, Word<O>, O, Void> state) {
49+
return state.getProperty();
50+
}
51+
52+
@Override
53+
public Collection<HState<I, Word<O>, O, Void>> getStates() {
54+
return dtHypothesis.getStates();
55+
}
56+
57+
@Override
58+
public @Nullable HState<I, Word<O>, O, Void> getInitialState() {
59+
return dtHypothesis.getInitialState();
60+
}
61+
62+
@Override
63+
public @Nullable HTransition<I, Word<O>, O, Void> getTransition(HState<I, Word<O>, O, Void> state, I input) {
64+
return dtHypothesis.getTransition(state, input);
65+
}
66+
67+
@Override
68+
public HState<I, Word<O>, O, Void> getSuccessor(HTransition<I, Word<O>, O, Void> transition) {
69+
return dtHypothesis.getSuccessor(transition);
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* Copyright (C) 2013-2022 TU Dortmund
2+
* This file is part of LearnLib, http://www.learnlib.de/.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package de.learnlib.algorithms.discriminationtree;
17+
18+
import de.learnlib.algorithms.discriminationtree.moore.DTLearnerMoore;
19+
import de.learnlib.api.oracle.MembershipOracle;
20+
import de.learnlib.counterexamples.LocalSuffixFinders;
21+
import de.learnlib.testsupport.AbstractGrowingAlphabetMooreTest;
22+
import net.automatalib.words.Alphabet;
23+
import net.automatalib.words.Word;
24+
25+
/**
26+
* @author frohme
27+
*/
28+
public class DTLearnerMooreGrowingAlphabetTest
29+
extends AbstractGrowingAlphabetMooreTest<DTLearnerMoore<Character, Character>> {
30+
31+
@Override
32+
protected DTLearnerMoore<Character, Character> getLearner(MembershipOracle<Character, Word<Character>> oracle,
33+
Alphabet<Character> alphabet) {
34+
return new DTLearnerMoore<>(alphabet, oracle, LocalSuffixFinders.RIVEST_SCHAPIRE, true);
35+
}
36+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/* Copyright (C) 2013-2022 TU Dortmund
2+
* This file is part of LearnLib, http://www.learnlib.de/.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package de.learnlib.algorithms.discriminationtree;
17+
18+
import de.learnlib.algorithms.discriminationtree.moore.DTLearnerMooreBuilder;
19+
import de.learnlib.api.oracle.MembershipOracle.MooreMembershipOracle;
20+
import de.learnlib.counterexamples.LocalSuffixFinder;
21+
import de.learnlib.counterexamples.LocalSuffixFinders;
22+
import de.learnlib.testsupport.it.learner.AbstractMooreLearnerIT;
23+
import de.learnlib.testsupport.it.learner.LearnerVariantList.MooreLearnerVariantList;
24+
import net.automatalib.words.Alphabet;
25+
import net.automatalib.words.Word;
26+
import org.testng.annotations.Test;
27+
28+
@Test
29+
public class DTLearnerMooreIT extends AbstractMooreLearnerIT {
30+
31+
@Override
32+
protected <I, O> void addLearnerVariants(Alphabet<I> alphabet,
33+
MooreMembershipOracle<I, O> mqOracle,
34+
MooreLearnerVariantList<I, O> variants) {
35+
DTLearnerMooreBuilder<I, O> builder = new DTLearnerMooreBuilder<>();
36+
builder.setAlphabet(alphabet);
37+
builder.setOracle(mqOracle);
38+
39+
for (LocalSuffixFinder<? super I, ? super Word<O>> suffixFinder : LocalSuffixFinders.values()) {
40+
builder.setSuffixFinder(suffixFinder);
41+
42+
String name = "suffixFinder=" + suffixFinder.toString();
43+
variants.addLearnerVariant(name, builder.create());
44+
}
45+
}
46+
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* Copyright (C) 2013-2022 TU Dortmund
2+
* This file is part of LearnLib, http://www.learnlib.de/.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package de.learnlib.algorithms.discriminationtree;
17+
18+
import de.learnlib.algorithms.discriminationtree.moore.DTLearnerMoore;
19+
import de.learnlib.algorithms.discriminationtree.moore.DTLearnerMooreBuilder;
20+
import de.learnlib.api.oracle.MembershipOracle;
21+
import de.learnlib.testsupport.AbstractResumableLearnerMooreTest;
22+
import net.automatalib.words.Alphabet;
23+
import net.automatalib.words.Word;
24+
25+
/**
26+
* @author frohme
27+
*/
28+
public class DTLearnerMooreResumableLearnerTest
29+
extends AbstractResumableLearnerMooreTest<DTLearnerMoore<Character, Character>, DTLearnerState<Character, Word<Character>, Character, Void>> {
30+
31+
@Override
32+
protected DTLearnerMoore<Character, Character> getLearner(final MembershipOracle<Character, Word<Character>> oracle,
33+
final Alphabet<Character> alphabet) {
34+
return new DTLearnerMooreBuilder<Character, Character>().withAlphabet(alphabet).withOracle(oracle).create();
35+
}
36+
37+
@Override
38+
protected int getRounds() {
39+
return 5;
40+
}
41+
}

0 commit comments

Comments
 (0)