/*
* Copyright (C) 2023 Philipp Müller (pm251@venus.uni-freiburg.de)
* Copyright (C) 2023 University of Freiburg
*
* This file is part of the ULTIMATE Automata Library.
*
* The ULTIMATE Automata Library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The ULTIMATE Automata Library 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 the ULTIMATE Automata Library. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify the ULTIMATE Automata Library, or any covered work, by linking
* or combining it with Eclipse RCP (or a modified version of Eclipse RCP),
* containing parts covered by the terms of the Eclipse Public License, the
* licensors of the ULTIMATE Automata Library grant you additional permission
* to convey the resulting work.
*/
package de.uni_freiburg.informatik.ultimate.automata.rabin;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import de.uni_freiburg.informatik.ultimate.automata.nestedword.transitions.OutgoingInternalTransition;
import de.uni_freiburg.informatik.ultimate.util.datastructures.relation.NestedMap2;
import de.uni_freiburg.informatik.ultimate.util.datastructures.relation.TransformIterator;
/**
* A class for explicitly declaring a Rabin automaton by declaring the relevant sets
*
* @author Philipp Müller (pm251@venus.uni-freiburg.de)
*
* @param
* letter type
* @param
* state type
*/
public class RabinAutomaton implements IRabinAutomaton {
private final Set mAlphabet;
private final Set mStates;
private final Set mInitialStates;
private final Set mAcceptingStates;
private final Set mFiniteStates;
private final NestedMap2> mTransitions;
/**
* A Rabin Automaton explicitly defined by the parameters
*
* @param alphabet
* The valid input characters for this automaton (should be a superset of the characters in transitions)
* @param states
* The valid states of the automaton (should be a superset of the states in initialStates,
* acceptingStates, finiteStates and transitions)
* @param initialStates
* The states that are active when no letter/word has been read
* @param acceptingStates
* States that when infinitely often visited lead to the acceptance of the input
* @param finiteStates
* States that can only be visited a finite amount of times, iff the automaton accepts
* @param transitions
* The transitions from one state to another for a one letter input
*/
public RabinAutomaton(final Set alphabet, final Set states, final Set initialStates,
final Set acceptingStates, final Set finiteStates,
final NestedMap2> transitions) {
mAlphabet = alphabet;
mStates = states;
mInitialStates = initialStates;
mAcceptingStates = acceptingStates;
mFiniteStates = finiteStates;
mTransitions = transitions;
}
public Set getStates() {
return mStates;
}
public Set getAcceptingStates() {
return mAcceptingStates;
}
public Set getFiniteStates() {
return mFiniteStates;
}
@Override
public Set getAlphabet() {
return mAlphabet;
}
@Override
public int size() {
return mStates.size();
}
@Override
public String sizeInformation() {
return "Number of states: " + size() + ", number of transitions: "
+ mTransitions.values().mapToInt(Set::size).sum();
}
@Override
public Set getInitialStates() {
return mInitialStates;
}
@Override
public boolean isAccepting(final STATE state) {
return mAcceptingStates.contains(state);
}
@Override
public boolean isFinite(final STATE state) {
return mFiniteStates.contains(state);
}
@Override
public Iterable> getSuccessors(final STATE state) {
final Map> successorMap = mTransitions.get(state);
if (successorMap == null) {
return () -> Collections.emptyIterator();
}
return () -> successorMap.entrySet().stream().flatMap(
entry -> entry.getValue().stream().map(succ -> new OutgoingInternalTransition<>(entry.getKey(), succ)))
.iterator();
}
@Override
public Iterable> getSuccessors(final STATE state, final LETTER letter) {
final Set successors = mTransitions.get(state, letter);
if (successors == null) {
return () -> Collections.emptyIterator();
}
return () -> new TransformIterator<>(successors.iterator(), x -> new OutgoingInternalTransition<>(letter, x));
}
public NestedMap2> getTransitions() {
return mTransitions;
}
}