• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LearnLib / learnlib / 31619759710

12 Aug 2026 04:27PM UTC coverage: 95.488% (+1.1%) from 94.368%
31619759710

push

github

mtf90
use new version scheme

15533 of 16267 relevant lines covered (95.49%)

1.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.87
/examples/src/main/java/de/learnlib/example/resumable/ResumableExample.java
1
/* Copyright (C) 2013-2026 TU Dortmund University
2
 * This file is part of LearnLib <https://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.example.resumable;
17

18
import java.util.Random;
19

20
import de.learnlib.Resumable;
21
import de.learnlib.algorithm.lstar.dfa.ClassicLStarDFA;
22
import de.learnlib.filter.cache.dfa.DFACacheOracle;
23
import de.learnlib.filter.cache.dfa.DFACaches;
24
import de.learnlib.filter.statistic.oracle.DFACounterOracle;
25
import de.learnlib.oracle.EquivalenceOracle.DFAEquivalenceOracle;
26
import de.learnlib.oracle.MembershipOracle.DFAMembershipOracle;
27
import de.learnlib.oracle.equivalence.DFASimulatorEQOracle;
28
import de.learnlib.oracle.membership.DFASimulatorOracle;
29
import de.learnlib.query.DefaultQuery;
30
import de.learnlib.statistic.Statistics;
31
import de.learnlib.statistic.StatisticsKey;
32
import de.learnlib.statistic.StatisticsService;
33
import net.automatalib.alphabet.Alphabet;
34
import net.automatalib.alphabet.impl.Alphabets;
35
import net.automatalib.alphabet.impl.GrowingMapAlphabet;
36
import net.automatalib.automaton.fsa.impl.CompactDFA;
37
import net.automatalib.util.automaton.random.RandomAutomata;
38
import org.apache.fory.Fory;
39
import org.apache.fory.logging.LoggerFactory;
40

41
/**
42
 * An example to demonstrate the {@link Resumable} feature of LearnLib to continue learning setups from previously
43
 * stored snapshots.
44
 */
45
@SuppressWarnings("PMD.SystemPrintln")
46
public final class ResumableExample {
47

48
    private static final CompactDFA<Character> TARGET;
49
    private static final Alphabet<Character> INITIAL_ALPHABET;
50
    private static final Fory FORY;
51

52
    static {
53
        LoggerFactory.useSlf4jLogging(true);
1✔
54

55
        final int seed = 42;
1✔
56
        final int size = 100;
1✔
57

58
        TARGET = RandomAutomata.randomDFA(new Random(seed), size, Alphabets.characters('a', 'd'));
1✔
59
        INITIAL_ALPHABET = Alphabets.characters('a', 'b');
1✔
60
        FORY = Fory.builder()
1✔
61
                   .requireClassRegistration(false)
1✔
62
                   .withCodegen(false)
1✔
63
                   .withRefTracking(true)
1✔
64
                   .withXlang(false)
1✔
65
                   .build();
1✔
66
    }
1✔
67

68
    private ResumableExample() {
69
        // prevent instantiation
70
    }
71

72
    public static void main(String[] args) {
73

74
        final Setup setup = new Setup();
1✔
75

76
        // construct initial model with inputs 'a' and 'b'
77
        setup.learner.startLearning();
1✔
78
        DefaultQuery<Character, Boolean> ce;
79
        while ((ce = setup.eqo.findCounterExample(setup.learner.getHypothesisModel(), INITIAL_ALPHABET)) != null) {
1✔
80
            setup.learner.refineHypothesis(ce);
1✔
81
        }
82

83
        System.out.println("## Initial setup");
1✔
84
        printStats(setup);
1✔
85

86
        // serialize the current state of the learning setup which may be stored somewhere external
87
        final byte[] learnerData = toBytes(setup.learner.suspend());
1✔
88
        final byte[] cacheData = toBytes(setup.cache.suspend());
1✔
89

90
        // continue exploring the previous snapshot with new input symbol 'c'
91
        continueExploring(learnerData, cacheData, 'c');
1✔
92

93
        // continue exploring the previous snapshot with new input symbol 'd'. Note that in this scenario we have never added 'c'.
94
        continueExploring(learnerData, cacheData, 'd');
1✔
95
    }
1✔
96

97
    private static void continueExploring(byte[] learnerData, byte[] cacheData, char newSymbol) {
98

99
        // re-initialize setup
100
        final Setup setup = new Setup();
1✔
101

102
        // resume from previous states and add new symbol
103
        setup.cache.resume(fromBytes(cacheData));
1✔
104
        setup.cache.addAlphabetSymbol(newSymbol);
1✔
105

106
        setup.learner.resume(fromBytes(learnerData));
1✔
107
        setup.learner.addAlphabetSymbol(newSymbol);
1✔
108

109
        // continue learning-loop
110
        DefaultQuery<Character, Boolean> ce;
111
        while ((ce = setup.eqo.findCounterExample(setup.learner.getHypothesisModel(), INITIAL_ALPHABET)) != null) {
1✔
112
            setup.learner.refineHypothesis(ce);
×
113
        }
114

115
        System.out.println("## After exploring '" + newSymbol + '\'');
1✔
116
        printStats(setup);
1✔
117
    }
1✔
118

119
    private static byte[] toBytes(Object state) {
120
        return FORY.serialize(state);
1✔
121
    }
122

123
    @SuppressWarnings("unchecked")
124
    private static <T> T fromBytes(byte[] bytes) {
125
        return (T) FORY.deserialize(bytes);
1✔
126
    }
127

128
    private static void printStats(Setup setup) {
129
        StatisticsService statistics = Statistics.getService();
1✔
130
        statistics.setCounter(new StatisticsKey("size", "Hypothesis size"), setup.learner.getHypothesisModel().size());
1✔
131
        System.out.println(statistics.print());
1✔
132
        statistics.clear();
1✔
133
    }
1✔
134

135
    private static class Setup {
136

137
        private final DFACacheOracle<Character> cache;
138
        private final DFAEquivalenceOracle<Character> eqo;
139
        private final ClassicLStarDFA<Character> learner;
140

141
        Setup() {
1✔
142
            final DFAMembershipOracle<Character> mqo = new DFASimulatorOracle<>(TARGET);
1✔
143
            final DFACounterOracle<Character> counter = new DFACounterOracle<>(mqo);
1✔
144
            this.cache = DFACaches.createCache(new GrowingMapAlphabet<>(INITIAL_ALPHABET), counter);
1✔
145
            this.eqo = new DFASimulatorEQOracle<>(TARGET);
1✔
146
            this.learner = new ClassicLStarDFA<>(new GrowingMapAlphabet<>(INITIAL_ALPHABET), cache);
1✔
147
        }
1✔
148
    }
149
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc