/* * 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-Sifa plug-in. * * The ULTIMATE Library-Sifa 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-Sifa 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-Sifa plug-in. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify the ULTIMATE Library-Sifa 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-Sifa plug-in grant you additional permission * to convey the resulting work. */ package de.uni_freiburg.informatik.ultimate.lib.sifa.test; import java.math.BigInteger; import java.util.function.BiFunction; import org.junit.Assert; import org.junit.Test; import de.uni_freiburg.informatik.ultimate.lib.sifa.domain.Interval; import de.uni_freiburg.informatik.ultimate.lib.sifa.domain.Interval.SatisfyingInputs; import de.uni_freiburg.informatik.ultimate.logic.Rational; public class IntervalTest { // TODO test arithmetic operations like +, -, ... in detail @Test public void testUnification() { Assert.assertSame(Interval.TOP, interval("-inf, inf")); Assert.assertSame(Interval.BOTTOM, interval("-4, -5")); Assert.assertSame(Interval.BOTTOM, interval("456/7, 455/7")); } @Test public void testNegate() { Assert.assertEquals(interval("-10/3, -3"), interval("3, 10/3").negate()); Assert.assertEquals(interval("-5, 2"), interval("-2, 5").negate()); Assert.assertEquals(Interval.TOP, Interval.TOP.negate()); } @Test public void testAdd() { Assert.assertEquals(interval("-3, 7"), interval("-2, 5").add(interval("-1, 2"))); } @Test public void testSubtract() { Assert.assertEquals(interval("-5/6, 35/3"), interval("7/6, 10").subtract(interval("-5/3, 2"))); } @Test public void testMultiply() { Assert.assertEquals(interval("0, 4"), interval("-4, 0").multiply(interval("-1"))); Assert.assertEquals(interval("-4, 4"), interval("-4, 0").multiply(interval("-1, 1"))); Assert.assertEquals(interval("-18/5, 51/2"), interval("3, 9/2").multiply(interval("-4/5, 17/3"))); } @Test public void testDivide() { Assert.assertEquals(interval("-6, -3/2"), interval("3, 6").divide(interval("-2, -1"))); Assert.assertEquals(interval("-2, 3"), interval("-2, 3").divide(interval("1, 4"))); Assert.assertEquals(interval("-inf, inf"), interval("4, 6").divide(interval("-3, 2"))); } @Test public void testWiden() { // constant left bound (widen right, if at all) Assert.assertEquals(interval("2, 5"), interval("2, 5").widen(interval("2, 4"))); Assert.assertEquals(interval("2, 5"), interval("2, 5").widen(interval("2, 5"))); Assert.assertEquals(interval("2, inf"), interval("2, 5").widen(interval("2, 6"))); // constant right bound (widen left, if at all) Assert.assertEquals(interval("2, 5"), interval("2, 5").widen(interval("3, 5"))); Assert.assertEquals(interval("2, 5"), interval("2, 5").widen(interval("2, 5"))); Assert.assertEquals(interval("-inf, 5"), interval("2, 5").widen(interval("1, 5"))); // strict subset Assert.assertEquals(interval("-4, 0"), interval("-4, 0").widen(interval("-2, -1"))); // widen in both directions Assert.assertEquals(interval("-inf, inf"), interval("-4, 0").widen(interval("-123, 1/5000"))); } @Test public void testSatEqual() { checkRelationPredefinedInputs(Interval::satisfyEqual, "2,3", "2,3", "2,3", "2,3", "2,3", "2,3", "2,3", "2,3", "∅", "∅", "∅", "∅"); } @Test public void testSatDistinct() { checkRelationPredefinedInputs(Interval::satisfyDistinct, "1,3", "2,4", "2,4", "1,3", "2,3", "1,4", "1,4", "2,3", "1,2", "3,4", "3,4", "1,2"); } @Test public void testSatLessOrEqual() { checkRelationPredefinedInputs(Interval::satisfyLessOrEqual, "1,3", "2,4", "2,3", "2,3", "2,3", "2,4", "1,3", "2,3", "1,2", "3,4", "∅", "∅"); } @Test public void testSatGreaterOrEqual() { checkRelationPredefinedInputs(Interval::satisfyGreaterOrEqual, "2,3", "2,3", "2,4", "1,3", "2,3", "1,3", "2,4", "2,3", "∅", "∅", "3,4", "1,2"); } private void checkRelationPredefinedInputs(final BiFunction relFun, final String lhsOverlapLeft, final String rhsOverlapLeft, final String lhsOverlapRight, final String rhsOverlapRight, final String lhsSubset, final String rhsSubset, final String lhsSuperset, final String rhsSuperset, final String lhsDisjointLeft, final String rhsDisjointLeft, final String lhsDisjointRight, final String rhsDisjointRight) { checkRelation("1,3", "2,4", relFun, lhsOverlapLeft, rhsOverlapLeft); checkRelation("2,4", "1,3", relFun, lhsOverlapRight, rhsOverlapRight); checkRelation("2,3", "1,4", relFun, lhsSubset, rhsSubset); checkRelation("1,4", "2,3", relFun, lhsSuperset, rhsSuperset); checkRelation("1,2", "3,4", relFun, lhsDisjointLeft, rhsDisjointLeft); checkRelation("3,4", "1,2", relFun, lhsDisjointRight, rhsDisjointRight); } private static void checkRelation(final String lhsInput, final String rhsInput, final BiFunction relFun, final String expectedLhs, final String expectedRhs) { Assert.assertEquals( new SatisfyingInputs(interval(expectedLhs), interval(expectedRhs)), relFun.apply(interval(lhsInput), interval(rhsInput))); } private static Interval interval(final String interval) { if ("∅".equals(interval)) { return Interval.BOTTOM; } final String[] lowAndHighBound = interval.split(", *"); if (lowAndHighBound.length < 1 || 2 < lowAndHighBound.length) { throw new IllegalArgumentException("Cannot parse interval: " + interval); } final Rational lowBound = rational(lowAndHighBound[0]); if (lowAndHighBound.length == 1) { return Interval.point(lowBound); } return Interval.of(lowBound, rational(lowAndHighBound[1])); } private static Rational rational(final String rational) { if ("inf".equals(rational) || "+inf".equals(rational)) { return Rational.POSITIVE_INFINITY; } else if ("-inf".equals(rational)) { return Rational.NEGATIVE_INFINITY; } final String[] numAndDenom = rational.split("/"); if (numAndDenom.length < 1 || 2 < numAndDenom.length) { throw new IllegalArgumentException("Cannot parse rational: " + rational); } final BigInteger numerator = new BigInteger(numAndDenom[0]); if (numAndDenom.length == 1) { return Rational.valueOf(numerator, BigInteger.ONE); } return Rational.valueOf(numerator, new BigInteger(numAndDenom[1])); } }