Search in sources :

Example 1 with IdentifierExpression

use of xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression in project atlas by lorenzleutgeb.

the class LetTreeCf method apply.

/**
 * P wird durch Q definiert: * p_i = q_i * p_(a,c) = q_(a,0,c)
 *
 * <p>P^(b,d,e) wird durch Q definiert: * sum ... p^(b,d,e)_(a,c) = q_(a,b,c) * p^(b,d,e)_i = 0
 * (implizit, keine Constraints)
 *
 * <p>P'^(b,d,e) wird durch P^(b,d,e) definiert: * p'^(b,d,e)_(d,e) ist 0 oder kleiner gleich
 * p^(b,d,e)_(a,c) * p'^(b,d,e)_i = 0 (implizit, keine Constraints)
 *
 * <p>R wird durch Q, P' und P'^(b,d,e) definiert: * r_j = q_{m+j} * r_{k+1} = p'_* * r_(b,d,e) =
 * p'^(b,d,e)_(d,e) (mit b != nullvektor) * r_(0,d,e) = p'_(d,e)
 *
 * <p>P' wird nicht direkt aus anderen Annotationen definiert, sondern es wird eine Form
 * angenommen, z.B. (a, c) mit a in {0, 1}, c in {0, 2}.
 */
public ApplicationResult apply(Obligation obligation, AnnotatingGlobals globals, Map<String, String> arguments) {
    final var deRange = cartesianProduct(D_RANGE, flag(LetTreeCf.class, arguments, "nege") ? E_RANGE_INCL_NEGATIVE_ONE : E_RANGE);
    final var expression = (LetExpression) obligation.getExpression();
    final var x = expression.getDeclared();
    final var value = expression.getValue();
    final var gammaDeltaQ = obligation.getContext();
    final var body = expression.getBody();
    final List<Constraint> crossConstraints = new ArrayList<>();
    if (value.getType().countTrees().get() != 1) {
        throw bug("cannot apply (let:tree:cf) to a variable that is not a tree");
    }
    // Γ is used as context for e1, so from the combined context,
    // take Γ to be exactly the variables that occur in e1.
    final var varsForGammaAsSet = value.freeVariables();
    // Δ on the other hand is "everything that's not in Γ".
    final var varsForDeltaAsSet = gammaDeltaQ.getIds().stream().filter(not(varsForGammaAsSet::contains)).collect(Collectors.toSet());
    // are not in Δ.
    if (!Sets.difference(Sets.difference(body.freeVariables(), singleton(x)), varsForDeltaAsSet).isEmpty()) {
        throw bug("there are free variables in the body of a let binding which do not occur in Δ");
    }
    if (!intersection(varsForGammaAsSet, varsForDeltaAsSet).isEmpty()) {
        throw bug("shared variables in let expression when attempting to generate constraints");
    }
    final var prefix = "(let:tree:cf `" + x.getName() + "`) ";
    final var varsForGammaAsList = obligation.getContext().getIds().stream().filter(varsForGammaAsSet::contains).toList();
    final var varsForDeltaAsList = obligation.getContext().getIds().stream().filter(varsForDeltaAsSet::contains).toList();
    // Construct the context Γ | P
    // P will be defined by Q.
    final var gammaP = new AnnotatingContext(varsForGammaAsList, "P(" + x + ")");
    // First main obligation about the value being bound by this let-expression.
    // Γ | P  ⊢  e1 : T | P'
    final var pp = globals.getHeuristic().generate("P'(" + x + ")", value);
    final Pair<Obligation, List<Constraint>> p = Pair.of(obligation.keepCost(gammaP, value, pp), new ArrayList<>());
    // Construct the context Δ, x : Tree | R
    // R will be defined by P' and P'^{(\vec{b},d,e)}.
    final var deltax = new ArrayList<>(varsForDeltaAsList);
    deltax.add(x);
    final var deltaxr = new AnnotatingContext(deltax, "R(" + x + ")");
    // Second main obligation about the body of this let-expression.
    // Δ, x : Tree | R  ⊢  e2 : β | Q'
    final Pair<Obligation, List<Constraint>> r = Pair.of(obligation.keepAnnotationAndCost(deltaxr, body), new ArrayList<>());
    // Define rank coefficients in P from Q.
    p.getRight().addAll(EqualityConstraint.eqRanksDefineFromLeft(varsForGammaAsList, gammaDeltaQ, gammaP, prefix + "q_i = p_i"));
    // Define rank coefficients in R from Q.
    r.getRight().addAll(EqualityConstraint.eqRanksDefineFromLeft(varsForDeltaAsList, gammaDeltaQ, deltaxr, prefix + "q_{m+j} = r_j"));
    // Define rank coefficient for x in R from P'.
    crossConstraints.add(// introduced variable, equate those coefficients.
    new EqualityConstraint(deltaxr.getRankCoefficientOrDefine(x), pp.getRankCoefficient(), prefix + "r_{k+1} = p'_{*}"));
    // TODO: Maybe also add that a + c != 0?
    // Define non-rank coefficients in P from Q.
    p.getRight().addAll(gammaDeltaQ.streamNonRank().filter(entry -> entry.allAssociatedIndicesMatch(varsForDeltaAsSet, b -> b == 0)).filter(entry -> {
        final var index = entry.instantiateWithOffset(varsForGammaAsList);
        // We skip the unit index here, because it is handled by "move const".
        return isSumAtLeastOne(index) && !isUnitIndex(index);
    }).map(entry -> new EqualityConstraint(gammaP.getCoefficientOrDefine(entry), entry.getValue(), prefix + "p_{(a⃗⃗,c)} = q_{(a⃗⃗,0⃗,c)} with (a⃗⃗,c) = " + entry.toIndexString())).collect(Collectors.toSet()));
    // Specifically addresses
    // r_{(\vec{0}, 2)} = p'_{(\vec{0}, 2)} - p_{(\vec{0}, 2) + q_{(\vec{0}, 2)}
    crossConstraints.add(new EqualsSumConstraint(deltaxr.getAnnotation().getCoefficientOrDefine(unitIndex(deltax.size())), List.of(pp.getCoefficientOrDefine(unitIndex(pp.size())), gammaP.getAnnotation().getCoefficientOrDefine(unitIndex(gammaP.size())).negate(), gammaDeltaQ.getAnnotation().getCoefficientOrZero(unitIndex(gammaDeltaQ.size()))), prefix + "move const"));
    // p_{(\vec{0}, 2)} ≤ q_{(\vec{0}, 2)}
    crossConstraints.add(new LessThanOrEqualConstraint(gammaP.getAnnotation().getCoefficientOrDefine(unitIndex(gammaP.size())), gammaDeltaQ.getAnnotation().getCoefficientOrZero(unitIndex(gammaDeltaQ.size())), prefix + "c_p less than c_q"));
    // Define some non-rank coefficients in R from P'.
    // Here we do not need to check whether d + e > 0 because P' was created via heuristics.
    crossConstraints.addAll(pp.streamNonRankCoefficients().map(entry -> {
        final var index = entry.getKey();
        final var d = index.get(0);
        final var e = index.get(1);
        return new EqualityConstraint(deltaxr.getCoefficientOrDefine(id -> id.equals(x) ? d : 0, e), entry.getValue(), prefix + "r_{(0⃗,d,e)} = p'_{(d,e)}");
    }).toList());
    final Map<Index, Pair<Obligation, List<Constraint>>> pbdes = new HashMap<>();
    if (!varsForDeltaAsList.isEmpty()) {
        // Define some non-rank coefficients in R from Q.
        crossConstraints.addAll(gammaDeltaQ.streamNonRank().filter(entry -> entry.getOffsetIndex() == 0).filter(entry -> entry.allAssociatedIndicesMatch(varsForGammaAsList, a -> a == 0)).filter(entry -> varsForDeltaAsList.isEmpty() || !entry.allAssociatedIndicesMatch(varsForDeltaAsList, b -> b == 0)).map(entry -> new EqualityConstraint(deltaxr.getCoefficientOrDefine(entry.mask(x, 0)), entry.getValue(), prefix + "r_{(b⃗,0,0)} = q_{(0⃗,b⃗,0)} with (b⃗,0) = " + entry.toIndexString())).toList());
        // Find all indices (\vec{b}, d, e) such that \vec{b} \neq \vec{0}.
        final List<Index> bdes = gammaDeltaQ.streamNonRank().filter(entry -> varsForDeltaAsList.isEmpty() || !entry.allAssociatedIndicesMatch(varsForDeltaAsList, b -> b == 0)).flatMap(entry -> deRange.stream().filter(index -> index.get(0) + max(index.get(1), 0) > 0).filter(de -> Util.isSumAtLeastOne(append(entry.instantiate(varsForDeltaAsList), de))).map(de -> {
            Map<IdentifierExpression, Integer> associatedIndices = new HashMap<>();
            for (IdentifierExpression id : varsForDeltaAsList) {
                associatedIndices.put(id, entry.getAssociatedIndex(id));
            }
            associatedIndices.put(x, de.get(0));
            return new MapIndex(associatedIndices, de.get(1));
        })).distinct().collect(Collectors.toUnmodifiableList());
        final Function<? super Index, Pair<Obligation, List<Constraint>>> pbProducer = (key) -> Pair.of(new Obligation(new AnnotatingContext(varsForGammaAsList, "P(" + x + ")(" + key + ")"), value, new Annotation(1, "P'(" + x + ")(" + key + ")"), false, false), new ArrayList<>());
        gammaDeltaQ.streamNonRank().filter(entry -> {
            // If a is empty or zero, then c must be non-zero.
            if (entry.allAssociatedIndicesMatch(varsForGammaAsList, a -> a == 0)) {
                return entry.getOffsetIndex() > 0;
            }
            // isn't).
            if (entry.getOffsetIndex() == 0) {
                return !varsForGammaAsList.isEmpty();
            }
            return true;
        }).filter(entry -> varsForDeltaAsList.isEmpty() || !entry.allAssociatedIndicesMatch(varsForDeltaAsList, b -> b == 0)).map(qEntry -> new EqualsSumConstraint(qEntry.getValue(), bdes.stream().filter(bde -> qEntry.agreeOnAssociatedIndices(bde, varsForDeltaAsSet)).filter(bde -> isSumAtLeastOne(qEntry.instantiateWithOffset(varsForGammaAsList))).map(bde -> {
            final var e = bde.getOffsetIndex();
            if (e == -1) {
                return pbdes.computeIfAbsent(bde, pbProducer).getLeft().getContext().getCoefficientOrDefine(qEntry.addToOffset(1));
            } else {
                return pbdes.computeIfAbsent(bde, pbProducer).getLeft().getContext().getCoefficientOrDefine(qEntry);
            }
        }).toList(), prefix + "q_{(a⃗⃗,b⃗,c)} = Σ_{(d,e)}{p^{(b⃗,d,e)}_{(a⃗⃗,c})}")).forEach(crossConstraints::add);
        for (var bde : bdes) {
            final var d = bde.getAssociatedIndex(x);
            final var e = bde.getOffsetIndex();
            final var cfpair = pbdes.computeIfAbsent(bde, pbProducer);
            final var cfobligation = cfpair.getLeft();
            final var cfconstraints = cfpair.getRight();
            final var cfp = cfobligation.getContext().getAnnotation();
            final var cfpp = cfobligation.getAnnotation();
            cfconstraints.add(new EqualityConstraint(deltaxr.getCoefficientOrDefine(bde), cfpp.getCoefficientOrDefine(d, max(e, 0)), prefix + "r_{(b⃗,d,e)} = p'^{(b⃗,d,e)}_{(d,e)}"));
            // We range over (d', e') here!
            for (final var dpep : deRange) {
                final var dp = dpep.get(0);
                final var ep = dpep.get(1);
                if (!Util.isSumAtLeastOne(dpep)) {
                    continue;
                }
                if (Objects.equals(dp, d) && Objects.equals(ep, max(e, 0))) {
                    // (d', e') = (d, max(e, 0))
                    continue;
                }
                cfconstraints.add(new EqualityConstraint(cfpp.getCoefficientOrDefine(dp, ep), ZERO, prefix + "p'^{(b⃗,d,e}_{(d',e')}=0"));
            }
            // \sum_(a,c) p^(b,d,e)_(a,c) >= p'^(b,d,e)_(d,e)
            final List<Coefficient> lemma14guard = cfp.streamNonRankCoefficients().map(Map.Entry::getValue).collect(Collectors.toList());
            UnknownCoefficient u = Coefficient.unknownFromPrefix("l14g." + x);
            cfconstraints.add(new EqualsSumConstraint(u, lemma14guard, prefix + "l14g " + bde + "Σ_{(a⃗⃗,c)} p^{(b⃗,d,e}_{(a⃗⃗,c)}"));
            cfconstraints.add(new LessThanOrEqualConstraint(cfpp.getCoefficientOrDefine(d, max(e, 0)), u, prefix + "l14g " + bde + "Σ_{(a⃗⃗,c)} p^{(b⃗,d,e}_{(a⃗⃗,c)} ≥ p'^{(b⃗,d,e}_{(d,e)}"));
            cfp.streamNonRankCoefficients().map(entry -> new DisjunctiveConstraint(List.of(new EqualityConstraint(entry.getValue(), ZERO, prefix + "p^{(b⃗,d,e}_{(a⃗⃗,c)} == 0"), new LessThanOrEqualConstraint(cfpp.getCoefficientOrDefine(d, max(e, 0)), entry.getValue(), prefix + "p'^{(b⃗,d,e}_{(d,e)} ≤ p^{(b⃗,d,e}_{(a⃗⃗,c)}")), prefix + "p^{(b⃗,d,e}_{(a⃗⃗,c)} ِ≠ 0 ⇒ p'^{(b⃗,d,e}_{(d,e)} ≤ p^{(b⃗,d,e}_{(a⃗⃗,c)}")).forEach(cfconstraints::add);
        }
    }
    final List<Pair<Obligation, List<Constraint>>> pbdesOrdered = pbdes.keySet().stream().sorted(new Index.DomainComparator(deltax)).map(pbdes::get).collect(Collectors.toList());
    final var old = append(List.of(p, r), pbdesOrdered);
    return new ApplicationResult(old.stream().map(Pair::getLeft).toList(), old.stream().map(Pair::getRight).toList(), crossConstraints);
}
Also used : Pair(xyz.leutgeb.lorenz.atlas.util.Pair) java.util(java.util) EqualityConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualityConstraint) Sets.cartesianProduct(com.google.common.collect.Sets.cartesianProduct) Obligation(xyz.leutgeb.lorenz.atlas.typing.resources.proving.Obligation) EqualsSumConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualsSumConstraint) Constraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.Constraint) SmartRangeHeuristic(xyz.leutgeb.lorenz.atlas.typing.resources.heuristics.SmartRangeHeuristic) Function(java.util.function.Function) AnnotatingGlobals(xyz.leutgeb.lorenz.atlas.typing.resources.AnnotatingGlobals) AnnotatingContext(xyz.leutgeb.lorenz.atlas.typing.resources.AnnotatingContext) Collections.singleton(java.util.Collections.singleton) Annotation.unitIndex(xyz.leutgeb.lorenz.atlas.typing.resources.Annotation.unitIndex) Coefficient(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.Coefficient) ZERO(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.KnownCoefficient.ZERO) UnknownCoefficient(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.UnknownCoefficient) DisjunctiveConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.DisjunctiveConstraint) Util(xyz.leutgeb.lorenz.atlas.util.Util) MapIndex(xyz.leutgeb.lorenz.atlas.typing.resources.indices.MapIndex) IdentifierExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Sets.intersection(com.google.common.collect.Sets.intersection) LessThanOrEqualConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.LessThanOrEqualConstraint) Index(xyz.leutgeb.lorenz.atlas.typing.resources.indices.Index) Annotation.isUnitIndex(xyz.leutgeb.lorenz.atlas.typing.resources.Annotation.isUnitIndex) LetExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.LetExpression) Math.max(java.lang.Math.max) Annotation(xyz.leutgeb.lorenz.atlas.typing.resources.Annotation) Predicate.not(java.util.function.Predicate.not) Obligation(xyz.leutgeb.lorenz.atlas.typing.resources.proving.Obligation) EqualityConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualityConstraint) EqualsSumConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualsSumConstraint) Constraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.Constraint) DisjunctiveConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.DisjunctiveConstraint) LessThanOrEqualConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.LessThanOrEqualConstraint) EqualsSumConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualsSumConstraint) Annotation.unitIndex(xyz.leutgeb.lorenz.atlas.typing.resources.Annotation.unitIndex) MapIndex(xyz.leutgeb.lorenz.atlas.typing.resources.indices.MapIndex) Index(xyz.leutgeb.lorenz.atlas.typing.resources.indices.Index) Annotation.isUnitIndex(xyz.leutgeb.lorenz.atlas.typing.resources.Annotation.isUnitIndex) LetExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.LetExpression) Pair(xyz.leutgeb.lorenz.atlas.util.Pair) UnknownCoefficient(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.UnknownCoefficient) Coefficient(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.Coefficient) UnknownCoefficient(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.UnknownCoefficient) AnnotatingContext(xyz.leutgeb.lorenz.atlas.typing.resources.AnnotatingContext) EqualityConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualityConstraint) Annotation(xyz.leutgeb.lorenz.atlas.typing.resources.Annotation) IdentifierExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression) LessThanOrEqualConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.LessThanOrEqualConstraint) MapIndex(xyz.leutgeb.lorenz.atlas.typing.resources.indices.MapIndex) DisjunctiveConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.DisjunctiveConstraint)

