• 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

89.89
/commons/datastructures/src/main/java/de/learnlib/datastructure/pta/BasePTA.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.datastructure.pta;
17

18
import java.util.ArrayDeque;
19
import java.util.ArrayList;
20
import java.util.Collection;
21
import java.util.Deque;
22
import java.util.HashSet;
23
import java.util.Iterator;
24
import java.util.List;
25
import java.util.Set;
26

27
import de.learnlib.datastructure.pta.visualization.PTAVisualizationHelper;
28
import net.automatalib.alphabet.Alphabet;
29
import net.automatalib.alphabet.impl.Alphabets;
30
import net.automatalib.automaton.FiniteAlphabetAutomaton;
31
import net.automatalib.automaton.UniversalDeterministicAutomaton;
32
import net.automatalib.automaton.graph.TransitionEdge;
33
import net.automatalib.automaton.graph.TransitionEdge.Property;
34
import net.automatalib.automaton.graph.UniversalAutomatonGraphView;
35
import net.automatalib.common.smartcollection.IntSeq;
36
import net.automatalib.common.util.collection.AbstractSimplifiedIterator;
37
import net.automatalib.graph.UniversalGraph;
38
import net.automatalib.visualization.VisualizationHelper;
39
import org.checkerframework.checker.nullness.qual.Nullable;
40

41
/**
42
 * Base class for prefix tree acceptors.
43
 *
44
 * @param <S>
45
 *         state type
46
 * @param <SP>
47
 *         state property type
48
 * @param <TP>
49
 *         transition property type
50
 */
51
public class BasePTA<S extends AbstractBasePTAState<S, SP, TP>, SP, TP>
52
        implements UniversalDeterministicAutomaton<S, Integer, PTATransition<S>, SP, TP>,
