mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-26 06:22:48 -04:00
new QMC prime selector
This commit is contained in:
parent
4f9239697e
commit
f3e1cd743b
@ -32,7 +32,7 @@ public class QuineMcCluskey {
|
||||
this.primes = new ArrayList<>();
|
||||
}
|
||||
|
||||
private QuineMcCluskey(List<Variable> variables, TableRows rows, ArrayList<TableRow> primes) {
|
||||
QuineMcCluskey(List<Variable> variables, TableRows rows, ArrayList<TableRow> primes) {
|
||||
this.variables = variables;
|
||||
this.rows = rows;
|
||||
this.primes = primes;
|
||||
@ -141,7 +141,7 @@ public class QuineMcCluskey {
|
||||
newRow.setToOptimized(index);
|
||||
|
||||
TableRow r = newRows.findRow(newRow);
|
||||
if (r==null) {
|
||||
if (r == null) {
|
||||
newRow.addSource(r1.getSource());
|
||||
newRow.addSource(r2.getSource());
|
||||
newRows.add(newRow);
|
||||
@ -225,67 +225,64 @@ public class QuineMcCluskey {
|
||||
/**
|
||||
* Simplify the primes
|
||||
*
|
||||
* @param primeSelector the prome selector to use
|
||||
* @return this for call chaning
|
||||
* @param primeSelector the prime selector to use
|
||||
* @return this for call chaining
|
||||
*/
|
||||
public QuineMcCluskey simplifyPrimes(PrimeSelector primeSelector) {
|
||||
ArrayList<TableRow> primesAvail = new ArrayList<TableRow>(primes);
|
||||
primes.clear();
|
||||
|
||||
TreeSet<Integer> termIndices = new TreeSet<>();
|
||||
for (TableRow r : primesAvail)
|
||||
termIndices.addAll(r.getSource());
|
||||
TreeSet<Integer> columns = new TreeSet<>();
|
||||
for (TableRow r : primes)
|
||||
columns.addAll(r.getSource());
|
||||
|
||||
// Nach primtermen suchen, welche einen index exclusiv enthalten
|
||||
// Diese müssen in jedem Falle enthalten sein!
|
||||
for (int pr : termIndices) {
|
||||
// remove all primes which are easy to remove
|
||||
while (true) {
|
||||
// find rows to delete
|
||||
HashSet<TableRow> rowsToDelete = new HashSet<>();
|
||||
for (TableRow r1 : primes)
|
||||
for (TableRow r2 : primes) {
|
||||
if ((r1 != r2) && !rowsToDelete.contains(r1) && r1.getSource().containsAll(r2.getSource()))
|
||||
rowsToDelete.add(r2);
|
||||
}
|
||||
|
||||
TableRow foundPrime = null;
|
||||
for (TableRow tr : primesAvail) {
|
||||
if (tr.getSource().contains(pr)) {
|
||||
if (foundPrime == null) {
|
||||
foundPrime = tr;
|
||||
} else {
|
||||
foundPrime = null;
|
||||
break;
|
||||
}
|
||||
primes.removeAll(rowsToDelete);
|
||||
|
||||
// find the cols to delete
|
||||
HashSet<Integer> colsToDelete = new HashSet<>();
|
||||
for (int c1 : columns) {
|
||||
for (int c2 : columns) {
|
||||
if ((c1 != c2) && !colsToDelete.contains(c1) && smaller(c1, c2, primes))
|
||||
colsToDelete.add(c2);
|
||||
}
|
||||
}
|
||||
|
||||
if (foundPrime != null) {
|
||||
if (!primes.contains(foundPrime))
|
||||
primes.add(foundPrime);
|
||||
}
|
||||
}
|
||||
primesAvail.removeAll(primes);
|
||||
if (colsToDelete.isEmpty() && rowsToDelete.isEmpty())
|
||||
break;
|
||||
|
||||
// Die, Indices die wir schon haben können raus;
|
||||
for (TableRow pr : primes) {
|
||||
termIndices.removeAll(pr.getSource());
|
||||
for (TableRow p : primes)
|
||||
p.getSource().removeAll(colsToDelete);
|
||||
|
||||
columns.removeAll(colsToDelete);
|
||||
}
|
||||
|
||||
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);
|
||||
// try to reduce the number of primes needed
|
||||
if (primeSelector != null && !columns.isEmpty()) {
|
||||
ArrayList<TableRow> availPrimes = new ArrayList<>(primes.size());
|
||||
availPrimes.addAll(primes);
|
||||
primes.clear();
|
||||
primeSelector.select(primes, availPrimes, columns);
|
||||
if (primes.size() < availPrimes.size())
|
||||
System.out.println("reduced from " + availPrimes.size() + " primes to " + primes.size()+" primes.");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean smaller(int c1, int c2, ArrayList<TableRow> primes) {
|
||||
for (TableRow r : primes) {
|
||||
Collection<Integer> s = r.getSource();
|
||||
if (s.contains(c1) && !s.contains(c2))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import de.neemann.digital.analyse.expression.Constant;
|
||||
import de.neemann.digital.analyse.expression.Expression;
|
||||
import de.neemann.digital.analyse.expression.Variable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
@ -55,12 +56,24 @@ public final class TableRow implements Comparable<TableRow> {
|
||||
* @param dontCare true if don't care
|
||||
*/
|
||||
public TableRow(int cols, int bitValue, int index, boolean dontCare) {
|
||||
this(cols);
|
||||
this(cols, bitValue);
|
||||
if (!dontCare)
|
||||
source.add(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new row.
|
||||
* Used only for exact cover tests!
|
||||
*
|
||||
* @param cols the number of columns
|
||||
* @param bitValue the value representing the bits in the row
|
||||
*/
|
||||
public TableRow(int cols, int bitValue) {
|
||||
this(cols);
|
||||
state = Integer.reverse(bitValue) >>> (32 - cols);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the given index to optimized
|
||||
*
|
||||
@ -163,6 +176,17 @@ public final class TableRow implements Comparable<TableRow> {
|
||||
source.addAll(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds some sources to this line
|
||||
*
|
||||
* @param s the sources to add
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public TableRow addSource(Integer... s) {
|
||||
addSource(Arrays.asList(s));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an expression build with the given variables
|
||||
*
|
||||
|
@ -17,7 +17,7 @@ public interface PrimeSelector {
|
||||
* Selects the primes to use
|
||||
*
|
||||
* @param primes the list to add the primes to
|
||||
* @param primesAvail the available promes
|
||||
* @param primesAvail the available primes
|
||||
* @param termIndices the indices
|
||||
*/
|
||||
void select(ArrayList<TableRow> primes, ArrayList<TableRow> primesAvail, TreeSet<Integer> termIndices);
|
||||
|
@ -43,12 +43,13 @@ public class QuineMcCluskeyDontCareTest extends TestCase {
|
||||
|
||||
|
||||
/**
|
||||
* for more the 3 variables we only test some random tables
|
||||
* for more then 3 variables we only test some random tables
|
||||
*
|
||||
* @throws ExpressionException
|
||||
*/
|
||||
public void testRegression() throws ExpressionException {
|
||||
for (int n = 4; n < 8; n++) {
|
||||
// test some tables with n variables
|
||||
for (int i = 0; i < 200; i++) {
|
||||
performTestCalculationRandom(n);
|
||||
}
|
||||
@ -63,6 +64,15 @@ public class QuineMcCluskeyDontCareTest extends TestCase {
|
||||
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, int[] tab) throws ExpressionException {
|
||||
ArrayList<Variable> v = vars(n);
|
||||
Expression e = new QuineMcCluskey(v)
|
||||
|
@ -0,0 +1,35 @@
|
||||
package de.neemann.digital.analyse.quinemc;
|
||||
|
||||
import de.neemann.digital.analyse.expression.Variable;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by hneemann on 09.03.17.
|
||||
*/
|
||||
public class QuineMcCluskeyExactCover extends TestCase {
|
||||
|
||||
|
||||
public void testExactCoverLoop() {
|
||||
ArrayList<Variable> vars = new ArrayList<>();
|
||||
vars.add(new Variable("a"));
|
||||
vars.add(new Variable("b"));
|
||||
vars.add(new Variable("c"));
|
||||
vars.add(new Variable("d"));
|
||||
ArrayList<TableRow> primes = new ArrayList<>();
|
||||
primes.add(new TableRow(9, 0).addSource(1,3,5,7,9));
|
||||
primes.add(new TableRow(9, 1).addSource(0,1,2,3,5,6,7,8,9));
|
||||
primes.add(new TableRow(9, 2).addSource(0,2,3,5,8,9));
|
||||
primes.add(new TableRow(9, 3).addSource(1,2,4,6,8,9));
|
||||
primes.add(new TableRow(9, 4).addSource(0,1,4,5,8,9));
|
||||
primes.add(new TableRow(9, 5).addSource(2,3,6,8,9));
|
||||
primes.add(new TableRow(9, 6).addSource(2,4,5,7,9));
|
||||
primes.add(new TableRow(9, 7).addSource(0,1,3,6,7,9));
|
||||
|
||||
|
||||
QuineMcCluskey qmc = new QuineMcCluskey(vars, null, primes);
|
||||
qmc=qmc.simplifyPrimes(null);
|
||||
}
|
||||
|
||||
}
|
@ -59,7 +59,7 @@ public class QuineMcCluskeyRegressionTest extends TestCase {
|
||||
}
|
||||
|
||||
|
||||
public static void testRegression(int n, int j) throws Exception, FormatterException {
|
||||
public static void testRegression(int n, int j) throws Exception {
|
||||
int size = 1 << n;
|
||||
boolean[] table = new boolean[size];
|
||||
|
||||
|
@ -50,7 +50,7 @@ public class QuineMcCluskeyTest extends TestCase {
|
||||
Variable c = new Variable("C");
|
||||
Variable d = new Variable("D");
|
||||
|
||||
Expression e = or(and(a, and(c, d)), or(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();
|
||||
assertFalse(t.isFinished());
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user