Example 2 with IdentifierExpression

use of xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression in project atlas by lorenzleutgeb.

the class Match method apply.

public Rule.ApplicationResult apply(Obligation obligation, AnnotatingGlobals globals, Map<String, String> arguments) {
    final var expression = (MatchTreeExpression) obligation.getExpression();
    final var x = (IdentifierExpression) expression.getScrut();
    final var pattern = expression.getNodePattern();
    final var gammaxq = obligation.getContext();
    final var gammap = pop(gammaxq.getIds(), x);
    final var pConstraints = new ArrayList<Constraint>();
    final var sums = new HashMap<List<Integer>, List<Coefficient>>();
    final var listWithRank = new ArrayList<Coefficient>();
    listWithRank.add(gammaxq.getRankCoefficient(x));
    sums.put(Annotation.unitIndex(gammap.size()), listWithRank);
    gammaxq.streamNonRank().forEach(entry -> {
        int a = entry.getAssociatedIndex(x);
        int b = entry.getOffsetIndex();
        if (b < 0 || a < 0) {
            return;
        }
        int c = a + b;
        if (gammap.isEmpty() && c == 1) {
            return;
        }
        final var index = new ArrayList<Integer>(gammap.size());
        for (var id : gammap.getIds()) {
            index.add(entry.getAssociatedIndex(id));
        }
        index.add(c);
        final var sum = sums.computeIfAbsent(index, key -> new ArrayList<>());
        sum.add(entry.getValue());
    });
    for (var entry : sums.entrySet()) {
        if (entry.getValue().isEmpty()) {
            continue;
        }
        pConstraints.add(new EqualsSumConstraint(gammap.getAnnotation().getCoefficientOrDefine(entry.getKey()), entry.getValue(), ruleName(obligation) + " p_{a⃗⃗, c} = Σ_{a+b=c} q_{a⃗⃗, a, b}"));
    }
    for (var id : gammaxq.getIds()) {
        if (id.equals(x)) {
            continue;
        }
        pConstraints.add(new EqualityConstraint(gammaxq.getRankCoefficient(id), gammap.getRankCoefficientOrDefine(id), ruleName(obligation) + " q_i = p_i"));
    }
    if (x.equals(pattern)) {
        return new Rule.ApplicationResult(List.of(obligation.keepAnnotationAndCost(gammap, expression.getLeaf()), obligation.keepContextAndAnnotationAndCost(expression.getNode())), List.of(pConstraints, emptyList()));
    }
    final var x1 = (IdentifierExpression) ((NodeExpression) pattern).getLeft();
    final var x3 = (IdentifierExpression) ((NodeExpression) pattern).getRight();
    final var gammaxsr = extend(gammap.getIds(), x, x1, x3);
    final var rConstraints = new ArrayList<Constraint>();
    rConstraints.addAll(List.of(new EqualityConstraint(gammaxsr.getRankCoefficientOrDefine(x1), gammaxq.getRankCoefficient(x), ruleName(obligation) + " r_{m+1} = q_{m+1} (for var " + x1 + ")"), new EqualityConstraint(gammaxsr.getRankCoefficientOrDefine(x3), gammaxq.getRankCoefficient(x), ruleName(obligation) + " r_{m+2} = q_{m+1} (for var " + x3 + ")"), new EqualityConstraint(gammaxsr.getCoefficientOrDefine(id -> id.equals(x1) ? 1 : 0, 0), gammaxq.getRankCoefficient(x), ruleName(obligation) + " r_{(0,...,0,1,0,0)} = q_{m+1}"), new EqualityConstraint(gammaxsr.getCoefficientOrDefine(id -> id.equals(x3) ? 1 : 0, 0), gammaxq.getRankCoefficient(x), ruleName(obligation) + " r_{(0,...,0,0,1,0)} = q_{m+1}")));
    gammaxq.streamNonRank().map(qEntry -> {
        final var a = qEntry.getAssociatedIndex(x);
        return new EqualityConstraint(gammaxsr.getCoefficientOrDefine(qEntry.mask(x1, a).mask(x3, a)), qEntry.getValue(), ruleName(obligation) + " r_{a⃗⃗,a,a,b} = q_{a⃗⃗,a,b} for expression " + expression);
    }).forEach(rConstraints::add);
    for (var id : gammaxq.getIds()) {
        if (id.equals(x)) {
            continue;
        }
        rConstraints.add(new EqualityConstraint(gammaxq.getRankCoefficient(id), gammaxsr.getRankCoefficientOrDefine(id), ruleName(obligation) + " q_i = r_i"));
    }
    return new Rule.ApplicationResult(List.of(obligation.keepAnnotationAndCost(gammap, expression.getLeaf()), obligation.keepAnnotationAndCost(gammaxsr, expression.getNode())), List.of(pConstraints, rConstraints));
}
Also used : MatchTreeExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.MatchTreeExpression) Collections.emptyList(java.util.Collections.emptyList) EqualityConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualityConstraint) Obligation(xyz.leutgeb.lorenz.atlas.typing.resources.proving.Obligation) EqualsSumConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualsSumConstraint) HashMap(java.util.HashMap) Constraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.Constraint) IdentifierExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression) AnnotatingGlobals(xyz.leutgeb.lorenz.atlas.typing.resources.AnnotatingGlobals) ArrayList(java.util.ArrayList) AnnotatingContext(xyz.leutgeb.lorenz.atlas.typing.resources.AnnotatingContext) List(java.util.List) Map(java.util.Map) NodeExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.NodeExpression) Coefficient(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.Coefficient) Annotation(xyz.leutgeb.lorenz.atlas.typing.resources.Annotation) Coefficient(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.Coefficient) HashMap(java.util.HashMap) EqualsSumConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualsSumConstraint) ArrayList(java.util.ArrayList) EqualityConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualityConstraint) EqualsSumConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualsSumConstraint) Constraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.Constraint) EqualityConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualityConstraint) IdentifierExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression) MatchTreeExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.MatchTreeExpression)

