net.automatalib.util.automata.Automata Maven / Gradle / Ivy
Show all versions of automata-util Show documentation
/* Copyright (C) 2013 TU Dortmund
* This file is part of AutomataLib, http://www.automatalib.net/.
*
* AutomataLib is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 3.0 as published by the Free Software Foundation.
*
* AutomataLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with AutomataLib; if not, see
* http://www.gnu.de/documents/lgpl.en.html.
*/
package net.automatalib.util.automata;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import net.automatalib.automata.Automaton;
import net.automatalib.automata.DeterministicAutomaton;
import net.automatalib.automata.MutableDeterministic;
import net.automatalib.automata.UniversalAutomaton;
import net.automatalib.automata.UniversalDeterministicAutomaton;
import net.automatalib.automata.graphs.TransitionEdge;
import net.automatalib.graphs.Graph;
import net.automatalib.graphs.UniversalGraph;
import net.automatalib.util.automata.asgraph.AutomatonAsGraph;
import net.automatalib.util.automata.asgraph.UniversalAutomatonAsGraph;
import net.automatalib.util.automata.equivalence.CharacterizingSets;
import net.automatalib.util.automata.equivalence.NearLinearEquivalenceTest;
import net.automatalib.util.minimizer.Block;
import net.automatalib.util.minimizer.BlockMap;
import net.automatalib.util.minimizer.MinimizationResult;
import net.automatalib.util.minimizer.Minimizer;
import net.automatalib.util.ts.TS;
import net.automatalib.words.Word;
public class Automata extends TS {
public static
Graph> asGraph(
Automaton automaton, Collection extends I> inputs) {
return new AutomatonAsGraph>(automaton, inputs);
}
public static
UniversalGraph,SP,TransitionEdge.Property> asUniversalGraph(
UniversalAutomaton automaton, Collection extends I> inputs) {
return new UniversalAutomatonAsGraph>(automaton, inputs);
}
public static >
A minimize(
UniversalDeterministicAutomaton automaton,
Collection extends I> inputs,
A output) {
UniversalGraph, SP, TransitionEdge.Property> aag = asUniversalGraph(automaton, inputs);
MinimizationResult> mr = Minimizer.minimize(aag, Collections.singleton(automaton.getInitialState()));
output.clear();
S init = automaton.getInitialState();
Block> initBlock = mr.getBlockForState(init);
BlockMap bm = new BlockMap(mr);
for(Block> block : mr.getBlocks()) {
S rep = mr.getRepresentative(block);
SO state;
SP repProp = automaton.getStateProperty(rep);
if(block == initBlock)
state = output.addInitialState(repProp);
else
state = output.addState(repProp);
bm.put(block, state);
}
for(Block> block : mr.getBlocks()) {
S rep = mr.getRepresentative(block);
SO state = bm.get(block);
for(I input : inputs) {
T trans = automaton.getTransition(rep, input);
if(trans != null) {
TP prop = automaton.getTransitionProperty(trans);
S oldSucc = automaton.getSuccessor(trans);
Block> succBlock = mr.getBlockForState(oldSucc);
SO newSucc = bm.get(succBlock);
output.addTransition(state, input, newSucc, prop);
}
}
}
return output;
}
private static final class ResultTransRecord {
public final int targetId;
public final TP property;
public ResultTransRecord(int targetId, TP property) {
this.targetId = targetId;
this.property = property;
}
}
private static final class ResultStateRecord {
public final SP property;
public final ResultTransRecord[] transitions;
@SuppressWarnings("unchecked")
public ResultStateRecord(int numInputs, SP property) {
this.property = property;
this.transitions = new ResultTransRecord[numInputs];
}
}
@SuppressWarnings("unchecked")
public static >
A invasiveMinimize(A automaton, Collection extends I> inputs) {
List extends I> inputList;
if(inputs instanceof List)
inputList = (List extends I>)inputs;
else
inputList = new ArrayList(inputs);
int numInputs = inputs.size();
UniversalGraph, SP, TransitionEdge.Property> aag = asUniversalGraph(automaton, inputs);
MinimizationResult> mr = Minimizer.minimize(aag, automaton.getInitialStates());
S init = automaton.getInitialState();
int initId = mr.getBlockForState(init).getId();
ResultStateRecord[] records = new ResultStateRecord[mr.getNumBlocks()];
for(Block> blk : mr.getBlocks()) {
int id = blk.getId();
S state = mr.getRepresentative(blk);
SP prop = automaton.getStateProperty(state);
ResultStateRecord rec = new ResultStateRecord<>(numInputs, prop);
records[id] = rec;
for(int i = 0; i < numInputs; i++) {
I input = inputList.get(i);
T trans = automaton.getTransition(state, input);
if(trans == null)
continue;
TP transProp = automaton.getTransitionProperty(trans);
S succ = automaton.getSuccessor(trans);
int tgtId = mr.getBlockForState(succ).getId();
rec.transitions[i] = new ResultTransRecord(tgtId, transProp);
}
}
automaton.clear();
Object[] states = new Object[records.length];
for(int i = 0; i < records.length; i++) {
ResultStateRecord rec = records[i];
SP prop = rec.property;
S state;
if(i == initId)
state = automaton.addInitialState(prop);
else
state = automaton.addState(prop);
states[i] = state;
}
for(int i = 0; i < records.length; i++) {
ResultStateRecord rec = records[i];
S state = (S)states[i];
for(int j = 0; j < numInputs; j++) {
ResultTransRecord transRec = rec.transitions[j];
if(transRec == null)
continue;
S succ = (S)states[transRec.targetId];
I input = inputList.get(j);
automaton.addTransition(state, input, succ, transRec.property);
}
}
return automaton;
}
/*
public static > A minimize(
A automaton, Collection extends I> inputs) {
return minimize(automaton, inputs, automaton);
}*/
/**
* Finds a separating word for two automata. A separating word is a word that exposes
* a difference (differing state or transition properties, or a transition undefined in
* only one of the automata) between the two automata.
*
* @param input symbol type
* @param reference the one automaton to consider
* @param other the other automaton to consider
* @param inputs the input symbols to consider
* @return a separating word, or null if no such word could be found.
*/
public static Word findSeparatingWord(
UniversalDeterministicAutomaton, I, ?, ?, ?> reference,
UniversalDeterministicAutomaton, I, ?, ?, ?> other,
Collection extends I> inputs) {
return NearLinearEquivalenceTest.findSeparatingWord(reference, other, inputs);
}
public static boolean testEquivalence(
UniversalDeterministicAutomaton, I, ?, ?, ?> reference,
UniversalDeterministicAutomaton, I, ?, ?, ?> other,
Collection extends I> inputs) {
return (findSeparatingWord(reference, other, inputs) == null);
}
/**
* Finds a separating word for two states in an automaton. A separating word is a word
* that exposes a difference (differing state or transition properties, or a transition
* undefined in only one of the paths) between the two states.
*
* @param state type
* @param input symbol type
* @param automaton the automaton containing the states
* @param state1 the one state
* @param state2 the other state
* @param inputs the input symbols to consider
* @return a separating word, or null if no such word could be found
*/
public static Word findSeparatingWord(
UniversalDeterministicAutomaton automaton,
S state1, S state2,
Collection extends I> inputs) {
return NearLinearEquivalenceTest.findSeparatingWord(automaton, state1, state2, inputs);
}
/**
* Computes a characterizing set for the given automaton.
*
* This is a convenience method acting as a shortcut to
* {@link CharacterizingSets#findCharacterizingSet(UniversalDeterministicAutomaton, Collection, Collection)}.
*
* @see CharacterizingSets
*
* @param input symbol type
* @param automaton the automaton for which to determine the characterizing set
* @param inputs the input symbols to consider
* @param result the collection in which to store the characterizing words
*/
public static void characterizingSet(UniversalDeterministicAutomaton, I, ?, ?, ?> automaton,
Collection extends I> inputs,
Collection super Word> result) {
CharacterizingSets.findCharacterizingSet(automaton, inputs, result);
}
/**
* Computes a characterizing set, and returns it as a {@link List}.
*
* @see CharacterizingSets
*
* @param input symbol type
* @param automaton the automaton for which to determine the characterizing set
* @param inputs the input symbols to consider
* @return a list containing the characterizing words
*/
public static List> characterizingSet(UniversalDeterministicAutomaton, I, ?, ?, ?> automaton,
Collection extends I> inputs) {
List> result = new ArrayList>();
characterizingSet(automaton, inputs, result);
return result;
}
public static boolean incrementalCharacterizingSet(UniversalDeterministicAutomaton, I, ?, ?, ?> automaton,
Collection extends I> inputs,
Collection extends Word> oldSuffixes,
Collection super Word> newSuffixes) {
return CharacterizingSets.findIncrementalCharacterizingSet(automaton, inputs, oldSuffixes, newSuffixes);
}
/**
* Computes a characterizing set for a single state.
*
* This is a convenience method acting as a shortcut to
* {@link CharacterizingSets#findCharacterizingSet(UniversalDeterministicAutomaton, Collection, Object, Collection)}.
*
* @see CharacterizingSets
*
* @param state type
* @param input symbol type
* @param automaton the automaton containing the state
* @param inputs the input symbols to consider
* @param state the state for which to determine a characterizing set
* @param result the collection in which to store the characterizing words
*/
public static void stateCharacterizingSet(UniversalDeterministicAutomaton automaton,
Collection extends I> inputs,
S state,
Collection super Word> result) {
CharacterizingSets.findCharacterizingSet(automaton, inputs, state, result);
}
/**
* Computes a characterizing set for a single state, and returns it as a {@link List}.
*
* @see CharacterizingSets
*
* @param state type
* @param input symbol type
* @param automaton the automaton containing the state
* @param inputs the input symbols to consider
* @param state the state for which to determine a characterizing set
* @return a list containing the characterizing words
*/
public static List> stateCharacterizingSet(UniversalDeterministicAutomaton automaton,
Collection extends I> inputs,
S state) {
List> result = new ArrayList>();
stateCharacterizingSet(automaton, inputs, state, result);
return result;
}
public static void cover(DeterministicAutomaton, I, ?> automaton,
Collection extends I> inputs, Collection super Word> states, Collection super Word> transitions) {
Covers.cover(automaton, inputs, states, transitions);
}
public static List> stateCover(DeterministicAutomaton, I, ?> automaton,
Collection extends I> inputs) {
List> states = new ArrayList>(automaton.size());
cover(automaton, inputs, states, null);
return states;
}
public static List> transitionCover(DeterministicAutomaton, I, ?> automaton,
Collection extends I> inputs) {
List> all = new ArrayList>(automaton.size() * inputs.size());
cover(automaton, inputs, all, all);
return all;
}
public static boolean incrementalCover(
DeterministicAutomaton, I, ?> automaton,
Collection extends I> inputs,
Collection extends Word> oldStates,
Collection extends Word> oldTransitions,
Collection super Word> newStates,
Collection super Word> newTransitions) {
return Covers.incrementalCover(automaton, inputs, oldStates, oldTransitions, newStates, newTransitions);
}
public static boolean incrementalStateCover(
DeterministicAutomaton, I, ?> automaton,
Collection extends I> inputs,
Collection extends Word> oldStates,
Collection super Word> newStates) {
return incrementalCover(automaton, inputs, oldStates, Collections.>emptyList(), newStates, null);
}
public static boolean incrementalStructuralCover(
DeterministicAutomaton, I, ?> automaton,
Collection extends I> inputs,
Collection extends Word> oldStructural,
Collection super Word> newStructural) {
return incrementalCover(automaton, inputs, oldStructural, Collections.>emptyList(), newStructural, newStructural);
}
public static
Iterator> allDefinedInputsIterator(
Automaton automaton,
Iterable extends I> inputs) {
return allDefinedInputsIterator(automaton, automaton.iterator(), inputs);
}
public static
Iterable> allDefinedInputs(
Automaton automaton,
Iterable extends I> inputs) {
return allDefinedInputs(automaton, automaton, inputs);
}
public static
Iterator> allUndefinedInputsIterator(
Automaton automaton,
Iterable extends I> inputs) {
return allUndefinedTransitionsIterator(automaton, automaton.iterator(), inputs);
}
public static
Iterable> allUndefinedInputs(
Automaton automaton,
Iterable extends I> inputs) {
return allUndefinedTransitions(automaton, automaton, inputs);
}
public static
TransRef findUndefinedInput(
Automaton automaton,
Iterable extends I> inputs) {
Iterator> it = allUndefinedInputsIterator(automaton, inputs);
if (!it.hasNext()) {
return null;
}
return it.next();
}
public static
boolean hasUndefinedInput(
Automaton,I,?> automaton,
Iterable extends I> inputs) {
return findUndefinedInput(automaton, inputs) != null;
}
}