/* * Code taken from https://github.com/johspaeth/PathExpression * Copyright (C) 2018 Johannes Spaeth * Copyright (C) 2018 Fraunhofer IEM, Paderborn, Germany * * Copyright (C) 2019 Claus Schätzle (schaetzc@tf.uni-freiburg.de) * Copyright (C) 2019 University of Freiburg * * This file is part of the ULTIMATE Library-PathExpressions plug-in. * * The ULTIMATE Library-PathExpressions plug-in 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 Library-PathExpressions plug-in 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 Library-PathExpressions plug-in. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify the ULTIMATE Library-PathExpressions plug-in, 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 Library-PathExpressions plug-in grant you additional permission * to convey the resulting work. */ package de.uni_freiburg.informatik.ultimate.lib.pathexpressions.test; import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.function.BinaryOperator; import java.util.function.Supplier; import org.junit.Test; import de.uni_freiburg.informatik.ultimate.lib.pathexpressions.GenericLabeledGraph; import de.uni_freiburg.informatik.ultimate.lib.pathexpressions.PathExpressionComputer; import de.uni_freiburg.informatik.ultimate.lib.pathexpressions.regex.IRegex; import de.uni_freiburg.informatik.ultimate.lib.pathexpressions.regex.Regex; import de.uni_freiburg.informatik.ultimate.lib.pathexpressions.regex.RegexToCompactTgf; public class PathExpressionTest { /** Abbreviation for long definition. */ private static class IntGraph extends GenericLabeledGraph{ public IntGraph() { super(new LinkedHashSet<>(), new LinkedHashSet<>()); } } @Test public void simple() { IntGraph g = new IntGraph(); g.addEdge(1, "w", 2); IRegex actual = exprBetween(g, 1, 2); IRegex expected = Regex.literal("w"); assertEquals(expected, actual); } @Test public void simple2() { IntGraph g = new IntGraph(); g.addEdge(1, "w", 2); g.addEdge(2, "w", 3); IRegex actual = exprBetween(g, 1, 3); IRegex expected = a("w", "w"); assertEquals(expected, actual); } @Test public void simple3() { IntGraph g = new IntGraph(); g.addEdge(1, "a", 2); g.addEdge(2, "b", 3); g.addEdge(3, "c", 4); IRegex actual = exprBetween(g, 1, 4); IRegex expected = a("a", "b", "c"); assertEquals(expected, actual); } @Test public void star2() { IntGraph g = new IntGraph(); g.addEdge(1, "a", 2); g.addEdge(2, "b", 1); IRegex actual = exprBetween(g, 1, 2); IRegex expected = a("a", star(a("b", "a"))); assertEquals(expected, actual); } @Test public void star3() { IntGraph g = new IntGraph(); g.addEdge(1, "a", 2); g.addEdge(2, "b", 1); g.addEdge(1, "c", 2); IRegex actual = exprBetween(g, 1, 2); IRegex expected = a(u("c", "a"), star(a("b", u("c", "a")))); assertEquals(expected, actual); } @Test public void simple4() { IntGraph g = new IntGraph(); g.addEdge(1, "a", 2); g.addEdge(2, "b", 3); g.addEdge(3, "c", 4); g.addEdge(1, "c", 4); IRegex actual = exprBetween(g, 1, 4); IRegex expected = u("c", a("a", "b", "c")); assertEquals(expected, actual); } @Test public void star() { IntGraph g = new IntGraph(); g.addEdge(1, "a", 2); g.addEdge(2, "b", 2); g.addEdge(2, "c", 3); IRegex actual = exprBetween(g, 1, 3); IRegex expected = a(a("a", star("b")), "c"); assertEquals(expected, actual); } @Test public void union() { IntGraph g = new IntGraph(); g.addEdge(1, "a", 2); g.addEdge(2, "b", 3); g.addEdge(1, "c", 4); g.addEdge(4, "d", 3); IRegex actual = exprBetween(g, 1, 3); IRegex expected = u(a("a", "b"), a("c", "d")); assertEquals(expected, actual); } @Test public void empty() { IntGraph g = new IntGraph(); g.addEdge(2, "a", 1); g.addEdge(2, "b", 3); g.addEdge(3, "c", 1); IRegex actual = exprBetween(g, 1, 3); IRegex expected = Regex.emptySet(); assertEquals(expected, actual); } @Test public void unionAndConcatenate() { IntGraph g = new IntGraph(); g.addEdge(1, "a", 2); g.addEdge(1, "a", 3); g.addEdge(2, "b", 4); g.addEdge(3, "b", 4); g.addEdge(4, "c", 5); IRegex actual = exprBetween(g, 1, 5); IRegex expected = a("a", "b", "c"); assertEquals(expected, actual); } @Test public void unionAndConcatenate2() { IntGraph g = new IntGraph(); g.addEdge(1, "a", 2); g.addEdge(2, "b", 4); g.addEdge(1, "a", 3); g.addEdge(3, "b", 4); g.addEdge(4, "c", 5); IRegex actual = exprBetween(g, 1, 5); IRegex expected = u(a(a("a", "b"), "c"), a("a", a("b", "c"))); assertEquals(expected, actual); } @Test public void empty2() { IntGraph g = new IntGraph(); g.addEdge(3, "c", 1); IRegex actual = exprBetween(g, 1, 3); IRegex expected = Regex.emptySet(); assertEquals(expected, actual); } @Test public void branchWithEps() { IntGraph g = new IntGraph(); g.addEdge(1, "a", 2); g.addEdge(2, "v", 4); g.addEdge(1, "c", 3); g.addEdge(1, "c", 4); IRegex actual = exprBetween(g, 1, 4); IRegex expected = u("c", a("a", "v")); assertEquals(expected, actual); } @Test public void branchWithEps2() { IntGraph g = new IntGraph(); g.addEdge(1, "a", 2); g.addEdge(2, "v", 3); g.addEdge(1, "c", 3); IRegex actual = exprBetween(g, 1, 3); IRegex expected = u("c", a("a", "v")); assertEquals(expected, actual); } @Test public void simpleReverse() { IntGraph g = new IntGraph(); g.addEdge(3, "a", 2); g.addEdge(2, "v", 1); IRegex actual = exprBetween(g, 3, 1); IRegex expected = a("a", "v"); assertEquals(expected, actual); } @Test public void loop() { IntGraph g = new IntGraph(); g.addEdge(1, "12", 2); g.addEdge(2, "23", 3); g.addEdge(3, "34", 4); g.addEdge(4, "43", 3); IRegex actual = exprBetween(g, 1, 3); IRegex expected = u(a("12", "23"), a(a(a("12", "23", "34"), star(a("43", "34"))), "43")); assertEquals(expected, actual); } @Test public void loop2() { IntGraph g = new IntGraph(); g.addEdge(1, "12", 2); g.addEdge(2, "21", 1); g.addEdge(2, "23", 3); g.addEdge(3, "34", 4); g.addEdge(4, "43", 3); IRegex actual = exprBetween(g, 1, 3); IRegex expected = u(a(a("12", star(a("21", "12"))), "23"), a(a(a(a(a("12", star(a("21", "12"))), "23"), "34"), star(a("43", "34"))), "43")); assertEquals(expected, actual); } @Test public void loop3() { IntGraph g = new IntGraph(); g.addEdge(1, "12", 2); g.addEdge(2, "23", 3); g.addEdge(3, "32", 2); g.addEdge(3, "34", 4); g.addEdge(4, "41", 1); IRegex actual = exprBetween(g, 1, 1); IRegex expected = u(Regex.epsilon(), a(a(a(a(a("12", "23"), star(a("32", "23"))), "34"), star(a(a(a("41", "12", "23"), star(a("32", "23"))), "34"))), "41")); assertEquals(expected, actual); } @Test public void loop4() { IntGraph g = new IntGraph(); g.addEdge(1, "13", 3); g.addEdge(3, "31", 1); g.addEdge(3, "34", 4); g.addEdge(4, "41", 1); IRegex actual = exprBetween(g, 1, 1); IRegex expected = u( u(Regex.epsilon(), a(a(a(a("13", star(a("31", "13"))), "34"), star(a(a(a("41", "13"), star(a("31", "13"))), "34"))), "41")), a(u(a("13", star(a("31", "13"))), a(a(a(a("13", star(a("31", "13"))), "34"), star(a(a(a("41", "13"), star(a("31", "13"))), "34"))), a(a("41", "13"), star(a("31", "13"))))), "31")); assertEquals(expected, actual); } private static IRegex exprBetween(IntGraph graph, int source, int target) { return new PathExpressionComputer<>(graph).exprBetween(source, target); } private static IRegex e(String e) { return Regex.literal(e); } private static IRegex a(IRegex a, IRegex b) { return Regex.simplifiedConcatenation(a, b); } private static IRegex a(String a, IRegex b) { return a(e(a), b); } private static IRegex a(IRegex a, String b) { return a(a, e(b)); } private static IRegex u(IRegex a, IRegex b) { return Regex.simplifiedUnion(a, b); } private static IRegex u(String a, IRegex b) { return u(e(a), b); } private static IRegex star(IRegex a) { return Regex.simplifiedStar(a); } private static IRegex star(String a) { return star(e(a)); } private static IRegex a(final String... letters) { return pairFromLeft(Regex::epsilon, Regex::concat, letters); } private static IRegex u(final String... letters) { return pairFromLeft(Regex::emptySet, Regex::union, letters); } private static IRegex pairFromLeft(final Supplier> neutralElem, final BinaryOperator> operator, final String... letters) { return Arrays.stream(letters).map(Regex::literal).reduce(operator).orElseGet(neutralElem); } // ----- "Tests" for experimenting with iteration order --------------------------------------- //@Test public void rersSmallBest() { IntGraph g = new IntGraph(); for (int i = 4; i >= 0; --i) { g.addNode(i); } g.addEdge(0, "a", 1); g.addEdge(1, "b", 2); g.addEdge(2, "c", 3); g.addEdge(3, "d", 0); g.addEdge(0, "e", 4); g.addEdge(1, "f", 3); IRegex actual = exprBetween(g, 0, 4); // not a real assert, just there to get output assertEquals(RegexToCompactTgf.apply(actual), actual); } //@Test public void rersSmallOk() { IntGraph g = new IntGraph(); for (int i = 0; i <= 4; ++i) { g.addNode(i); } g.addEdge(0, "a", 1); g.addEdge(1, "b", 2); g.addEdge(2, "c", 3); g.addEdge(3, "d", 0); g.addEdge(0, "e", 4); g.addEdge(1, "f", 3); IRegex actual = exprBetween(g, 0, 4); // not a real assert, just there to get output assertEquals(RegexToCompactTgf.apply(actual), actual); } //@Test public void rersSmallWorst() { IntGraph g = new IntGraph(); g.addNode(0); g.addNode(3); g.addNode(4); g.addNode(1); g.addNode(2); g.addEdge(3, "d", 0); g.addEdge(1, "b", 2); g.addEdge(1, "f", 3); g.addEdge(0, "a", 1); g.addEdge(2, "c", 3); g.addEdge(0, "e", 4); IRegex actual = exprBetween(g, 0, 4); // not a real assert, just there to get output assertEquals(RegexToCompactTgf.apply(actual), actual); } //@Test public void dagWorst() { IntGraph g = new IntGraph(); g.addNode(0); g.addNode(3); g.addNode(4); g.addNode(1); g.addNode(2); g.addEdge(3, "d", 0); g.addEdge(1, "b", 2); g.addEdge(1, "f", 3); g.addEdge(0, "a", 1); g.addEdge(2, "c", 3); g.addEdge(0, "e", 4); g.addEdge(0, "g", 5); // not a real assert, just there to get output RegexToCompactTgf re2tgf = new RegexToCompactTgf<>(); exprBetween(g, 0, 4).accept(re2tgf); exprBetween(g, 0, 5).accept(re2tgf); assertEquals(exprBetween(g, 0, 5), ""); } //@Test public void dagBest() { IntGraph g = new IntGraph(); for (int i = 5; i >= 0; --i) { g.addNode(i); } g.addEdge(0, "a", 1); g.addEdge(1, "b", 2); g.addEdge(2, "c", 3); g.addEdge(3, "d", 0); g.addEdge(0, "e", 4); g.addEdge(1, "f", 3); g.addEdge(0, "g", 5); // not a real assert, just there to get output RegexToCompactTgf re2tgf = new RegexToCompactTgf<>(); exprBetween(g, 0, 4).accept(re2tgf); exprBetween(g, 0, 5).accept(re2tgf); assertEquals(exprBetween(g, 0, 5), ""); } }