Example 3 with IdentifierExpression

use of xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression in project atlas by lorenzleutgeb.

the class Assertions method assertContextEqualsByPrefixes.

public static <V> V assertContextEqualsByPrefixes(List<String> expectedIds, Annotation expectedAnnotation, AnnotatingContext actual) {
    Set<IdentifierExpression> actualIds = new HashSet<>(actual.getIds());
    List<IdentifierExpression> matchedIds = new ArrayList<>(actual.size());
    outer: for (String expectedId : expectedIds) {
        for (Iterator<IdentifierExpression> iterator = actualIds.iterator(); iterator.hasNext(); ) {
            final IdentifierExpression actualId = iterator.next();
            if (actualId.getName().startsWith(expectedId)) {
                matchedIds.add(actualId);
                iterator.remove();
                continue outer;
            }
        }
    }
    return assertContextEquals(new AnnotatingContext(matchedIds, expectedAnnotation), actual);
}
Also used : AnnotatingContext(xyz.leutgeb.lorenz.atlas.typing.resources.AnnotatingContext) ArrayList(java.util.ArrayList) Iterator(java.util.Iterator) IdentifierExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression) HashSet(java.util.HashSet)

Example 4 with IdentifierExpression

use of xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression in project atlas by lorenzleutgeb.

