net.automatalib.util.automata.vpda.OneSEVPAUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of automata-util Show documentation
Show all versions of automata-util Show documentation
This artifact provides various common utility operations for analyzing and manipulating
automata and graphs, such as traversal, minimization and copying.
/* Copyright (C) 2013-2019 TU Dortmund
* This file is part of AutomataLib, http://www.automatalib.net/.
*
* 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 net.automatalib.util.automata.vpda;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import net.automatalib.automata.vpda.OneSEVPA;
import net.automatalib.commons.smartcollections.ArrayStorage;
import net.automatalib.words.VPDAlphabet;
import net.automatalib.words.Word;
/**
* Utility class revolving around 1-SEVPAs.
*
* @author Malte Isberner
*/
public final class OneSEVPAUtil {
private OneSEVPAUtil() {
}
public static List findReachableLocations(final OneSEVPA sevpa, final VPDAlphabet alphabet) {
return computeAccessSequences(sevpa, alphabet, false, l -> false).reachableLocs;
}
public static ReachResult computeAccessSequences(final OneSEVPA sevpa,
final VPDAlphabet alphabet,
final boolean computeAs,
final Predicate super L> terminatePred) {
final ArrayStorage> result = new ArrayStorage<>(sevpa.size());
final L initLoc = sevpa.getInitialLocation();
final List reachable = new ArrayList<>();
reachable.add(initLoc);
result.set(sevpa.getLocationId(initLoc), Word.epsilon());
if (terminatePred.test(initLoc)) {
return new ReachResult<>(initLoc, reachable, result);
}
int queuePtr = 0;
while (queuePtr < reachable.size()) {
final L curr = reachable.get(queuePtr++);
final Word currAs = result.get(sevpa.getLocationId(curr));
for (I intSym : alphabet.getInternalSymbols()) {
final L succ = sevpa.getInternalSuccessor(curr, intSym);
final int succIdx = sevpa.getLocationId(succ);
if (result.get(succIdx) != null) {
continue;
}
final Word succAs = computeAs ? currAs.append(intSym) : Word.epsilon();
result.set(succIdx, succAs);
if (terminatePred.test(succ)) {
return new ReachResult<>(succ, reachable, result);
}
reachable.add(succ);
}
for (I callSym : alphabet.getCallSymbols()) {
for (I returnSym : alphabet.getReturnSymbols()) {
for (int i = 0; i < queuePtr; i++) {
final L src = reachable.get(i);
int stackSym = sevpa.encodeStackSym(src, callSym);
L succ = sevpa.getReturnSuccessor(curr, returnSym, stackSym);
int succIdx = sevpa.getLocationId(succ);
if (result.get(succIdx) == null) {
Word succAs = computeAs ?
result.get(sevpa.getLocationId(src))
.append(callSym)
.concat(currAs.append(returnSym)) :
Word.epsilon();
result.set(succIdx, succAs);
if (terminatePred.test(succ)) {
return new ReachResult<>(succ, reachable, result);
}
reachable.add(succ);
}
if (src != curr) {
stackSym = sevpa.encodeStackSym(curr, callSym);
succ = sevpa.getReturnSuccessor(src, returnSym, stackSym);
succIdx = sevpa.getLocationId(succ);
if (result.get(succIdx) == null) {
final Word succAs = computeAs ?
currAs.append(callSym)
.concat(result.get(sevpa.getLocationId(src)).append(returnSym)) :
Word.epsilon();
result.set(succIdx, succAs);
if (terminatePred.test(succ)) {
return new ReachResult<>(succ, reachable, result);
}
reachable.add(succ);
}
}
}
}
}
}
return new ReachResult<>(null, reachable, result);
}
public static ArrayStorage> computeAccessSequences(final OneSEVPA sevpa,
final VPDAlphabet alphabet) {
return computeAccessSequences(sevpa, alphabet, true, l -> false).accessSequences;
}
public static Word findRejectedWord(final OneSEVPA sevpa, final VPDAlphabet alphabet) {
return computeAccessSequence(sevpa, alphabet, l -> !sevpa.isAcceptingLocation(l));
}
public static Word computeAccessSequence(final OneSEVPA sevpa,
final VPDAlphabet alphabet,
final Predicate super L> predicate) {
final ReachResult result = computeAccessSequences(sevpa, alphabet, true, predicate);
L resultLoc = result.terminateLoc;
if (resultLoc != null) {
return result.accessSequences.get(sevpa.getLocationId(resultLoc));
}
return null;
}
public static boolean testEquivalence(final OneSEVPA, I> sevpa1,
final OneSEVPA, I> sevpa2,
final VPDAlphabet alphabet) {
return findSeparatingWord(sevpa1, sevpa2, alphabet) == null;
}
public static Word findSeparatingWord(final OneSEVPA, I> sevpa1,
final OneSEVPA, I> sevpa2,
final VPDAlphabet alphabet) {
final OneSEVPA, I> prod = OneSEVPAs.xor(sevpa1, sevpa2, alphabet);
return findAcceptedWord(prod, alphabet);
}
public static Word findAcceptedWord(final OneSEVPA sevpa, final VPDAlphabet alphabet) {
return computeAccessSequence(sevpa, alphabet, sevpa::isAcceptingLocation);
}
public static class ReachResult {
public final L terminateLoc;
public final List reachableLocs;
public final ArrayStorage> accessSequences;
public ReachResult(final L terminateLoc,
final List reachableLocs,
final ArrayStorage> accessSequences) {
this.terminateLoc = terminateLoc;
this.reachableLocs = reachableLocs;
this.accessSequences = accessSequences;
}
}
}