Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
name: "Tests and Analysis (JDK: ${{ matrix.jdk }})"
strategy:
matrix:
jdk: [ 11, 17, 21 ]
jdk: [ 17, 21, 25 ]
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand Down Expand Up @@ -56,7 +56,7 @@ jobs:
needs: [ tests-and-analysis ]
strategy:
matrix:
jdk: [ 11, 17, 21 ]
jdk: [ 17, 21, 25 ]
os: [ ubuntu-latest, windows-latest, macOS-latest ]
runs-on: ${{ matrix.os }}
steps:
Expand Down Expand Up @@ -99,7 +99,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 11
java-version: 17
- name: Set up cache
uses: actions/cache@v3
with:
Expand Down Expand Up @@ -150,7 +150,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 11
java-version: 17
- name: Set up cache
uses: actions/cache@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### Changed

* LearnLib now requires Java 11 at runtime.
* LearnLib now requires Java 17 at runtime.
* The `generateTestWords` method of `AbstractTestWordEQOracle` now needs to be public.

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Contributions -- whether it is in the form of new features, better documentation

For simply using LearnLib you may use the Maven artifacts which are available in the [Maven Central repository][maven-central].
It is also possible to download a bundled [distribution artifact][maven-central-distr] if you want to use LearnLib without Maven support.
Note that LearnLib requires Java 11 (or newer) to build but still supports Java 8 at runtime.
Note that LearnLib requires Java 17 (or newer) to build and run.

#### Building development versions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ public Collection<CI> getRepresentativeSymbols() {