the class Node method apply.

public Rule.ApplicationResult apply(Obligation obligation, AnnotatingGlobals globals, Map<String, String> arguments) {
    final var expression = (NodeExpression) obligation.getExpression();
    final var leftId = ((IdentifierExpression) expression.getLeft());
    final var rightId = ((IdentifierExpression) expression.getRight());
    final var qunordered = obligation.getContext();
    final var missing = Sets.difference(Set.of(leftId, rightId), Set.copyOf(qunordered.getIds()));
    if (!missing.isEmpty()) {
        throw bug("missing variable(s) in context: " + missing);
    }
    final var prefix = "(node `" + expression + "`) ";
    // We reorder the context such that it matches the syntax.
    final var q = qunordered.reorder(List.of(leftId, rightId)).getAnnotation();
    Annotation qp = obligation.getAnnotation();
    final var rankCoefficient = qp.getRankCoefficientOrZero(0);
    // Rank coefficient is covered, we will however check on non-rank coefficients.
    final var occurred = new HashSet<Coefficient>();
    final var constraints = new ArrayList<Constraint>();
    q.streamNonRankCoefficients().filter(qEntry -> qEntry.getKey().get(0).equals(qEntry.getKey().get(1))).filter(qEntry -> {
        var a = qEntry.getKey().get(0);
        var c = qEntry.getKey().get(2);
        return a + c > 0;
    }).map(qEntry -> {
        var a = qEntry.getKey().get(0);
        var c = qEntry.getKey().get(2);
        Coefficient qpCoeff = qp.getCoefficientOrZero(List.of(a, c));
        occurred.add(qpCoeff);
        return new EqualityConstraint(q.getCoefficientOrZero(a, a, c), qpCoeff, prefix + "q_{(a,a,c)} = q'_{(a,c)}" + " with (a,a,c)=" + toVectorString(qEntry.getKey()));
    }).forEach(constraints::add);
    constraints.add(new EqualityConstraint(q.getRankCoefficientOrZero(0), q.getRankCoefficientOrZero(1), prefix + "q₀ = q₁"));
    constraints.add(new EqualityConstraint(q.getRankCoefficientOrZero(1), rankCoefficient, prefix + "q₂ = q'₀"));
    constraints.add(new EqualityConstraint(q.getCoefficientOrZero(1, 0, 0), rankCoefficient, prefix + "q₍₁ ₀ ₀₎ = q'₀"));
    constraints.add(new EqualityConstraint(q.getCoefficientOrZero(0, 1, 0), rankCoefficient, prefix + "q₍₀ ₁ ₀₎ = q'₀"));
    qp.streamNonRankCoefficients().filter(entry -> !occurred.contains(entry.getValue())).map(x -> new EqualityConstraint(x.getValue(), ZERO, prefix + "setToZero " + x.getKey())).forEach(constraints::add);
    return Rule.ApplicationResult.onlyConstraints(constraints);
}
Also used : Util.toVectorString(xyz.leutgeb.lorenz.atlas.util.Util.toVectorString) EqualityConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualityConstraint) Obligation(xyz.leutgeb.lorenz.atlas.typing.resources.proving.Obligation) Set(java.util.Set) Constraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.Constraint) Util.bug(xyz.leutgeb.lorenz.atlas.util.Util.bug) IdentifierExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression) Sets(com.google.common.collect.Sets) AnnotatingGlobals(xyz.leutgeb.lorenz.atlas.typing.resources.AnnotatingGlobals) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) List(java.util.List) Map(java.util.Map) NodeExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.NodeExpression) Coefficient(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.Coefficient) Annotation(xyz.leutgeb.lorenz.atlas.typing.resources.Annotation) ZERO(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.KnownCoefficient.ZERO) Coefficient(xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.Coefficient) NodeExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.NodeExpression) ArrayList(java.util.ArrayList) Annotation(xyz.leutgeb.lorenz.atlas.typing.resources.Annotation) EqualityConstraint(xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualityConstraint) HashSet(java.util.HashSet)

Example 5 with IdentifierExpression

use of xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression in project atlas by lorenzleutgeb.

the class Run method run.

@Override
public void run() {
    final var start = Instant.now();
    Loader loader = Loader.atDefaultHome();
    /*
    try {
      loader.autoload();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }*/
    Program program;
    try {
        program = loader.load(fqns);
    // program = loader.loadMatching(pattern);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    if (name != null && !name.isBlank()) {
        program.setName(name);
    }
    if (program.isEmpty()) {
        System.out.println("Program to analyze is empty, nothing to do!");
        System.exit(3);
    }
    program.normalize();
    if (!program.infer()) {
        return;
    }
    program.unshare(true);
    program.analyzeSizes();
    // log.info("Loaded definitions:");
    // program.printAllSimpleSignaturesInOrder(System.out);
    System.out.println("Output Directory: " + program.getBasePath().toAbsolutePath());
    System.out.println();
    Map<String, Path> tacticsMap = new HashMap<>();
    // log.info(infer ? "Given for comparison:" : "Will check following types:");
    log.info("Manual tactics disabled. All tactics will be automatically generated.");
    System.out.println("Function Definitions:");
    for (int i = 0; i < program.getOrder().size(); i++) {
        final var stratum = program.getOrder().get(i);
        for (var fqn : stratum) {
            FunctionDefinition fd = program.getFunctionDefinitions().get(fqn);
            if (tactics != null) {
                var path = tactics.resolve(fd.getModuleName().replace(".", "/") + "/" + fd.getName() + ".txt");
                if (Files.exists(path) && Files.isReadable(path)) {
                    tacticsMap.put(fd.getFullyQualifiedName(), path);
                }
            }
            System.out.println(fd.getAnnotatedSignatureString());
            // log.info("\tDependencies: " + fd.getOcurringFunctionsNonRecursive());
            System.out.println("\tSource:       " + fd.getBody().getSource().getRoot());
            System.out.println("\tBound:        " + fd.getAnnotatedSignature().getAnnotation().map(a -> a.getBounds(fd.treeLikeArguments().stream().map(IdentifierExpression::getName).toList())).orElse("?"));
            if (tactics != null) {
                final var p = tacticsMap.get(fd.getFullyQualifiedName());
                if (p == null) {
                    System.out.println("\tTactic:       n/a (will be automatically generated)");
                } else {
                    System.out.println("\tTactic:       " + p.toAbsolutePath());
                }
            }
        }
    }
    System.out.println();
    System.setProperty(Util.getPropertyName(Prover.class, "tickAst"), useTickAst.toString());
    final var result = program.solve(new HashMap<>(), tacticsMap, infer, consistentModules, equalRanks, simpleAnnotations, !infer, Collections.emptySet());
    final var stop = Instant.now();
    System.out.println("Elapsed Walltime: " + Duration.between(start, stop));
    System.out.println();
    if (Status.UNSATISFIABLE.equals(result.getStatus())) {
        System.out.println("UNSAT");
        System.exit(1);
    } else if (Status.UNKNOWN.equals(result.getStatus())) {
        System.out.println("UNKNOWN");
        System.exit(2);
    } else if (Status.SATISFIABLE.equals(result.getStatus())) {
        if (!infer) {
            System.out.println("SAT");
            System.out.println();
        } else {
            System.out.println("Results:");
            program.printAllInferredAnnotationsAndBoundsInOrder(System.out);
            System.out.println();
        }
    } else {
        throw new RuntimeException("encountered unknown status");
    }
    /*
    if (json != null) {
      JsonObjectBuilder builder = Json.createObjectBuilder();

      builder.add("result", program.inferredSignaturesToJson());
      builder.add("duration", Json.createValue(Duration.between(start, stop).toString()));

      JsonObjectBuilder z3ObjectBuilder = Json.createObjectBuilder();
      z3ObjectBuilder.add("status", Json.createValue(result.getStatus().toString()));

      JsonObjectBuilder z3StatisticsBuilder = Json.createObjectBuilder();
      result.getStatistics().forEach(z3StatisticsBuilder::add);
      z3ObjectBuilder.add("statistics", z3StatisticsBuilder.build());

      if (result.getSmtFile().isPresent()) {
        z3ObjectBuilder.add("file", Json.createValue(result.getSmtFile().get().toString()));
      }

      builder.add("z3", z3ObjectBuilder.build());

      log.info("Writing JSON output to {}", json);
      try (final var out = output(json)) {
        Json.createWriter(out).writeObject(builder.build());
      } catch (IOException ioException) {
        log.error("Failed to write JSON output.", ioException);
      }
    }
     */
    // System.exit(result.toExitCode());
    System.exit(0);
}
Also used : Path(java.nio.file.Path) Program(xyz.leutgeb.lorenz.atlas.ast.Program) Files(java.nio.file.Files) FunctionDefinition(xyz.leutgeb.lorenz.atlas.ast.FunctionDefinition) Loader(xyz.leutgeb.lorenz.atlas.module.Loader) Util(xyz.leutgeb.lorenz.atlas.util.Util) Set(java.util.Set) IOException(java.io.IOException) HashMap(java.util.HashMap) Instant(java.time.Instant) IdentifierExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression) Slf4j(lombok.extern.slf4j.Slf4j) Prover(xyz.leutgeb.lorenz.atlas.typing.resources.proving.Prover) Duration(java.time.Duration) Map(java.util.Map) Status(com.microsoft.z3.Status) Path(java.nio.file.Path) Collections(java.util.Collections) CommandLine(picocli.CommandLine) Program(xyz.leutgeb.lorenz.atlas.ast.Program) HashMap(java.util.HashMap) Prover(xyz.leutgeb.lorenz.atlas.typing.resources.proving.Prover) Loader(xyz.leutgeb.lorenz.atlas.module.Loader) IOException(java.io.IOException) IdentifierExpression(xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression) FunctionDefinition(xyz.leutgeb.lorenz.atlas.ast.FunctionDefinition)

