net.automatalib.util.automata.conformance.WpMethodTestsIterator Maven / Gradle / Ivy
Show all versions of automata-util Show documentation
/* 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.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.annotation.ParametersAreNonnullByDefault;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import net.automatalib.automata.UniversalDeterministicAutomaton;
import net.automatalib.commons.util.collections.AbstractThreeLevelIterator;
import net.automatalib.commons.util.collections.CollectionsUtil;
import net.automatalib.commons.util.collections.DelegatingIterator;
import net.automatalib.commons.util.collections.ReusableIterator;
import net.automatalib.commons.util.mappings.MutableMapping;
import net.automatalib.util.automata.Automata;
import net.automatalib.util.automata.cover.Covers;
import net.automatalib.util.automata.equivalence.CharacterizingSets;
import net.automatalib.words.Word;
import net.automatalib.words.WordBuilder;
/**
* Iterator that returns test words generated by the partial W Method.
*
* See "Test selection based on finite state models" by S. Fujiwara et al.
*
* @param
* input symbol type
*
* @author frohme
*/
@ParametersAreNonnullByDefault
public class WpMethodTestsIterator extends DelegatingIterator> {
public WpMethodTestsIterator(UniversalDeterministicAutomaton, I, ?, ?, ?> automaton,
Collection extends I> alphabet,
int maxDepth) {
super(buildIterators(automaton, alphabet, maxDepth));
}
private static Iterator> buildIterators(UniversalDeterministicAutomaton, I, ?, ?, ?> automaton,
Collection extends I> inputs,
int maxDepth) {
final Set> stateCover = Sets.newHashSetWithExpectedSize(automaton.size());
final Set> transitionCover = Sets.newHashSetWithExpectedSize(automaton.size() * inputs.size());
Covers.cover(automaton, inputs, stateCover, transitionCover);
final Iterable> characterizingSet;
final Iterator> characterizingIter = CharacterizingSets.characterizingSetIterator(automaton, inputs);
// Special case: List of characterizing suffixes may be empty,
// but in this case we still need to iterate over the prefixes!
if (!characterizingIter.hasNext()) {
characterizingSet = Collections.singletonList(Word.epsilon());
} else {
characterizingSet = new ReusableIterator<>(characterizingIter);
}
// Phase 1: state cover * middle part * global suffixes
final Iterator> firstIterator =
new FirstPhaseIterator<>(stateCover, CollectionsUtil.allTuples(inputs, 0, maxDepth), characterizingSet);
// Phase 2: transitions (not in state cover) * middle part * local suffixes
transitionCover.removeAll(stateCover);
final Iterator> secondIterator = new SecondPhaseIterator<>(automaton,
inputs,
transitionCover,
CollectionsUtil.allTuples(inputs,
0,
maxDepth));
return Iterators.concat(firstIterator, secondIterator);
}
private static class FirstPhaseIterator extends AbstractThreeLevelIterator, Word, Word, Word> {
private final Iterable> prefixes;
private final Iterable> suffixes;
private final WordBuilder wordBuilder = new WordBuilder<>();
FirstPhaseIterator(Iterable> prefixes, Iterable> middleParts, Iterable> suffixes) {
super(middleParts.iterator());
this.prefixes = prefixes;
this.suffixes = suffixes;
}
@Override
protected Iterator> l2Iterator(List l1Object) {
return prefixes.iterator();
}
@Override
protected Iterator> l3Iterator(List l1Object, Word l2Object) {
return suffixes.iterator();
}
@Override
protected Word combine(List middle, Word prefix, Word suffix) {
wordBuilder.ensureAdditionalCapacity(prefix.size() + middle.size() + suffix.size());
Word word = wordBuilder.append(prefix).append(middle).append(suffix).toWord();
wordBuilder.clear();
return word;
}
}
private static class SecondPhaseIterator
extends AbstractThreeLevelIterator, Word, Word, Word> {
private final UniversalDeterministicAutomaton automaton;
private final Collection extends I> inputs;
private final MutableMapping>> localSuffixSets;
private final Iterable> prefixes;
private final WordBuilder wordBuilder = new WordBuilder<>();
SecondPhaseIterator(UniversalDeterministicAutomaton automaton,
Collection extends I> inputs,
Iterable> prefixes,
Iterable> middleParts) {
super(middleParts.iterator());
this.automaton = automaton;
this.inputs = inputs;
this.localSuffixSets = automaton.createStaticStateMapping();
this.prefixes = prefixes;
}
@Override
protected Iterator> l2Iterator(List l1Object) {
return prefixes.iterator();
}
@Override
protected Iterator> l3Iterator(List middle, Word prefix) {
final S tmp = automaton.getState(prefix);
final S state = automaton.getSuccessor(tmp, middle);
List> localSuffixes = localSuffixSets.get(state);
if (localSuffixes == null) {
localSuffixes = Automata.stateCharacterizingSet(automaton, inputs, state);
if (localSuffixes.isEmpty()) {
localSuffixes = Collections.singletonList(Word.epsilon());
}
localSuffixSets.put(state, localSuffixes);
}
return localSuffixes.iterator();
}
@Override
protected Word combine(List middle, Word prefix, Word suffix) {
wordBuilder.ensureAdditionalCapacity(prefix.size() + middle.size() + suffix.size());
Word word = wordBuilder.append(prefix).append(middle).append(suffix).toWord();
wordBuilder.clear();
return word;
}
}
}