/*
* Copyright (C) 2020 Matthias Heizmann (heizmann@informatik.uni-freiburg.de)
* Copyright (C) 2020 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.counting;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import de.uni_freiburg.informatik.ultimate.automata.AutomataLibraryException;
import de.uni_freiburg.informatik.ultimate.automata.AutomataLibraryServices;
import de.uni_freiburg.informatik.ultimate.automata.IOperation;
import de.uni_freiburg.informatik.ultimate.automata.statefactory.IIntersectionStateFactory;
import de.uni_freiburg.informatik.ultimate.automata.statefactory.IStateFactory;
import de.uni_freiburg.informatik.ultimate.core.model.services.ILogger;
/**
* Intersection method for Counting Automata
*
* @author Marcel Ebbinghaus
* @author who is the author?
*/
public class Intersect> implements IOperation {
private final AutomataLibraryServices mServices;
private final ILogger mLogger;
private final CountingAutomaton mFstOperand;
private final CountingAutomaton mSndOperand;
private final CountingAutomaton mResult;
private final IIntersectionStateFactory mStateFactory;
public Intersect(
final AutomataLibraryServices services,
final IIntersectionStateFactory stateFactory,
final CountingAutomaton fstOperand,
final CountingAutomaton sndOperand) throws AutomataLibraryException {
mServices = services;
mLogger = mServices.getLoggingService().getLogger(this.getClass());
mFstOperand = fstOperand;
mSndOperand = sndOperand;
mStateFactory = stateFactory;
if (mLogger.isInfoEnabled()) {
mLogger.info(startMessage());
}
mResult = computeResult();
if (mLogger.isInfoEnabled()) {
mLogger.info(exitMessage());
}
}
private CountingAutomaton computeResult() {
Set intersectAlphabet = mFstOperand.getAlphabet();
ArrayList intersectCounter = new ArrayList();
for (Counter counter : mFstOperand.getCounter()) {
intersectCounter.add(counter.copyCounter());
}
for (Counter counter : mSndOperand.getCounter()) {
intersectCounter.add(counter.copyCounter());
}
Set intersectStates = new HashSet();
Map intersectInitialConditions = new HashMap();
Map intersectFinalConditions = new HashMap();
Map>> intersectTransitions = new HashMap>>();
Map, STATE> stateMemory = new HashMap, STATE>();
//states
for (STATE stateFstOp : mFstOperand.getStates()) {
for (STATE stateSndOp : mSndOperand.getStates()) {
STATE newState = mStateFactory.intersection(stateFstOp, stateSndOp);
intersectStates.add(newState);
ArrayList statePair = new ArrayList();
statePair.add(stateFstOp);
statePair.add(stateSndOp);
stateMemory.put(statePair, newState);
}
}
for (STATE stateFstOp : mFstOperand.getStates()) {
for (STATE stateSndOp : mSndOperand.getStates()) {
ArrayList statePair = new ArrayList();
statePair.add(stateFstOp);
statePair.add(stateSndOp);
STATE newState = stateMemory.get(statePair);
//initialConditions
ConjunctGuards initialConjunction = new ConjunctGuards(
mFstOperand.getInitialConditions().get(stateFstOp).copyInitialCondition().getCondition(),
mSndOperand.getInitialConditions().get(stateSndOp).copyInitialCondition().getCondition());
ArrayList> newInitialConditions = initialConjunction.getResult();
intersectInitialConditions.put(newState, new InitialCondition(newInitialConditions));
//finalConditions
ConjunctGuards finalConjunction = new ConjunctGuards(
mFstOperand.getFinalConditions().get(stateFstOp).copyFinalCondition().getCondition(),
mSndOperand.getFinalConditions().get(stateSndOp).copyFinalCondition().getCondition());
ArrayList> newFinalConditions = finalConjunction.getResult();
intersectFinalConditions.put(newState, new FinalCondition(newFinalConditions));
//transitions
ArrayList> newOutgoingTransitions = new ArrayList>();
for (Transition transOfStateFstOp : mFstOperand.getTransitions().get(stateFstOp)) {
for (Transition transOfStateSndOp : mSndOperand.getTransitions().get(stateSndOp)) {
if (transOfStateFstOp.getLetter().equals(transOfStateSndOp.getLetter())) {
Transition transCopy1 = transOfStateFstOp.copyTransition();
Transition transCopy2 = transOfStateSndOp.copyTransition();
ConjunctGuards transitionConjunction = new ConjunctGuards(transCopy1.getGuards(), transCopy2.getGuards());
ArrayList> newTransitionGuards = transitionConjunction.getResult();
ArrayList newTransitionUpdates = new ArrayList();
newTransitionUpdates.addAll(transCopy1.getUpdates());
newTransitionUpdates.addAll(transCopy2.getUpdates());
ArrayList sucStatePair = new ArrayList();
sucStatePair.add(transCopy1.getSucState());
sucStatePair.add(transCopy2.getSucState());
STATE newSuccessorState = stateMemory.get(sucStatePair);
newOutgoingTransitions.add(new Transition(transCopy1.getLetter(), newState, newSuccessorState, newTransitionGuards, newTransitionUpdates));
}
}
}
intersectTransitions.put(newState, newOutgoingTransitions);
}
}
//result
CountingAutomaton resultAutomaton = new CountingAutomaton(
mServices,
intersectAlphabet,
intersectStates,
intersectCounter,
intersectInitialConditions,
intersectFinalConditions,
intersectTransitions);
return resultAutomaton;
}
@Override
public String startMessage() {
return "Start " + getOperationName() + ". First operand " + getFirstOperand().sizeInformation()
+ " Second operand " + getSecondOperand().sizeInformation();
}
@Override
public String exitMessage() {
return "Finished " + getOperationName() + ". Result " + mResult.sizeInformation();
}
public CountingAutomaton getFirstOperand() {
return mFstOperand;
}
public CountingAutomaton getSecondOperand() {
return mSndOperand;
}
@Override
public CountingAutomaton getResult() {
return mResult;
}
@Override
public boolean checkResult(final CRSF stateFactory) throws AutomataLibraryException {
// TODO #CountingAutomataTodo: how can we check that the result is correct
return true;
}
}