Skip to content

Commit dfa2850

Browse files
committed
Merge branch 'development'
2 parents 7d852d0 + 3066329 commit dfa2850

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1085
-180
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![wercker status](https://app.wercker.com/status/24c4765f3a0d79520ad80a1e4c20cfa2/s/master "wercker status")](https://app.wercker.com/project/bykey/24c4765f3a0d79520ad80a1e4c20cfa2) [![Coverage Status](https://coveralls.io/repos/logic-ng/LogicNG/badge.svg?branch=master&service=github)](https://coveralls.io/github/logic-ng/LogicNG?branch=master) ![License](https://img.shields.io/badge/license-Apache%202-blue.svg) ![Version](https://img.shields.io/badge/version-1.6.1-ff69b4.svg)
1+
[![wercker status](https://app.wercker.com/status/24c4765f3a0d79520ad80a1e4c20cfa2/s/master "wercker status")](https://app.wercker.com/project/bykey/24c4765f3a0d79520ad80a1e4c20cfa2) [![Coverage Status](https://coveralls.io/repos/logic-ng/LogicNG/badge.svg?branch=master&service=github)](https://coveralls.io/github/logic-ng/LogicNG?branch=master) ![License](https://img.shields.io/badge/license-Apache%202-blue.svg) ![Version](https://img.shields.io/badge/version-1.6.2-ff69b4.svg)
22

33
<img src="https://github.com/logic-ng/LogicNG/blob/master/doc/logo/logo_big.png" alt="logo" width="300">
44

@@ -19,7 +19,7 @@ LogicNG is released in the Maven Central Repository. To include it just add
1919
<dependency>
2020
<groupId>org.logicng</groupId>
2121
<artifactId>logicng</artifactId>
22-
<version>1.6.1</version>
22+
<version>1.6.2</version>
2323
</dependency>
2424
```
2525
to your Maven POM.
@@ -62,6 +62,11 @@ We recently started a Wiki section for a [FAQ](https://github.com/logic-ng/Logic
6262
The library is released under the Apache License and therefore is free to use in any private, educational, or commercial projects. Commercial support is available through the German company [BooleWorks GmbH](http://www.booleworks.com) - the company behind LogicNG. Please contact Christoph Zengler at christoph@logicng.org for further details.
6363

6464
## Changelog
65+
66+
### Version 1.6.2 (Release January 2020)
67+
* Some improvements to handlers for computations
68+
* New BDD handlers
69+
6570
### Version 1.6.1 (Release September 2019)
6671
* A new method for solving a formula with a given literal ordering.
6772
* Minor refactoring of the Formatter super class (no effects on callers).

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<modelVersion>4.0.0</modelVersion>
2727
<groupId>org.logicng</groupId>
2828
<artifactId>logicng</artifactId>
29-
<version>1.6.1</version>
29+
<version>1.6.2</version>
3030
<packaging>jar</packaging>
3131

3232
<name>LogicNG</name>

src/main/java/org/logicng/bdds/BDDFactory.java

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@
5757

5858
package org.logicng.bdds;
5959

60-
import static org.logicng.formulas.FType.AND;
61-
6260
import org.logicng.bdds.datastructures.BDD;
6361
import org.logicng.bdds.datastructures.BDDConstant;
6462
import org.logicng.bdds.datastructures.BDDInnerNode;
@@ -67,12 +65,15 @@
6765
import org.logicng.collections.LNGVector;
6866
import org.logicng.datastructures.Assignment;
6967
import org.logicng.formulas.Equivalence;
68+
import org.logicng.formulas.FType;
7069
import org.logicng.formulas.Formula;
7170
import org.logicng.formulas.FormulaFactory;
7271
import org.logicng.formulas.Implication;
7372
import org.logicng.formulas.Literal;
7473
import org.logicng.formulas.Not;
7574
import org.logicng.formulas.Variable;
75+
import org.logicng.handlers.BDDHandler;
76+
import org.logicng.handlers.TimeoutHandler;
7677

7778
import java.math.BigDecimal;
7879
import java.util.ArrayList;
@@ -91,7 +92,7 @@
9192

9293
/**
9394
* The factory for the jBuddy implementation.
94-
* @version 1.4.0
95+
* @version 1.6.2
9596
* @since 1.4.0
9697
*/
9798
public class BDDFactory {
@@ -135,15 +136,41 @@ protected BDDFactory(final BDDKernel kernel, final FormulaFactory f) {
135136
* @return the top node of the BDD
136137
*/
137138
public BDD build(final Formula formula) {
138-
return new BDD(buildRec(formula), this);
139+
return build(formula, null);
140+
}
141+
142+
/**
143+
* Builds a BDD for a given formula. BDDs support all Boolean formula types but not pseudo-Boolean constraints.
144+
* The reason is that before converting a formula to a BDD one must specify the number of variables. In case of
145+
* pseudo-Boolean constraints this number depends on the translation of the constraint. Therefore the caller first
146+
* has to transform any pseudo-Boolean constraints in their respective CNF representation before converting them
147+
* to a BDD.
148+
*
149+
* If a BDD handler is given and the BDD generation is aborted due to the handler, the method will return
150+
* {@link BDDKernel#BDD_ABORT} as result. If {@code null} is passed as handler, the generation will continue without
151+
* interruption.
152+
* @param formula the formula
153+
* @param handler the BDD handler
154+
* @return the top node of the BDD or {@link BDDKernel#BDD_ABORT} if the computation was aborted
155+
*/
156+
public BDD build(final Formula formula, final BDDHandler handler) {
157+
if (handler != null) {
158+
handler.started();
159+
}
160+
return new BDD(buildRec(formula, handler), this);
139161
}
140162

141163
/**
142164
* Recursive build procedure for the BDD.
165+
*
166+
* If a BDD handler is given and the BDD generation is aborted due to the handler, the method will return
167+
* {@link BDDKernel#BDD_ABORT} as result. If {@code null} is passed as handler, the generation will continue without
168+
* interruption.
143169
* @param formula the formula
144-
* @return the BDD index
170+
* @param handler the BDD handler
171+
* @return the BDD index or {@link BDDKernel#BDD_ABORT} if the computation was aborted
145172
*/
146-
private int buildRec(final Formula formula) {
173+
private int buildRec(final Formula formula, final BDDHandler handler) {
147174
switch (formula.type()) {
148175
case FALSE:
149176
return BDDKernel.BDD_FALSE;
@@ -158,26 +185,59 @@ private int buildRec(final Formula formula) {
158185
this.idx2var.put(idx, lit.variable());
159186
}
160187
return lit.phase() ? this.kernel.ithVar(idx) : this.kernel.nithVar(idx);
161-
case NOT:
188+
case NOT: {
162189
final Not not = (Not) formula;
163-
return this.kernel.addRef(this.kernel.not(buildRec(not.operand())));
164-
case IMPL:
190+
final int operand = buildRec(not.operand(), handler);
191+
if (operand == BDDKernel.BDD_ABORT) {
192+
return BDDKernel.BDD_ABORT;
193+
} else {
194+
return this.kernel.addRef(this.kernel.not(operand), handler);
195+
}
196+
}
197+
case IMPL: {
165198
final Implication impl = (Implication) formula;
166-
return this.kernel.addRef(this.kernel.implication(buildRec(impl.left()), buildRec(impl.right())));
167-
case EQUIV:
199+
final int left = buildRec(impl.left(), handler);
200+
if (left == BDDKernel.BDD_ABORT) {
201+
return BDDKernel.BDD_ABORT;
202+
}
203+
final int right = buildRec(impl.right(), handler);
204+
if (right == BDDKernel.BDD_ABORT) {
205+
return BDDKernel.BDD_ABORT;
206+
}
207+
return this.kernel.addRef(this.kernel.implication(left, right), handler);
208+
}
209+
case EQUIV: {
168210
final Equivalence equiv = (Equivalence) formula;
169-
return this.kernel.addRef(this.kernel.equivalence(buildRec(equiv.left()), buildRec(equiv.right())));
211+
final int left = buildRec(equiv.left(), handler);
212+
if (left == BDDKernel.BDD_ABORT) {
213+
return BDDKernel.BDD_ABORT;
214+
}
215+
final int right = buildRec(equiv.right(), handler);
216+
if (right == BDDKernel.BDD_ABORT) {
217+
return BDDKernel.BDD_ABORT;
218+
}
219+
return this.kernel.addRef(this.kernel.equivalence(left, right), handler);
220+
}
170221
case AND:
171-
case OR:
222+
case OR: {
172223
final Iterator<Formula> it = formula.iterator();
173-
int res = buildRec(it.next());
174-
while (it.hasNext())
175-
res = formula.type() == AND
176-
? this.kernel.addRef(this.kernel.and(res, buildRec(it.next())))
177-
: this.kernel.addRef(this.kernel.or(res, buildRec(it.next())));
224+
int res = buildRec(it.next(), handler);
225+
if (res == BDDKernel.BDD_ABORT) {
226+
return BDDKernel.BDD_ABORT;
227+
}
228+
while (it.hasNext()) {
229+
final int operand = buildRec(it.next(), handler);
230+
if (operand == BDDKernel.BDD_ABORT) {
231+
return BDDKernel.BDD_ABORT;
232+
}
233+
res = formula.type() == FType.AND
234+
? this.kernel.addRef(this.kernel.and(res, operand), handler)
235+
: this.kernel.addRef(this.kernel.or(res, operand), handler);
236+
}
178237
return res;
238+
}
179239
case PBC:
180-
return buildRec(formula.nnf());
240+
return buildRec(formula.nnf(), handler);
181241
default:
182242
throw new IllegalArgumentException("Unsupported operator for BDD generation: " + formula.type());
183243
}

src/main/java/org/logicng/bdds/jbuddy/BDDKernel.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757

5858
package org.logicng.bdds.jbuddy;
5959

60+
import org.logicng.handlers.BDDHandler;
61+
6062
import java.math.BigDecimal;
6163
import java.util.ArrayList;
6264
import java.util.Arrays;
@@ -65,11 +67,12 @@
6567

6668
/**
6769
* The jBuddy kernel.
68-
* @version 1.4.0
70+
* @version 1.6.2
6971
* @since 1.4.0
7072
*/
7173
public class BDDKernel {
7274

75+
public static final int BDD_ABORT = -1;
7376
public static final int BDD_TRUE = 1;
7477
public static final int BDD_FALSE = 0;
7578

@@ -115,7 +118,7 @@ private enum Operand {
115118
protected int varnum; // Number of defined BDD variables
116119
private int[] refstack; // Internal node reference stack
117120
private int refstacktop; // Internal node reference stack top
118-
protected int[] level2var; // Level -> variable table
121+
protected int[] level2var; // Level -> variable table
119122

120123
private int[] quantvarset; // Current variable set for quant.
121124
private int quantvarsetID; // Current id used in quantvarset
@@ -391,12 +394,17 @@ private int notRec(final int r) {
391394
/**
392395
* Adds a reference for a given node. Reference counting is done on externally referenced nodes only and the count for
393396
* a specific node {@code r} can and must be increased using this function to avoid loosing the node in the next
394-
* garbage collection.
395-
* @param root the node
397+
* garbage collection. If a BDD handler is given, the handler's {@link BDDHandler#newRefAdded()} method is called.
398+
* If the generation gets aborted due to the handler, the method will return {@link BDDKernel#BDD_ABORT} as result. If
399+
* {@code null} is passed as handler, the generation will continue without interruption.
400+
* @param root the node
401+
* @param handler the BDD handler
396402
* @return return the node
397403
* @throws IllegalArgumentException if the root node was invalid
398404
*/
399-
public int addRef(final int root) {
405+
public int addRef(final int root, final BDDHandler handler) {
406+
if (handler != null && !handler.newRefAdded())
407+
return BDD_ABORT;
400408
if (root < 2)
401409
return root;
402410
if (root >= this.nodesize)
@@ -1061,7 +1069,7 @@ public int support(final int r) {
10611069

10621070
for (int n = this.supportMax; n >= supportMin; --n)
10631071
if (this.supportSet[n] == this.supportID) {
1064-
addRef(res);
1072+
addRef(res, null);
10651073
final int tmp = makeNode(n, 0, res);
10661074
delRef(res);
10671075
res = tmp;

src/main/java/org/logicng/formulas/printer/FormulaStringRepresentation.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,31 @@ protected String toInnerString(Formula formula) {
9292
}
9393

9494
/**
95-
* Returns a bracketed string version of a given formula.
95+
* Returns a bracketed string version of a given formula. Exception: If the formula is a trivial pseudo-Boolean
96+
* constraint, then the string version of the formula is returned without brackets.
9697
* @param formula the formula
9798
* @return {@code "(" + formula.toString() + ")"}
9899
*/
99100
protected String bracket(final Formula formula) {
100-
return String.format("%s%s%s", this.lbr(), this.toInnerString(formula), this.rbr());
101+
if (isTrivialCase(formula)) {
102+
return this.toInnerString(formula);
103+
} else {
104+
return String.format("%s%s%s", this.lbr(), this.toInnerString(formula), this.rbr());
105+
}
106+
}
107+
108+
/**
109+
* Checks if the formula is a pseudo-Boolean constraint that is trivially false or trivially true.
110+
* @param formula the formula
111+
* @return {@code true} if the formula is a trivial pseudo-Boolean constraint, otherwise {@code false}
112+
*/
113+
protected boolean isTrivialCase(Formula formula) {
114+
if (formula.type() == FType.PBC) {
115+
PBConstraint pbc = (PBConstraint) formula;
116+
return pbc.isTrivialFalse() || pbc.isTrivialTrue();
117+
} else {
118+
return false;
119+
}
101120
}
102121

103122
/**
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
///////////////////////////////////////////////////////////////////////////
2+
// __ _ _ ________ //
3+
// / / ____ ____ _(_)____/ | / / ____/ //
4+
// / / / __ \/ __ `/ / ___/ |/ / / __ //
5+
// / /___/ /_/ / /_/ / / /__/ /| / /_/ / //
6+
// /_____/\____/\__, /_/\___/_/ |_/\____/ //
7+
// /____/ //
8+
// //
9+
// The Next Generation Logic Library //
10+
// //
11+
///////////////////////////////////////////////////////////////////////////
12+
// //
13+
// Copyright 2015-20xx Christoph Zengler //
14+
// //
15+
// Licensed under the Apache License, Version 2.0 (the "License"); //
16+
// you may not use this file except in compliance with the License. //
17+
// You may obtain a copy of the License at //
18+
// //
19+
// http://www.apache.org/licenses/LICENSE-2.0 //
20+
// //
21+
// Unless required by applicable law or agreed to in writing, software //
22+
// distributed under the License is distributed on an "AS IS" BASIS, //
23+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or //
24+
// implied. See the License for the specific language governing //
25+
// permissions and limitations under the License. //
26+
// //
27+
///////////////////////////////////////////////////////////////////////////
28+
29+
package org.logicng.handlers;
30+
31+
/**
32+
* Interface for a handler for the BDD factory.
33+
* @version 1.6.2
34+
* @since 1.6.2
35+
*/
36+
public interface BDDHandler extends Handler {
37+
38+
/**
39+
* This method is called every a new reference is added, i.e the method {@link org.logicng.bdds.jbuddy.BDDKernel#addRef(int, BDDHandler)} is called.
40+
* @return whether BDD generation should be continued or not
41+
*/
42+
boolean newRefAdded();
43+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.logicng.handlers;
2+
3+
/**
4+
* A computation handler.
5+
* @version 1.6.2
6+
* @since 1.6.2
7+
*/
8+
public abstract class ComputationHandler implements Handler {
9+
10+
protected boolean aborted;
11+
12+
@Override
13+
public boolean aborted() {
14+
return this.aborted;
15+
}
16+
17+
@Override
18+
public void started() {
19+
this.aborted = false;
20+
}
21+
}

src/main/java/org/logicng/handlers/FactorizationHandler.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232

3333
/**
3434
* A handler for factorization methods (CNF, DNF).
35-
* @version 1.0
35+
* @version 1.6.2
3636
* @since 1.0
3737
*/
38-
public interface FactorizationHandler {
38+
public interface FactorizationHandler extends Handler {
3939

4040
/**
4141
* This method is called every time a distribution is performed.
@@ -49,5 +49,4 @@ public interface FactorizationHandler {
4949
* @return whether the factorization should be continued or not
5050
*/
5151
boolean createdClause(final Formula clause);
52-
5352
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.logicng.handlers;
2+
3+
/**
4+
* Interface for a handler. A handler can be used as callback for different time-intensive computations in order
5+
* to abort these computations. There are same often used default handlers already implemented and users can
6+
* implement their own handlers by implementing the respective interfaces.
7+
* @version 1.6.2
8+
* @since 1.6.2
9+
*/
10+
public interface Handler {
11+
12+
/**
13+
* Returns whether the computation was aborted by the handler.
14+
* @return {@code true} if the computation was aborted by the handler, otherwise {@code false}
15+
*/
16+
public boolean aborted();
17+
18+
/**
19+
* This method is called when the computation starts.
20+
*/
21+
public void started();
22+
}

0 commit comments

Comments
 (0)