Skip to content

Check code coverage and good practices #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/benchmarks/README.org
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ The word lists ~colors.txt~ and ~monsters.txt~ takes the most time by far (aroun
generateCrossword 3
#+END_SRC


** Configure the algorithm

*** Addition
Expand All @@ -245,7 +246,6 @@ The word lists ~colors.txt~ and ~monsters.txt~ takes the most time by far (aroun
* Solve
** Create the solver
*** Cryptator
**** Simple Precision

#+BEGIN_SRC sh :tangle solver.sh
JAR=cryptator-0.6.0-SNAPSHOT-with-dependencies.jar
Expand Down
6 changes: 6 additions & 0 deletions src/main/cryptarithms/long-multiplications/samples.db.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
in * gag = vain && in * '1' + kan * '10' + in * '100' = vain && in * g = in && in * a = kan && in * g = in
in * gag = vain && in * '1' + km * '10' + in * '100' = vain && in * g = in && in * a = km && in * g = in
in * go = kan && in * '1' + km * '10' = kan && in * g = km && in * o = in
in * ive = olim && km * '1' + go * '10' + in * '100' = olim && in * i = in && in * v = go && in * e = km
km * km = kan && in * '1' + km * '10' = kan && km * k = km && km * m = in
surs * cc = relus && surs * '1' + surs * '10' = relus && surs * c = surs && surs * c = surs
2 changes: 1 addition & 1 deletion src/main/java/cryptator/config/CryptaLogConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public final Verbosity getVerbosity() {
return verbosity;
}

public final void setVerbosity(Verbosity verbosity) {
public final void setVerbosity(final Verbosity verbosity) {
this.verbosity = verbosity;
}

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/cryptator/config/CryptagenConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public final int getGridSize() {
return gridSize;
}

public final void setGridSize(int gridSize) {
public final void setGridSize(final int gridSize) {
this.gridSize = gridSize;
}

Expand Down Expand Up @@ -98,15 +98,15 @@ public final boolean isMultModel() {
return multModel;
}

public final void setMultModel(boolean multModel) {
public final void setMultModel(final boolean multModel) {
this.multModel = multModel;
}

public final boolean isLongMultModel() {
return longMultModel;
}

public final void setLongMultModel(boolean longMultModel) {
public final void setLongMultModel(final boolean longMultModel) {
this.longMultModel = longMultModel;
}

Expand Down
55 changes: 55 additions & 0 deletions src/main/java/cryptator/gen/AbstractCryptaGenModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ public abstract class AbstractCryptaGenModel implements ICryptaGenModel {
/** The maximum length of a present word. */
protected final IntVar maxLength;

/**
* Instantiates a new model for the generation.
*
* @param model the model
* @param words the words
* @param prefix the prefix for variable names
*/
protected AbstractCryptaGenModel(final Model model, final String[] words, final String prefix) {
super();
this.model = model;
Expand All @@ -46,6 +53,11 @@ protected AbstractCryptaGenModel(final Model model, final String[] words, final
this.maxLength = model.intVar(prefix + "maxLength", 0, AbstractCryptaGenModel.getMaxLength(words), false);
}

/**
* Gets the model.
*
* @return the model
*/
@Override
public final Model getModel() {
return model;
Expand Down Expand Up @@ -87,14 +99,26 @@ private static BoolVar[] buildWordVars(final Model model, final String[] words,
return vars;
}

/**
* Post constraints for the presence of words.
*/
protected abstract void postWordConstraints();

/**
* Post word count constraint.
*/
protected void postWordCountConstraint() {
model.sum(vwords, "=", wordCount).post();
}

/**
* Post the constraints that set the maximum length.
*/
protected abstract void postMaxLengthConstraints();

/**
* Builds the model.
*/
@Override
public void buildModel() {
postWordConstraints();
Expand All @@ -115,6 +139,11 @@ public void postWordCountConstraints(final int min, final int max) {
}
}

/**
* Post a constraint that set the number of words.
*
* @param val the number of words
*/
public void postWordCountConstraints(final int val) {
wordCount.eq(val).post();
}
Expand All @@ -124,18 +153,44 @@ public String toString() {
return GenerateUtil.recordString(this, " ");
}

/**
* Gets the maximum length of the words.
*
* @param words the words
* @return the maximum length
*/
public static final int getMaxLength(final String[] words) {
return Arrays.stream(words).mapToInt(String::length).max().orElse(0);
}

/**
* Gets the sum of the word lengths.
*
* @param words the words
* @return the sum of the lengths
*/
public static final int getSumLength(final String[] words) {
return Arrays.stream(words).mapToInt(String::length).reduce(0, Integer::sum);
}

/**
* Gets the array of word lengths.
*
* @param words the words
* @return the array of lengths
*/
public static final int[] getLengths(final String[] words) {
return Arrays.stream(words).mapToInt(String::length).toArray();
}

/**
* Gets the array of length cardinalities.
*
* The cardinality of a word is its number of distinct characters.
*
* @param words the words
* @return the array of cardinalities
*/
public static final int[] getCards(final String[] words) {
final ToIntFunction<String> distinctCharCount = s -> (int) s.chars().distinct().count();
return Arrays.stream(words).mapToInt(distinctCharCount).toArray();
Expand Down
39 changes: 37 additions & 2 deletions src/main/java/cryptator/gen/AbstractCryptaListModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,50 @@ protected AbstractCryptaListModel(final Model model, final String[] words) {
symbolCount = model.intVar("symbCount", 0, symbolsToVariables.size());
}

/**
* Gets the symbol count.
*
* @return the symbol count
*/
public final IntVar getSymbolCount() {
return symbolCount;
}

/**
* Builds the model.
*/
@Override
public void buildModel() {
super.buildModel();
postSymbolCountConstraint();
postChannelingConstraints();
}

/**
* Post the constraint for the fixed right member.
*/
public abstract void postFixedRightMemberConstraints();

public abstract void postDoublyTrueConstraints(final int lowerBound);
/**
* Post constraints for doubly true cryptarithms.
*
* @param lowerBound the lower bound for the sum
*/
public abstract void postDoublyTrueConstraints(int lowerBound);

/**
* Post optional constraints for the numerical precision.
*
* @param base the arithmetic base
*/
public abstract void postPrecisionConstraints(int base);

public abstract void postHeavyConstraints(final int base);
/**
* Post heavy constraints for filtering more candidates.
*
* @param base the arithmetic base
*/
public abstract void postHeavyConstraints(int base);

/**
* Post a constraint over the maximum number of distinct symbols in the words.
Expand All @@ -73,6 +99,9 @@ public void postMaxSymbolCountConstraint(final int max) {
symbolCount.le(max).post();
}

/**
* Post symbol count constraint.
*/
private void postSymbolCountConstraint() {
final BoolVar[] symbols = AbstractCryptaListModel.toArray(symbolsToVariables.values());
model.sum(symbols, "=", symbolCount).post();
Expand Down Expand Up @@ -125,6 +154,12 @@ private void postChannelingConstraints() {
}
}

/**
* Transform a collection of boolean variables into an array.
*
* @param vars the boolean variable collection
* @return the array
*/
private static BoolVar[] toArray(final Collection<BoolVar> vars) {
return vars.toArray(new BoolVar[vars.size()]);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/cryptator/gen/CryptaGenAdd.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void postDoublyTrueConstraints(final int lb) {
}

@Override
public void postPrecisionConstraints(int base) {
public void postPrecisionConstraints(final int base) {
// Nothing to do.
}

Expand Down
27 changes: 8 additions & 19 deletions src/main/java/cryptator/gen/CryptaGenCrossword.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class CryptaCrossPair extends CryptaMemberPair {

private final IntVar[] indices;

public CryptaCrossPair(final IntVar[] indices, final String[] words, final String prefix, boolean useLenModel) {
public CryptaCrossPair(final IntVar[] indices, final String[] words, final String prefix,
final boolean useLenModel) {
super(indices[indices.length - 1], words, prefix, useLenModel);
this.indices = indices;
}
Expand Down Expand Up @@ -56,15 +57,15 @@ public class CryptaGenCrossword extends AbstractCryptaListModel {

private final CryptaCrossPair[] additions;

public CryptaGenCrossword(int n, String[] words, boolean useLenModel) {
public CryptaGenCrossword(final int n, final String[] words, final boolean useLenModel) {
super(new Model("Generate-Crossword"), words);
this.n = n;
this.grid = new CryptaGridModel(model, n, words.length);
this.additions = new CryptaCrossPair[2 * n];
createMembers(useLenModel);
}

private void createMembers(boolean useLenModel) {
private void createMembers(final boolean useLenModel) {
for (int i = 0; i < n; i++) {
final String prefix = "R" + (i + 1) + "_";
additions[i] = new CryptaCrossPair(grid.getRow(i), words, prefix, useLenModel);
Expand All @@ -76,24 +77,12 @@ private void createMembers(boolean useLenModel) {
}
}

private void setSolution() {
int[][] solgrid = new int[][] {new int[] {0, 3, 4}, new int[] {1, 5, 7}, new int[] {2, 6, 8}};
for (int i = 0; i < solgrid.length; i++) {
for (int j = 0; j < solgrid[i].length; j++) {
grid.getCell(i, j).eq(solgrid[i][j]).post();
}
}
}

@Override
public void buildModel() {
super.buildModel();
grid.buildModel();
Stream.of(additions).forEach(CryptaCrossPair::buildModel);
// setSolution();
// TODO Set search strategy ?
// getSolver().setSearch(Search.intVarSearch(ArrayUtils.flatten(grid.getMatrix())));

// TODO change search strategy ?
}

@Override
Expand All @@ -102,17 +91,17 @@ public void postFixedRightMemberConstraints() {
}

@Override
public void postDoublyTrueConstraints(int lowerBound) {
public void postDoublyTrueConstraints(final int lowerBound) {
throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public void postHeavyConstraints(int base) {
public void postHeavyConstraints(final int base) {
Stream.of(additions).forEach(m -> m.postHeavyConstraints(base));
}

@Override
public void postPrecisionConstraints(int base) {
public void postPrecisionConstraints(final int base) {
// Nothing to do.
}

Expand Down
15 changes: 8 additions & 7 deletions src/main/java/cryptator/gen/CryptaGenLongMult.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class CryptaGenLongMult extends AbstractCryptaListModel {

private int arithmeticBase;

public CryptaGenLongMult(String[] words, int arithmeticBase) {
public CryptaGenLongMult(final String[] words, final int arithmeticBase) {
super(new Model("Generate-Long-Multiplication"), words);
this.arithmeticBase = arithmeticBase;
final int[] lengths = getLengths(words);
Expand All @@ -45,7 +45,7 @@ public final int getArithmeticBase() {
return arithmeticBase;
}

public final void setArithmeticBase(int arithmeticBase) {
public final void setArithmeticBase(final int arithmeticBase) {
this.arithmeticBase = arithmeticBase;
}

Expand Down Expand Up @@ -77,17 +77,17 @@ public void postFixedRightMemberConstraints() {
}

@Override
public void postDoublyTrueConstraints(int lowerBound) {
public void postDoublyTrueConstraints(final int lowerBound) {
throw new UnsupportedOperationException("Doubly true long multiplication is undefined.");
}

@Override
public void postHeavyConstraints(int base) {
public void postHeavyConstraints(final int base) {
// Nothing to do
}

@Override
public void postPrecisionConstraints(int base) {
public void postPrecisionConstraints(final int base) {
final int thresh = AdaptiveSolver.computeThreshold(base);
longMult.getProductLength().le(thresh).post();
}
Expand All @@ -107,7 +107,7 @@ private String[] getTermWords() {
return twords;
}

private static ICryptaNode recordTermAddition(final String[] terms, String product, int base) {
private static ICryptaNode recordTermAddition(final String[] terms, final String product, final int base) {
ArrayList<ICryptaNode> nodes = new ArrayList<>();
int exponent = 1;
for (int i = terms.length - 1; i >= 0; i--) {
Expand All @@ -119,7 +119,8 @@ private static ICryptaNode recordTermAddition(final String[] terms, String produ
return new CryptaNode(CryptaOperator.EQ, addition, new CryptaLeaf(product));
}

private static ICryptaNode recordTermMultiplications(String[] terms, String multiplicand, String multiplier) {
private static ICryptaNode recordTermMultiplications(final String[] terms, final String multiplicand,
final String multiplier) {
final char[] multipliers = multiplier.toCharArray();
final ArrayList<ICryptaNode> nodes = new ArrayList<>();
for (int i = 0; i < terms.length; i++) {
Expand Down
Loading