![JAR search and dependency download from the Maven repository](/logo.png)
de.learnlib.algorithm.ttt.dfa.PrefixTTTLearnerDFA Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of learnlib-ttt Show documentation
Show all versions of learnlib-ttt Show documentation
This artifact provides the implementation of the TTT algorithm as described in the paper "The TTT Algorithm: A
Redundancy-Free Approach to Active Automata Learning" (https://doi.org/10.1007/978-3-319-11164-3_26) by Malte
Isberner, Falk Howar, and Bernhard Steffen.
The newest version!
/* Copyright (C) 2013-2023 TU Dortmund
* This file is part of LearnLib, http://www.learnlib.de/.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.learnlib.algorithm.ttt.dfa;
import java.util.Iterator;
import com.google.common.collect.AbstractIterator;
import de.learnlib.acex.AbstractCounterexample;
import de.learnlib.acex.AcexAnalyzer;
import de.learnlib.algorithm.ttt.base.TTTState;
import de.learnlib.algorithm.ttt.base.TTTTransition;
import de.learnlib.oracle.MembershipOracle;
import de.learnlib.query.DefaultQuery;
import net.automatalib.alphabet.Alphabet;
import net.automatalib.common.smartcollection.ArrayStorage;
import net.automatalib.word.Word;
public class PrefixTTTLearnerDFA extends TTTLearnerDFA {
private final ExtDTNode unlabeledList = new ExtDTNode<>();
public PrefixTTTLearnerDFA(Alphabet alphabet, MembershipOracle oracle, AcexAnalyzer analyzer) {
super(alphabet, oracle, analyzer, ExtDTNode::new);
}
@Override
public boolean refineHypothesis(DefaultQuery ceQuery) {
boolean refined = refineHypothesisSingle(ceQuery);
if (!refined) {
return false;
}
while (refineHypothesisSingle(ceQuery)) {}
return true;
}
@Override
protected boolean refineHypothesisSingle(DefaultQuery ceQuery) {
if (getHypothesisModel().computeSuffixOutput(ceQuery.getPrefix(), ceQuery.getSuffix())
.equals(ceQuery.getOutput())) {
return false;
}
Word ceWord = ceQuery.getInput();
int currReachInconsLength = ceWord.length();
EasyTTTPrefAcex acex = new EasyTTTPrefAcex(ceWord);
do {
acex.update(currReachInconsLength);
int breakpoint = analyzer.analyzeAbstractCounterexample(acex, 0, currReachInconsLength);
ExtDTNode toSplit = acex.getHypNode(breakpoint);
TTTState splitState = toSplit.getData();
ExtDTNode lca = acex.getLCA(breakpoint + 1);
I sym = ceWord.getSymbol(breakpoint);
Word newDiscr = lca.getDiscriminator().prepend(sym);
ExtDTNode succHyp = acex.getHypNode(breakpoint + 1);
Boolean hypOut = lca.subtreeLabel(succHyp);
assert hypOut != null;
openTransitions.insertAllIncoming(toSplit.getIncoming());
ExtDTNode.SplitResult splitResult = toSplit.split(newDiscr, hypOut, !hypOut);
link(splitResult.nodeOld, splitState);
ExtDTNode extUnlabeled = (ExtDTNode) splitResult.nodeNew;
extUnlabeled.tempPrefix = currReachInconsLength;
unlabeledList.addUnlabeled(extUnlabeled);
closeTransitions();
currReachInconsLength = findMinReachIncons();
} while (currReachInconsLength != -1);
return true;
}
@Override
protected TTTState makeTree(TTTTransition trans) {
ExtDTNode node = (ExtDTNode) trans.getNonTreeTarget();
if (node.tempPrefix != -1) {
node.removeFromUnlabeledList();
}
return super.makeTree(trans);
}
private int findMinReachIncons() {
int minLength = -1;
for (ExtDTNode n : unlabeledList.unlabeled()) {
int len = n.tempPrefix;
if (minLength == -1 || len < minLength) {
minLength = len;
}
}
return minLength;
}
protected static class ExtDTNode extends TTTDTNodeDFA {
private ExtDTNode prevUnlabeled, nextUnlabeled;
private int tempPrefix = -1;
public ExtDTNode() {
// default constructor
}
public ExtDTNode(ExtDTNode parent, Boolean parentOut) {
super(parent, parentOut);
}
public void removeFromUnlabeledList() {
prevUnlabeled.nextUnlabeled = nextUnlabeled;
if (nextUnlabeled != null) {
nextUnlabeled.prevUnlabeled = prevUnlabeled;
}
}
@Override
protected ExtDTNode createChild(Boolean outcome, TTTState data) {
return new ExtDTNode<>(this, outcome);
}
public boolean hasUnlabeled() {
return nextUnlabeled != null;
}
public void addUnlabeled(ExtDTNode node) {
node.nextUnlabeled = nextUnlabeled;
if (nextUnlabeled != null) {
nextUnlabeled.prevUnlabeled = node;
}
node.prevUnlabeled = this;
this.nextUnlabeled = node;
}
public Iterable> unlabeled() {
return this::unlabeledIterator;
}
public Iterator> unlabeledIterator() {
return new UnlabeledIterator<>(this);
}
private static class UnlabeledIterator extends AbstractIterator> {
private ExtDTNode curr;
UnlabeledIterator(ExtDTNode curr) {
this.curr = curr;
}
@Override
protected ExtDTNode computeNext() {
curr = curr.nextUnlabeled;
if (curr == null) {
return endOfData();
}
return curr;
}
}
}
private final class EasyTTTPrefAcex implements AbstractCounterexample {
private final Word ceWord;
private final ArrayStorage> hypNodes;
private final ArrayStorage> siftNodes;
EasyTTTPrefAcex(Word ceWord) {
this.ceWord = ceWord;
this.hypNodes = new ArrayStorage<>(ceWord.length() + 1);
this.siftNodes = new ArrayStorage<>(ceWord.length() + 1);
update(ceWord.length());
}
public void update(int len) {
TTTStateDFA curr = (TTTStateDFA) hypothesis.getInitialState();
assert curr != null;
hypNodes.set(0, (ExtDTNode) curr.getDTLeaf());
siftNodes.set(0, (ExtDTNode) curr.getDTLeaf());
boolean wasTree = true;
for (int i = 0; i < len; i++) {
I sym = ceWord.getSymbol(i);
TTTTransition trans = hypothesis.getInternalTransition(curr, sym);
curr = (TTTStateDFA) trans.getTarget();
hypNodes.set(i + 1, (ExtDTNode) curr.getDTLeaf());
if (wasTree) {
siftNodes.set(i + 1, (ExtDTNode) curr.getDTLeaf());
if (!trans.isTree()) {
wasTree = false;
}
}
}
}
@Override
public int getLength() {
return ceWord.length() + 1;
}
@Override
public boolean checkEffects(Boolean eff1, Boolean eff2) {
return !eff1 || eff2;
}
@Override
public Boolean effect(int index) {
ExtDTNode hypNode = hypNodes.get(index);
ExtDTNode siftNode = siftNodes.get(index);
if (siftNode == null) {
siftNode = (ExtDTNode) dtree.getRoot();
}
ExtDTNode lca = (ExtDTNode) dtree.leastCommonAncestor(hypNode, siftNode);
Word cePref = ceWord.prefix(index);
while (lca == siftNode && siftNode != hypNode) {
Boolean out = oracle.answerQuery(cePref, siftNode.getDiscriminator());
siftNode = (ExtDTNode) siftNode.getChild(out);
lca = (ExtDTNode) dtree.leastCommonAncestor(hypNode, siftNode);
}
siftNodes.set(index, siftNode);
return siftNode == hypNode;
}
public ExtDTNode getLCA(int index) {
return (ExtDTNode) dtree.leastCommonAncestor(hypNodes.get(index), siftNodes.get(index));
}
public ExtDTNode getHypNode(int index) {
return hypNodes.get(index);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy