Skip to content

Commit b76d423

Browse files
authored
LearnLib CLI (#166)
* initial work on CLI application * update build profiles * github: add worflow for attaching cli artifacts * cli: include OS classifiers in artifact name * do not include cli module in releases for now * update docs * tidy:pom * add support for SAF serialization * cli: add ADT and LSHARP algorithm * cli oracles still need some rework regarding error handling * cleanup CLI oracles * experiment: allow for logging intermediate hypotheses * jacoco: also depend on cli module before aggregating reports * cli: improve documentation * fix code-analysis * cli: add support for parallel oracles * cli: add unit- and integration-tests * add support for snapshotting * use LocalDateTime * simplify --eqo-* param names * Revert "simplify --eqo-* param names" This reverts commit d209e96. * add MalerPnueli + RivestSchapire learner and adjust learner names * include license information in jlink artifact * cleanup checkerframework config * add rudimentary class validation during deserialization + cleanups * add changelog * add missing --add-opens + test * cleanup * wording * handle python availability more gracefully * conditionally set --add-opens option * cli: invoke script via python interpreter as on Windows the scripts alone are not detected as executable applications * sett full (and platform-specific) path in jlink IT * wording * coveralls: s/Example/Experiment/
1 parent 6c9a24b commit b76d423

124 files changed

Lines changed: 6827 additions & 295 deletions

File tree

Some content is hidden

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

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
mvn -B install -DskipTests
4848
cd $GITHUB_WORKSPACE
4949
- name: Run Maven
50-
run: mvn -B install site -Pintegration-tests,code-analysis,bundles,jlink
50+
run: mvn -B install site -Pintegration-tests,code-analysis,bundles
5151
platform-integration:
5252
name: "Platform Integration (JDK: ${{ matrix.jdk }}, OS: ${{ matrix.os }})"
5353
needs: [ tests-and-analysis ]
@@ -81,7 +81,7 @@ jobs:
8181
mvn -B install -DskipTests
8282
cd $GITHUB_WORKSPACE
8383
- name: Run Maven
84-
run: mvn -B install -Pjlink
84+
run: mvn -B install -Pcli
8585
coverage:
8686
name: "Coverage"
8787
needs: [ platform-integration ]

.github/workflows/release.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Attach artifacts to GitHub release
2+
on:
3+
release:
4+
types: [published]
5+
jobs:
6+
publish:
7+
name: "Build and attach artifacts"
8+
runs-on: ${{ matrix.os }}
9+
strategy:
10+
matrix:
11+
os: [ ubuntu-22.04, windows-2022, macos-15-intel, macos-15 ]
12+
permissions:
13+
contents: write
14+
steps:
15+
- uses: actions/checkout@v6
16+
- uses: actions/setup-java@v5
17+
with:
18+
java-version: '25'
19+
distribution: 'temurin'
20+
cache: 'maven'
21+
- name: Build AutomataLib # can be removed on actual stable releases
22+
shell: bash
23+
run: |
24+
git clone -b develop --single-branch https://github.com/LearnLib/automatalib.git ${HOME}/automatalib-git
25+
cd ${HOME}/automatalib-git
26+
mvn -B install -DskipTests
27+
cd $GITHUB_WORKSPACE
28+
- name: Build
29+
run: mvn -B package -DskipTests -Pcli
30+
- name: Release
31+
uses: softprops/action-gh-release@v3
32+
with:
33+
working_directory: cli/target
34+
files: learnlib-cli-*.zip
35+
fail_on_unmatched_files: true

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
88

99
### Added
1010

11+
* GitHub releases now provide `learnlib-cli` artifacts for using LearnLib via the command-line interface without the need for Java or Maven.
1112
* Added a new (L*-based) learning algorithm for *Mealy machines with local timers* (MMLTs), including support for parallel queries, caching, and conformance testing (thanks to [Paul Kogel](https://github.com/pdev55)).
1213
* Added the L<sup>s</sup> active learning algorithm for Mealy machines (thanks to [Wolffhardt Schwabe](https://github.com/stateMachinist)).
1314
* Added an `EarlyExitEQOracle` which for a given `AdaptiveMembershipOracle` and `TestWordGenerator` stops the evaluation of (potentially long) Mealy-based equivalence tests as soon as a mismatch with the hypothesis is detected, potentially improving the symbol performance of the given equivalence oracle.
@@ -21,12 +22,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2122
* Statistics collection has received a major rework. Previously, classes would implement the `StatisticCollector` interface and return a `StatisticData` object which 1) only allows for describing a very limited amount of data, and 2) requires you to keep track of all the objects that collect data. This approach has been *replaced* by a new `StatisticsService`. Instances of this service can be obtained similar to a logger via `Statistics.getService()` and require you to provide an implementation of this service on the classpath (a default one is provided by the `learnlib-statistics` module). The new service allows arbitrary components to collect various data which can be conveniently extracted based on the new `StatisticsKey`s used by the components. For more details on advanced scenarios (such as multi-threaded benchmarking), see the documentation of the respective classes. While this may require you to adjust the way you are collecting statistics, all functionality from beforehand should still be available.
2223
* `SimpleProfiler` has been replaced by the new clock-based statistics.
2324
* Most learners now more rigorously implement the `LearningAlgorithm` contract that, e.g., duplicate invocations of `startLearning` or calling `refineHypothesis` / `getHypothesisModel` before `startLearning` throw `IllegalStateException`s.
25+
* `Experiment` now has type variables for the input symbol type and output domain type.
26+
* `{DFA,Mealy,Moore}Experiment` have been moved to the `de.learnlib.util` package.
2427
* The `generateTestWords` method of `AbstractTestWordEQOracle` now needs to be public.
2528
* The classes of `de.learnlib.testsupport.it.learner` have been split into the packages `de.learnlib.testsupport.it{,testcase,util,variant}` in the same module (`de.learnlib.testsupport:learnlib-learner-it-support`).
2629

2730
### Removed
2831

29-
* All *adapters* from the `learnlib-procedural` learner have been removed to due main learners implementing `AccessSequenceTransformer` now. Use the constructors of the main learners instead.
32+
* All *adapters* from the `learnlib-procedural` learner have been removed due to main learners implementing `AccessSequenceTransformer` now. Use the constructors of the main learners instead.
3033

3134
### Fixed
3235

algorithms/active/aaar/src/test/java/de/learnlib/algorithm/aaar/AbstractAAARTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ public void testAbstractHypothesisEquivalence() {
5252
final WpMethodTestsIterator<I> iter = new WpMethodTestsIterator<>(automaton, alphabet);
5353
final List<Word<I>> testCases = IteratorUtil.list(iter);
5454

55-
final SampleSetEQOracle<I, D> eqo = new SampleSetEQOracle<>();
56-
eqo.addAll(new SimulatorOracle<>(automaton), testCases);
55+
final SampleSetEQOracle<I, D> eqo =
56+
new SampleSetEQOracle<I, D>().addAll(new SimulatorOracle<>(automaton), testCases);
5757

5858
final LearningAlgorithm<A, I, D> learner =
5959
new TranslatingLearnerWrapper<>((AbstractAAARLearner<?, A, A, I, I, D>) aaarLearner);
60-
final Experiment<A> exp = new Experiment<>(learner, eqo, alphabet);
60+
final Experiment<A, I, D> exp = new Experiment<>(learner, eqo, alphabet);
6161

6262
exp.run();
6363

algorithms/active/adt/src/main/java/de/learnlib/algorithm/adt/learner/ADTLearner.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import de.learnlib.query.DefaultQuery;
6161
import de.learnlib.tooling.annotation.builder.GenerateBuilder;
6262
import de.learnlib.util.MQUtil;
63+
import de.learnlib.util.mealy.Adaptive2MembershipWrapper;
6364
import net.automatalib.alphabet.Alphabet;
6465
import net.automatalib.alphabet.SupportsGrowingAlphabet;
6566
import net.automatalib.automaton.transducer.MealyMachine;
@@ -104,12 +105,26 @@ public class ADTLearner<I, O> implements LearningAlgorithm.MealyLearner<I, O>,
104105
private ADTHypothesis<I, O> hypothesis;
105106
private ADT<ADTState<I, O>, I, O> adt;
106107

108+
public ADTLearner(Alphabet<I> alphabet, AdaptiveMembershipOracle<I, O> oracle) {
109+
this(alphabet,
110+
oracle,
111+
BuilderDefaults.leafSplitter(),
112+
BuilderDefaults.adtExtender(),
113+
BuilderDefaults.subtreeReplacer());
114+
}
115+
107116
public ADTLearner(Alphabet<I> alphabet,
108117
AdaptiveMembershipOracle<I, O> oracle,
109118
LeafSplitter leafSplitter,
110119
ADTExtender adtExtender,
111120
SubtreeReplacer subtreeReplacer) {
112-
this(alphabet, oracle, leafSplitter, adtExtender, subtreeReplacer, true, LocalSuffixFinders.RIVEST_SCHAPIRE);
121+
this(alphabet,
122+
oracle,
123+
leafSplitter,
124+
adtExtender,
125+
subtreeReplacer,
126+
BuilderDefaults.useObservationTree(),
127+
BuilderDefaults.suffixFinder());
113128
}
114129

115130
@GenerateBuilder(defaults = BuilderDefaults.class)

algorithms/active/adt/src/test/java/de/learnlib/algorithm/adt/it/ADTIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
import de.learnlib.testsupport.MQ2AQWrapper;
4848
import de.learnlib.testsupport.it.AbstractMealyLearnerIT;
4949
import de.learnlib.testsupport.it.variant.LearnerVariantList;
50-
import de.learnlib.util.Experiment.MealyExperiment;
50+
import de.learnlib.util.MealyExperiment;
5151
import net.automatalib.alphabet.Alphabet;
5252
import net.automatalib.automaton.transducer.impl.CompactMealy;
5353
import net.automatalib.exception.FormatException;

algorithms/active/lambda/src/test/java/de/learnlib/algorithm/lambda/AbstractCounterexampleQueueTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import de.learnlib.oracle.MembershipOracle.DFAMembershipOracle;
2020
import de.learnlib.oracle.equivalence.SampleSetEQOracle;
2121
import de.learnlib.oracle.membership.DFASimulatorOracle;
22-
import de.learnlib.util.Experiment.DFAExperiment;
22+
import de.learnlib.util.Experiment;
2323
import net.automatalib.alphabet.Alphabet;
2424
import net.automatalib.alphabet.impl.Alphabets;
2525
import net.automatalib.automaton.fsa.DFA;
@@ -80,7 +80,8 @@ public void testPop() {
8080
final Word<Character> b = new WordBuilder<>('b', 9).toWord();
8181
eqOracle.addAll(mqOracle, Word.fromWords(b, a, b, a, b, a, b, a));
8282

83-
final DFAExperiment<Character> experiment = new DFAExperiment<>(learner, eqOracle, alphabet);
83+
final Experiment<DFA<?, Character>, Character, Boolean> experiment =
84+
new Experiment<>(learner, eqOracle, alphabet);
8485
experiment.run();
8586

8687
final DFA<?, Character> result = experiment.getFinalHypothesis();

algorithms/active/lambda/src/test/java/de/learnlib/algorithm/lambda/lstar/mealy/it/LLambdaMealyIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import de.learnlib.query.DefaultQuery;
3131
import de.learnlib.testsupport.it.AbstractMealyLearnerIT;
3232
import de.learnlib.testsupport.it.variant.LearnerVariantList.MealyLearnerVariantList;
33-
import de.learnlib.util.Experiment.MealyExperiment;
33+
import de.learnlib.util.MealyExperiment;
3434
import de.learnlib.util.mealy.MealyUtil;
3535
import net.automatalib.alphabet.Alphabet;
3636
import net.automatalib.automaton.transducer.MealyMachine;

algorithms/active/nlstar/src/test/java/de/learnlib/algorithm/nlstar/NLStarTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ public void testIssue70() {
6262

6363
final NLStarLearner<Character> learner = new NLStarLearner<>(alphabet, mqOracle);
6464

65-
final Experiment<NFA<?, Character>> experiment = new Experiment<>(learner, eqOracle, alphabet);
65+
final Experiment<NFA<?, Character>, Character, Boolean> experiment =
66+
new Experiment<>(learner, eqOracle, alphabet);
6667
experiment.run();
6768
final NFA<?, Character> hyp = experiment.getFinalHypothesis();
6869

algorithms/active/observation-pack-vpa/src/test/java/de/learnlib/algorithm/observationpack/vpa/DTVisualizationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public DTVisualizationTest() {
5050
final SimulatorEQOracle<Character> eqo = new SimulatorEQOracle<>(vpa);
5151
this.learner = new OPLearnerVPA<>(alphabet, mqo, AcexAnalyzers.BINARY_SEARCH_FWD);
5252

53-
final Experiment<OneSEVPA<?, Character>> exp = new Experiment<>(learner, eqo, alphabet);
53+
final Experiment<OneSEVPA<?, Character>, Character, Boolean> exp = new Experiment<>(learner, eqo, alphabet);
5454
exp.run();
5555
}
5656

0 commit comments

Comments
 (0)