53
                   FiniteAlphabetAutomaton<S, Integer, PTATransition<S>> {
54

55
    private final int alphabetSize;
56
    private final S root;
57

58
    /**
59
     * Constructor.
60
     *
61
     * @param alphabetSize
62
     *         the size of the input alphabet
63
     * @param root
64
     *         the root state
65
     */
66
    public BasePTA(int alphabetSize, S root) {
2✔
67
        this.alphabetSize = alphabetSize;
2✔
68
        this.root = root;
2✔
69
    }
2✔
70

71
    /**
72
     * Retrieves the root of the PTA.
73
     *
74
     * @return the root state
75
     */
76
    public S getRoot() {
77
        return root;
2✔
78
    }
79

80
    @Override
81
    public Alphabet<Integer> getInputAlphabet() {
82
        return Alphabets.integers(0, alphabetSize - 1);
2✔
83
    }
84

85
    /**
86
     * Adds a sample to the PTA, and sets the property of the last reached (or inserted) state accordingly.
87
     *
88
     * @param sample
89
     *         the word to add to the PTA
90
     * @param lastProperty
91
     *         the property of the last state to set
92
     */
93
    public void addSample(IntSeq sample, SP lastProperty) {
94
        S target = getOrCreateState(sample);
2✔
95
        target.mergeStateProperty(lastProperty);
2✔
96
    }
2✔
97

98
    /**
99
     * Retrieves the state reached by the given word. If there is no path for the word in the PTA, it will be added to
100
     * the PTA on-the-fly.
101
     *
102
     * @param word
103
     *         the word
104
     *
105
     * @return the state reached by this word, which might have been newly created (along with all required predecessor
106
     * states)
107
     */
108
    public S getOrCreateState(IntSeq word) {
109
        S curr = root;
2✔
110
        for (int sym : word) {
2✔
111
            curr = curr.getOrCreateSuccessor(sym, alphabetSize);
2✔
112
        }
2✔
113

114
        return curr;
2✔
115
    }
116

117
    public void addSampleWithStateProperties(IntSeq sample, List<? extends SP> lastStateProperties) {
118
        int sampleLen = sample.size();
2✔
119
        int skip = sampleLen + 1 - lastStateProperties.size();
2✔
120
        if (skip < 0) {
2✔
121
            throw new IllegalArgumentException();
×
122
        }
123

124
        S curr = getRoot();
2✔
125
        int i = 0;
2✔
126
        while (i < skip) {
2✔
127
            int sym = sample.get(i++);
×
128
            curr = curr.getOrCreateSuccessor(sym, alphabetSize);
×
129
        }
×
130

131
        Iterator<? extends SP> spIt = lastStateProperties.iterator();
2✔
132

133
        while (i < sampleLen) {
2✔
134
            curr.mergeStateProperty(spIt.next());
2✔
135
            int sym = sample.get(i++);
2✔
136
            curr = curr.getOrCreateSuccessor(sym, alphabetSize);
2✔
137
        }
2✔
138

139
        curr.mergeStateProperty(spIt.next());
2✔
140
    }
2✔
141

142
    public void addSampleWithTransitionProperties(IntSeq sample, List<? extends TP> lastTransitionProperties) {
143
        int sampleLen = sample.size();
2✔
144
        int skip = sampleLen - lastTransitionProperties.size();
2✔
145
        if (skip < 0) {
2✔
146
            throw new IllegalArgumentException();
×
147
        }
148

149
        S curr = getRoot();
2✔
150
        int i = 0;
2✔
151
        while (i < skip) {
2✔
152
            int sym = sample.get(i++);
×
153
            curr = curr.getOrCreateSuccessor(sym, alphabetSize);
×
154
        }
×
155

156
        Iterator<? extends TP> tpIt = lastTransitionProperties.iterator();
2✔
157
        while (i < sampleLen) {
2✔
158
            int sym = sample.get(i++);
2✔
159
            curr.mergeTransitionProperty(sym, alphabetSize, tpIt.next());
2✔
160
            curr = curr.getOrCreateSuccessor(sym, alphabetSize);
2✔
161
        }
2✔
162
    }
2✔
163

164
    @Override
165
    public S getSuccessor(PTATransition<S> transition) {
166
        return transition.getTarget();
2✔
167
    }
168

169
    @Override
170
    public @Nullable S getSuccessor(S state, Integer input) {
171
        return state.getSuccessor(input);
2✔
172
    }
173

174
    @Override
175
    public Iterator<S> iterator() {
176
        Set<S> visited = new HashSet<>();
2✔
177
        final Deque<S> bfsQueue = new ArrayDeque<>();
2✔
178
        bfsQueue.add(root);
2✔
179
        visited.add(root);
2✔
180

181
        return new AbstractSimplifiedIterator<>() {
2✔
182

183
            @Override
184
            protected boolean calculateNext() {
185
                final S next = bfsQueue.poll();
2✔
186
                if (next == null) {
2✔
187
                    return false;
2✔
188
                }
189
                super.nextValue = next;
2✔
190
                for (int i = 0; i < alphabetSize; i++) {
2✔
191
                    final S child = next.getSuccessor(i);
2✔
192
                    if (child != null && visited.add(child)) {
2✔
193
                        bfsQueue.offer(child);
2✔
194
                    }
195
                }
196
                return true;
2✔
197
            }
198
        };
199
    }
200

201
    @Override
202
    public Collection<S> getStates() {
203
        List<S> stateList = new ArrayList<>();
2✔
204
        Set<S> visited = new HashSet<>();
2✔
205

206
        int ptr = 0;
2✔
207
        stateList.add(root);
2✔
208
        visited.add(root);
2✔
209
        int numStates = 1;
2✔
210

211
        while (ptr < numStates) {
2✔
212
            S curr = stateList.get(ptr++);
2✔
213
            for (int i = 0; i < alphabetSize; i++) {
2✔
214
                S succ = curr.getSuccessor(i);
2✔
215
                if (succ != null && visited.add(succ)) {
2✔
216
                    stateList.add(succ);
2✔
217
                    numStates++;
2✔
218
                }
219
            }
220
        }
2✔
221

222
        return stateList;
2✔
223
    }
224

225
    @Override
226
    public S getInitialState() {
227
        return getRoot();
2✔
228
    }
229

230
    @Override
231
    public @Nullable PTATransition<S> getTransition(S state, Integer input) {
232
        if (state.getSuccessor(input) == null) {
2✔
233
            return null;
2✔
234
        }
235

236
        return new PTATransition<>(state, input);
2✔
237
    }
238

239
    @Override
240
    public SP getStateProperty(S state) {
241
        return state.getStateProperty();
2✔
242
    }
243

244
    @Override
245
    public TP getTransitionProperty(PTATransition<S> transition) {
246
        return transition.getSource().getTransProperty(transition.getIndex());
2✔
247
    }
248

249
    @Override
250
    public UniversalGraph<S, TransitionEdge<Integer, PTATransition<S>>, SP, Property<Integer, TP>> transitionGraphView(
251
            Collection<? extends Integer> inputs) {
252
        return new UniversalAutomatonGraphView<>(this, inputs) {
2✔
253

254
            @Override
255
            public VisualizationHelper<S, TransitionEdge<Integer, PTATransition<S>>> getVisualizationHelper() {
256
                return BasePTA.this.getVisualizationHelper();
2✔
257
            }
258
        };
259
    }
260

261
    protected VisualizationHelper<S, TransitionEdge<Integer, PTATransition<S>>> getVisualizationHelper() {
262
        return new PTAVisualizationHelper<>(this);
×
263
    }
264
}
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