Skip to content

Commit 72a1b8f

Browse files
authored
Merge pull request #69 from arnaud-m/feature-64
Improve logging of cryptarithm generation close #64
2 parents e7c6177 + fdbeae3 commit 72a1b8f

File tree

7 files changed

+78
-67
lines changed

7 files changed

+78
-67
lines changed

src/main/java/cryptator/Cryptagen.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,10 @@ protected CryptagenOptionsParser() {
104104

105105
@Override
106106
protected void configureLoggers() {
107-
if (config.isDryRun()) {
108-
getLogger().setLevel(config.isVerbose() ? Level.FINE : Level.CONFIG);
107+
if (config.isVerbose()) {
108+
JULogUtil.configureLoggers(Level.ALL);
109109
} else {
110-
if (config.isVerbose()) {
111-
JULogUtil.setLevel(Level.CONFIG, getLogger());
112-
} else {
113-
JULogUtil.setLevel(Level.WARNING, CryptaSolver.LOGGER);
114-
}
110+
JULogUtil.setLevel(Level.WARNING, CryptaSolver.LOGGER);
115111
}
116112
}
117113

@@ -124,9 +120,6 @@ public String getArgumentName() {
124120
private static CryptaBiConsumer buildBiConsumer(final CryptagenConfig config) {
125121
CryptaBiConsumer consumer = new CryptaBiConsumer(LOGGER);
126122
consumer.withCryptarithmLog();
127-
if (config.isCheckSolution()) {
128-
consumer.withSolutionCheck(config.getArithmeticBase());
129-
}
130123
if (config.isExportGraphiz()) {
131124
consumer.withGraphvizExport();
132125
}
@@ -138,8 +131,10 @@ private static int generate(final WordArray words, final CryptagenConfig config)
138131
final CryptaBiConsumer cons = buildBiConsumer(config);
139132
try {
140133
gen.generate(cons);
134+
LOGGER.log(Level.INFO, "Found {0} cryptarithm(s).", cons.getSolutionCount());
135+
141136
} catch (CryptaModelException e) {
142-
LOGGER.log(Level.SEVERE, "fail to build the model.", e);
137+
LOGGER.log(Level.SEVERE, "Fail to build the model.", e);
143138
return -1;
144139
}
145140
return gen.getErrorCount() + cons.getErrorCount();

src/main/java/cryptator/choco/ChocoLogger.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import org.chocosolver.solver.Solution;
1818
import org.chocosolver.solver.Solver;
1919

20+
import cryptator.specs.IChocoModel;
21+
2022
public final class ChocoLogger {
2123

2224
private final Logger logger;
@@ -26,6 +28,10 @@ public ChocoLogger(Logger logger) {
2628
this.logger = logger;
2729
}
2830

31+
public void logOnModel(final IChocoModel m) {
32+
logOnModel(m.getModel());
33+
}
34+
2935
public void logOnModel(final Model model) {
3036
if (logger.isLoggable(Level.CONFIG)) {
3137
logger.log(Level.CONFIG, "Model diagnostics:\n{0}", toDimacs(model));
@@ -40,10 +46,18 @@ public void logOnSolution(final Solution solution) {
4046
}
4147
}
4248

49+
public void logOnSolution(final IChocoModel m) {
50+
logOnSolution(m.getModel());
51+
}
52+
4353
public void logOnSolution(final Model model) {
4454
logOnSolution(new Solution(model));
4555
}
4656

57+
public void logOnSolver(final IChocoModel m) {
58+
logOnSolver(m.getModel());
59+
}
60+
4761
public void logOnSolver(Model model) {
4862
if (logger.isLoggable(Level.INFO)) {
4963
logger.log(Level.INFO, "Solver diagnostics:\n{0}", toDimacs(model.getSolver()));

src/main/java/cryptator/gen/CryptaListGenerator.java

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99
package cryptator.gen;
1010

11+
import java.util.Optional;
1112
import java.util.concurrent.ExecutorService;
1213
import java.util.concurrent.Executors;
1314
import java.util.concurrent.TimeUnit;
@@ -20,6 +21,8 @@
2021
import org.chocosolver.solver.Solution;
2122
import org.chocosolver.solver.Solver;
2223

24+
import cryptator.choco.ChocoLogger;
25+
import cryptator.cmd.CryptaBiConsumer;
2326
import cryptator.cmd.WordArray;
2427
import cryptator.config.CryptagenConfig;
2528
import cryptator.solver.AdaptiveSolver;
@@ -35,19 +38,22 @@ public class CryptaListGenerator implements ICryptaGenerator {
3538

3639
private static final int TICK = 1000;
3740

38-
private WordArray words;
41+
private final WordArray words;
3942

40-
private CryptagenConfig config;
43+
private final CryptagenConfig config;
4144

42-
private Logger logger;
45+
private final Logger logger;
4346

44-
private AtomicInteger errorCount;
47+
private final ChocoLogger clog;
48+
49+
private final AtomicInteger errorCount;
4550

4651
public CryptaListGenerator(final WordArray words, final CryptagenConfig config, final Logger logger) {
4752
super();
4853
this.words = words;
4954
this.config = config;
5055
this.logger = logger;
56+
this.clog = new ChocoLogger(logger);
5157
this.errorCount = new AtomicInteger();
5258
}
5359

@@ -109,7 +115,7 @@ private static void parallelSolve(final CryptaGenModel gen, final Consumer<ICryp
109115
@Override
110116
public void generate(final BiConsumer<ICryptaNode, ICryptaSolution> consumer) throws CryptaModelException {
111117
final CryptaGenModel gen = buildModel();
112-
logger.log(Level.FINE, "Display model{0}", gen.getModel());
118+
clog.logOnModel(gen);
113119

114120
final Consumer<ICryptaNode> cons = buildConsumer(gen, consumer);
115121

@@ -119,10 +125,7 @@ public void generate(final BiConsumer<ICryptaNode, ICryptaSolution> consumer) th
119125
} else {
120126
parallelSolve(gen, cons, nthreads);
121127
}
122-
123-
if (logger.isLoggable(Level.FINE)) {
124-
logger.log(Level.FINE, "{0}", gen.getModel().getSolver().getMeasures());
125-
}
128+
clog.logOnSolver(gen);
126129
}
127130

128131
// FIXME are consumers thread-safe ? they are used in parallel !
@@ -138,37 +141,13 @@ private class LogConsumer implements Consumer<ICryptaNode> {
138141
@Override
139142
public void accept(final ICryptaNode t) {
140143
if (logger.isLoggable(Level.CONFIG)) {
141-
logger.log(Level.CONFIG, "candidate: {0}", TreeUtils.writeInorder(t));
142-
if (logger.isLoggable(Level.FINE)) {
143-
solution.record();
144-
logger.log(Level.FINE, "candidate from solver:\n{0}", solution);
145-
}
144+
logger.log(Level.CONFIG, "Candidate cryptarithm:\n{0}", TreeUtils.writeInorder(t));
145+
clog.logOnSolution(solution);
146146
}
147147
}
148148

149149
}
150150

151-
private static class SolutionCollect implements Consumer<ICryptaSolution> {
152-
153-
private int solutionCount;
154-
155-
private ICryptaSolution solution;
156-
157-
@Override
158-
public void accept(final ICryptaSolution u) {
159-
solutionCount++;
160-
this.solution = u;
161-
}
162-
163-
public final boolean hasUniqueSolution() {
164-
return solutionCount == 1;
165-
}
166-
167-
public final ICryptaSolution getSolution() {
168-
return solution;
169-
}
170-
}
171-
172151
private class GenerateConsumer implements Consumer<ICryptaNode> {
173152

174153
private final ICryptaSolver solver;
@@ -182,17 +161,26 @@ private class GenerateConsumer implements Consumer<ICryptaNode> {
182161
this.solver.limitSolution(2);
183162
}
184163

164+
private CryptaBiConsumer buildBiConsumer() {
165+
CryptaBiConsumer consumer = new CryptaBiConsumer(logger);
166+
if (config.isCheckSolution()) {
167+
consumer.withSolutionCheck(config.getArithmeticBase());
168+
}
169+
return consumer;
170+
}
171+
185172
@Override
186173
public void accept(final ICryptaNode t) {
187174
try {
188-
final SolutionCollect collect = new SolutionCollect();
175+
final CryptaBiConsumer collect = buildBiConsumer();
189176
solver.solve(t, config, collect);
190-
if (collect.hasUniqueSolution()) {
191-
internal.accept(t, collect.getSolution());
177+
Optional<ICryptaSolution> solution = collect.getUniqueSolution();
178+
if (solution.isPresent()) {
179+
internal.accept(t, solution.get());
192180
}
193181
} catch (CryptaModelException | CryptaSolverException e) {
194182
errorCount.incrementAndGet();
195-
logger.log(Level.WARNING, "failed to solve the cryptarithm", e);
183+
logger.log(Level.WARNING, "Fail to solve the cryptarithm", e);
196184
}
197185
}
198186
}

src/main/java/cryptator/solver/CryptaModel.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313
import org.chocosolver.solver.Model;
1414
import org.chocosolver.solver.variables.IntVar;
1515

16+
import cryptator.specs.IChocoModel;
1617
import cryptator.specs.ICryptaSolution;
1718

1819
/**
1920
* The Class CryptaModel encapsulates the choco model and solution.
2021
*/
21-
public final class CryptaModel {
22+
public final class CryptaModel implements IChocoModel {
2223

2324
/** The model. */
2425
private final Model model;
@@ -39,11 +40,7 @@ public CryptaModel(final Model model, final Map<Character, IntVar> symbolsToVari
3940
this.solution = new CryptaSolutionVars(symbolsToVariables);
4041
}
4142

42-
/**
43-
* Gets the model.
44-
*
45-
* @return the model
46-
*/
43+
@Override
4744
public Model getModel() {
4845
return model;
4946
}

src/main/java/cryptator/solver/CryptaSolver.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public boolean solve(final ICryptaNode cryptarithm, final CryptaConfig config,
9191
final CryptaModel m = modeler.model(cryptarithm, config);
9292
logOnCryptarithm(cryptarithm);
9393
logOnConfiguration(config);
94-
CLOG.logOnModel(m.getModel());
94+
CLOG.logOnModel(m);
9595

9696
final Solver s = m.getModel().getSolver();
9797
if (timeLimit > 0) {
@@ -111,7 +111,7 @@ public boolean solve(final ICryptaNode cryptarithm, final CryptaConfig config,
111111
solutionCount++;
112112
}
113113
}
114-
CLOG.logOnSolver(m.getModel());
114+
CLOG.logOnSolver(m);
115115
return solutionCount > 0;
116116
}
117117

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* This file is part of cryptator, https://github.com/arnaud-m/cryptator
3+
*
4+
* Copyright (c) 2022, Université Côte d'Azur. All rights reserved.
5+
*
6+
* Licensed under the BSD 3-clause license.
7+
* See LICENSE file in the project root for full license information.
8+
*/
9+
package cryptator.specs;
10+
11+
import org.chocosolver.solver.Model;
12+
13+
/**
14+
* Getter interface of a Choco model.
15+
*/
16+
public interface IChocoModel {
17+
18+
/**
19+
* Gets the model.
20+
*
21+
* @return the model
22+
*/
23+
Model getModel();
24+
25+
}

src/main/java/cryptator/specs/ICryptaGenModel.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,14 @@
88
*/
99
package cryptator.specs;
1010

11-
import org.chocosolver.solver.Model;
1211
import org.chocosolver.solver.variables.BoolVar;
1312
import org.chocosolver.solver.variables.IntVar;
1413

1514
/**
1615
* The Interface ICryptaGenVariables to access variables used for generating
1716
* cryptarithms.
1817
*/
19-
public interface ICryptaGenModel {
20-
21-
/**
22-
* Gets the model.
23-
*
24-
* @return the model
25-
*/
26-
Model getModel();
18+
public interface ICryptaGenModel extends IChocoModel {
2719

2820
/**
2921
* Gets the number of words or word variables.

0 commit comments

Comments
 (0)