@Override
public Collection<Node> getOutgoingEdges(Node node) {
if (node instanceof InnerNode) {
final InnerNode<?, ?> n = (InnerNode<?, ?>) node;
if (node instanceof InnerNode<?, ?> n) {
return Arrays.asList(n.equalsNext, n.otherNext);
}

Expand All @@ -155,8 +154,7 @@ public Collection<Node> getNodes() {

while (!nodes.isEmpty()) {
final Node n = nodes.poll();
if (n instanceof InnerNode) {
final InnerNode<?, ?> in = (InnerNode<?, ?>) n;
if (n instanceof InnerNode<?, ?> in) {
result.add(in);
nodes.add(in.equalsNext);
nodes.add(in.otherNext);
Expand All @@ -177,11 +175,9 @@ public VisualizationHelper<Node, Node> getVisualizationHelper() {
public boolean getNodeProperties(Node node, Map<String, String> properties) {
super.getNodeProperties(node, properties);

if (node instanceof InnerNode) {
final InnerNode<?, ?> n = (InnerNode<?, ?>) node;
if (node instanceof InnerNode<?, ?> n) {
properties.put(NodeAttrs.LABEL, n.prefix + ", " + n.suffix);
} else if (node instanceof Leaf) {
final Leaf<?, ?> l = (Leaf<?, ?>) node;
} else if (node instanceof Leaf<?, ?> l) {
properties.put(NodeAttrs.LABEL, String.format("Abs.: '%s'%nRep.: '%s'", l.abs, l.rep));
}

Expand All @@ -192,8 +188,7 @@ public boolean getNodeProperties(Node node, Map<String, String> properties) {
public boolean getEdgeProperties(Node src, Node edge, Node tgt, Map<String, String> properties) {
super.getEdgeProperties(src, edge, tgt, properties);

if (src instanceof InnerNode) {
final InnerNode<?, ?> n = (InnerNode<?, ?>) src;
if (src instanceof InnerNode<?, ?> n) {
if (n.equalsNext == tgt) {
properties.put(EdgeAttrs.LABEL, "== " + n.out);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import net.automatalib.word.Word;

class Node {
public class Node {

static class InnerNode<CI, D> extends Node {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,11 @@ public String getAbstractSymbol(CI c) {

@Override
public CI getRepresentative(String a) {
switch (a) {
case "even":
return alphabet.getSymbol(0);
case "odd":
return alphabet.getSymbol(1);
default:
throw new IllegalArgumentException("Unknown symbol: " + a);
}
return switch (a) {
case "even" -> alphabet.getSymbol(0);
case "odd" -> alphabet.getSymbol(1);
default -> throw new IllegalArgumentException("Unknown symbol: " + a);
};
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Interface for configuration objects that specify how to finalize the temporary splitter given by regular
* counterexample decomposition.
*/
@FunctionalInterface
public interface ADTExtender {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* Interface for configuration objects that specify how to split the ADT leaf of a hypothesis state that needs
* refinement.
*/
@FunctionalInterface
public interface LeafSplitter {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
/**
* Interface for configuration objects that specify how nodes of the current ADT should be replaced.
*/
@FunctionalInterface
public interface SubtreeReplacer {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import net.automatalib.alphabet.Alphabet;
import net.automatalib.automaton.transducer.MealyMachine;

@FunctionalInterface
public interface ADSCalculator {

<S, I, O> Optional<ADTNode<S, I, O>> compute(MealyMachine<S, I, ?, O> hypothesis,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import net.automatalib.alphabet.Alphabet;
import net.automatalib.automaton.transducer.MealyMachine;

@FunctionalInterface
public interface DefensiveADSCalculator {

<S, I, O> Optional<ADTNode<S, I, O>> compute(MealyMachine<S, I, ?, O> automaton,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,7 @@ private void updateTransitions(List<Long> transList,

final List<Word<I>> transAs = new ArrayList<>(numTrans);

for (int i = 0; i < numTrans; i++) {
long encodedTrans = transList.get(i);

for (long encodedTrans : transList) {
int sourceState = (int) (encodedTrans >> Integer.SIZE);
int transIdx = (int) encodedTrans;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,7 @@ private void updateTransitions(List<Long> transList,

final List<Word<I>> transAs = new ArrayList<>(numTrans);

for (int i = 0; i < numTrans; i++) {
long encodedTrans = transList.get(i);

for (long encodedTrans : transList) {
int sourceState = (int) (encodedTrans >> Integer.SIZE);
int transIdx = (int) encodedTrans;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ public void split(PTNode<I, D> u1, PTNode<I, D> u2, I a) {
DTLeaf<I, D> ua2 = s2.state();
AbstractDTNode<I, D> n = lca(ua1, ua2);
STNode<I> av;
if (n instanceof DTInnerNode) {
av = ((DTInnerNode<I, D>) n).suffix().prepend(a);
if (n instanceof DTInnerNode<I, D> in) {
av = in.suffix().prepend(a);
} else {
av = tree.newSuffix(a);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,9 @@ private <T> List<T> sample2(Collection<T> collection) {
return shuffled.subList(0, 2);
}

@SuppressWarnings("PMD.SwitchDensity")
private Pair<Word<I>, Word<O>> rule3IO(List<Word<I>> candidates, Word<I> prefix) {
switch (this.rule3) {
return switch (this.rule3) {
case ADS:
if (candidates.size() == 2) {
Word<I> q1Acc = candidates.get(0);
Expand All @@ -92,28 +93,25 @@ private Pair<Word<I>, Word<O>> rule3IO(List<Word<I>> candidates, Word<I> prefix)
Word<I> wit = ApartnessUtil.computeWitness(obsTree, q1, q2);
assert wit != null;

WordBuilder<I> inputSeq = new WordBuilder<>(prefix);
assert !(ApartnessUtil.accStatesAreApart(obsTree, prefix, q1Acc) ||
ApartnessUtil.accStatesAreApart(obsTree, prefix, q2Acc));
inputSeq.append(wit);
Word<O> outputSeq = this.outputQuery(inputSeq.toWord());

return Pair.of(inputSeq.toWord(), outputSeq);
Word<I> inputSeq = prefix.concat(wit);
Word<O> outputSeq = this.outputQuery(inputSeq);

yield Pair.of(inputSeq, outputSeq);
} else {
List<Integer> candss = getSuccs(candidates);
ADSTree<Integer, I, O> suffix = new ADSTree<>(obsTree, candss, sinkOutput);
return this.adaptiveOutputQuery(prefix, null, suffix);
yield this.adaptiveOutputQuery(prefix, null, suffix);
}
case SEPSEQ:
List<Integer> withS = getSuccs(sample2(candidates));
Word<I> wit = ApartnessUtil.computeWitness(obsTree, withS.get(0), withS.get(1));
assert wit != null;
Word<I> inputSeq = prefix.concat(wit);
return Pair.of(inputSeq, this.outputQuery(inputSeq));
default:
throw new IllegalStateException("Shouldn't get here!");
}
yield Pair.of(inputSeq, this.outputQuery(inputSeq));
};
}

private List<Integer> getSuccs(Collection<Word<I>> candidates) {
Expand Down Expand Up @@ -148,14 +146,14 @@ public List<Word<I>> identifyFrontier(Word<I> fsAcc, List<Word<I>> candidates) {
}

private Pair<Word<I>, Word<O>> rule2IO(Word<I> accessQ, I i, List<Integer> bss, Collection<Word<I>> basis) {
switch (this.rule2) {
return switch (this.rule2) {
case ADS:
ADSTree<Integer, I, O> suffix = new ADSTree<>(obsTree, bss, sinkOutput);
return this.adaptiveOutputQuery(accessQ, i, suffix);
yield this.adaptiveOutputQuery(accessQ, i, suffix);
case NOTHING:
Word<I> prefix = accessQ.append(i);
Word<O> oSeq = this.outputQuery(prefix);
return Pair.of(prefix, oSeq);
yield Pair.of(prefix, oSeq);
case SEPSEQ:
Word<I> wit;
if (basis.size() >= 2) {
Expand All @@ -167,10 +165,8 @@ private Pair<Word<I>, Word<O>> rule2IO(Word<I> accessQ, I i, List<Integer> bss,
}
Word<I> inputSeq = accessQ.append(i).concat(wit);
Word<O> outputSeq = this.outputQuery(inputSeq);
return Pair.of(inputSeq, outputSeq);
default:
throw new IllegalStateException("Shouldn't get here!");
}
yield Pair.of(inputSeq, outputSeq);
};
}

public List<Pair<Word<I>, List<Word<I>>>> exploreFrontier(Collection<Word<I>> basis) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public static <S extends Comparable<S>, I, O> ADSNode<I, O> constructADS(Observa
}
}

assert bestInput != null && bestChildren != null;
assert bestInput != null;

return new ADSNode<>(bestInput, toMap(bestChildren), bestIScore);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public void resume(AutomatonLStarState<I, D, AI, S> state) {
}
}

static final class StateInfo<S, I> {
protected static final class StateInfo<S, I> {

private final Row<I> row;
private final S state;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* @param <D>
* type variable for output symbol upper bound.
*/
@FunctionalInterface
public interface ClosingStrategy<I, D> {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,16 @@ public ContextPair<I> getNewDiscriminator() {
Word<I> prefix = succSeparator.getDiscriminator().getPrefix();
Word<I> suffix = succSeparator.getDiscriminator().getSuffix();

switch (type) {
case INTERNAL:
return new ContextPair<>(prefix, suffix.prepend(symbol));
case RETURN:
return new ContextPair<>(prefix.concat(location.getAccessSequence()).append(otherSymbol),
suffix.prepend(symbol));
case CALL:
return new ContextPair<>(prefix,
location.getAccessSequence()
.prepend(symbol)
.append(otherSymbol)
.concat(suffix));
default:
throw new IllegalStateException("Unhandled type " + type);
}
return switch (type) {
case INTERNAL -> new ContextPair<>(prefix, suffix.prepend(symbol));
case RETURN -> new ContextPair<>(prefix.concat(location.getAccessSequence()).append(otherSymbol),
suffix.prepend(symbol));
case CALL -> new ContextPair<>(prefix,
location.getAccessSequence()
.prepend(symbol)
.append(otherSymbol)
.concat(suffix));
};
}

public int getNewDiscriminatorLength() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ protected State<HypLoc<I>> getAnySuccessor(State<HypLoc<I>> state, I sym) {
final VPAlphabet.SymbolType type = alphabet.getSymbolType(sym);
final StackContents stackContents = state.getStackContents();

switch (type) {
return switch (type) {
case INTERNAL: {
AbstractHypTrans<I> trans = hypothesis.getInternalTransition(state.getLocation(), sym);
HypLoc<I> succLoc;
Expand All @@ -227,11 +227,11 @@ protected State<HypLoc<I>> getAnySuccessor(State<HypLoc<I>> state, I sym) {
} else {
succLoc = trans.getNonTreeTarget().subtreeLocsIterator().next();
}
return new State<>(succLoc, stackContents);
yield new State<>(succLoc, stackContents);
}
case CALL: {
int stackSym = hypothesis.encodeStackSym(state.getLocation(), sym);
return new State<>(hypothesis.getInitialLocation(), StackContents.push(stackSym, stackContents));
yield new State<>(hypothesis.getInitialLocation(), StackContents.push(stackSym, stackContents));
}
case RETURN: {
assert stackContents != null;
Expand All @@ -243,11 +243,9 @@ protected State<HypLoc<I>> getAnySuccessor(State<HypLoc<I>> state, I sym) {
} else {
succLoc = trans.getNonTreeTarget().subtreeLocsIterator().next();
}
return new State<>(succLoc, stackContents.pop());
yield new State<>(succLoc, stackContents.pop());
}
default:
throw new IllegalStateException("Unhandled type " + type);
}
};
}

private PrefixTransformAcex deriveAcex(OutputInconsistency<I> outIncons) {
Expand Down Expand Up @@ -592,16 +590,11 @@ private static <I> void markAndPropagate(DTNode<I> node, Boolean label) {
}

public AbstractHypTrans<I> getSplitterTrans(HypLoc<I> loc, Splitter<I> splitter) {
switch (splitter.type) {
case INTERNAL:
return hypothesis.getInternalTransition(loc, splitter.symbol);
case RETURN:
return hypothesis.getReturnTransition(loc, splitter.symbol, splitter.location, splitter.otherSymbol);
case CALL:
return hypothesis.getReturnTransition(splitter.location, splitter.otherSymbol, loc, splitter.symbol);
default:
throw new IllegalStateException("Unhandled type " + splitter.type);
}
return switch (splitter.type) {
case INTERNAL -> hypothesis.getInternalTransition(loc, splitter.symbol);
case RETURN -> hypothesis.getReturnTransition(loc, splitter.symbol, splitter.location, splitter.otherSymbol);
case CALL -> hypothesis.getReturnTransition(splitter.location, splitter.otherSymbol, loc, splitter.symbol);
};
}

private static <I> void moveIncoming(DTNode<I> newNode, DTNode<I> oldNode, Boolean label) {
Expand Down
Loading