/* * Copyright (C) 2018 Alexander Nutz (nutz@informatik.uni-freiburg.de) * Copyright (C) 2018 University of Freiburg * * This file is part of the ULTIMATE Util Library. * * The ULTIMATE Util 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 Util 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 Util Library. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify the ULTIMATE Util 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 Util Library grant you additional permission * to convey the resulting work. */ package de.uni_freiburg.informatik.ultimate.util; import java.util.Deque; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.function.Function; import de.uni_freiburg.informatik.ultimate.core.model.services.ILogger; import de.uni_freiburg.informatik.ultimate.util.datastructures.HashDeque; import de.uni_freiburg.informatik.ultimate.util.datastructures.relation.LinkedHashRelation; import de.uni_freiburg.informatik.ultimate.util.scc.DefaultSccComputation; import de.uni_freiburg.informatik.ultimate.util.scc.SccComputation.ISuccessorProvider; import de.uni_freiburg.informatik.ultimate.util.scc.StronglyConnectedComponent; /** * Please see {@link TransitiveClosure#computeClosure} for documentation. * * TODO: find a better name for this class. * * @author Alexander Nutz (nutz@informatik.uni-freiburg.de) * */ public class TransitiveClosure { private TransitiveClosure() { // do not instantiate utility class } /** * Input: * * This procedure computes the minimal labeling l' where for each edge (n1, n2) in the node graph, the label of n2 * is a superset of the label of n1, i.e. l'(n1) \subseteq l'(n2). * * @param logger * @param allNodes * set of all nodes * @param initialLabeling * initial labeling function l * @param graphSuccessorProvider * graph over the nodes * @return */ public static Map> computeClosure(final ILogger logger, final Set allNodes, final Function> initialLabeling, final ISuccessorProvider graphSuccessorProvider) { final Map> closedProcToModGlobals; final int numberOfAllNodes = allNodes.size(); final Set startNodes = allNodes; final DefaultSccComputation dssc = new DefaultSccComputation<>(logger, graphSuccessorProvider, numberOfAllNodes, startNodes); /* * Initialize the modified globals for each SCC with the union of each method's modified globals. (within an SCC * all procedure may call all others (possibly transitively) thus all must have the same modifies clause * contents) */ final LinkedHashRelation, LABEL> sccToLabel = new LinkedHashRelation<>(); for (final StronglyConnectedComponent scc : dssc.getSCCs()) { for (final NODE procInfo : scc.getNodes()) { for (final LABEL modGlobal : initialLabeling.apply(procInfo)) { sccToLabel.addPair(scc, modGlobal); } } } /* * update the modified globals for the sccs according to the edges in the call graph that connect different SCCs * * algorithmic idea: start with the leafs of the graph and propagate all modified globals back along call edges. * The frontier is where we have already propagated modified globals. * */ final Deque> frontier = new HashDeque<>(); frontier.addAll(dssc.getRootComponents()); while (!frontier.isEmpty()) { final StronglyConnectedComponent currentScc = frontier.pollFirst(); /* * Note (concerns "transitive modified globals" application of this method): We have chosen the * ISuccessorProvider for the SccComputation such that the caller is the successor of the callee. (i.e., the * successor relation is the inverse of the call graph) */ final Set