net.automatalib.util.automata.conformance.IncrementalWMethodTestsIterator 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.conformance;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import net.automatalib.automata.UniversalDeterministicAutomaton;
import net.automatalib.util.automata.Automata;
import net.automatalib.util.automata.cover.Covers;
import net.automatalib.words.Alphabet;
import net.automatalib.words.Word;
/**
* An iterator that enumerates the test cases as obtained through the W method conformance test in an incremental
* fashion.
*
* @param
* input symbol type
*
* @author Malte Isberner
*/
public class IncrementalWMethodTestsIterator implements Iterator> {
private final Alphabet alphabet;
private final StrictPriorityQueue- > itemQueue;
private final List
> prefixes = new ArrayList<>();
private final List> suffixes = new ArrayList<>();
private int maxDepth;
public IncrementalWMethodTestsIterator(Alphabet alphabet) {
this.alphabet = alphabet;
this.itemQueue = new StrictPriorityQueue<>(new ItemComparator<>(alphabet), new ItemMerge<>());
}
public int getMaxDepth() {
return maxDepth;
}
public void setMaxDepth(int maxDepth) {
this.maxDepth = maxDepth;
}
public void update(UniversalDeterministicAutomaton, I, ?, ?, ?> automaton) {
int oldNumPrefixes = prefixes.size();
boolean newPrefixes = Covers.incrementalTransitionCover(automaton, alphabet, prefixes, prefixes);
int oldNumSuffixes = suffixes.size();
boolean newSuffixes = Automata.incrementalCharacterizingSet(automaton, alphabet, suffixes, suffixes);
// old prefixes with all *new* suffixes
if (newSuffixes && oldNumPrefixes > 0) {
Item item = new Item<>();
item.prefixIdx = 0;
item.minPrefix = 0;
item.maxPrefix = oldNumPrefixes;
item.suffixIdx = oldNumSuffixes;
item.minSuffix = oldNumSuffixes;
item.middle = startMiddleWord();
itemQueue.insert(item);
}
// new prefixes with *all* suffixes
if (newPrefixes) {
Item item = new Item<>();
item.prefixIdx = oldNumPrefixes;
item.minPrefix = oldNumPrefixes;
item.maxPrefix = prefixes.size();
item.suffixIdx = 0;
item.minSuffix = 0;
item.middle = startMiddleWord();
itemQueue.insert(item);
}
}
private Word startMiddleWord() {
return Word.epsilon();
}
@Override
public boolean hasNext() {
return !itemQueue.isEmpty();
}
@Override
public Word next() {
Item nextItem = itemQueue.extractMin();
Word result = assembleWord(nextItem);
Item inc = increment(nextItem);
if (inc != null) {
itemQueue.insert(inc);
}
return result;
}
private Word assembleWord(Item item) {
Word prefix = prefixes.get(item.prefixIdx);
Word suffix = suffixes.get(item.suffixIdx);
return prefix.concat(item.middle, suffix);
}
private Item increment(Item item) {
item.suffixIdx++;
if (item.suffixIdx >= suffixes.size()) {
item.suffixIdx = item.minSuffix;
item.prefixIdx++;
if (item.prefixIdx >= item.maxPrefix) {
item.prefixIdx = item.minPrefix;
item.middle = item.middle.canonicalNext(alphabet);
if (item.middle.length() > maxDepth) {
return null;
}
}
}
return item;
}
private static final class Item {
private int prefixIdx;
private int suffixIdx;
private Word middle;
private int minSuffix;
private int minPrefix;
private int maxPrefix;
@Override
public String toString() {
return Integer.toString(prefixIdx) + " | " + middle + " | " + Integer.toString(suffixIdx);
}
}
private static final class ItemMerge implements StrictPriorityQueue.MergeOperation- > {
@Override
public Item merge(Item oldObject, Item newObject) {
oldObject.minSuffix = Math.min(oldObject.minSuffix, newObject.minSuffix);
oldObject.minPrefix = Math.min(oldObject.minPrefix, newObject.minPrefix);
oldObject.maxPrefix = Math.max(oldObject.maxPrefix, newObject.maxPrefix);
return oldObject;
}
}
private static final class ItemComparator implements Comparator
- > {
private final Comparator super Word extends I>> canonicalCmp;
ItemComparator(Comparator super I> symComparator) {
this.canonicalCmp = Word.canonicalComparator(symComparator);
}
@Override
public int compare(Item extends I> o1, Item extends I> o2) {
int cmp = canonicalCmp.compare(o1.middle, o2.middle);
if (cmp != 0) {
return cmp;
}
cmp = o1.prefixIdx - o2.prefixIdx;
if (cmp != 0) {
return cmp;
}
return o1.suffixIdx - o2.suffixIdx;
}
}
}