From 5273950f82e7ed1e51a99ae5553de0c6f8504acc Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Wed, 5 Feb 2020 16:59:57 +0100 Subject: [PATCH 01/18] new package at.ac.tuwien.kr.alpha.api for classes making up the Alpha's public API, moved Alpha there --- src/main/java/at/ac/tuwien/kr/alpha/Main.java | 1 + src/main/java/at/ac/tuwien/kr/alpha/{ => api}/Alpha.java | 3 ++- src/test/java/at/ac/tuwien/kr/alpha/AlphaTest.java | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) rename src/main/java/at/ac/tuwien/kr/alpha/{ => api}/Alpha.java (98%) diff --git a/src/main/java/at/ac/tuwien/kr/alpha/Main.java b/src/main/java/at/ac/tuwien/kr/alpha/Main.java index 3585792c6..117d25f16 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/Main.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/Main.java @@ -38,6 +38,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.ac.tuwien.kr.alpha.api.Alpha; import at.ac.tuwien.kr.alpha.common.AnswerSet; import at.ac.tuwien.kr.alpha.common.Program; import at.ac.tuwien.kr.alpha.config.AlphaConfig; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/Alpha.java b/src/main/java/at/ac/tuwien/kr/alpha/api/Alpha.java similarity index 98% rename from src/main/java/at/ac/tuwien/kr/alpha/Alpha.java rename to src/main/java/at/ac/tuwien/kr/alpha/api/Alpha.java index 5fdae794d..c03fa3691 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/Alpha.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/api/Alpha.java @@ -25,8 +25,9 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha; +package at.ac.tuwien.kr.alpha.api; +import at.ac.tuwien.kr.alpha.Util; import at.ac.tuwien.kr.alpha.common.AnswerSet; import at.ac.tuwien.kr.alpha.common.AtomStore; import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; diff --git a/src/test/java/at/ac/tuwien/kr/alpha/AlphaTest.java b/src/test/java/at/ac/tuwien/kr/alpha/AlphaTest.java index cb6568514..cf6810695 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/AlphaTest.java +++ b/src/test/java/at/ac/tuwien/kr/alpha/AlphaTest.java @@ -48,6 +48,7 @@ import org.junit.Ignore; import org.junit.Test; +import at.ac.tuwien.kr.alpha.api.Alpha; import at.ac.tuwien.kr.alpha.common.AnswerSet; import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; import at.ac.tuwien.kr.alpha.common.DisjunctiveHead; From e17f47b246c5ba965a787389f5ea1a972184edc7 Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Wed, 5 Feb 2020 17:09:48 +0100 Subject: [PATCH 02/18] interface definition for AnswerSetToObjectMapper --- .../api/mapper/AnswerSetToObjectMapper.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToObjectMapper.java diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToObjectMapper.java b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToObjectMapper.java new file mode 100644 index 000000000..8f745e556 --- /dev/null +++ b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToObjectMapper.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2020, the Alpha Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.api.mapper; + +import at.ac.tuwien.kr.alpha.common.AnswerSet; + +/** + * Copyright (c) 2020, the Alpha Team. + * + * Interface definition for an adapter that maps from an {@link AnswerSet} to an instance of the implementation's generic type T. + * + * @param the type to which to map answer sets + */ +public interface AnswerSetToObjectMapper { + + T mapFromAnswerSet(AnswerSet answerSet); + +} From e9bdf45eb118c0ce891f98cd4c5f45abfc86b4bf Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Wed, 5 Feb 2020 17:25:24 +0100 Subject: [PATCH 03/18] added dependency for ms office library apache poi, created skeleton for AnswerSetToWorkbookMapper --- build.gradle | 2 + .../impl/AnswerSetToWorkbookMapper.java | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java diff --git a/build.gradle b/build.gradle index c10da735e..183022a44 100644 --- a/build.gradle +++ b/build.gradle @@ -44,6 +44,8 @@ dependencies { implementation group: 'org.apache.commons', name: 'commons-collections4', version: '4.1' implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.6' implementation group: 'org.reflections', name: 'reflections', version: '0.9.11' + implementation group: 'org.apache.poi', name: 'poi', version: '4.1.1' + implementation group: 'org.apache.poi', name: 'poi-ooxml', version: '4.1.1' testImplementation group: 'junit', name: 'junit', version: '4.12' } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java new file mode 100644 index 000000000..cc0d326ff --- /dev/null +++ b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2020, the Alpha Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.api.mapper.impl; + +import org.apache.poi.ss.usermodel.Workbook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.ac.tuwien.kr.alpha.api.mapper.AnswerSetToObjectMapper; +import at.ac.tuwien.kr.alpha.common.AnswerSet; + +/** + * Implementation of {@link AnswerSetToObjectMapper} that generates an office open xml workbook ("excel file") from a given answer set. + * + * Copyright (c) 2019, the Alpha Team. + */ +public class AnswerSetToWorkbookMapper implements AnswerSetToObjectMapper { + + private static final Logger LOGGER = LoggerFactory.getLogger(AnswerSetToWorkbookMapper.class); + + @Override + public Workbook mapFromAnswerSet(AnswerSet answerSet) { + // TODO Auto-generated method stub + return null; + } + +} From 9cb287c9e664c718917d72b28ed31a5e7396ac14 Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Mon, 10 Feb 2020 15:38:19 +0100 Subject: [PATCH 04/18] moved AlphaTest to correct package --- src/test/java/at/ac/tuwien/kr/alpha/{ => api}/AlphaTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/test/java/at/ac/tuwien/kr/alpha/{ => api}/AlphaTest.java (99%) diff --git a/src/test/java/at/ac/tuwien/kr/alpha/AlphaTest.java b/src/test/java/at/ac/tuwien/kr/alpha/api/AlphaTest.java similarity index 99% rename from src/test/java/at/ac/tuwien/kr/alpha/AlphaTest.java rename to src/test/java/at/ac/tuwien/kr/alpha/api/AlphaTest.java index cf6810695..28a349edc 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/AlphaTest.java +++ b/src/test/java/at/ac/tuwien/kr/alpha/api/AlphaTest.java @@ -25,7 +25,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha; +package at.ac.tuwien.kr.alpha.api; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; @@ -48,7 +48,7 @@ import org.junit.Ignore; import org.junit.Test; -import at.ac.tuwien.kr.alpha.api.Alpha; +import at.ac.tuwien.kr.alpha.AnswerSetsParser; import at.ac.tuwien.kr.alpha.common.AnswerSet; import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; import at.ac.tuwien.kr.alpha.common.DisjunctiveHead; From e3b4b2dae897babc08a0e7793ad7b2278f2e71d2 Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Mon, 10 Feb 2020 15:38:55 +0100 Subject: [PATCH 05/18] implementation and tests for mapping from AnswerSet to Workbook --- .../impl/AnswerSetToWorkbookMapper.java | 59 ++++++++++- .../impl/AnswerSetToWorkbookMapperTest.java | 98 +++++++++++++++++++ 2 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 src/test/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapperTest.java diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java index cc0d326ff..677c1a3a7 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java @@ -25,12 +25,22 @@ */ package at.ac.tuwien.kr.alpha.api.mapper.impl; +import java.util.List; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.ac.tuwien.kr.alpha.api.mapper.AnswerSetToObjectMapper; import at.ac.tuwien.kr.alpha.common.AnswerSet; +import at.ac.tuwien.kr.alpha.common.Predicate; +import at.ac.tuwien.kr.alpha.common.atoms.Atom; +import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.common.terms.Term; /** * Implementation of {@link AnswerSetToObjectMapper} that generates an office open xml workbook ("excel file") from a given answer set. @@ -41,10 +51,55 @@ public class AnswerSetToWorkbookMapper implements AnswerSetToObjectMapper terms = atom.getTerms(); + Cell currCell; + if (terms.isEmpty()) { + // 0-arity atom + currCell = atomRow.createCell(0); + currCell.setCellValue(atom.getPredicate().getName()); + sheet.autoSizeColumn(0); + } else { + for (int i = 0; i < terms.size(); i++) { + currCell = atomRow.createCell(i); + currCell.setCellValue(terms.get(i).toString()); + sheet.autoSizeColumn(i); + } + } } } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapperTest.java b/src/test/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapperTest.java new file mode 100644 index 000000000..0237df700 --- /dev/null +++ b/src/test/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapperTest.java @@ -0,0 +1,98 @@ +package at.ac.tuwien.kr.alpha.api.mapper.impl; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.junit.Assert; +import org.junit.Test; + +import at.ac.tuwien.kr.alpha.api.Alpha; +import at.ac.tuwien.kr.alpha.common.AnswerSet; +import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; +import at.ac.tuwien.kr.alpha.common.Predicate; +import at.ac.tuwien.kr.alpha.common.atoms.Atom; +import at.ac.tuwien.kr.alpha.common.terms.Term; + +public class AnswerSetToWorkbookMapperTest { + + private AnswerSetToWorkbookMapper mapper = new AnswerSetToWorkbookMapper(); + + @Test + public void smokeTest() throws IOException { + AnswerSet as = new AnswerSetBuilder().predicate("bla").instance("blubb", "blubb").instance("foo", "bar").predicate("foo").instance("bar") + .instance("baz").predicate("complex").instance(Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)).build(); + Workbook wb = this.mapper.mapFromAnswerSet(as); + Assert.assertNotNull(wb.getSheet("Flags")); + Assert.assertNotNull(wb.getSheet("bla_2")); + Assert.assertNotNull(wb.getSheet("foo_1")); + Assert.assertNotNull(wb.getSheet("complex_3")); + wb.close(); + } + + @Test + public void solveAndWriteWorkbookTest() { + //@formatter:off + String progstr = "aFlag. oneMoreFlag. yetAnotherFlag. createPs. maxP(5). r(s(1, 2, 3), 4). r(bla, blubb). r(foo, bar(baaz))." + + "p(0) :- createPs. " + + "p(N) :- p(I), N = I + 1, N <= MX, maxP(MX)." + + "q(A, B) :- p(A), p(B)."; + //@formatter:on + Alpha alpha = new Alpha(); + List answerSets = alpha.solve(alpha.readProgramString(progstr, null)).collect(Collectors.toList()); + Assert.assertEquals(1, answerSets.size()); + AnswerSet as = answerSets.get(0); + Workbook answerSetWorkbook = this.mapper.mapFromAnswerSet(as); + AnswerSetToWorkbookMapperTest.assertWorkbookMatchesAnswerSet(answerSetWorkbook, as); + } + + private static void assertWorkbookMatchesAnswerSet(Workbook wb, AnswerSet as) { + for (Predicate pred : as.getPredicates()) { + if (pred.getArity() == 0) { + boolean flagFound = false; + Sheet flagsSheet = wb.getSheet("Flags"); + Assert.assertNotNull(flagsSheet); + for (Row row : flagsSheet) { + if (row.getCell(0).getStringCellValue().equals(pred.getName())) { + flagFound = true; + break; + } + } + Assert.assertTrue("0-arity predicate " + pred.getName() + " not found in workbook!", flagFound); + } else { + Sheet predicateSheet = wb.getSheet(pred.getName() + "_" + pred.getArity()); + for (Atom atom : as.getPredicateInstances(pred)) { + boolean atomFound = false; + Assert.assertNotNull(predicateSheet); + for (Row row : predicateSheet) { + if (AnswerSetToWorkbookMapperTest.rowMatchesAtom(row, atom)) { + atomFound = true; + break; + } + } + Assert.assertTrue("Atom " + atom.toString() + " not found in workbook!", atomFound); + } + } + } + } + + private static boolean rowMatchesAtom(Row row, Atom atom) { + List terms = atom.getTerms(); + Cell cell; + for (int i = 0; i < terms.size(); i++) { + cell = row.getCell(i); + if (cell == null) { + return false; + } + if (!(cell.getStringCellValue().equals(terms.get(i).toString()))) { + return false; + } + } + return true; + } + +} From d6abdad69f31f815b4900ede7005af7a222a6942 Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Mon, 10 Feb 2020 16:52:17 +0100 Subject: [PATCH 06/18] perform dupilicate handling also for LICENSE and NOTICE files without txt extension since apache poi bundles them without ext --- build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 183022a44..a71cf7bc4 100644 --- a/build.gradle +++ b/build.gradle @@ -87,16 +87,16 @@ task bundledJar(type: Jar) { } archiveFileName = "${project.name}-bundled.jar" - + /* - * In order to make sure wo don't overwrite NOTICE and LICENSE files coming from dependency + * In order to make sure we don't overwrite NOTICE and LICENSE files coming from dependency * jars with each other, number them while copying */ int i = 1 - rename { name -> name.equals("NOTICE.txt") ? "NOTICE." + (i++) + ".txt" : null } + rename { name -> (name.equals("NOTICE.txt") || name.equals("NOTICE")) ? "NOTICE." + (i++) + ".txt" : null } int j = 1 - rename { name -> name.equals("LICENSE.txt") ? "LICENSE." + (j++) + ".txt" : null } + rename { name -> (name.equals("LICENSE.txt") || name.equals("LICENSE")) ? "LICENSE." + (j++) + ".txt" : null } with jar } From 46b2d3b638e312ae29a640d73a74a8d8be7a6b10 Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Mon, 10 Feb 2020 16:52:57 +0100 Subject: [PATCH 07/18] commandline option and handling in Main for xlsx output --- src/main/java/at/ac/tuwien/kr/alpha/Main.java | 27 +++++++++++++- .../kr/alpha/config/CommandLineParser.java | 36 +++++++++++-------- .../tuwien/kr/alpha/config/InputConfig.java | 20 +++++++++++ 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/src/main/java/at/ac/tuwien/kr/alpha/Main.java b/src/main/java/at/ac/tuwien/kr/alpha/Main.java index 117d25f16..4598e75b6 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/Main.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/Main.java @@ -29,16 +29,23 @@ import java.io.FileNotFoundException; import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.Stream; import org.antlr.v4.runtime.RecognitionException; import org.apache.commons.cli.ParseException; +import org.apache.poi.ss.usermodel.Workbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.ac.tuwien.kr.alpha.api.Alpha; +import at.ac.tuwien.kr.alpha.api.mapper.impl.AnswerSetToWorkbookMapper; import at.ac.tuwien.kr.alpha.common.AnswerSet; import at.ac.tuwien.kr.alpha.common.Program; import at.ac.tuwien.kr.alpha.config.AlphaConfig; @@ -99,7 +106,25 @@ private static void computeAndConsumeAnswerSets(Alpha alpha, InputConfig inputCf if (!alpha.getConfig().isQuiet()) { AtomicInteger counter = new AtomicInteger(0); - stream.forEach(as -> System.out.println("Answer set " + counter.incrementAndGet() + ":" + System.lineSeparator() + as.toString())); + // stream.forEach(as -> System.out.println("Answer set " + counter.incrementAndGet() + ":" + System.lineSeparator() + as.toString())); + stream.forEach(as -> { + int cnt = counter.incrementAndGet(); + System.out.println("Answer set " + Integer.toString(cnt) + ":" + System.lineSeparator() + as.toString()); + if (inputCfg.isWriteAnswerSetsAsXlsx()) { + try { + Path outputPath = Paths.get(inputCfg.getAnswerSetFileOutputPath() + "." + Integer.toString(cnt) + ".xlsx"); + OutputStream os = Files.newOutputStream(outputPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE, + StandardOpenOption.TRUNCATE_EXISTING); + Workbook wb = new AnswerSetToWorkbookMapper().mapFromAnswerSet(as); + wb.write(os); + wb.close(); + os.close(); + System.out.println("Answer set written to file " + outputPath.toString()); + } catch (IOException ex) { + System.err.println("Failed writing answer set as xlsx file! (" + ex.getMessage() + ")"); + } + } + }); if (counter.get() == 0) { System.out.println("UNSATISFIABLE"); } else { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java b/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java index 0f6b3d873..9c4312e9a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java @@ -73,6 +73,8 @@ public class CommandLineParser { .desc("provide the asp program as a string").build(); private static final Option OPT_LITERATE = Option.builder("l").longOpt("literate") .desc("enable literate programming mode (default: " + InputConfig.DEFAULT_LITERATE + ")").build(); + private static final Option OPT_WRITE_XSLX = Option.builder("wx").longOpt("write-xlsx").hasArg(true).argName("path").type(String.class) + .desc("Write answer sets to xlsx workbooks (one workbook per answer set)").build(); // general system-wide config private static final Option OPT_GROUNDER = Option.builder("g").longOpt("grounder").hasArg(true).argName("grounder") @@ -94,8 +96,8 @@ public class CommandLineParser { private static final Option OPT_MOMS_STRATEGY = Option.builder("ms").longOpt("momsStrategy").hasArg(true).argName("strategy") .desc("strategy for mom's heuristic (CountBinaryWatches or BinaryNoGoodPropagation, default: " + SystemConfig.DEFAULT_MOMS_STRATEGY.name() + ")") .build(); - private static final Option OPT_REPLAY_CHOICES = Option.builder("rc").longOpt("replayChoices").hasArg().argName("choices") - .desc("comma-separated list of choices to be replayed (each choice is represented by a signed integer whose absolute value designates an atom ID and whose sign designates a truth value)") + private static final Option OPT_REPLAY_CHOICES = Option.builder("rc").longOpt("replayChoices").hasArg().argName("choices").desc( + "comma-separated list of choices to be replayed (each choice is represented by a signed integer whose absolute value designates an atom ID and whose sign designates a truth value)") .build(); private static final Option OPT_QUIET = Option.builder("q").longOpt("quiet").desc("do not print answer sets (default: " + SystemConfig.DEFAULT_QUIET) .build(); @@ -109,19 +111,15 @@ public class CommandLineParser { .desc("use counting grid normalization instead of sorting circuit for #count (default: " + SystemConfig.DEFAULT_USE_NORMALIZATION_GRID + ")") .build(); private static final Option OPT_NO_NOGOOD_DELETION = Option.builder("dnd").longOpt("disableNoGoodDeletion") - .desc("disable the deletion of (learned, little active) nogoods (default: " - + SystemConfig.DEFAULT_DISABLE_NOGOOD_DELETION + ")") - .build(); + .desc("disable the deletion of (learned, little active) nogoods (default: " + SystemConfig.DEFAULT_DISABLE_NOGOOD_DELETION + ")").build(); private static final Option OPT_GROUNDER_TOLERANCE_CONSTRAINTS = Option.builder("gtc").longOpt("grounderToleranceConstraints") - .desc("grounder tolerance for constraints (default: " + SystemConfig.DEFAULT_GROUNDER_TOLERANCE_CONSTRAINTS + ")") - .hasArg().argName("tolerance") + .desc("grounder tolerance for constraints (default: " + SystemConfig.DEFAULT_GROUNDER_TOLERANCE_CONSTRAINTS + ")").hasArg().argName("tolerance") .build(); private static final Option OPT_GROUNDER_TOLERANCE_RULES = Option.builder("gtr").longOpt("grounderToleranceRules") - .desc("grounder tolerance for rules (default: " + SystemConfig.DEFAULT_GROUNDER_TOLERANCE_RULES + ")") - .hasArg().argName("tolerance") - .build(); + .desc("grounder tolerance for rules (default: " + SystemConfig.DEFAULT_GROUNDER_TOLERANCE_RULES + ")").hasArg().argName("tolerance").build(); private static final Option OPT_GROUNDER_ACCUMULATOR_ENABLED = Option.builder("acc").longOpt("enableAccumulator") - .desc("activates the accumulator grounding strategy by disabling removal of instances from grounder memory in certain cases (default: " + SystemConfig.DEFAULT_GROUNDER_ACCUMULATOR_ENABLED + ")") + .desc("activates the accumulator grounding strategy by disabling removal of instances from grounder memory in certain cases (default: " + + SystemConfig.DEFAULT_GROUNDER_ACCUMULATOR_ENABLED + ")") .build(); private static final Options CLI_OPTS = new Options(); @@ -137,6 +135,7 @@ public class CommandLineParser { CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_LITERATE); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_INPUT); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_ASPSTRING); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_WRITE_XSLX); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_GROUNDER); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SOLVER); @@ -208,6 +207,7 @@ public CommandLineParser(String cmdLineSyntax, Consumer abortAction) { this.inputOptionHandlers.put(CommandLineParser.OPT_FILTER.getOpt(), this::handleFilters); this.inputOptionHandlers.put(CommandLineParser.OPT_ASPSTRING.getOpt(), this::handleAspString); this.inputOptionHandlers.put(CommandLineParser.OPT_LITERATE.getOpt(), this::handleLiterate); + this.inputOptionHandlers.put(CommandLineParser.OPT_WRITE_XSLX.getOpt(), this::handleWriteXlsx); } public AlphaConfig parseCommandLine(String[] args) throws ParseException { @@ -335,16 +335,18 @@ private void handleBranchingHeuristic(Option opt, SystemConfig cfg) throws Parse try { cfg.setBranchingHeuristicName(branchingHeuristicName); } catch (IllegalArgumentException e) { - throw new ParseException("Unknown branching heuristic: " + branchingHeuristicName + ". Please try one of the following: " + Heuristic.listAllowedValues()); + throw new ParseException( + "Unknown branching heuristic: " + branchingHeuristicName + ". Please try one of the following: " + Heuristic.listAllowedValues()); } } - + private void handleMomsStrategy(Option opt, SystemConfig cfg) throws ParseException { String momsStrategyName = opt.getValue(SystemConfig.DEFAULT_MOMS_STRATEGY.name()); try { cfg.setMomsStrategyName(momsStrategyName); } catch (IllegalArgumentException e) { - throw new ParseException("Unknown mom's strategy: " + momsStrategyName + ". Please try one of the following: " + BinaryNoGoodPropagationEstimation.Strategy.listAllowedValues()); + throw new ParseException("Unknown mom's strategy: " + momsStrategyName + ". Please try one of the following: " + + BinaryNoGoodPropagationEstimation.Strategy.listAllowedValues()); } } @@ -365,6 +367,12 @@ private void handleLiterate(Option opt, InputConfig cfg) { cfg.setLiterate(true); } + private void handleWriteXlsx(Option opt, InputConfig cfg) { + cfg.setWriteAnswerSetsAsXlsx(true); + String outputPath = opt.getValue(InputConfig.DEFAULT_OUTFILE_PATH); + cfg.setAnswerSetFileOutputPath(outputPath); + } + private void handleStats(Option opt, SystemConfig cfg) { cfg.setPrintStats(true); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/InputConfig.java b/src/main/java/at/ac/tuwien/kr/alpha/config/InputConfig.java index d7401fb78..8772b2316 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/InputConfig.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/config/InputConfig.java @@ -15,6 +15,8 @@ public class InputConfig { public static final java.util.function.Predicate DEFAULT_FILTER = p -> true; public static final boolean DEFAULT_LITERATE = false; public static final int DEFAULT_NUM_ANSWER_SETS = 0; + public static final boolean DEFAULT_WRITE_XLSX = false; + public static final String DEFAULT_OUTFILE_PATH = "alphaAnswerSet"; // current directory, files named "alphaAnswerSet.{num}.{ext}" private List aspStrings = new ArrayList<>(); private List files = new ArrayList<>(); @@ -22,6 +24,8 @@ public class InputConfig { private int numAnswerSets = InputConfig.DEFAULT_NUM_ANSWER_SETS; private Set desiredPredicates = new HashSet<>(); private Map predicateMethods = new HashMap<>(); + private boolean writeAnswerSetsAsXlsx = InputConfig.DEFAULT_WRITE_XLSX; + private String answerSetFileOutputPath; public static InputConfig forString(String str) { InputConfig retVal = new InputConfig(); @@ -85,4 +89,20 @@ public void setDesiredPredicates(Set desiredPredicates) { this.desiredPredicates = desiredPredicates; } + public boolean isWriteAnswerSetsAsXlsx() { + return this.writeAnswerSetsAsXlsx; + } + + public void setWriteAnswerSetsAsXlsx(boolean writeAnswerSetsAsXslx) { + this.writeAnswerSetsAsXlsx = writeAnswerSetsAsXslx; + } + + public String getAnswerSetFileOutputPath() { + return this.answerSetFileOutputPath; + } + + public void setAnswerSetFileOutputPath(String answerSetFileOutputPath) { + this.answerSetFileOutputPath = answerSetFileOutputPath; + } + } From 26cbee0d9f2eb416b0185f40e61e1e7e005f2446 Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Tue, 11 Feb 2020 14:38:52 +0100 Subject: [PATCH 08/18] corrected formatting --- .../java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java b/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java index 9c4312e9a..b8e8e7805 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java @@ -96,8 +96,8 @@ public class CommandLineParser { private static final Option OPT_MOMS_STRATEGY = Option.builder("ms").longOpt("momsStrategy").hasArg(true).argName("strategy") .desc("strategy for mom's heuristic (CountBinaryWatches or BinaryNoGoodPropagation, default: " + SystemConfig.DEFAULT_MOMS_STRATEGY.name() + ")") .build(); - private static final Option OPT_REPLAY_CHOICES = Option.builder("rc").longOpt("replayChoices").hasArg().argName("choices").desc( - "comma-separated list of choices to be replayed (each choice is represented by a signed integer whose absolute value designates an atom ID and whose sign designates a truth value)") + private static final Option OPT_REPLAY_CHOICES = Option.builder("rc").longOpt("replayChoices").hasArg().argName("choices") + .desc("comma-separated list of choices to be replayed (each choice is represented by a signed integer whose absolute value designates an atom ID and whose sign designates a truth value)") .build(); private static final Option OPT_QUIET = Option.builder("q").longOpt("quiet").desc("do not print answer sets (default: " + SystemConfig.DEFAULT_QUIET) .build(); From 5e442eb2c752746dc7e1bfc9ed5f3cead3cbd46a Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Tue, 11 Feb 2020 14:41:25 +0100 Subject: [PATCH 09/18] improved description for write xlsx option --- .../java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java b/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java index b8e8e7805..303265423 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java @@ -74,7 +74,7 @@ public class CommandLineParser { private static final Option OPT_LITERATE = Option.builder("l").longOpt("literate") .desc("enable literate programming mode (default: " + InputConfig.DEFAULT_LITERATE + ")").build(); private static final Option OPT_WRITE_XSLX = Option.builder("wx").longOpt("write-xlsx").hasArg(true).argName("path").type(String.class) - .desc("Write answer sets to xlsx workbooks (one workbook per answer set)").build(); + .desc("Write answer sets to excel files, i.e. xlsx workbooks (one workbook per answer set)").build(); // general system-wide config private static final Option OPT_GROUNDER = Option.builder("g").longOpt("grounder").hasArg(true).argName("grounder") From ebca8982ebcd5d9324a3f1390014718f0f7e5679 Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Tue, 11 Feb 2020 14:47:43 +0100 Subject: [PATCH 10/18] corrected copyright year --- .../kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java index 677c1a3a7..b04833cc3 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java @@ -45,7 +45,7 @@ /** * Implementation of {@link AnswerSetToObjectMapper} that generates an office open xml workbook ("excel file") from a given answer set. * - * Copyright (c) 2019, the Alpha Team. + * Copyright (c) 2020, the Alpha Team. */ public class AnswerSetToWorkbookMapper implements AnswerSetToObjectMapper { From c037b9874d37d41edc354d89fa9a9b5d336bc40b Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Tue, 11 Feb 2020 15:42:32 +0100 Subject: [PATCH 11/18] encapsulate xlsx output handling in main --- .../kr/alpha/AnswerSetToXlsxWriter.java | 42 +++++++++++++++++++ src/main/java/at/ac/tuwien/kr/alpha/Main.java | 38 ++++++++--------- .../kr/alpha/config/CommandLineParser.java | 2 +- 3 files changed, 61 insertions(+), 21 deletions(-) create mode 100644 src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java diff --git a/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java b/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java new file mode 100644 index 000000000..3f4d30fce --- /dev/null +++ b/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java @@ -0,0 +1,42 @@ +package at.ac.tuwien.kr.alpha; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.function.BiConsumer; + +import org.apache.poi.ss.usermodel.Workbook; + +import at.ac.tuwien.kr.alpha.api.mapper.AnswerSetToObjectMapper; +import at.ac.tuwien.kr.alpha.api.mapper.impl.AnswerSetToWorkbookMapper; +import at.ac.tuwien.kr.alpha.common.AnswerSet; + +public class AnswerSetToXlsxWriter implements BiConsumer { + + private String targetBasePath; + private AnswerSetToObjectMapper answerSetMapper; + + public AnswerSetToXlsxWriter(String targetBasePath) { + this.targetBasePath = targetBasePath; + this.answerSetMapper = new AnswerSetToWorkbookMapper(); + } + + @Override + public void accept(Integer num, AnswerSet as) { + try { + Path outputPath = Paths.get(this.targetBasePath + "." + num + ".xlsx"); + OutputStream os = Files.newOutputStream(outputPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); + Workbook wb = this.answerSetMapper.mapFromAnswerSet(as); + wb.write(os); + wb.close(); + os.close(); + System.out.println("Answer set written to file " + outputPath.toString()); + } catch (IOException ex) { + System.err.println("Failed writing answer set as xlsx file! (" + ex.getMessage() + ")"); + } + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/Main.java b/src/main/java/at/ac/tuwien/kr/alpha/Main.java index 4598e75b6..4c3b2be59 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/Main.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/Main.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2019, the Alpha Team. + * Copyright (c) 2016-2020, the Alpha Team. * All rights reserved. * * Additional changes made by Siemens. @@ -29,23 +29,19 @@ import java.io.FileNotFoundException; import java.io.IOException; -import java.io.OutputStream; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; import java.util.stream.Collectors; import java.util.stream.Stream; import org.antlr.v4.runtime.RecognitionException; import org.apache.commons.cli.ParseException; -import org.apache.poi.ss.usermodel.Workbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.api.mapper.impl.AnswerSetToWorkbookMapper; import at.ac.tuwien.kr.alpha.common.AnswerSet; import at.ac.tuwien.kr.alpha.common.Program; import at.ac.tuwien.kr.alpha.config.AlphaConfig; @@ -106,27 +102,29 @@ private static void computeAndConsumeAnswerSets(Alpha alpha, InputConfig inputCf if (!alpha.getConfig().isQuiet()) { AtomicInteger counter = new AtomicInteger(0); - // stream.forEach(as -> System.out.println("Answer set " + counter.incrementAndGet() + ":" + System.lineSeparator() + as.toString())); + final BiConsumer answerSetHandler; + BiConsumer stdoutPrinter = (n, as) -> { + System.out.println("Answer set " + Integer.toString(n) + ":" + System.lineSeparator() + as.toString()); + }; + if (inputCfg.isWriteAnswerSetsAsXlsx()) { + BiConsumer xlsxWriter = new AnswerSetToXlsxWriter(inputCfg.getAnswerSetFileOutputPath()); + answerSetHandler = stdoutPrinter.andThen(xlsxWriter); + } else { + answerSetHandler = stdoutPrinter; + } stream.forEach(as -> { int cnt = counter.incrementAndGet(); - System.out.println("Answer set " + Integer.toString(cnt) + ":" + System.lineSeparator() + as.toString()); + answerSetHandler.accept(cnt, as); + }); + if (counter.get() == 0) { + System.out.println("UNSATISFIABLE"); if (inputCfg.isWriteAnswerSetsAsXlsx()) { try { - Path outputPath = Paths.get(inputCfg.getAnswerSetFileOutputPath() + "." + Integer.toString(cnt) + ".xlsx"); - OutputStream os = Files.newOutputStream(outputPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE, - StandardOpenOption.TRUNCATE_EXISTING); - Workbook wb = new AnswerSetToWorkbookMapper().mapFromAnswerSet(as); - wb.write(os); - wb.close(); - os.close(); - System.out.println("Answer set written to file " + outputPath.toString()); + Files.createFile(Paths.get(inputCfg.getAnswerSetFileOutputPath() + ".UNSAT.xlsx")); } catch (IOException ex) { - System.err.println("Failed writing answer set as xlsx file! (" + ex.getMessage() + ")"); + System.err.println("Failed writing unsat file!"); } } - }); - if (counter.get() == 0) { - System.out.println("UNSATISFIABLE"); } else { System.out.println("SATISFIABLE"); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java b/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java index 303265423..1459b899e 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2016-2019, the Alpha Team. + * Copyright (c) 2016-2020, the Alpha Team. * All rights reserved. * * Additional changes made by Siemens. From eae94301d249e5517465dede7e7620c5fcbdceff Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Fri, 14 Feb 2020 18:22:29 +0100 Subject: [PATCH 12/18] write xlsx also when unsatisfiable, write headers in generated xlsx sheets --- .../kr/alpha/AnswerSetToXlsxWriter.java | 18 +++++++++ src/main/java/at/ac/tuwien/kr/alpha/Main.java | 3 +- .../impl/AnswerSetToWorkbookMapper.java | 39 ++++++++++++++++++- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java b/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java index 3f4d30fce..1995bcda9 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java @@ -8,7 +8,11 @@ import java.nio.file.StandardOpenOption; import java.util.function.BiConsumer; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import at.ac.tuwien.kr.alpha.api.mapper.AnswerSetToObjectMapper; import at.ac.tuwien.kr.alpha.api.mapper.impl.AnswerSetToWorkbookMapper; @@ -39,4 +43,18 @@ public void accept(Integer num, AnswerSet as) { } } + public static void writeUnsatInfo(Path path) throws IOException { + Workbook workbook = new XSSFWorkbook(); + // first, create a worksheet for 0-arity predicates + Sheet sheet = workbook.createSheet("Unsatisfiable"); + Row row = sheet.createRow(0); + Cell cell = row.createCell(0); + cell.setCellValue("Input is unsatisfiable - No answer sets!"); + sheet.autoSizeColumn(0); + OutputStream os = Files.newOutputStream(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); + workbook.write(os); + workbook.close(); + os.close(); + } + } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/Main.java b/src/main/java/at/ac/tuwien/kr/alpha/Main.java index 4c3b2be59..aa31aeb99 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/Main.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/Main.java @@ -29,7 +29,6 @@ import java.io.FileNotFoundException; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Paths; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; @@ -120,7 +119,7 @@ private static void computeAndConsumeAnswerSets(Alpha alpha, InputConfig inputCf System.out.println("UNSATISFIABLE"); if (inputCfg.isWriteAnswerSetsAsXlsx()) { try { - Files.createFile(Paths.get(inputCfg.getAnswerSetFileOutputPath() + ".UNSAT.xlsx")); + AnswerSetToXlsxWriter.writeUnsatInfo(Paths.get(inputCfg.getAnswerSetFileOutputPath() + ".UNSAT.xlsx")); } catch (IOException ex) { System.err.println("Failed writing unsat file!"); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java index b04833cc3..aa52a16c9 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java @@ -28,6 +28,10 @@ import java.util.List; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; @@ -60,15 +64,23 @@ public class AnswerSetToWorkbookMapper implements AnswerSetToObjectMapper Date: Fri, 14 Feb 2020 19:00:10 +0100 Subject: [PATCH 13/18] test for answerSetToXlsxWriter --- .../kr/alpha/AnswerSetToXlsxWriterTest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java diff --git a/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java b/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java new file mode 100644 index 000000000..fe36829e4 --- /dev/null +++ b/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java @@ -0,0 +1,33 @@ +package at.ac.tuwien.kr.alpha; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.Assert; +import org.junit.Test; + +import at.ac.tuwien.kr.alpha.common.AnswerSet; +import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; + +public class AnswerSetToXlsxWriterTest { + + @Test + public void writeAnswerSetFilesTest() throws IOException { + AnswerSet as = new AnswerSetBuilder().predicate("bla").instance("blubb", "blubb").instance("foo", "bar").predicate("foo").instance("bar") + .instance("baz").predicate("complex").instance(Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)).build(); + Path tmpDir = Files.createTempDirectory("alpha-test-xlsx-output"); + AnswerSetToXlsxWriter writer = new AnswerSetToXlsxWriter(tmpDir.toString() + "/alphaAnswerSet"); + writer.accept(0, as); + File tmpDirFile = tmpDir.toFile(); + File[] generatedFiles = tmpDirFile.listFiles(); + Assert.assertEquals(generatedFiles.length, 1); + File answerSetFile = generatedFiles[0]; + Assert.assertEquals("alphaAnswerSet.0.xlsx", answerSetFile.getName()); + // clean up + answerSetFile.delete(); + tmpDirFile.delete(); + } + +} From 3250a55fabc1de5e1e1d00be49689adbd6ad65fb Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Mon, 17 Feb 2020 12:03:17 +0100 Subject: [PATCH 14/18] get rid of useless dummy atom when mapping 0-arity predicates --- .../kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java index aa52a16c9..447d35eb4 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java @@ -43,7 +43,6 @@ import at.ac.tuwien.kr.alpha.common.AnswerSet; import at.ac.tuwien.kr.alpha.common.Predicate; import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; import at.ac.tuwien.kr.alpha.common.terms.Term; /** @@ -74,7 +73,7 @@ public Workbook mapFromAnswerSet(AnswerSet answerSet) { for (Predicate pred : answerSet.getPredicates()) { if (pred.getArity() == 0) { // 0-artiy predicate has no instances in answer set, create a dummy atom - this.writeAtomToSheet(flags, new BasicAtom(pred)); + this.writeAtomToSheet(flags, answerSet.getPredicateInstances(pred).first()); } else { headerContent = new String[pred.getArity()]; for (int i = 0; i < headerContent.length; i++) { From b7186f829a5f952f473e7b6adaa49cbf3586f138 Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Mon, 17 Feb 2020 12:09:48 +0100 Subject: [PATCH 15/18] corrected formatting --- .../tuwien/kr/alpha/config/CommandLineParser.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java b/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java index 1459b899e..35981a5a5 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java @@ -60,6 +60,7 @@ public class CommandLineParser { * to the handler. */ // "special", i.e. non-configuration options + //@formatter:off private static final Option OPT_HELP = Option.builder("h").longOpt("help").hasArg(false).desc("shows this help").build(); // input-specific options @@ -111,16 +112,22 @@ public class CommandLineParser { .desc("use counting grid normalization instead of sorting circuit for #count (default: " + SystemConfig.DEFAULT_USE_NORMALIZATION_GRID + ")") .build(); private static final Option OPT_NO_NOGOOD_DELETION = Option.builder("dnd").longOpt("disableNoGoodDeletion") - .desc("disable the deletion of (learned, little active) nogoods (default: " + SystemConfig.DEFAULT_DISABLE_NOGOOD_DELETION + ")").build(); + .desc("disable the deletion of (learned, little active) nogoods (default: " + + SystemConfig.DEFAULT_DISABLE_NOGOOD_DELETION + ")") + .build(); private static final Option OPT_GROUNDER_TOLERANCE_CONSTRAINTS = Option.builder("gtc").longOpt("grounderToleranceConstraints") - .desc("grounder tolerance for constraints (default: " + SystemConfig.DEFAULT_GROUNDER_TOLERANCE_CONSTRAINTS + ")").hasArg().argName("tolerance") + .desc("grounder tolerance for constraints (default: " + SystemConfig.DEFAULT_GROUNDER_TOLERANCE_CONSTRAINTS + ")") + .hasArg().argName("tolerance") .build(); private static final Option OPT_GROUNDER_TOLERANCE_RULES = Option.builder("gtr").longOpt("grounderToleranceRules") - .desc("grounder tolerance for rules (default: " + SystemConfig.DEFAULT_GROUNDER_TOLERANCE_RULES + ")").hasArg().argName("tolerance").build(); + .desc("grounder tolerance for rules (default: " + SystemConfig.DEFAULT_GROUNDER_TOLERANCE_RULES + ")") + .hasArg().argName("tolerance") + .build(); private static final Option OPT_GROUNDER_ACCUMULATOR_ENABLED = Option.builder("acc").longOpt("enableAccumulator") .desc("activates the accumulator grounding strategy by disabling removal of instances from grounder memory in certain cases (default: " - + SystemConfig.DEFAULT_GROUNDER_ACCUMULATOR_ENABLED + ")") + + SystemConfig.DEFAULT_GROUNDER_ACCUMULATOR_ENABLED + ")") .build(); + //@formatter:on private static final Options CLI_OPTS = new Options(); From 357232c1d547fe2f0e8645625fcf9cdebadfe331 Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Mon, 17 Feb 2020 12:12:35 +0100 Subject: [PATCH 16/18] removed obsolete implementation comment --- .../kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java index 447d35eb4..f044e19bd 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java +++ b/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapper.java @@ -72,7 +72,6 @@ public Workbook mapFromAnswerSet(AnswerSet answerSet) { String[] headerContent; for (Predicate pred : answerSet.getPredicates()) { if (pred.getArity() == 0) { - // 0-artiy predicate has no instances in answer set, create a dummy atom this.writeAtomToSheet(flags, answerSet.getPredicateInstances(pred).first()); } else { headerContent = new String[pred.getArity()]; From 04aa93fec7263af28b9d9a907d5cf7a779c08078 Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Mon, 17 Feb 2020 12:16:12 +0100 Subject: [PATCH 17/18] added verification on written file to AnswerSetToxlsxWriterTest --- .../at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java | 5 +++++ .../alpha/api/mapper/impl/AnswerSetToWorkbookMapperTest.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java b/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java index fe36829e4..3c4aed02f 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java +++ b/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java @@ -5,9 +5,12 @@ import java.nio.file.Files; import java.nio.file.Path; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; import org.junit.Assert; import org.junit.Test; +import at.ac.tuwien.kr.alpha.api.mapper.impl.AnswerSetToWorkbookMapperTest; import at.ac.tuwien.kr.alpha.common.AnswerSet; import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; @@ -25,6 +28,8 @@ public void writeAnswerSetFilesTest() throws IOException { Assert.assertEquals(generatedFiles.length, 1); File answerSetFile = generatedFiles[0]; Assert.assertEquals("alphaAnswerSet.0.xlsx", answerSetFile.getName()); + Workbook wb = WorkbookFactory.create(answerSetFile); + AnswerSetToWorkbookMapperTest.assertWorkbookMatchesAnswerSet(wb, as); // clean up answerSetFile.delete(); tmpDirFile.delete(); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapperTest.java b/src/test/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapperTest.java index 0237df700..cd4a4765e 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapperTest.java +++ b/src/test/java/at/ac/tuwien/kr/alpha/api/mapper/impl/AnswerSetToWorkbookMapperTest.java @@ -50,7 +50,7 @@ public void solveAndWriteWorkbookTest() { AnswerSetToWorkbookMapperTest.assertWorkbookMatchesAnswerSet(answerSetWorkbook, as); } - private static void assertWorkbookMatchesAnswerSet(Workbook wb, AnswerSet as) { + public static void assertWorkbookMatchesAnswerSet(Workbook wb, AnswerSet as) { for (Predicate pred : as.getPredicates()) { if (pred.getArity() == 0) { boolean flagFound = false; From 8f1d5a2058b2638a0fd111531ba369d6fa87c1be Mon Sep 17 00:00:00 2001 From: Michael Langowski Date: Mon, 17 Feb 2020 14:10:07 +0100 Subject: [PATCH 18/18] additional test case for writing unsat info --- .../kr/alpha/AnswerSetToXlsxWriterTest.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java b/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java index 3c4aed02f..a63dbd639 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java +++ b/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java @@ -4,7 +4,10 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import org.junit.Assert; @@ -30,9 +33,32 @@ public void writeAnswerSetFilesTest() throws IOException { Assert.assertEquals("alphaAnswerSet.0.xlsx", answerSetFile.getName()); Workbook wb = WorkbookFactory.create(answerSetFile); AnswerSetToWorkbookMapperTest.assertWorkbookMatchesAnswerSet(wb, as); + wb.close(); // clean up answerSetFile.delete(); tmpDirFile.delete(); } + @Test + public void writeUnsatTest() throws IOException { + Path tmpDir = Files.createTempDirectory("alpha-test-xlsx-unsat"); + AnswerSetToXlsxWriter.writeUnsatInfo(Paths.get(tmpDir.toString() + "/alphaAnswerSet.UNSAT.xlsx")); + File tmpDirFile = tmpDir.toFile(); + File[] generatedFiles = tmpDirFile.listFiles(); + Assert.assertEquals(generatedFiles.length, 1); + File unsatFile = generatedFiles[0]; + Assert.assertEquals("alphaAnswerSet.UNSAT.xlsx", unsatFile.getName()); + Workbook wb = WorkbookFactory.create(unsatFile); + Sheet unsatSheet = wb.getSheet("Unsatisfiable"); + Assert.assertNotNull(unsatSheet); + Cell cell = unsatSheet.getRow(0).getCell(0); + Assert.assertNotNull(cell); + String cellValue = cell.getStringCellValue(); + Assert.assertEquals("Input is unsatisfiable - No answer sets!", cellValue); + wb.close(); + // clean up + unsatFile.delete(); + tmpDirFile.delete(); + } + }