Skip to content

Commit 3e2dfe7

Browse files
authored
Merge pull request #43 from logic-ng/development
Development
2 parents 7d42d02 + e32e82e commit 3e2dfe7

File tree

263 files changed

+176849
-2463
lines changed

Some content is hidden

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

263 files changed

+176849
-2463
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ src/test/resources/partialweightedmaxsat/log.txt
2020

2121
# test temporary files
2222
src/test/resources/writers/temp/*.dot
23+
src/test/resources/writers/temp/*.txt
24+
src/test/resources/writers/temp/*.cnf
25+
src/test/resources/writers/temp/*.map
2326

2427
# LSP
2528
.settings

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@
22

33
LogicNG uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
44

5+
## [2.4.0] - 2022-11-24
6+
7+
### Added
8+
9+
- Completely rewritten graphical outputs of formulas, BDDs, and graphs in the package `org.logicng.io.graphical`. It is now possible to configure the
10+
generated graphs by dynamically styling nodes, edges, and computing node labels. Also, there are now two possible output formats: GraphViz DOT and Mermaid.js.
11+
- Convenience methods `isSatisfiable`, `isTautology`, `isContradiction`, `implies`, `isImpliedBy` and `isEquivalentTo` in the `Formula` class.
12+
- New OLL algorithm for OpenWBO for more efficient weighted MaxSAT solving.
13+
- Two overloaded factory methods `mk` in `MiniSat` to construct a solver by formula factory, solver style and optional configuration.
14+
- Methods to directly apply Boolean functions on BDDs
15+
- Added `toFormula` method on BDDs to generate a formula via Shannon expansion
16+
- Convenience methods `variables(Collection<String> names)` and `variables(String... names)` for creating a list of variables in the `FormulaFactory` class.
17+
18+
### Changed
19+
20+
- Methods `generateFromCnf(Formula formula)` and `generateFromCnf(Collection<Formula> formulas)` in `ConstraintGraphGenerator` are now deprecated, since the
21+
constraint graph generation is not CNF specific. Both methods will be removed with LogicNG 3.0. Instead, use the general
22+
method `generateFromFormulas(Collection<Formula> formulas)`.
23+
524
## [2.3.2] - 2022-08-02
625

726
### Changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ LogicNG is released in the Maven Central Repository. To include it just add
3434
<dependency>
3535
<groupId>org.logicng</groupId>
3636
<artifactId>logicng</artifactId>
37-
<version>2.3.2</version>
37+
<version>2.4.0</version>
3838
</dependency>
3939
```
4040

pom.xml

Lines changed: 8 additions & 7 deletions
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>2.3.2</version>
29+
<version>2.4.0</version>
3030
<packaging>bundle</packaging>
3131

3232
<name>LogicNG</name>
@@ -76,18 +76,18 @@
7676

7777
<!-- Dependency Versions -->
7878
<version.antlr>4.9.3</version.antlr>
79-
<version.junit>5.6.2</version.junit>
80-
<version.assertj>3.16.1</version.assertj>
81-
<version.mockito>3.11.2</version.mockito>
79+
<version.junit>5.9.0</version.junit>
80+
<version.assertj>3.23.1</version.assertj>
81+
<version.mockito>4.7.0</version.mockito>
8282

8383
<!-- Plugin Versions -->
8484
<version.antlr-plugin>4.9.3</version.antlr-plugin>
85-
<version.jacoco>0.8.5</version.jacoco>
85+
<version.jacoco>0.8.8</version.jacoco>
8686
<version.coveralls>4.3.0</version.coveralls>
87-
<version.surefire>3.0.0-M5</version.surefire>
87+
<version.surefire>3.0.0-M7</version.surefire>
8888
<version.nexus-staging>1.6.8</version.nexus-staging>
8989
<version.maven-gpg>1.6</version.maven-gpg>
90-
<version.osgi-plugin>5.1.6</version.osgi-plugin>
90+
<version.osgi-plugin>5.1.8</version.osgi-plugin>
9191
<version.maven-source>3.2.1</version.maven-source>
9292
<version.maven-javadoc>3.2.0</version.maven-javadoc>
9393
<version.maven-jar>3.2.0</version.maven-jar>
@@ -384,3 +384,4 @@
384384
</profile>
385385
</profiles>
386386
</project>
387+

src/main/java/org/logicng/formulas/Formula.java

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,17 @@
4444
import org.logicng.predicates.CNFPredicate;
4545
import org.logicng.predicates.DNFPredicate;
4646
import org.logicng.predicates.NNFPredicate;
47+
import org.logicng.predicates.satisfiability.ContradictionPredicate;
48+
import org.logicng.predicates.satisfiability.SATPredicate;
49+
import org.logicng.predicates.satisfiability.TautologyPredicate;
4750
import org.logicng.transformations.NNFTransformation;
4851

4952
import java.util.SortedSet;
5053
import java.util.stream.Stream;
5154

5255
/**
5356
* Super class for formulas.
54-
* @version 2.3.0
57+
* @version 2.4.0
5558
* @since 1.0
5659
*/
5760
public abstract class Formula implements Iterable<Formula> {
@@ -267,6 +270,78 @@ public Formula cnf() {
267270
return this.f.cnfEncoder().encode(this);
268271
}
269272

273+
/**
274+
* Returns whether this formula is satisfiable.
275+
* A new SAT solver is used to check the satisfiability. This is a convenience method for the
276+
* predicate {@link org.logicng.predicates.satisfiability.SATPredicate}. If you want to
277+
* have more influence on the solver (e.g. which solver type or configuration) you must create and
278+
* use a {@link org.logicng.solvers.SATSolver} on your own.
279+
* @return {@code true} when this formula is satisfiable, {@code false} otherwise
280+
*/
281+
public boolean isSatisfiable() {
282+
return this.holds(new SATPredicate(this.f));
283+
}
284+
285+
/**
286+
* Returns whether this formula is a tautology, hence always true.
287+
* A new SAT solver is used to check the tautology. This is a convenience method for the
288+
* predicate {@link org.logicng.predicates.satisfiability.TautologyPredicate}. If you want to
289+
* have more influence on the solver (e.g. which solver type or configuration) you must create and
290+
* use a {@link org.logicng.solvers.SATSolver} on your own.
291+
* @return {@code true} when this formula is a tautology, {@code false} otherwise
292+
*/
293+
public boolean isTautology() {
294+
return this.holds(new TautologyPredicate(this.f));
295+
}
296+
297+
/**
298+
* Returns whether this formula is a contradiction, hence always false.
299+
* A new SAT solver is used to check the contradiction. This is a convenience method for the
300+
* predicate {@link org.logicng.predicates.satisfiability.ContradictionPredicate}. If you want to
301+
* have more influence on the solver (e.g. which solver type or configuration) you must create and
302+
* use a {@link org.logicng.solvers.SATSolver} on your own.
303+
* @return {@code true} when this formula is a contradiction, {@code false} otherwise
304+
*/
305+
public boolean isContradiction() {
306+
return this.holds(new ContradictionPredicate(this.f));
307+
}
308+
309+
/**
310+
* Returns whether this formula implies the given other formula, i.e. `this =&gt; other` is a tautology.
311+
* A new SAT solver is used to check this tautology. This is a convenience method. If you want to
312+
* have more influence on the solver (e.g. which solver type or configuration) you must create and
313+
* use a {@link org.logicng.solvers.SATSolver} on your own.
314+
* @param other the formula which should be checked if it is implied by this formula
315+
* @return {@code true} when this formula implies the given other formula, {@code false} otherwise
316+
*/
317+
public boolean implies(final Formula other) {
318+
return this.f.implication(this, other).holds(new TautologyPredicate(this.f));
319+
}
320+
321+
/**
322+
* Returns whether this formula is implied by the given other formula, i.e. `other =&gt; this` is a tautology.
323+
* A new SAT solver is used to check this tautology. This is a convenience method. If you want to
324+
* have more influence on the solver (e.g. which solver type or configuration) you must create and
325+
* use a {@link org.logicng.solvers.SATSolver} on your own.
326+
* @param other the formula which should be checked if it implies this formula
327+
* @return {@code true} when this formula is implied by the given other formula, {@code false} otherwise
328+
*/
329+
public boolean isImpliedBy(final Formula other) {
330+
return this.f.implication(other, this).holds(new TautologyPredicate(this.f));
331+
}
332+
333+
/**
334+
* Returns whether this formula is equivalent to the given other formula, i.e. `other &lt;=&gt; this` is a tautology.
335+
* A new SAT solver is used to check this tautology. This is a convenience method. If you want to
336+
* have more influence on the solver (e.g. which solver type or configuration) you must create and
337+
* use a {@link org.logicng.solvers.SATSolver} on your own.
338+
* @param other the formula which should be checked if it is equivalent with this formula
339+
* @return {@code true} when this formula is equivalent to the given other formula, {@code false} otherwise
340+
*/
341+
public boolean isEquivalentTo(final Formula other) {
342+
return this.f.equivalence(this, other).holds(new TautologyPredicate(this.f));
343+
}
344+
270345
/**
271346
* Generates a BDD from this formula with a given variable ordering. This is done by generating a new BDD factory,
272347
* generating the variable order for this formula, and building a new BDD. If more sophisticated operations should

src/main/java/org/logicng/formulas/FormulaFactory.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.logicng.util.FormulaRandomizerConfig;
6060
import org.logicng.util.Pair;
6161

62+
import java.util.ArrayList;
6263
import java.util.Arrays;
6364
import java.util.Collection;
6465
import java.util.Collections;
@@ -79,7 +80,7 @@
7980
* <p>
8081
* A formula factory is NOT thread-safe. If you generate formulas from more than one thread you either need to synchronize the formula factory
8182
* yourself or you use a formula factory for each single thread.
82-
* @version 2.3.2
83+
* @version 2.4.0
8384
* @since 1.0
8485
*/
8586
public class FormulaFactory {
@@ -909,6 +910,32 @@ public Variable variable(final String name) {
909910
return var;
910911
}
911912

913+
/**
914+
* Creates a list of literals with the given names and positive phase.
915+
* @param names the variable names
916+
* @return a new list of literals with the given names and positive phase
917+
*/
918+
public List<Variable> variables(final Collection<String> names) {
919+
final List<Variable> variables = new ArrayList<>();
920+
for (final String name : names) {
921+
variables.add(variable(name));
922+
}
923+
return variables;
924+
}
925+
926+
/**
927+
* Creates a list of literals with the given names and positive phase.
928+
* @param names the variable names
929+
* @return a new list of literals with the given names and positive phase
930+
*/
931+
public List<Variable> variables(final String... names) {
932+
final List<Variable> variables = new ArrayList<>();
933+
for (final String name : names) {
934+
variables.add(variable(name));
935+
}
936+
return variables;
937+
}
938+
912939
/**
913940
* Creates a new pseudo-Boolean constraint.
914941
* @param comparator the comparator of the constraint

src/main/java/org/logicng/graphs/generators/ConstraintGraphGenerator.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
/**
3838
* A graph generator which generates a constraint graph for a
3939
* given list of formulas.
40-
* @version 2.0.0
40+
* @version 2.4.0
4141
* @since 2.0.0
4242
*/
4343
public final class ConstraintGraphGenerator {
@@ -53,7 +53,9 @@ private ConstraintGraphGenerator() {
5353
* Constructs the constraint graph.
5454
* @param formula the formula in extended CNF
5555
* @return the constraint graph for the given formula
56+
* @deprecated the constraint graph generation is not CNF specific. Use general method {@link #generateFromFormulas(Collection)} instead.
5657
*/
58+
@Deprecated
5759
public static Graph<Variable> generateFromCnf(final Formula formula) {
5860
final Graph<Variable> constraintGraph = new Graph<>();
5961
addToGraph(formula, constraintGraph);
@@ -64,7 +66,9 @@ public static Graph<Variable> generateFromCnf(final Formula formula) {
6466
* Constructs the constraint graph.
6567
* @param formulas the formulas in extended CNF as set of CNFs
6668
* @return the constraint graph for the given formula
69+
* @deprecated the constraint graph generation is not CNF specific. Use general method {@link #generateFromFormulas(Collection)} instead.
6770
*/
71+
@Deprecated
6872
public static Graph<Variable> generateFromCnf(final Collection<Formula> formulas) {
6973
final Graph<Variable> constraintGraph = new Graph<>();
7074
for (final Formula clause : formulas) {

src/main/java/org/logicng/graphs/io/GraphDimacsFileWriter.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,14 @@
4545

4646
/**
4747
* A dimacs file writer for graphs. Writes the internal data structure of a graph to a dimacs file.
48-
* @version 1.2
48+
* @version 2.4.0
4949
* @since 1.2
5050
*/
5151
public final class GraphDimacsFileWriter {
5252

53+
private static final String COL_EXTENSION = ".col";
54+
private static final String MAP_EXTENSION = ".map";
55+
5356
/**
5457
* Private constructor.
5558
*/
@@ -59,24 +62,24 @@ private GraphDimacsFileWriter() {
5962

6063
/**
6164
* Writes a given graph's internal data structure as a dimacs file.
62-
* @param fileName the file name of the dimacs file to write
63-
* @param g the graph
65+
* @param fileName the file name of the dimacs file to write, will be extended by suffix {@code .col} if not already present
66+
* @param graph the graph
6467
* @param writeMapping indicates whether an additional file for translating the ids to variable names shall be written
6568
* @param <T> the type of the graph content
6669
* @throws IOException if there was a problem writing the file
6770
*/
68-
public static <T> void write(final String fileName, final Graph<T> g, final boolean writeMapping) throws IOException {
69-
final File file = new File(fileName.endsWith(".col") ? fileName : fileName + ".col");
71+
public static <T> void write(final String fileName, final Graph<T> graph, final boolean writeMapping) throws IOException {
72+
final File file = new File(fileName.endsWith(COL_EXTENSION) ? fileName : fileName + COL_EXTENSION);
7073
final Map<Node<T>, Long> node2id = new LinkedHashMap<>();
7174
long i = 1;
72-
for (final Node<T> node : g.nodes()) {
75+
for (final Node<T> node : graph.nodes()) {
7376
node2id.put(node, i++);
7477
}
7578

7679
final StringBuilder sb = new StringBuilder("p edge ");
7780
final Set<Pair<Node<T>, Node<T>>> edges = new LinkedHashSet<>();
7881
final Set<Node<T>> doneNodes = new LinkedHashSet<>();
79-
for (final Node<T> d : g.nodes()) {
82+
for (final Node<T> d : graph.nodes()) {
8083
for (final Node<T> n : d.neighbours()) {
8184
if (!doneNodes.contains(n)) {
8285
edges.add(new Pair<>(d, n));
@@ -95,7 +98,7 @@ public static <T> void write(final String fileName, final Graph<T> g, final bool
9598
writer.flush();
9699
}
97100
if (writeMapping) {
98-
final String mappingFileName = (fileName.endsWith(".col") ? fileName.substring(0, fileName.length() - 4) : fileName) + ".map";
101+
final String mappingFileName = (fileName.endsWith(COL_EXTENSION) ? fileName.substring(0, fileName.length() - 4) : fileName) + MAP_EXTENSION;
99102
writeMapping(new File(mappingFileName), node2id);
100103
}
101104
}

src/main/java/org/logicng/graphs/io/GraphDotFileWriter.java

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,24 @@
2929
package org.logicng.graphs.io;
3030

3131
import org.logicng.graphs.datastructures.Graph;
32-
import org.logicng.graphs.datastructures.Node;
32+
import org.logicng.io.graphical.GraphicalDotWriter;
33+
import org.logicng.io.graphical.generators.GraphGraphicalGenerator;
3334

34-
import java.io.BufferedWriter;
3535
import java.io.File;
3636
import java.io.IOException;
37-
import java.io.OutputStreamWriter;
38-
import java.nio.charset.StandardCharsets;
39-
import java.nio.file.Files;
40-
import java.util.LinkedHashSet;
41-
import java.util.Set;
4237

4338
/**
44-
* A dot file writer for a graph. Writes the internal data structure of the formula to a dot file.
45-
* @version 2.0.0
39+
* A dot file writer for a graph. Writes the internal data structure of the graph to a dot file.
40+
* @version 2.4.0
4641
* @since 1.2
42+
* @deprecated This legacy writer will be removed in LogicNG 3.0.0. For a more configurable and flexible
43+
* to use graph writer use {@link GraphGraphicalGenerator} within the new graphical writer framework.
4744
*/
45+
@Deprecated
4846
public final class GraphDotFileWriter {
4947

48+
private static final String DOT_EXTENSION = ".dot";
49+
5050
/**
5151
* Private constructor.
5252
*/
@@ -55,14 +55,14 @@ private GraphDotFileWriter() {
5555
}
5656

5757
/**
58-
* Writes a given formula's internal data structure as a dimacs file.
59-
* @param fileName the file name of the dimacs file to write
58+
* Writes a given graph's internal data structure as a dot file.
59+
* @param fileName the file name of the dot file to write, will be extended by suffix {@code .dot} if not already present
6060
* @param graph the graph
6161
* @param <T> the type of the graph content
6262
* @throws IOException if there was a problem writing the file
6363
*/
6464
public static <T> void write(final String fileName, final Graph<T> graph) throws IOException {
65-
write(new File(fileName.endsWith(".dot") ? fileName : fileName + ".dot"), graph);
65+
write(new File(fileName.endsWith(DOT_EXTENSION) ? fileName : fileName + DOT_EXTENSION), graph);
6666
}
6767

6868
/**
@@ -73,27 +73,6 @@ public static <T> void write(final String fileName, final Graph<T> graph) throws
7373
* @throws IOException if there was a problem writing the file
7474
*/
7575
public static <T> void write(final File file, final Graph<T> graph) throws IOException {
76-
final StringBuilder sb = new StringBuilder(String.format("strict graph {%n"));
77-
78-
final Set<Node<T>> doneNodes = new LinkedHashSet<>();
79-
for (final Node<T> d : graph.nodes()) {
80-
for (final Node<T> n : d.neighbours()) {
81-
if (!doneNodes.contains(n)) {
82-
sb.append(" ").append(d.content()).append(" -- ").append(n.content()).append(System.lineSeparator());
83-
}
84-
}
85-
doneNodes.add(d);
86-
}
87-
for (final Node<T> d : graph.nodes()) {
88-
if (d.neighbours().isEmpty()) {
89-
sb.append(" ").append(d.content()).append(System.lineSeparator());
90-
}
91-
}
92-
sb.append("}");
93-
94-
try (final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8))) {
95-
writer.append(sb);
96-
writer.flush();
97-
}
76+
GraphGraphicalGenerator.<T>builder().build().translate(graph).write(file, GraphicalDotWriter.get());
9877
}
9978
}

0 commit comments

Comments
 (0)