All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.unive.lisa.analysis.nonRedundantSet.NonRedundantPowersetOfInterval Maven / Gradle / Ivy

The newest version!
package it.unive.lisa.analysis.nonRedundantSet;

import it.unive.lisa.analysis.SemanticException;
import it.unive.lisa.analysis.SemanticOracle;
import it.unive.lisa.analysis.nonrelational.value.ValueEnvironment;
import it.unive.lisa.analysis.numeric.Interval;
import it.unive.lisa.program.cfg.ProgramPoint;
import it.unive.lisa.symbolic.value.Identifier;
import it.unive.lisa.symbolic.value.ValueExpression;
import it.unive.lisa.symbolic.value.operator.binary.BinaryOperator;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonEq;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonGe;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonGt;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonLe;
import it.unive.lisa.symbolic.value.operator.binary.ComparisonLt;
import it.unive.lisa.util.numeric.MathNumber;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * The finite non redundant powerset of {@link Interval} abstract domain
 * approximating integer values as a non redundant set of interval. It is
 * implemented as a {@link NonRedundantPowersetOfBaseNonRelationalValueDomain},
 * which handles most of the basic operation (such as
 * {@link NonRedundantPowersetOfBaseNonRelationalValueDomain#lubAux lub},
 * {@link NonRedundantPowersetOfBaseNonRelationalValueDomain#glbAux glb},
 * {@link NonRedundantPowersetOfBaseNonRelationalValueDomain#wideningAux
 * widening} and others operations needed to calculate the previous ones).
 */
public class NonRedundantPowersetOfInterval
		extends
		NonRedundantPowersetOfBaseNonRelationalValueDomain {

	/**
	 * Constructs an empty non redundant set of intervals.
	 */
	public NonRedundantPowersetOfInterval() {
		super(new TreeSet<>(), Interval.BOTTOM);
	}

	/**
	 * Constructs a non redundant set of intervals with the given intervals.
	 * 
	 * @param elements the set of intervals
	 */
	public NonRedundantPowersetOfInterval(
			SortedSet elements) {
		super(elements, Interval.BOTTOM);
	}

	/**
	 * This specific Egli-Milner connector follows this definition:
* given two subsets S1 and S2 of a domain of a * lattice: *

* S1 +EM S2 = {s2 ∋ * S2 | ∃ s1 ∋ S1 : s1 * ≤ s2} ∪ {lub(s'1, s2) | * s'1 ∋ S1, s2 ∋ S2, NOT * ∃ s1 ∋ S1 : s1 ≤ * s2} *

* s'1 can be chosen randomly but in this case is chosen to be * the closest interval to s2 (closest based on * {@link #middlePoint(Interval) middle point}). */ @Override protected NonRedundantPowersetOfInterval EgliMilnerConnector( NonRedundantPowersetOfInterval other) throws SemanticException { SortedSet newElementsSet = new TreeSet<>(); SortedSet notCoverSet = new TreeSet<>(); // first side of the union for (Interval s2 : other.elementsSet) { boolean existsLower = false; for (Interval s1 : elementsSet) if (s1.lessOrEqual(s2)) { existsLower = true; break; } if (existsLower) newElementsSet.add(s2); else notCoverSet.add(s2); } // second side of the union for (Interval s2 : notCoverSet) { MathNumber middlePoint = middlePoint(s2); MathNumber closestValue = middlePoint; MathNumber closestDiff = closestValue.subtract(middlePoint).abs(); Interval closest = Interval.TOP; for (Interval s1 : elementsSet) { if (closestValue.compareTo(middlePoint) == 0) { closest = s1; closestValue = middlePoint(s1); closestDiff = closestValue.subtract(middlePoint).abs(); } else { MathNumber s1Diff = middlePoint(s1).subtract(middlePoint).abs(); if (s1Diff.compareTo(closestDiff) < 0) { closest = s1; closestValue = middlePoint(s1); closestDiff = closestValue.subtract(middlePoint).abs(); } } } newElementsSet.add(s2.lub(closest)); } return new NonRedundantPowersetOfInterval(newElementsSet).removeRedundancy().removeOverlapping(); } /** * Yields the middle point of an {@link Interval}. If both extremes are * non-infinite the middle point is the sum of the two divided by two. If * only one of the two extreme is infinite the middle point is said to be * the non-infinite extreme. If both the extremes are infinite the middle * point is said to be 0. * * @param interval the interval to calculate the middle point of * * @return the middle point of the interval */ protected MathNumber middlePoint( Interval interval) { if (interval.interval.isFinite()) return interval.interval.getLow().add(interval.interval.getHigh()).divide(new MathNumber(2)); else if (interval.interval.getHigh().isFinite() && !interval.interval.getLow().isFinite()) return interval.interval.getHigh(); else if (!interval.interval.getHigh().isFinite() && interval.interval.getLow().isFinite()) return interval.interval.getLow().subtract(MathNumber.ONE); // both infinite return MathNumber.ZERO; } @Override public ValueEnvironment assumeBinaryExpression( ValueEnvironment environment, BinaryOperator operator, ValueExpression left, ValueExpression right, ProgramPoint src, ProgramPoint dest, SemanticOracle oracle) throws SemanticException { Identifier id; NonRedundantPowersetOfInterval eval; boolean rightIsExpr; if (left instanceof Identifier) { eval = eval(right, environment, src, oracle); id = (Identifier) left; rightIsExpr = true; } else if (right instanceof Identifier) { eval = eval(left, environment, src, oracle); id = (Identifier) right; rightIsExpr = false; } else return environment; NonRedundantPowersetOfInterval starting = environment.getState(id); if (eval.isBottom() || starting.isBottom()) return environment.bottom(); SortedSet newSet = new TreeSet<>(); for (Interval startingInterval : starting.elementsSet) for (Interval interval : eval.elementsSet) { boolean lowIsMinusInfinity = interval.interval.lowIsMinusInfinity(); Interval low_inf = new Interval(interval.interval.getLow(), MathNumber.PLUS_INFINITY); Interval lowp1_inf = new Interval(interval.interval.getLow().add(MathNumber.ONE), MathNumber.PLUS_INFINITY); Interval inf_high = new Interval(MathNumber.MINUS_INFINITY, interval.interval.getHigh()); Interval inf_highm1 = new Interval(MathNumber.MINUS_INFINITY, interval.interval.getHigh().subtract(MathNumber.ONE)); if (operator == ComparisonEq.INSTANCE) newSet.add(interval); else if (operator == ComparisonGe.INSTANCE) if (rightIsExpr) if (lowIsMinusInfinity) newSet.add(startingInterval); else newSet.add(startingInterval.glb(low_inf)); else newSet.add(startingInterval.glb(inf_high)); else if (operator == ComparisonGt.INSTANCE) if (rightIsExpr) newSet.add(startingInterval.glb(lowp1_inf)); else newSet.add(lowIsMinusInfinity ? interval : startingInterval.glb(inf_highm1)); else if (operator == ComparisonLe.INSTANCE) if (rightIsExpr) newSet.add(startingInterval.glb(inf_high)); else if (lowIsMinusInfinity) newSet.add(startingInterval); else newSet.add(startingInterval.glb(low_inf)); else if (operator == ComparisonLt.INSTANCE) if (rightIsExpr) newSet.add(lowIsMinusInfinity ? interval : startingInterval.glb(inf_highm1)); else if (lowIsMinusInfinity) newSet.add(startingInterval); else newSet.add(startingInterval.glb(lowp1_inf)); else newSet.add(startingInterval); } NonRedundantPowersetOfInterval intervals = new NonRedundantPowersetOfInterval(newSet) .removeRedundancy() .removeOverlapping(); if (intervals.isBottom()) return environment.bottom(); else return environment.putState(id, intervals); } @Override protected NonRedundantPowersetOfInterval mk( SortedSet elements) { return new NonRedundantPowersetOfInterval(elements); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy