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

hu.bme.mit.theta.solver.javasmt.JavaSMTUserPropagator Maven / Gradle / Ivy

/*
 *  Copyright 2024 Budapest University of Technology and Economics
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package hu.bme.mit.theta.solver.javasmt;

import hu.bme.mit.theta.core.type.Expr;
import hu.bme.mit.theta.core.type.booltype.BoolType;
import org.sosy_lab.java_smt.api.BooleanFormula;
import org.sosy_lab.java_smt.api.Formula;
import org.sosy_lab.java_smt.api.PropagatorBackend;
import org.sosy_lab.java_smt.basicimpl.AbstractUserPropagator;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

import static com.google.common.base.Preconditions.checkState;
import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool;
import static hu.bme.mit.theta.core.utils.TypeUtils.cast;

public abstract class JavaSMTUserPropagator extends AbstractUserPropagator {
    private Function, Formula> toTerm;
    private Function> toExpr;
    private final Map, BooleanFormula> registeredTerms;

    protected JavaSMTUserPropagator() {
        super();
        registeredTerms = new LinkedHashMap<>();
    }

    final void setToTerm(final Function, Formula> toTerm) {
        this.toTerm = toTerm;
    }

    final void setToExpr(final Function> toExpr) {
        this.toExpr = toExpr;
    }

    @Override
    protected final PropagatorBackend getBackend() {
        return super.getBackend();
    }

    /**
     * Gets called when the solver decides on the value for a bool expression.
     * Can call propagate* calls from here.
     * When overriding, no need to call super.
     *
     * @param expr  The expression for which a value became available
     * @param value The value of the expression
     */
    public void onKnownValue(final Expr expr, final boolean value) {
    }

    @Override
    public final void onKnownValue(final BooleanFormula expr, final boolean value) {
        super.onKnownValue(expr, value);
        final var entry = registeredTerms.entrySet().stream().filter(e -> e.getValue().equals(expr)).findAny();
        final var tExpr = entry.isPresent() ? entry.get().getKey() : cast(toExpr.apply(expr), Bool());
        onKnownValue(tExpr, value);
    }

    /**
     * Gets called when a branching is done on a registered expression.
     * Change the decision by calling propagateNextDecision.
     *
     * @param expr
     * @param value
     */
    public void onDecision(final Expr expr, final boolean value) {
    }

    @Override
    public final void onDecision(final BooleanFormula expr, final boolean value) {
        super.onDecision(expr, value);
        final var tExpr = cast(toExpr.apply(expr), Bool());
        onDecision(tExpr, value);
    }

    @Override
    public final void initializeWithBackend(final PropagatorBackend pBackend) {
        super.initializeWithBackend(pBackend);
        getBackend().notifyOnFinalCheck();
        getBackend().notifyOnKnownValue();
        getBackend().notifyOnDecision();
    }

    /**
     * Register an expression with the propagator. Does NOT add it to the solver.
     *
     * @param expr The expression to register
     */
    public void registerExpression(final Expr expr) {
        final BooleanFormula booleanFormula = (BooleanFormula) toTerm.apply(expr);
        registeredTerms.put(expr, booleanFormula);
        registerExpression(booleanFormula);
    }

    @Override
    public final void registerExpression(final BooleanFormula theoryExpr) {
        super.registerExpression(theoryExpr);
    }

    public final void propagateConflict(final List> exprs) {
        final var terms = exprs.stream().map(registeredTerms::get).toArray(BooleanFormula[]::new);
        checkState(Arrays.stream(terms).noneMatch(Objects::isNull));
        getBackend().propagateConflict(terms);
    }

    public final void propagateConsequence(final List> exprs, final Expr consequence) {
        final var terms = exprs.stream().map(registeredTerms::get).toArray(BooleanFormula[]::new);
        for (var expr : exprs) {
            if (registeredTerms.get(expr) == null) {
                System.err.println(expr);
            }
        }
        checkState(Arrays.stream(terms).noneMatch(Objects::isNull), "Registered terms failed to look up one or more expressions from %s. Registered terms: %s", exprs, registeredTerms.keySet());
        final BooleanFormula consequenceTerm = (BooleanFormula) toTerm.apply(consequence);
        getBackend().propagateConsequence(terms, consequenceTerm);
    }

    public final boolean propagateNextDecision(final Expr formula, Optional optional) {
        final BooleanFormula term = (BooleanFormula) toTerm.apply(formula);
        return getBackend().propagateNextDecision(term, optional);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy