/* * Copyright (C) 2015 David Zschocke * Copyright (C) 2015 Dirk Steinmetz * Copyright (C) 2015-2017 Matthias Heizmann (heizmann@informatik.uni-freiburg.de) * Copyright (C) 2017 Dennis Wölfing * Copyright (C) 2015-2017 University of Freiburg * * * This file is part of the ULTIMATE ModelCheckerUtils Library. * * The ULTIMATE ModelCheckerUtils 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 ModelCheckerUtils 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 ModelCheckerUtils Library. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify the ULTIMATE ModelCheckerUtils 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 ModelCheckerUtils Library grant you additional permission * to convey the resulting work. */ package de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.xnf; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import de.uni_freiburg.informatik.ultimate.core.lib.exceptions.ToolchainCanceledException; import de.uni_freiburg.informatik.ultimate.core.model.services.IUltimateServiceProvider; /** * TODO 2019-01-06: fix documentation of this class' methods * @author Matthias Heizmann (heizmann@informatik.uni-freiburg.de) */ public class XnfUtils { private XnfUtils() { // do not instantiate } /** * Given two disjunctions a and b of conjunctions, this method calculates a new disjunction of conjunctions * equivalent to a /\ b * * @param a * the first dnf * @param b * the second dnf * @param * the type of the literals in the dnf * @return a new dnf equivalent to a /\ b */ static Dnf expandConjunctionSingle(final Dnf a, final Dnf b) { final Dnf result = new Dnf<>(); for (final Collection aItem : a) { for (final Collection bItem : b) { final Collection resultItem = new ArrayList<>(); resultItem.addAll(aItem); resultItem.addAll(bItem); result.add(resultItem); } } return result; } /** * Given a set of {@link DNF}s, construct a {@link DNF} that represent the conjunction of the input {@link DNF}s. * * @param * the type of the literals in the dnfs * @return DNF representing the conjunction of the DNFs provided, returns NULL if no DNFs were given. */ @SafeVarargs public static Dnf and(final IUltimateServiceProvider services, final Dnf... dnfs) { boolean firstElement = true; Dnf expandedDnf = null; for (final Dnf currentDnf : dnfs) { if (!services.getProgressMonitorService().continueProcessing()) { throw new ToolchainCanceledException(XnfUtils.class, "transforming conjunction of length " + dnfs.length + " to DNF"); } if (firstElement) { expandedDnf = currentDnf; firstElement = false; } else { expandedDnf = expandConjunctionSingle(currentDnf, expandedDnf); } } return expandedDnf; } /** * Transforms a cnf (given as two nested Collections of atoms (usually linear inequalites)) into dnf (given as two * nested Collections of atoms (usually linear inequalites)). * * @param * type of the atoms * * @param cnf * the collection of conjuncts consisting of disjuncts of linear inequalities * @return a dnf (Collection of disjuncts consisting of conjuncts of linear inequalities), equivalent to the given * cnf */ static Dnf expandCnfToDnf(final IUltimateServiceProvider services, final Cnf cnf) { if (cnf.isEmpty()) { final Collection empty = Collections.emptyList(); return new Dnf<>(empty); } boolean firstElement = true; Dnf expandedDnf = null; for (final Collection conjunct : cnf) { if (!services.getProgressMonitorService().continueProcessing()) { throw new ToolchainCanceledException(XnfUtils.class, "transforming CNF with " + cnf.size() + "conjuncts to DNF"); } if (firstElement) { expandedDnf = new Dnf<>(); for (final E e : conjunct) { final Collection conjunctSingleton = new ArrayList<>(); conjunctSingleton.add(e); expandedDnf.add(conjunctSingleton); } firstElement = false; } else { expandedDnf = expandCnfToDnfSingle(services, expandedDnf, conjunct); } } assert expandedDnf != null; return expandedDnf; } /** * Performs a single expandation, meaning transforming conjunct /\ dnf to an equivalent dnf * * @param dnf * the dnf the conjunct is conjuncted to * @param conjunct * the conjunct that is conjuncted to the dnf * @param * : the type of Literals in the cnf/dnf * @return a new dnf equivalent to conjunct /\ dnf */ static Dnf expandCnfToDnfSingle(final IUltimateServiceProvider services, final Dnf dnf, final Collection conjunct) { final Dnf result = new Dnf<>(); for (final Collection disjunct : dnf) { for (final E item : conjunct) { if (!services.getProgressMonitorService().continueProcessing()) { throw new ToolchainCanceledException(XnfUtils.class, "transforming CNF to DNF"); } final Collection resultItem = new ArrayList<>(); resultItem.addAll(disjunct); resultItem.add(item); result.add(resultItem); } } return result; } }