Skip to content

Commit 265e6a2

Browse files
authored
Merge pull request #65 from arnaud-m/constraintGen
- close #34
2 parents 946924c + 29ae25e commit 265e6a2

15 files changed

+983
-291
lines changed

src/main/java/cryptator/config/CryptagenConfig.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
public class CryptagenConfig extends CryptaCmdConfig {
1515

16-
@Option(name="-d",handler=ExplicitBooleanOptionHandler.class,usage="dry run (generate but do not solve candidate cryptarithms)")
16+
@Option(name="-d",handler=ExplicitBooleanOptionHandler.class, usage="dry run (generate but do not solve candidate cryptarithms)")
1717
private boolean dryRun;
1818

1919
@Option(name="-ctry",usage="country code for doubly true cryptarithms)")
@@ -31,6 +31,11 @@ public class CryptagenConfig extends CryptaCmdConfig {
3131
@Option(name="-maxop", usage="maximum number of left operands")
3232
private int maxLeftOperands= -1;
3333

34+
@Option(name="-lightM", handler=ExplicitBooleanOptionHandler.class, usage="use less auxiliary variables")
35+
private boolean lightModel = true;
36+
37+
@Option(name="-lightP", handler=ExplicitBooleanOptionHandler.class, usage="use weak consistency")
38+
private boolean lightPropagation;
3439

3540
public final boolean isDryRun() {
3641
return dryRun;
@@ -56,9 +61,26 @@ public final int getMaxLeftOperands() {
5661
return maxLeftOperands;
5762
}
5863

64+
65+
public final boolean isLightModel() {
66+
return lightModel;
67+
}
68+
69+
public final void setLightModel(boolean lightModel) {
70+
this.lightModel = lightModel;
71+
}
72+
73+
public final boolean isLightPropagation() {
74+
return lightPropagation;
75+
}
76+
77+
public final void setLightPropagation(boolean lightPropagation) {
78+
this.lightPropagation = lightPropagation;
79+
}
80+
5981
@Override
6082
public String toString() {
61-
return super.toString() + "\nc LANG " + langCode + "\nc THREADS " + nthreads;
83+
return super.toString() + "\nc LANG " + langCode + "\nc THREADS " + nthreads+"\nc LIGHT_MOD " + lightModel+"\nc LIGHT_PROPAG " + lightPropagation;
6284
}
6385

6486

src/main/java/cryptator/gen/CryptaEqnMember.java

Lines changed: 0 additions & 83 deletions
This file was deleted.
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
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.gen;
10+
11+
import java.util.Arrays;
12+
import java.util.Collection;
13+
import java.util.function.BinaryOperator;
14+
import java.util.stream.Collectors;
15+
import java.util.stream.IntStream;
16+
import java.util.stream.Stream;
17+
18+
import org.chocosolver.solver.Model;
19+
import org.chocosolver.solver.variables.BoolVar;
20+
import org.chocosolver.solver.variables.IntVar;
21+
22+
import cryptator.CryptaOperator;
23+
import cryptator.specs.ICryptaGenModel;
24+
import cryptator.specs.ICryptaNode;
25+
import cryptator.tree.CryptaConstant;
26+
import cryptator.tree.CryptaLeaf;
27+
import cryptator.tree.CryptaNode;
28+
import cryptator.tree.TreeUtils;
29+
30+
/**
31+
* Base class for generation model..
32+
*/
33+
class CryptaGenBaseModel implements ICryptaGenModel {
34+
35+
36+
/** The model. */
37+
protected final Model model;
38+
39+
/** The word array . */
40+
protected final String[] words;
41+
42+
/** The word variables that indicates if the word is present. */
43+
protected final BoolVar[] vwords;
44+
45+
/** The word count. */
46+
protected final IntVar wordCount;
47+
48+
/** The maximum length of a present word. */
49+
protected final IntVar maxLength;
50+
51+
public CryptaGenBaseModel(Model model, String[] words, String prefix, boolean boundedDomain) {
52+
super();
53+
this.model = model;
54+
this.words = words;
55+
this.vwords = buildWordVars(model, words, prefix);
56+
this.wordCount = model.intVar(prefix+ "wordCount", 0, words.length);
57+
this.maxLength = model.intVar(prefix+ "maxLength", 0, getMaxLength(words), boundedDomain);
58+
}
59+
60+
@Override
61+
public final Model getModel() {
62+
return model;
63+
}
64+
65+
@Override
66+
public final String[] getWords() {
67+
return words;
68+
}
69+
70+
@Override
71+
public final BoolVar[] getWordVars() {
72+
return vwords;
73+
}
74+
75+
@Override
76+
public final IntVar getWordCount() {
77+
return wordCount;
78+
}
79+
80+
@Override
81+
public final IntVar getMaxLength() {
82+
return maxLength;
83+
}
84+
85+
/**
86+
* Builds named boolean variables associated to the words.
87+
*
88+
* @param model the model
89+
* @param words the words list
90+
* @param prefix the prefix for the variable names
91+
* @return the array of boolean variables
92+
*/
93+
private static BoolVar[] buildWordVars(Model model, String[] words, String prefix) {
94+
final BoolVar[] vars = new BoolVar[words.length];
95+
for (int i = 0; i < words.length; i++) {
96+
vars[i] = model.boolVar(prefix + words[i]);
97+
}
98+
return vars;
99+
}
100+
101+
protected void postWordCountConstraint() {
102+
model.sum(vwords, "=", wordCount).post();
103+
}
104+
105+
protected void postMaxLengthConstraints() {
106+
maxLength.eq(0).decompose().post();
107+
}
108+
109+
@Override
110+
public void buildModel() {
111+
postWordCountConstraint();
112+
postMaxLengthConstraints();
113+
}
114+
115+
public static int[] getLengths(String[] words) {
116+
return Arrays.stream(words).mapToInt(String::length).toArray();
117+
}
118+
119+
public static int getMaxLength(String[] words) {
120+
return Arrays.stream(words).mapToInt(String::length).max().orElse(0);
121+
}
122+
123+
public static int[] getLengthCounts(String[] words) {
124+
final int n = getMaxLength(words);
125+
int[] v = new int[n + 1];
126+
for (String w : words) {
127+
v[w.length()]++;
128+
}
129+
return v;
130+
}
131+
132+
public static BoolVar[] toArray(Collection<BoolVar> vars) {
133+
return vars.toArray(new BoolVar[vars.size()]);
134+
}
135+
136+
public static Stream<String> wordStream(ICryptaGenModel model) {
137+
final BoolVar[] v = model.getWordVars();
138+
final String[] w = model.getWords();
139+
return IntStream.range(0, model.getN())
140+
.filter(i -> v[i].isInstantiatedTo(1))
141+
.mapToObj(i -> w[i]);
142+
}
143+
144+
public static String recordString(ICryptaGenModel model, String separator) {
145+
return wordStream(model).collect( Collectors.joining(separator ) );
146+
}
147+
148+
public static ICryptaNode recordAddition(ICryptaGenModel model) {
149+
BinaryOperator<ICryptaNode> add = (a, b) -> {
150+
return a == null ? b : new CryptaNode(CryptaOperator.ADD, a, b);
151+
};
152+
return wordStream(model)
153+
.map(CryptaLeaf::new)
154+
.map(ICryptaNode.class::cast)
155+
.reduce(null, add);
156+
}
157+
158+
159+
@Override
160+
public String toString() {
161+
return recordString(this, " + ");
162+
}
163+
164+
}

0 commit comments

Comments
 (0)