/* * Copyright (C) 2012-2015 Jan Hättig (haettigj@informatik.uni-freiburg.de) * Copyright (C) 2013-2015 Matthias Heizmann (heizmann@informatik.uni-freiburg.de) * Copyright (C) 2009-2015 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; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import de.uni_freiburg.informatik.ultimate.automata.nestedword.INestedWordAutomaton; import de.uni_freiburg.informatik.ultimate.core.model.services.ILogger; /** * Given two nondeterministic NWAs {@code minuend} and {@code subtrahend} a. *

* TODO Christian 2016-08-20: unfinished documentation * * @author Jan Hättig (haettigj@informatik.uni-freiburg.de) * @param * Content. Type of the labels that are assigned to the states of the automata. In many cases you want to use * {@link String} as {@link STATE} and your states are labeled, e.g., with "q0", "q1", ... */ public class AutomatonEpimorphism { private static final String INVALID_STATE_NAME_MESSAGE = "Invalid state name: "; private final ILogger mLogger; private final Map mEpimorphism; /** * Constructor. * * @param services * Ultimate services */ public AutomatonEpimorphism(final AutomataLibraryServices services) { mLogger = services.getLoggingService().getLogger(LibraryIdentifiers.PLUGIN_ID); mEpimorphism = new HashMap<>(); } /** * Creates the epimorphism for two automata from {@code nwa1} to {@code nwa2}. The Labels of {@code nwa1} have to be * of type {@link String} and have to be of the following scheme:

{@code l1_l2},
where * {@code l1} is the actual label of the state and {@code l2} is the label of the state of {@code nwa2} which it is * epimorphic to. * * @param services * Ultimate services * @param nwa1 * automaton where the epimorphism is encoded in the labels * @param nwa2 * automaton where the epimorphism maps to * @return an epimorphism structure from nwa1 to nwa2 */ public static AutomatonEpimorphism createFromAutomatonLabels(final AutomataLibraryServices services, final INestedWordAutomaton nwa1, final INestedWordAutomaton nwa2) { final AutomatonEpimorphism epimorphism = new AutomatonEpimorphism<>(services); // traversing the states for (final String state1 : nwa1.getStates()) { final int indexOfUnderscore = state1.indexOf('_'); if (indexOfUnderscore == -1) { continue; } // check that '_' is not the last char in the string if (indexOfUnderscore + 1 == state1.length()) { throw new IllegalArgumentException(INVALID_STATE_NAME_MESSAGE + state1); } // get the name of the epimorph state final String state2 = state1.substring(indexOfUnderscore + 1); // check that '_' does not occur multiple times if (state2.indexOf('_') != -1) { throw new IllegalArgumentException(INVALID_STATE_NAME_MESSAGE + state1); } // search the state in nwa2; if it is not found, error if (!nwa2.getStates().contains(state2)) { throw new IllegalArgumentException("Missing epimorphism partner for: " + state1); } // set the mapping from state1 to state2 epimorphism.mEpimorphism.put(state1, state2); } return epimorphism; } /** * Returns the state where the epimorphism points to. * * @param source * source state * @return target state under the epimorphism */ public STATE getMapping(final STATE source) { return mEpimorphism.get(source); } /** * Inserts a new mapping of two states. * * @param source * mapping from this state * @param target * mapping to this state */ public void insert(final STATE source, final STATE target) { mEpimorphism.put(source, target); } /** * Prints the object to the logger in DEBUG level. */ public void print() { if (mLogger.isDebugEnabled()) { for (final Entry e : mEpimorphism.entrySet()) { mLogger.debug(e.getKey() + " --> " + e.getValue()); } } } }