Introduced a MinimizerInterface to abstract a minimizer algorithm.

This commit is contained in:
hneemann 2017-03-13 14:30:45 +01:00
parent 7877c2de4f
commit bf4b8c3976
13 changed files with 411 additions and 185 deletions

View File

@ -0,0 +1,29 @@
package de.neemann.digital.analyse;
import de.neemann.digital.analyse.expression.ExpressionException;
import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.analyse.expression.format.FormatterException;
import de.neemann.digital.analyse.quinemc.BoolTable;
import de.neemann.digital.gui.components.table.ExpressionListener;
import java.util.List;
/**
* Interface to abstract a minimizer algorithm.
* Created by hneemann on 13.03.17.
*/
public interface MinimizerInterface {
/**
* Called to minimize a bool table
*
* @param vars the variables used
* @param boolTable the bool table
* @param resultName name of the result
* @param listener the listener to report the result to
* @throws ExpressionException ExpressionException
* @throws FormatterException FormatterException
*/
void minimize(List<Variable> vars, BoolTable boolTable, String resultName, ExpressionListener listener) throws ExpressionException, FormatterException;
}

View File

@ -0,0 +1,48 @@
package de.neemann.digital.analyse;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.expression.ExpressionException;
import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.analyse.expression.format.FormatterException;
import de.neemann.digital.analyse.quinemc.BoolTable;
import de.neemann.digital.analyse.quinemc.QuineMcCluskey;
import de.neemann.digital.analyse.quinemc.TableRow;
import de.neemann.digital.analyse.quinemc.primeselector.PrimeSelector;
import de.neemann.digital.analyse.quinemc.primeselector.PrimeSelectorDefault;
import de.neemann.digital.gui.components.table.ExpressionListener;
import java.util.ArrayList;
import java.util.List;
/**
* The normal QMC minimizer.
* Created by hneemann on 13.03.17.
*/
public class MinimizerQuineMcCluskey implements MinimizerInterface {
@Override
public void minimize(List<Variable> vars, BoolTable boolTable, String resultName, ExpressionListener listener) throws ExpressionException, FormatterException {
QuineMcCluskey qmc = createQuineMcCluskey(vars)
.fillTableWith(boolTable);
PrimeSelector ps = new PrimeSelectorDefault();
Expression e = qmc.simplify(ps).getExpression();
if (ps.getAllSolutions() != null) {
for (ArrayList<TableRow> i : ps.getAllSolutions()) {
listener.resultFound(resultName, QuineMcCluskey.addAnd(null, i, vars));
}
} else {
listener.resultFound(resultName, e);
}
}
/**
* Creates a specific QMC algorithm
*
* @param vars the variables to use
* @return the QMC instance
*/
protected QuineMcCluskey createQuineMcCluskey(List<Variable> vars) {
return new QuineMcCluskey(vars);
}
}

View File

@ -0,0 +1,19 @@
package de.neemann.digital.analyse;
import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.analyse.quinemc.QuineMcCluskey;
import de.neemann.digital.analyse.quinemc.QuineMcCluskeyExam;
import java.util.List;
/**
* The QMC-Minimizer used for exam correction.
* Should only be used if there are not more then 4 variables.
* Created by hneemann on 13.03.17.
*/
public class MinimizerQuineMcCluskeyExam extends MinimizerQuineMcCluskey {
@Override
protected QuineMcCluskey createQuineMcCluskey(List<Variable> vars) {
return new QuineMcCluskeyExam(vars);
}
}

View File

