mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-28 15:32:40 -04:00
Introduced a MinimizerInterface to abstract a minimizer algorithm.
This commit is contained in:
parent
7877c2de4f
commit
bf4b8c3976
@ -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;
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -20,9 +20,9 @@ import static de.neemann.digital.analyse.expression.Operation.or;
|
|||||||
public class QuineMcCluskey {
|
public class QuineMcCluskey {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(QuineMcCluskey.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(QuineMcCluskey.class);
|
||||||
|
|
||||||
private final TableRows rows;
|
|
||||||
private final List<Variable> variables;
|
private final List<Variable> variables;
|
||||||
private final ArrayList<TableRow> primes;
|
private final ArrayList<TableRow> primes;
|
||||||
|
private TableRows rows;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
@ -120,16 +120,17 @@ public class QuineMcCluskey {
|
|||||||
* @return the simplified QMC instance
|
* @return the simplified QMC instance
|
||||||
*/
|
*/
|
||||||
public QuineMcCluskey simplify(PrimeSelector ps) {
|
public QuineMcCluskey simplify(PrimeSelector ps) {
|
||||||
QuineMcCluskey t = this;
|
while (!isFinished()) {
|
||||||
while (!t.isFinished()) {
|
LOGGER.debug("QMC rows " + rows.size());
|
||||||
LOGGER.debug("QMC rows " + t.rows.size());
|
simplifyStep();
|
||||||
t = t.simplifyStep();
|
|
||||||
}
|
}
|
||||||
return t.simplifyPrimes(ps);
|
simplifyPrimes(ps);
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QuineMcCluskey simplifyStep() {
|
void simplifyStep() {
|
||||||
TableRows newRows = new TableRows();
|
TableRows newRows = new TableRows();
|
||||||
|
|
||||||
for (TableRows.InnerList list : rows.listIterable())
|
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)
|
for (TableRow row : rows)
|
||||||
if (!row.isUsed() && row.getSource().size() > 0)
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
ArrayList<TableRow> newList = new ArrayList<TableRow>();
|
ArrayList<TableRow> newList = new ArrayList<>();
|
||||||
for (TableRow r : rows) {
|
for (TableRow r : rows) {
|
||||||
newList.add(r);
|
newList.add(r);
|
||||||
}
|
}
|
||||||
@ -192,6 +191,13 @@ public class QuineMcCluskey {
|
|||||||
return primes;
|
return primes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the variables used
|
||||||
|
*/
|
||||||
|
public List<Variable> getVariables() {
|
||||||
|
return variables;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the simplified expression which represent this table
|
* @return the simplified expression which represent this table
|
||||||
*/
|
*/
|
||||||
@ -226,9 +232,8 @@ public class QuineMcCluskey {
|
|||||||
* Simplify the primes
|
* Simplify the primes
|
||||||
*
|
*
|
||||||
* @param primeSelector the prime selector to use
|
* @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<>();
|
TreeSet<Integer> columns = new TreeSet<>();
|
||||||
for (TableRow r : primes)
|
for (TableRow r : primes)
|
||||||
@ -276,8 +281,6 @@ public class QuineMcCluskey {
|
|||||||
primeSelector.select(primes, availPrimes, columns);
|
primeSelector.select(primes, availPrimes, columns);
|
||||||
LOGGER.debug("final primes " + primes.size());
|
LOGGER.debug("final primes " + primes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean smaller(int c1, int c2, ArrayList<TableRow> primes) {
|
private boolean smaller(int c1, int c2, ArrayList<TableRow> primes) {
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,23 +1,19 @@
|
|||||||
package de.neemann.digital.gui.components.table;
|
package de.neemann.digital.gui.components.table;
|
||||||
|
|
||||||
import de.neemann.digital.analyse.AnalyseException;
|
import de.neemann.digital.analyse.AnalyseException;
|
||||||
|
import de.neemann.digital.analyse.MinimizerInterface;
|
||||||
import de.neemann.digital.analyse.TruthTable;
|
import de.neemann.digital.analyse.TruthTable;
|
||||||
import de.neemann.digital.analyse.expression.Expression;
|
import de.neemann.digital.analyse.expression.Expression;
|
||||||
import de.neemann.digital.analyse.expression.ExpressionException;
|
import de.neemann.digital.analyse.expression.ExpressionException;
|
||||||
import de.neemann.digital.analyse.expression.Variable;
|
import de.neemann.digital.analyse.expression.Variable;
|
||||||
import de.neemann.digital.analyse.expression.format.FormatterException;
|
import de.neemann.digital.analyse.expression.format.FormatterException;
|
||||||
import de.neemann.digital.analyse.quinemc.BoolTable;
|
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.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.gui.Main;
|
||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@ -34,14 +30,17 @@ public class ExpressionCreator {
|
|||||||
private static final int MAX_INPUTS_ALLOWED = 12;
|
private static final int MAX_INPUTS_ALLOWED = 12;
|
||||||
|
|
||||||
private final TruthTable theTable;
|
private final TruthTable theTable;
|
||||||
|
private final MinimizerInterface minimizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* 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.theTable = theTable;
|
||||||
|
this.minimizer = minimizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,18 +93,7 @@ public class ExpressionCreator {
|
|||||||
if (!Main.enableExperimental() && localVars.size() > MAX_INPUTS_ALLOWED)
|
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()));
|
throw new AnalyseException(Lang.get("err_toManyInputsIn_N0_max_N1_is_N2", resultName, MAX_INPUTS_ALLOWED, localVars.size()));
|
||||||
|
|
||||||
QuineMcCluskey qmc = new QuineMcCluskey(localVars)
|
minimizer.minimize(localVars, boolTable, resultName, listener);
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static class ThreadSaveExpressionListener implements ExpressionListener {
|
private final static class ThreadSaveExpressionListener implements ExpressionListener {
|
||||||
|
@ -58,6 +58,13 @@ public class ExpressionListenerStore implements ExpressionListener {
|
|||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the first found expression
|
||||||
|
*/
|
||||||
|
public Expression getFirst() {
|
||||||
|
return results.get(0).expression;
|
||||||
|
}
|
||||||
|
|
||||||
private static final class Result {
|
private static final class Result {
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Expression expression;
|
private final Expression expression;
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package de.neemann.digital.gui.components.table;
|
package de.neemann.digital.gui.components.table;
|
||||||
|
|
||||||
import de.neemann.digital.analyse.AnalyseException;
|
import de.neemann.digital.analyse.*;
|
||||||
import de.neemann.digital.analyse.TruthTable;
|
|
||||||
import de.neemann.digital.analyse.TruthTableTableModel;
|
|
||||||
import de.neemann.digital.analyse.expression.Expression;
|
import de.neemann.digital.analyse.expression.Expression;
|
||||||
import de.neemann.digital.analyse.expression.ExpressionException;
|
import de.neemann.digital.analyse.expression.ExpressionException;
|
||||||
import de.neemann.digital.analyse.expression.Variable;
|
import de.neemann.digital.analyse.expression.Variable;
|
||||||
@ -72,6 +70,7 @@ public class TableDialog extends JDialog {
|
|||||||
private AllSolutionsDialog allSolutionsDialog;
|
private AllSolutionsDialog allSolutionsDialog;
|
||||||
private PinMap pinMap;
|
private PinMap pinMap;
|
||||||
private ExpressionListenerStore lastGeneratedExpressions;
|
private ExpressionListenerStore lastGeneratedExpressions;
|
||||||
|
private MinimizerInterface minimizer = new MinimizerQuineMcCluskey();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
@ -596,7 +595,7 @@ public class TableDialog extends JDialog {
|
|||||||
expressionListener = new ExpressionListenerJK(expressionListener);
|
expressionListener = new ExpressionListenerJK(expressionListener);
|
||||||
|
|
||||||
lastGeneratedExpressions = new ExpressionListenerStore(expressionListener);
|
lastGeneratedExpressions = new ExpressionListenerStore(expressionListener);
|
||||||
new ExpressionCreator(model.getTable()).create(lastGeneratedExpressions);
|
new ExpressionCreator(model.getTable(), minimizer).create(lastGeneratedExpressions);
|
||||||
|
|
||||||
} catch (ExpressionException | FormatterException | AnalyseException e1) {
|
} catch (ExpressionException | FormatterException | AnalyseException e1) {
|
||||||
new ErrorMessage(Lang.get("msg_errorDuringCalculation")).addCause(e1).show();
|
new ErrorMessage(Lang.get("msg_errorDuringCalculation")).addCause(e1).show();
|
||||||
|
@ -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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,7 +9,7 @@ import java.util.Collection;
|
|||||||
/**
|
/**
|
||||||
* Created by hneemann on 09.03.17.
|
* Created by hneemann on 09.03.17.
|
||||||
*/
|
*/
|
||||||
public class QuineMcCluskeyExactCover extends TestCase {
|
public class QuineMcCluskeyExactCoverTest extends TestCase {
|
||||||
|
|
||||||
|
|
||||||
public void testExactCoverLoop() {
|
public void testExactCoverLoop() {
|
||||||
@ -30,7 +30,7 @@ public class QuineMcCluskeyExactCover extends TestCase {
|
|||||||
|
|
||||||
|
|
||||||
QuineMcCluskey qmc = new QuineMcCluskey(vars, null, primes);
|
QuineMcCluskey qmc = new QuineMcCluskey(vars, null, primes);
|
||||||
qmc=qmc.simplifyPrimes(null);
|
qmc.simplifyPrimes(null);
|
||||||
final ArrayList<TableRow> pri = qmc.getPrimes();
|
final ArrayList<TableRow> pri = qmc.getPrimes();
|
||||||
assertEquals(2, pri.size());
|
assertEquals(2, pri.size());
|
||||||
|
|
@ -51,7 +51,7 @@ public class QuineMcCluskeyRegressionTest extends TestCase {
|
|||||||
System.out.println("--");
|
System.out.println("--");
|
||||||
while (!t.isFinished()) {
|
while (!t.isFinished()) {
|
||||||
System.out.println(FormatToExpression.FORMATTER_JAVA.format(t.getExpression()));
|
System.out.println(FormatToExpression.FORMATTER_JAVA.format(t.getExpression()));
|
||||||
t = t.simplifyStep();
|
t.simplifyStep();
|
||||||
}
|
}
|
||||||
t.simplifyPrimes(new PrimeSelectorDefault());
|
t.simplifyPrimes(new PrimeSelectorDefault());
|
||||||
assertEquals("A || C", FormatToExpression.FORMATTER_JAVA.format(t.getExpression()));
|
assertEquals("A || C", FormatToExpression.FORMATTER_JAVA.format(t.getExpression()));
|
||||||
|
@ -1,26 +1,35 @@
|
|||||||
package de.neemann.digital.analyse.quinemc;
|
package de.neemann.digital.analyse.quinemc;
|
||||||
|
|
||||||
|
|
||||||
import de.neemann.digital.analyse.expression.Constant;
|
import de.neemann.digital.analyse.expression.*;
|
||||||
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.FormatToExpression;
|
import de.neemann.digital.analyse.expression.format.FormatToExpression;
|
||||||
import de.neemann.digital.analyse.expression.format.FormatterException;
|
import de.neemann.digital.analyse.expression.format.FormatterException;
|
||||||
import de.neemann.digital.analyse.quinemc.primeselector.PrimeSelectorDefault;
|
import de.neemann.digital.analyse.quinemc.primeselector.PrimeSelectorDefault;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static de.neemann.digital.analyse.expression.Not.not;
|
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.and;
|
||||||
import static de.neemann.digital.analyse.expression.Operation.or;
|
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
|
* @author hneemann
|
||||||
*/
|
*/
|
||||||
public class QuineMcCluskeyTest extends TestCase {
|
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 {
|
public void testGenerator() throws ExpressionException {
|
||||||
Variable a = new Variable("A");// Vorlesung
|
Variable a = new Variable("A");// Vorlesung
|
||||||
@ -51,7 +60,8 @@ public class QuineMcCluskeyTest extends TestCase {
|
|||||||
Variable d = new Variable("D");
|
Variable d = new Variable("D");
|
||||||
|
|
||||||
Expression e = or(and(a, c, d), and(not(c), not(d)), and(not(b), c));
|
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());
|
assertFalse(t.isFinished());
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@ -68,7 +78,7 @@ public class QuineMcCluskeyTest extends TestCase {
|
|||||||
"101-,6,7\n",
|
"101-,6,7\n",
|
||||||
t.toString());
|
t.toString());
|
||||||
|
|
||||||
t = t.simplifyStep();
|
t.simplifyStep();
|
||||||
assertFalse(t.isFinished());
|
assertFalse(t.isFinished());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -90,9 +100,9 @@ public class QuineMcCluskeyTest extends TestCase {
|
|||||||
assertEquals(
|
assertEquals(
|
||||||
"--00,1,4,5,8\n" +
|
"--00,1,4,5,8\n" +
|
||||||
"-0-0,1,2,5,6\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());
|
assertTrue(t.isFinished());
|
||||||
|
|
||||||
assertEquals("", t.toString());
|
assertEquals("", t.toString());
|
||||||
@ -164,4 +174,55 @@ public class QuineMcCluskeyTest extends TestCase {
|
|||||||
assertTrue(e instanceof Constant);
|
assertTrue(e instanceof Constant);
|
||||||
assertTrue(((Constant) e).getValue());
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user