Aggregations

IdentifierExpression (xyz.leutgeb.lorenz.atlas.ast.expressions.IdentifierExpression)5 ArrayList (java.util.ArrayList)3 Map (java.util.Map)3 AnnotatingContext (xyz.leutgeb.lorenz.atlas.typing.resources.AnnotatingContext)3 AnnotatingGlobals (xyz.leutgeb.lorenz.atlas.typing.resources.AnnotatingGlobals)3 Annotation (xyz.leutgeb.lorenz.atlas.typing.resources.Annotation)3 Coefficient (xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.Coefficient)3 Constraint (xyz.leutgeb.lorenz.atlas.typing.resources.constraints.Constraint)3 EqualityConstraint (xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualityConstraint)3 Obligation (xyz.leutgeb.lorenz.atlas.typing.resources.proving.Obligation)3 Sets (com.google.common.collect.Sets)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 List (java.util.List)2 Set (java.util.Set)2 NodeExpression (xyz.leutgeb.lorenz.atlas.ast.expressions.NodeExpression)2 ZERO (xyz.leutgeb.lorenz.atlas.typing.resources.coefficients.KnownCoefficient.ZERO)2 EqualsSumConstraint (xyz.leutgeb.lorenz.atlas.typing.resources.constraints.EqualsSumConstraint)2 Util (xyz.leutgeb.lorenz.atlas.util.Util)2 Sets.cartesianProduct (com.google.common.collect.Sets.cartesianProduct)1