@ -20,9 +20,9 @@ import static de.neemann.digital.analyse.expression.Operation.or;
public class QuineMcCluskey {
private static final Logger LOGGER = LoggerFactory.getLogger(QuineMcCluskey.class);
private final TableRows rows;
private final List<Variable> variables;
private final ArrayList<TableRow> primes;
private TableRows rows;
/**
* Creates a new instance
@ -120,16 +120,17 @@ public class QuineMcCluskey {
* @return the simplified QMC instance
*/
public QuineMcCluskey simplify(PrimeSelector ps) {
QuineMcCluskey t = this;
while (!t.isFinished()) {
LOGGER.debug("QMC rows " + t.rows.size());
t = t.simplifyStep();
while (!isFinished()) {
LOGGER.debug("QMC rows " + rows.size());
simplifyStep();
}
return t.simplifyPrimes(ps);
simplifyPrimes(ps);
return this;
}
QuineMcCluskey simplifyStep() {
void simplifyStep() {
TableRows newRows = new TableRows();
for (TableRows.InnerList list : rows.listIterable())
@ -154,13 +155,11 @@ public class QuineMcCluskey {
}
}
ArrayList<TableRow> np = new ArrayList<TableRow>();
np.addAll(primes);
for (TableRow row : rows)
if (!row.isUsed() && row.getSource().size() > 0)
np.add(row);
primes.add(row);
return new QuineMcCluskey(variables, newRows, np);
rows=newRows;
}
/**
@ -173,7 +172,7 @@ public class QuineMcCluskey {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
ArrayList<TableRow> newList = new ArrayList<TableRow>();
ArrayList<TableRow> newList = new ArrayList<>();
for (TableRow r : rows) {
newList.add(r);
}
@ -192,6 +191,13 @@ public class QuineMcCluskey {
return primes;
}
/**
* @return the variables used
*/
public List<Variable> getVariables() {
return variables;
}
/**
* @return the simplified expression which represent this table
*/
@ -226,9 +232,8 @@ public class QuineMcCluskey {
* Simplify the primes
*
* @param primeSelector the prime selector to use
* @return this for call chaining
*/
public QuineMcCluskey simplifyPrimes(PrimeSelector primeSelector) {
public void simplifyPrimes(PrimeSelector primeSelector) {
TreeSet<Integer> columns = new TreeSet<>();
for (TableRow r : primes)
@ -276,8 +281,6 @@ public class QuineMcCluskey {
primeSelector.select(primes, availPrimes, columns);
LOGGER.debug("final primes " + primes.size());
}
return this;
}
private boolean smaller(int c1, int c2, ArrayList<TableRow> primes) {

View File

@ -0,0 +1,102 @@
package de.neemann.digital.analyse.quinemc;
import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.analyse.quinemc.primeselector.PrimeSelector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
/**
* Not as efficient as {@link QuineMcCluskey} but it shows all possible solutions.
* Needed for exam correction.
* It does not throw away all primes which are not necessary but tries to find the primes
* which are necessary. So is is possible to find all possible solutions.
* Works only if there are not more then 4 variables.
* <p>
* Created by hneemann on 13.03.17.
*/
public class QuineMcCluskeyExam extends QuineMcCluskey {
private static final Logger LOGGER = LoggerFactory.getLogger(QuineMcCluskeyExam.class);
/**
* Creates a new instance
*
* @param variables the variables to use
*/
public QuineMcCluskeyExam(List<Variable> variables) {
super(variables);
}
/**
* Simplify the primes
*
* @param primeSelector the prime selector to use
*/
@Override
public void simplifyPrimes(PrimeSelector primeSelector) {
ArrayList<TableRow> primes = getPrimes();
ArrayList<TableRow> primesAvail = new ArrayList<>(primes);
primes.clear();
TreeSet<Integer> termIndices = new TreeSet<>();
for (TableRow r : primesAvail)
termIndices.addAll(r.getSource());
// Nach primtermen suchen, welche einen index exclusiv enthalten
// Diese müssen in jedem Falle enthalten sein!
for (int pr : termIndices) {
TableRow foundPrime = null;
for (TableRow tr : primesAvail) {
if (tr.getSource().contains(pr)) {
if (foundPrime == null) {
foundPrime = tr;
} else {
foundPrime = null;
break;
}
}
}
if (foundPrime != null) {
if (!primes.contains(foundPrime))
primes.add(foundPrime);
}
}
primesAvail.removeAll(primes);
// Die, Indices die wir schon haben können raus;
for (TableRow pr : primes) {
termIndices.removeAll(pr.getSource());
}
LOGGER.debug("residual primes " + primesAvail.size());
if (!termIndices.isEmpty()) {
//Die noch übrigen Terme durchsuchen ob sie schon komplett dabei sind;
Iterator<TableRow> it = primesAvail.iterator();
while (it.hasNext()) {
TableRow tr = it.next();
boolean needed = false;
for (int i : tr.getSource()) {
if (termIndices.contains(i)) {
needed = true;
break;
}
}
if (!needed) {
it.remove();
}
}
primeSelector.select(primes, primesAvail, termIndices);
}
LOGGER.debug("final primes " + primes.size());
}
}

View File

@ -1,23 +1,19 @@
package de.neemann.digital.gui.components.table;
import de.neemann.digital.analyse.AnalyseException;
import de.neemann.digital.analyse.MinimizerInterface;
import de.neemann.digital.analyse.TruthTable;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.expression.ExpressionException;
import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.analyse.expression.format.FormatterException;
import de.neemann.digital.analyse.quinemc.BoolTable;
import de.neemann.digital.analyse.quinemc.QuineMcCluskey;
import de.neemann.digital.analyse.quinemc.TableReducer;
import de.neemann.digital.analyse.quinemc.TableRow;
import de.neemann.digital.analyse.quinemc.primeselector.PrimeSelector;
import de.neemann.digital.analyse.quinemc.primeselector.PrimeSelectorDefault;
import de.neemann.digital.gui.Main;
import de.neemann.digital.lang.Lang;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
@ -34,14 +30,17 @@ public class ExpressionCreator {
private static final int MAX_INPUTS_ALLOWED = 12;
private final TruthTable theTable;
private final MinimizerInterface minimizer;
/**
* Creates a new instance
*
* @param theTable the table to use
* @param theTable the table to use
* @param minimizer the minimizer to use
*/
public ExpressionCreator(TruthTable theTable) {
public ExpressionCreator(TruthTable theTable, MinimizerInterface minimizer) {
this.theTable = theTable;
this.minimizer = minimizer;
}
/**
@ -94,18 +93,7 @@ public class ExpressionCreator {
if (!Main.enableExperimental() && localVars.size() > MAX_INPUTS_ALLOWED)
throw new AnalyseException(Lang.get("err_toManyInputsIn_N0_max_N1_is_N2", resultName, MAX_INPUTS_ALLOWED, localVars.size()));
QuineMcCluskey qmc = new QuineMcCluskey(localVars)
.fillTableWith(boolTable);
PrimeSelector ps = new PrimeSelectorDefault();
Expression e = qmc.simplify(ps).getExpression();
if (ps.getAllSolutions() != null) {
for (ArrayList<TableRow> i : ps.getAllSolutions()) {
listener.resultFound(resultName, QuineMcCluskey.addAnd(null, i, localVars));
}
} else {
listener.resultFound(resultName, e);
}
minimizer.minimize(localVars, boolTable, resultName, listener);
}
private final static class ThreadSaveExpressionListener implements ExpressionListener {

View File

@ -58,6 +58,13 @@ public class ExpressionListenerStore implements ExpressionListener {
listener.close();
}
/**
* @return the first found expression
*/
public Expression getFirst() {
return results.get(0).expression;
}
private static final class Result {
private final String name;
private final Expression expression;

View File

@ -1,8 +1,6 @@
package de.neemann.digital.gui.components.table;
import de.neemann.digital.analyse.AnalyseException;
import de.neemann.digital.analyse.TruthTable;
import de.neemann.digital.analyse.TruthTableTableModel;
import de.neemann.digital.analyse.*;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.expression.ExpressionException;
import de.neemann.digital.analyse.expression.Variable;
@ -72,6 +70,7 @@ public class TableDialog extends JDialog {
private AllSolutionsDialog allSolutionsDialog;
private PinMap pinMap;
private ExpressionListenerStore lastGeneratedExpressions;
private MinimizerInterface minimizer = new MinimizerQuineMcCluskey();
/**
* Creates a new instance
@ -596,7 +595,7 @@ public class TableDialog extends JDialog {
expressionListener = new ExpressionListenerJK(expressionListener);
lastGeneratedExpressions = new ExpressionListenerStore(expressionListener);
new ExpressionCreator(model.getTable()).create(lastGeneratedExpressions);
new ExpressionCreator(model.getTable(), minimizer).create(lastGeneratedExpressions);
} catch (ExpressionException | FormatterException | AnalyseException e1) {
new ErrorMessage(Lang.get("msg_errorDuringCalculation")).addCause(e1).show();

View File

@ -0,0 +1,105 @@
package de.neemann.digital.analyse.quinemc;
import de.neemann.digital.analyse.MinimizerInterface;
import de.neemann.digital.analyse.MinimizerQuineMcCluskey;
import de.neemann.digital.analyse.MinimizerQuineMcCluskeyExam;
import de.neemann.digital.analyse.expression.ContextFiller;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.expression.ExpressionException;
import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.analyse.expression.format.FormatterException;
import de.neemann.digital.gui.components.table.ExpressionListenerStore;
import junit.framework.TestCase;
import java.util.ArrayList;
import static de.neemann.digital.analyse.expression.Variable.vars;
/**
* @author hneemann
*/
public class MinimizerRegressionTest extends TestCase {
public void testQuineMcCluskey() throws ExpressionException, FormatterException {
MinimizerInterface m = new MinimizerQuineMcCluskey();
performTests(m);
}
public void testQuineMcCluskeyExam() throws ExpressionException, FormatterException {
MinimizerInterface m = new MinimizerQuineMcCluskeyExam();
performTests(m);
}
private void performTests(MinimizerInterface m) throws ExpressionException, FormatterException {
performFull(m);
performRegression(m);
}
/**
* up to 3 variables we can calculate all tables possible!
*
* @throws ExpressionException
*/
public void performFull(MinimizerInterface minimizer) throws ExpressionException, FormatterException {
new FullVariantDontCareCreator() {
@Override
public void handleTable(int n, byte[] tab) throws ExpressionException, FormatterException {
performTestCalculation(n, tab, minimizer);
}
}.create();
}
/**
* for more then 3 variables we only test some random tables
*
* @throws ExpressionException
*/
public void performRegression(MinimizerInterface minimizer) throws ExpressionException, FormatterException {
int numOfTest = 2048;
for (int n = 4; n <= 8; n++) {
// test some tables with n variables
// System.out.println(n + " vars: " + numOfTest + "tests");
for (int i = 0; i < numOfTest; i++) {
performTestCalculationRandom(n, minimizer);
}
numOfTest /= 4;
}
}
static private void performTestCalculationRandom(int n, MinimizerInterface minimizer) throws ExpressionException, FormatterException {
byte[] tab = new byte[1 << n];
for (int i = 0; i < tab.length; i++)
tab[i] = (byte) Math.round(Math.random() * 3); // half of the values are don't care
performTestCalculation(n, tab, minimizer);
}
/**
* Generates a expression from the table and then checks if
* the expression reproduces the given table.
* Does not test if the expression is minimal.
*
* @param n the number of variables
* @param tab the truth table
* @throws ExpressionException
*/
static private void performTestCalculation(int n, byte[] tab, MinimizerInterface minimizer) throws ExpressionException, FormatterException {
ArrayList<Variable> v = vars(n);
final ExpressionListenerStore listener = new ExpressionListenerStore(null);
minimizer.minimize(v, new BoolTableByteArray(tab), "Y", listener);
Expression e = listener.getFirst();
;
assertNotNull(e);
ContextFiller context = new ContextFiller(v);
for (int i = 0; i < tab.length; i++) {
if (tab[i] <= 1)
assertEquals(tab[i] == 1, e.calculate(context.setContextTo(i)));
}
}
}

View File

@ -1,135 +0,0 @@
package de.neemann.digital.analyse.quinemc;
import de.neemann.digital.analyse.expression.*;
import de.neemann.digital.analyse.expression.format.FormatToExpression;
import de.neemann.digital.analyse.expression.format.FormatterException;
import junit.framework.TestCase;
import java.util.ArrayList;
import java.util.Arrays;
import static de.neemann.digital.analyse.expression.Variable.vars;
import static de.neemann.digital.analyse.expression.format.FormatToExpression.FORMATTER_UNICODE;
/**
* @author hneemann
*/
public class QuineMcCluskeyDontCareTest extends TestCase {
public void testDontCare() throws Exception, FormatterException {
ArrayList<Variable> v = vars("A", "B", "C");
Expression e = new QuineMcCluskey(v)
.fillTableWith(new BoolTableByteArray(new byte[]{1, 1, 0, 0, 1, 2, 2, 0}))
.simplify()
.getExpression();
assertEquals("!B", FormatToExpression.FORMATTER_JAVA.format(e));
}
/**
* up to 3 variables we can calculate all tables possible!
*
* @throws ExpressionException
*/
public void testFull() throws ExpressionException, FormatterException {
new FullVariantDontCareCreator() {
@Override
public void handleTable(int n, byte[] tab) throws ExpressionException {
performTestCalculation(n, tab);
}
}.create();
}
/**
* for more then 3 variables we only test some random tables
*
* @throws ExpressionException
*/
public void testRegression() throws ExpressionException {
int numOfTest = 2048;
for (int n = 4; n <= 8; n++) {
// test some tables with n variables
// System.out.println(n + " vars: " + numOfTest + "tests");
for (int i = 0; i < numOfTest; i++) {
performTestCalculationRandom(n);
}
numOfTest /= 4;
}
}
static private void performTestCalculationRandom(int n) throws ExpressionException {
byte[] tab = new byte[1 << n];
for (int i = 0; i < tab.length; i++)
tab[i] = (byte) Math.round(Math.random() * 3); // half of the values are don't care
performTestCalculation(n, tab);
}
/**
* Generates a expression from the table and then checks if
* the expression reproduces the given table.
* Does not test if the expression is minimal.
*
* @param n the number of variables
* @param tab the truth table
* @throws ExpressionException
*/
static private void performTestCalculation(int n, byte[] tab) throws ExpressionException {
ArrayList<Variable> v = vars(n);
Expression e = new QuineMcCluskey(v)
.fillTableWith(new BoolTableByteArray(tab))
.simplify()
.getExpression();
assertNotNull(e);
ContextFiller context = new ContextFiller(v);
for (int i = 0; i < tab.length; i++) {
if (tab[i] <= 1)
assertEquals(tab[i] == 1, e.calculate(context.setContextTo(i)));
}
}
public void testComplexity() throws Exception {
new FullVariantDontCareCreator() {
@Override
public void handleTable(int n, byte[] tab) throws ExpressionException, FormatterException {
Expression e = createExpression(n, tab);
byte[] tabZero = Arrays.copyOf(tab, tab.length);
for (int i = 0; i < tabZero.length; i++)
if (tabZero[i] > 1) tabZero[i] = 0;
Expression eZero = createExpression(n, tabZero);
byte[] tabOne = Arrays.copyOf(tab, tab.length);
for (int i = 0; i < tabOne.length; i++)
if (tabOne[i] > 1) tabOne[i] = 1;
Expression eOne = createExpression(n, tabOne);
int c = e.traverse(new ComplexityVisitor()).getComplexity();
int cOne = eOne.traverse(new ComplexityVisitor()).getComplexity();
int cZero = eZero.traverse(new ComplexityVisitor()).getComplexity();
boolean ok = (c <= cOne) && (c <= cZero);
if (!ok) {
System.out.println("\nX: " + FORMATTER_UNICODE.format(e) + ", " + c);
System.out.println("0: " + FORMATTER_UNICODE.format(eZero) + ", " + cZero);
System.out.println("1: " + FORMATTER_UNICODE.format(eOne) + ", " + cOne);
assertTrue(false);
}
}
}.create();
}
private Expression createExpression(int n, byte[] tab) throws ExpressionException {
ArrayList<Variable> v = vars(n);
return new QuineMcCluskey(v)
.fillTableWith(new BoolTableByteArray(tab))
.simplify()
.getExpression();
}
}

View File

@ -9,7 +9,7 @@ import java.util.Collection;
/**
* Created by hneemann on 09.03.17.
*/
public class QuineMcCluskeyExactCover extends TestCase {
public class QuineMcCluskeyExactCoverTest extends TestCase {
public void testExactCoverLoop() {
@ -30,7 +30,7 @@ public class QuineMcCluskeyExactCover extends TestCase {
QuineMcCluskey qmc = new QuineMcCluskey(vars, null, primes);
qmc=qmc.simplifyPrimes(null);
qmc.simplifyPrimes(null);
final ArrayList<TableRow> pri = qmc.getPrimes();
assertEquals(2, pri.size());

View File

@ -51,7 +51,7 @@ public class QuineMcCluskeyRegressionTest extends TestCase {
System.out.println("--");
while (!t.isFinished()) {
System.out.println(FormatToExpression.FORMATTER_JAVA.format(t.getExpression()));
t = t.simplifyStep();
t.simplifyStep();
}
t.simplifyPrimes(new PrimeSelectorDefault());
assertEquals("A || C", FormatToExpression.FORMATTER_JAVA.format(t.getExpression()));

View File

@ -1,26 +1,35 @@
package de.neemann.digital.analyse.quinemc;
import de.neemann.digital.analyse.expression.Constant;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.expression.ExpressionException;
import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.analyse.expression.*;
import de.neemann.digital.analyse.expression.format.FormatToExpression;
import de.neemann.digital.analyse.expression.format.FormatterException;
import de.neemann.digital.analyse.quinemc.primeselector.PrimeSelectorDefault;
import junit.framework.TestCase;
import java.util.ArrayList;
import java.util.Arrays;
import static de.neemann.digital.analyse.expression.Not.not;
import static de.neemann.digital.analyse.expression.Operation.and;
import static de.neemann.digital.analyse.expression.Operation.or;
import static de.neemann.digital.analyse.expression.Variable.vars;
import static de.neemann.digital.analyse.expression.format.FormatToExpression.FORMATTER_UNICODE;
/**
* @author hneemann
*/
public class QuineMcCluskeyTest extends TestCase {
public void testDontCare() throws Exception, FormatterException {
ArrayList<Variable> v = vars("A", "B", "C");
Expression e = new QuineMcCluskey(v)
.fillTableWith(new BoolTableByteArray(new byte[]{1, 1, 0, 0, 1, 2, 2, 0}))
.simplify()
.getExpression();
assertEquals("!B", FormatToExpression.FORMATTER_JAVA.format(e));
}
public void testGenerator() throws ExpressionException {
Variable a = new Variable("A");// Vorlesung
@ -51,7 +60,8 @@ public class QuineMcCluskeyTest extends TestCase {
Variable d = new Variable("D");
Expression e = or(and(a, c, d), and(not(c), not(d)), and(not(b), c));
QuineMcCluskey t = new QuineMcCluskey(e).simplifyStep();
QuineMcCluskey t = new QuineMcCluskey(e);
t.simplifyStep();
assertFalse(t.isFinished());
assertEquals(
@ -68,7 +78,7 @@ public class QuineMcCluskeyTest extends TestCase {
"101-,6,7\n",
t.toString());
t = t.simplifyStep();
t.simplifyStep();
assertFalse(t.isFinished());
/*
@ -90,9 +100,9 @@ public class QuineMcCluskeyTest extends TestCase {
assertEquals(
"--00,1,4,5,8\n" +
"-0-0,1,2,5,6\n" +
"-01-,2,3,6,7\n", t.toString());
"-01-,2,3,6,7\n", t.toString());
t = t.simplifyStep();
t.simplifyStep();
assertTrue(t.isFinished());
assertEquals("", t.toString());
@ -164,4 +174,55 @@ public class QuineMcCluskeyTest extends TestCase {
assertTrue(e instanceof Constant);
assertTrue(((Constant) e).getValue());
}
public void testMultipleResults() throws ExpressionException {
QuineMcCluskeyExam t = new QuineMcCluskeyExam(Variable.vars("A", "B", "C"));
t.fillTableWith(new BoolTableByteArray(new byte[]{0, 1, 1, 0, 0, 1, 1, 1}));
PrimeSelectorDefault ps = new PrimeSelectorDefault();
t.simplify(ps);
assertEquals(2, ps.getAllSolutions().size());
}
public void testComplexity() throws Exception {
new FullVariantDontCareCreator() {
@Override
public void handleTable(int n, byte[] tab) throws ExpressionException, FormatterException {
Expression e = createExpression(n, tab);
byte[] tabZero = Arrays.copyOf(tab, tab.length);
for (int i = 0; i < tabZero.length; i++)
if (tabZero[i] > 1) tabZero[i] = 0;
Expression eZero = createExpression(n, tabZero);
byte[] tabOne = Arrays.copyOf(tab, tab.length);
for (int i = 0; i < tabOne.length; i++)
if (tabOne[i] > 1) tabOne[i] = 1;
Expression eOne = createExpression(n, tabOne);
int c = e.traverse(new ComplexityVisitor()).getComplexity();
int cOne = eOne.traverse(new ComplexityVisitor()).getComplexity();
int cZero = eZero.traverse(new ComplexityVisitor()).getComplexity();
boolean ok = (c <= cOne) && (c <= cZero);
if (!ok) {
System.out.println("\nX: " + FORMATTER_UNICODE.format(e) + ", " + c);
System.out.println("0: " + FORMATTER_UNICODE.format(eZero) + ", " + cZero);
System.out.println("1: " + FORMATTER_UNICODE.format(eOne) + ", " + cOne);
assertTrue(false);
}
}
}.create();
}
private Expression createExpression(int n, byte[] tab) throws ExpressionException {
ArrayList<Variable> v = vars(n);
return new QuineMcCluskey(v)
.fillTableWith(new BoolTableByteArray(tab))
.simplify()
.getExpression();
}
}