
de.learnlib.algorithm.observationpack.vpa.OPLearnerVPA Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of learnlib-observation-pack-vpa Show documentation
Show all versions of learnlib-observation-pack-vpa Show documentation
This artifact provides the implementation of the VPA adaption of the Observation-Pack learning algorithm as
discussed in the PhD thesis "Foundations of Active Automata Learning: An Algorithmic Perspective"
(https://dx.doi.org/10.17877/DE290R-16359) by Malte Isberner.
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.observationpack.vpa;
import java.util.ArrayList;
import java.util.List;
import com.github.misberner.buildergen.annotations.GenerateBuilder;
import com.google.common.collect.Iterables;
import de.learnlib.acex.AbstractBaseCounterexample;
import de.learnlib.acex.AcexAnalyzer;
import de.learnlib.algorithm.observationpack.vpa.hypothesis.AbstractHypTrans;
import de.learnlib.algorithm.observationpack.vpa.hypothesis.ContextPair;
import de.learnlib.algorithm.observationpack.vpa.hypothesis.DTNode;
import de.learnlib.algorithm.observationpack.vpa.hypothesis.HypLoc;
import de.learnlib.oracle.MembershipOracle.DFAMembershipOracle;
import de.learnlib.query.DefaultQuery;
import net.automatalib.alphabet.VPAlphabet;
import net.automatalib.automaton.vpa.StackContents;
import net.automatalib.automaton.vpa.State;
import net.automatalib.word.Word;
import net.automatalib.word.WordBuilder;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* @param
* input alphabet type
*/
public class OPLearnerVPA extends AbstractVPALearner {
protected final AcexAnalyzer analyzer;
@GenerateBuilder
public OPLearnerVPA(VPAlphabet alphabet, DFAMembershipOracle oracle, AcexAnalyzer analyzer) {
super(alphabet, oracle);
this.analyzer = analyzer;
}
protected State> getDefinitiveSuccessor(State> baseState, Word suffix) {
return hypothesis.getSuccessor(baseState, suffix);
}
protected Word transformAccessSequence(State> state) {
return transformAccessSequence(state.getStackContents(), state.getLocation());
}
protected Word transformAccessSequence(@Nullable StackContents contents) {
return transformAccessSequence(contents, hypothesis.getInitialLocation());
}
protected Word transformAccessSequence(@Nullable StackContents contents, HypLoc loc) {
List stackElems = new ArrayList<>();
if (contents != null) {
StackContents iter = contents;
while (iter != null) {
stackElems.add(iter.peek());
iter = iter.pop();
}
}
WordBuilder wb = new WordBuilder<>();
for (int i = stackElems.size() - 1; i >= 0; i--) {
int elem = stackElems.get(i);
HypLoc stackLoc = hypothesis.getStackLoc(elem);
wb.append(stackLoc.getAccessSequence());
I callSym = hypothesis.getCallSym(elem);
wb.append(callSym);
}
wb.append(loc.getAccessSequence());
return wb.toWord();
}
@Override
protected boolean refineHypothesisSingle(DefaultQuery ceQuery) {
Word ceWord = ceQuery.getInput();
boolean hypOut = hypothesis.computeOutput(ceWord);
if (hypOut == ceQuery.getOutput()) {
return false;
}
PrefixTransformAcex acex = new PrefixTransformAcex(Word.epsilon(), new ContextPair<>(Word.epsilon(), ceWord));
acex.setEffect(0, !hypOut);
acex.setEffect(acex.getLength() - 1, hypOut);
int breakpoint = analyzer.analyzeAbstractCounterexample(acex);
Word prefix = ceWord.prefix(breakpoint);
I act = ceWord.getSymbol(breakpoint);
Word suffix = ceWord.subWord(breakpoint + 1);
State> state = hypothesis.getState(prefix);
assert state != null;
State> succState = hypothesis.getSuccessor(state, act);
assert succState != null;
ContextPair context = new ContextPair<>(transformAccessSequence(succState.getStackContents()), suffix);
AbstractHypTrans trans = hypothesis.getInternalTransition(state, act);
assert trans != null;
HypLoc newLoc = makeTree(trans);
DTNode oldDtNode = succState.getLocation().getLeaf();
openTransitions.addAll(oldDtNode.getIncoming());
DTNode.SplitResult children = oldDtNode.split(context, acex.effect(breakpoint), acex.effect(breakpoint + 1));
link(children.nodeOld, newLoc);
link(children.nodeNew, succState.getLocation());
initializeLocation(trans.getTreeTarget());
closeTransitions();
return true;
}
protected class PrefixTransformAcex extends AbstractBaseCounterexample {
private final Word suffix;
private final State> baseState;
public PrefixTransformAcex(Word word, ContextPair context) {
super(context.getSuffix().length() + 1);
this.suffix = context.getSuffix();
this.baseState = hypothesis.getState(Iterables.concat(context.getPrefix(), word));
}
public State> getBaseState() {
return baseState;
}
public Word getSuffix() {
return suffix;
}
@Override
public boolean checkEffects(Boolean eff1, Boolean eff2) {
return eff1.equals(eff2);
}
@Override
protected Boolean computeEffect(int index) {
Word suffPref = suffix.prefix(index);
State> state = getDefinitiveSuccessor(baseState, suffPref);
Word suffSuff = suffix.subWord(index);
return oracle.answerQuery(transformAccessSequence(state), suffSuff);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy