Skip to content

Commit e9ed631

Browse files
authored
Merge pull request #144 from arnaud-m/feat-138
Generation of bignum multiplications - close #138
2 parents d85413b + 820c1dc commit e9ed631

16 files changed

+98
-80
lines changed

src/main/benchmarks/README.org

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ The word lists ~colors.txt~ and ~monsters.txt~ takes the most time by far (aroun
236236

237237
*** Multiplication
238238
#+BEGIN_SRC sh
239-
echo -v quiet -d FALSE -mult TRUE -lightM FALSE -lightP FALSE > algorithms/ALL.dat
239+
echo -v quiet -d FALSE -mult TRUE -multUnique TRUE -lightP FALSE > algorithms/ALL.dat
240240
#+END_SRC
241241

242242
*** Long Multiplication
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
sechzehn = zwei * acht
22
vier * funf = zwei * zehn
3+
funf * dreißig = drei * funfzig
4+
neun * dreißig = drei * neunzig

src/main/cryptarithms/multiplications/tr-1-500.db.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ uc * kırkuc = bir * on * onuc
1313
ucyuz = on * otuz
1414
yedi * otuz = iki * yuzuc
1515
yetmis = yedi * on
16+
bir * on * yirmi = ikiyuzbir
17+
iki * ikiyuz = dortyuzuc
18+
altı * elliuc = uc * yuzaltı
19+
oniki * onaltı = altı * otuziki
20+
dort * otuzuc = uc * kırkdort

src/main/java/cryptator/config/CryptaCmdConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public final boolean useBignum() {
4141
return useBigNum;
4242
}
4343

44-
public final void setUseBigNum(boolean useBigNum) {
44+
public final void setUseBigNum(final boolean useBigNum) {
4545
this.useBigNum = useBigNum;
4646
}
4747

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ public class CryptagenConfig extends CryptaCmdConfig {
4343
@Option(name = "-lightP", handler = ExplicitBooleanOptionHandler.class, usage = "use weak consistency")
4444
private boolean lightPropagation;
4545

46+
@Option(name = "-multUnique", handler = ExplicitBooleanOptionHandler.class, usage = "use weak consistency")
47+
private boolean multUnique;
48+
4649
public final boolean isDryRun() {
4750
return dryRun;
4851
}
@@ -79,6 +82,10 @@ public final boolean isLightPropagation() {
7982
return lightPropagation;
8083
}
8184

85+
public final boolean isMultUnique() {
86+
return multUnique;
87+
}
88+
8289
public final void setLightPropagation(final boolean lightPropagation) {
8390
this.lightPropagation = lightPropagation;
8491
}

src/main/java/cryptator/gen/AbstractCryptaListModel.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,6 @@ public void buildModel() {
7676
*/
7777
public abstract void postDoublyTrueConstraints(int lowerBound);
7878

79-
/**
80-
* Post optional constraints for the numerical precision.
81-
*
82-
* @param base the arithmetic base
83-
*/
84-
public abstract void postPrecisionConstraints(int base);
85-
8679
/**
8780
* Post heavy constraints for filtering more candidates.
8881
*

src/main/java/cryptator/gen/CryptaGenAdd.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,6 @@ public void postDoublyTrueConstraints(final int lb) {
6767
model.scalar(rvars, coeffs, "=", 0).post();
6868
}
6969

70-
@Override
71-
public void postPrecisionConstraints(final int base) {
72-
// Nothing to do.
73-
}
74-
7570
@Override
7671
public final ICryptaNode recordCryptarithm() {
7772
return addition.recordCryptarithm();

src/main/java/cryptator/gen/CryptaGenCrossword.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,6 @@ public void postHeavyConstraints(final int base) {
9999
Stream.of(additions).forEach(m -> m.postHeavyConstraints(base));
100100
}
101101

102-
@Override
103-
public void postPrecisionConstraints(final int base) {
104-
// Nothing to do.
105-
}
106-
107102
@Override
108103
protected void postWordConstraints() {
109104
final IntVar one = model.intVar(1);

src/main/java/cryptator/gen/CryptaGenLongMult.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
*/
99
package cryptator.gen;
1010

11+
import java.math.BigInteger;
1112
import java.util.ArrayList;
1213
import java.util.Arrays;
1314
import java.util.HashMap;
15+
import java.util.HashSet;
1416
import java.util.Map;
17+
import java.util.Set;
1518

1619
import org.chocosolver.solver.Model;
1720
import org.chocosolver.solver.variables.BoolVar;
@@ -21,7 +24,6 @@
2124

2225
import cryptator.CryptaOperator;
2326
import cryptator.gen.pattern.CryptaLongMultModel;
24-
import cryptator.solver.AdaptiveSolver;
2527
import cryptator.specs.ICryptaNode;
2628
import cryptator.tree.CryptaConstant;
2729
import cryptator.tree.CryptaLeaf;
@@ -82,12 +84,6 @@ public void postHeavyConstraints(final int base) {
8284
// Nothing to do
8385
}
8486

85-
@Override
86-
public void postPrecisionConstraints(final int base) {
87-
final int thresh = AdaptiveSolver.computeThreshold(base);
88-
longMult.getProductLength().le(thresh).post();
89-
}
90-
9187
private String[] getTermWords() {
9288
final int[] terms = longMult.getTermIndices();
9389
final char[] mult = words[longMult.getMultiplierIndex()].toCharArray();
@@ -104,12 +100,13 @@ private String[] getTermWords() {
104100
}
105101

106102
private static ICryptaNode recordTermAddition(final String[] terms, final String product, final int base) {
103+
107104
ArrayList<ICryptaNode> nodes = new ArrayList<>();
108-
int exponent = 1;
105+
BigInteger exponent = BigInteger.valueOf(1);
109106
for (int i = terms.length - 1; i >= 0; i--) {
110107
nodes.add(new CryptaNode(CryptaOperator.MUL, new CryptaLeaf(terms[i]),
111-
new CryptaConstant(Integer.toString(exponent))));
112-
exponent *= base;
108+
new CryptaConstant(exponent.toString())));
109+
exponent = exponent.multiply(BigInteger.valueOf(base));
113110
}
114111
ICryptaNode addition = GenerateUtil.reduceOperation(CryptaOperator.ADD, nodes.stream());
115112
return new CryptaNode(CryptaOperator.EQ, addition, new CryptaLeaf(product));
@@ -119,8 +116,12 @@ private static ICryptaNode recordTermMultiplications(final String[] terms, final
119116
final String multiplier) {
120117
final char[] multipliers = multiplier.toCharArray();
121118
final ArrayList<ICryptaNode> nodes = new ArrayList<>();
119+
final Set<Character> letters = new HashSet<>();
122120
for (int i = 0; i < terms.length; i++) {
123-
nodes.add(GenerateUtil.recordMultiplication(multiplicand, Character.toString(multipliers[i]), terms[i]));
121+
Character letter = Character.valueOf(multipliers[i]);
122+
if (letters.add(letter)) {
123+
nodes.add(GenerateUtil.recordMultiplication(multiplicand, letter.toString(), terms[i]));
124+
}
124125
}
125126
return GenerateUtil.reduceOperation(CryptaOperator.AND, nodes.stream());
126127
}

src/main/java/cryptator/gen/CryptaGenMult.java

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,12 @@
1414

1515
import cryptator.gen.member.CryptaMemberLen;
1616
import cryptator.gen.member.CryptaMemberPair;
17-
import cryptator.solver.AdaptiveSolver;
1817
import cryptator.specs.ICryptaNode;
1918

2019
class CryptaMemberMult extends CryptaMemberPair {
2120

22-
private final IntVar sumL;
23-
24-
private final IntVar sumR;
25-
26-
public CryptaMemberMult(final Model model, final String[] words, final String prefix) {
27-
super(new CryptaMemberLen(model, words, prefix + "L_"), new CryptaMemberLen(model, words, prefix + "R_"));
28-
final int ub = AbstractCryptaGenModel.getSumLength(words);
29-
this.sumL = model.intVar("L_sumLength", 0, ub);
30-
this.sumR = model.intVar("R_sumLength", 0, ub);
31-
21+
public CryptaMemberMult(final Model model, final String[] words, final String prefix, final boolean isRightUnique) {
22+
super(model, words, prefix, isRightUnique);
3223
}
3324

3425
@Override
@@ -45,18 +36,18 @@ public ICryptaNode recordCryptarithm() {
4536

4637
@Override
4738
protected void postSymBreakLengthConstraint() {
48-
getModel().lexLess(left.getWordVars(), right.getWordVars()).post();
49-
}
50-
51-
public void postMultPrecisionConstraints(final int base) {
52-
getModel().sum(left.lengths, "=", sumL).post();
53-
getModel().sum(((CryptaMemberLen) right).lengths, "=", sumR).post();
54-
final int thresh = AdaptiveSolver.computeThreshold(base) + 1;
55-
sumL.le(thresh).post();
56-
sumR.le(thresh).post();
39+
if (right instanceof CryptaMemberLen) {
40+
getModel().lexLess(left.getWordVars(), right.getWordVars()).post();
41+
} else {
42+
left.getMaxLength().le(right.getMaxLength()).post();
43+
}
5744
}
5845

5946
public void postMultHeavyConstraints(final int base) {
47+
final IntVar sumL = getModel().sum("L_sumLength", left.lengths);
48+
final IntVar sumR = (right instanceof CryptaMemberLen)
49+
? getModel().sum("R_sumLength", ((CryptaMemberLen) right).lengths)
50+
: right.getMaxLength();
6051
final ArExpression minL = sumL.sub(left.getWordCount()).add(1);
6152
final ArExpression minR = sumR.sub(right.getWordCount()).add(1);
6253
minL.le(sumR).post();
@@ -71,9 +62,9 @@ public class CryptaGenMult extends AbstractCryptaListModel {
7162

7263
private final CryptaMemberMult multiplication;
7364

74-
public CryptaGenMult(final String[] words) {
65+
public CryptaGenMult(final String[] words, final boolean isRightUnique) {
7566
super(new Model("Generate-Multiplication"), words);
76-
multiplication = new CryptaMemberMult(model, words, "");
67+
multiplication = new CryptaMemberMult(model, words, "", isRightUnique);
7768
}
7869

7970
@Override
@@ -132,13 +123,6 @@ public void postDoublyTrueConstraints(final int lb) {
132123
sumL.sub(sumR).abs().mul(2).le(wordCount).post();
133124
}
134125

135-
@Override
136-
public void postPrecisionConstraints(final int base) {
137-
final int thresh = AdaptiveSolver.computeThreshold(base);
138-
getMaxLength().le(thresh).post();
139-
multiplication.postMultPrecisionConstraints(base);
140-
}
141-
142126
@Override
143127
public final ICryptaNode recordCryptarithm() {
144128
return multiplication.recordCryptarithm();

0 commit comments

Comments
 (0)