Skip to content

Commit

Permalink
DNNF timeout handler and pass handlers to factory and model counter
Browse files Browse the repository at this point in the history
  • Loading branch information
czengler committed Jun 16, 2024
1 parent 9bccf64 commit fc5b142
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: Apache-2.0 and MIT
// Copyright 2015-2023 Christoph Zengler
// Copyright 2023-20xx BooleWorks GmbH

package com.booleworks.logicng.handlers;

/**
* A DNNF handler which cancels the compilation process after a given timeout.
* @version 3.0.0
* @since 3.0.0
*/
public class TimeoutDnnfHandler extends TimeoutHandler implements DnnfCompilationHandler {

/**
* Constructs a new timeout handler with a given timeout and a timeout type.
* The interpretation of the timeout depends on the timeout type:
* <ul>
* <li>{@link TimerType#SINGLE_TIMEOUT}: The timeout is started when
* {@link Handler#started()} is called. Further calls to
* {@link Handler#started()} have no effect on the timeout. Thus, the
* timeout can only be started once.</li>
* <li>{@link TimerType#RESTARTING_TIMEOUT}: The timeout is restarted when
* {@link Handler#started()} is called.</li>
* <li>{@link TimerType#FIXED_END}: Timeout which is interpreted as fixed
* point in time (in milliseconds) at which the computation should be
* aborted. The method {@link Handler#started()} must still be called, but
* does not have an effect on the timeout.</li>
* </ul>
* @param timeout the timeout in milliseconds, its meaning is defined by the
* timeout type
* @param type the type of the timer, must not be {@code null}
*/
public TimeoutDnnfHandler(final long timeout, final TimerType type) {
super(timeout, type);
}

/**
* Constructs a new timeout handler with a given timeout and uses the
* timeout type {@link TimerType#SINGLE_TIMEOUT}. Thus, the timeout is
* started when {@link Handler#started()} is called and further calls to
* {@link Handler#started()} have no effect on the timeout.
* @param timeout the timeout in milliseconds
*/
public TimeoutDnnfHandler(final long timeout) {
super(timeout);
}

@Override
public boolean shannonExpansion() {
return !timeLimitExceeded();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.booleworks.logicng.formulas.Formula;
import com.booleworks.logicng.formulas.FormulaFactory;
import com.booleworks.logicng.formulas.Variable;
import com.booleworks.logicng.handlers.DnnfCompilationHandler;
import com.booleworks.logicng.knowledgecompilation.dnnf.datastructures.Dnnf;
import com.booleworks.logicng.knowledgecompilation.dnnf.datastructures.dtree.MinFillDTreeGenerator;
import com.booleworks.logicng.transformations.cnf.CNFSubsumption;
Expand All @@ -24,18 +25,28 @@ public class DnnfFactory {

/**
* Compiles the given formula to a DNNF instance.
* @param f the formula factory to generate new formulas
* @param formula the formula
* @return the compiled DNNF
*/
public Dnnf compile(final FormulaFactory f, final Formula formula) {
return compile(f, formula, null);
}

/**
* Compiles the given formula to a DNNF instance.
* @param f the formula factory to generate new formulas
* @param formula the formula
* @param handler the DNNF handler
* @return the compiled DNNF
*/
public Dnnf compile(final FormulaFactory f, final Formula formula, final DnnfCompilationHandler handler) {
final SortedSet<Variable> originalVariables = new TreeSet<>(formula.variables(f));
final Formula cnf = formula.cnf(f);
originalVariables.addAll(cnf.variables(f));
final Formula simplifiedFormula = simplifyFormula(f, cnf);
final DnnfCompiler compiler = new DnnfCompiler(f, simplifiedFormula);
final Formula dnnf = compiler.compile(new MinFillDTreeGenerator());
return new Dnnf(originalVariables, dnnf);
final Formula dnnf = compiler.compile(new MinFillDTreeGenerator(), handler);
return dnnf == null ? null : new Dnnf(originalVariables, dnnf);
}

protected Formula simplifyFormula(final FormulaFactory f, final Formula formula) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

package com.booleworks.logicng.modelcounting;

import static com.booleworks.logicng.handlers.Handler.aborted;

import com.booleworks.logicng.datastructures.Assignment;
import com.booleworks.logicng.formulas.FType;
import com.booleworks.logicng.formulas.Formula;
Expand All @@ -14,6 +16,7 @@
import com.booleworks.logicng.graphs.datastructures.Graph;
import com.booleworks.logicng.graphs.datastructures.Node;
import com.booleworks.logicng.graphs.generators.ConstraintGraphGenerator;
import com.booleworks.logicng.handlers.DnnfCompilationHandler;
import com.booleworks.logicng.knowledgecompilation.dnnf.DnnfFactory;
import com.booleworks.logicng.knowledgecompilation.dnnf.datastructures.Dnnf;
import com.booleworks.logicng.knowledgecompilation.dnnf.functions.DnnfModelCountFunction;
Expand All @@ -29,6 +32,7 @@
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
Expand All @@ -46,17 +50,32 @@ private ModelCounter() {
}

/**
* Computes the model count for a given set of formulas (interpreted as
* conjunction) and a set of relevant variables. This set can only be a
* superset of the original formulas' variables. No projected model counting
* is supported.
* Computes the model count for a given set of formulas (interpreted as conjunction)
* and a set of relevant variables. This set can only be a superset of the original
* formulas' variables. No projected model counting is supported.
* @param f the formula factory to generate new formulas
* @param formulas the list of formulas
* @param variables the relevant variables
* @return the model count of the formulas for the variables
*/
public static BigInteger count(final FormulaFactory f, final Collection<Formula> formulas,
final SortedSet<Variable> variables) {
public static BigInteger count(final FormulaFactory f, final Collection<Formula> formulas, final SortedSet<Variable> variables) {
return count(f, formulas, variables, () -> null);
}

/**
* Computes the model count for a given set of formulas (interpreted as conjunction)
* and a set of relevant variables. This set can only be a superset of the original
* formulas' variables. No projected model counting is supported.
* @param f the formula factory to generate new formulas
* @param formulas the list of formulas
* @param variables the relevant variables
* @param dnnfHandlerSupplier a supplier for a DNNF handler, it may return a new handler on each call or always the same.
* Since multiple DNNFs may be computed, the supplier may be called several times. It must not
* be {@code null}, but it may return {@code null} (i.e. return no handler).
* @return the model count of the formulas for the variables or {@code null} if the DNNF handler aborted the DNNF computation
*/
public static BigInteger count(final FormulaFactory f, final Collection<Formula> formulas, final SortedSet<Variable> variables,
final Supplier<DnnfCompilationHandler> dnnfHandlerSupplier) {
if (!variables.containsAll(FormulaHelper.variables(f, formulas))) {
throw new IllegalArgumentException("Expected variables to contain all of the formulas' variables.");
}
Expand All @@ -67,7 +86,10 @@ public static BigInteger count(final FormulaFactory f, final Collection<Formula>
}
final List<Formula> cnfs = encodeAsCnf(f, formulas);
final SimplificationResult simplification = simplify(f, cnfs);
final BigInteger count = count(f, simplification.simplifiedFormulas);
final BigInteger count = count(f, simplification.simplifiedFormulas, dnnfHandlerSupplier);
if (count == null) {
return null;
}
final SortedSet<Variable> dontCareVariables = simplification.getDontCareVariables(variables);
return count.multiply(BigInteger.valueOf(2).pow(dontCareVariables.size()));
}
Expand Down Expand Up @@ -104,15 +126,19 @@ private static SimplificationResult simplify(final FormulaFactory f, final Colle
return new SimplificationResult(f, backboneVariables, simplified);
}

private static BigInteger count(final FormulaFactory f, final Collection<Formula> formulas) {
private static BigInteger count(final FormulaFactory f, final Collection<Formula> formulas,
final Supplier<DnnfCompilationHandler> dnnfHandlerSupplier) {
final Graph<Variable> constraintGraph = ConstraintGraphGenerator.generateFromFormulas(f, formulas);
final Set<Set<Node<Variable>>> ccs = ConnectedComponentsComputation.compute(constraintGraph);
final List<List<Formula>> components =
ConnectedComponentsComputation.splitFormulasByComponent(f, formulas, ccs);
final List<List<Formula>> components = ConnectedComponentsComputation.splitFormulasByComponent(f, formulas, ccs);
final DnnfFactory factory = new DnnfFactory();
BigInteger count = BigInteger.ONE;
for (final List<Formula> component : components) {
final Dnnf dnnf = factory.compile(f, f.and(component));
final DnnfCompilationHandler handler = dnnfHandlerSupplier.get();
final Dnnf dnnf = factory.compile(f, f.and(component), handler);
if (dnnf == null || aborted(handler)) {
return null;
}
count = count.multiply(dnnf.execute(new DnnfModelCountFunction(f)));
}
return count;
Expand Down

0 comments on commit fc5b142

Please sign in to comment.