mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-18 09:24:42 -04:00
made QMC much faster by using a better data structure tostore the QMC tables.
This commit is contained in:
parent
ea163b569f
commit
33a24aa418
@ -58,8 +58,8 @@ public class ModelAnalyser {
|
||||
|
||||
if (inputs.size() == 0)
|
||||
throw new AnalyseException(Lang.get("err_analyseNoInputs"));
|
||||
if (inputs.size() > 9)
|
||||
throw new AnalyseException(Lang.get("err_toManyInputs_N", 9));
|
||||
if (inputs.size() > 12)
|
||||
throw new AnalyseException(Lang.get("err_toManyInputs_N", 12));
|
||||
if (outputs.size() == 0)
|
||||
throw new AnalyseException(Lang.get("err_analyseNoOutputs"));
|
||||
rows = 1 << inputs.size();
|
||||
|
@ -20,7 +20,7 @@ import static de.neemann.digital.analyse.expression.Operation.or;
|
||||
*/
|
||||
public class QuineMcCluskey {
|
||||
|
||||
private final ArrayList<TableRow> rows;
|
||||
private final TableRows rows;
|
||||
private final ArrayList<Variable> variables;
|
||||
private final ArrayList<TableRow> primes;
|
||||
|
||||
@ -31,11 +31,11 @@ public class QuineMcCluskey {
|
||||
*/
|
||||
public QuineMcCluskey(ArrayList<Variable> variables) {
|
||||
this.variables = variables;
|
||||
this.rows = new ArrayList<>();
|
||||
this.rows = new TableRows();
|
||||
this.primes = new ArrayList<>();
|
||||
}
|
||||
|
||||
private QuineMcCluskey(ArrayList<Variable> variables, ArrayList<TableRow> rows, ArrayList<TableRow> primes) {
|
||||
private QuineMcCluskey(ArrayList<Variable> variables, TableRows rows, ArrayList<TableRow> primes) {
|
||||
this.variables = variables;
|
||||
this.rows = rows;
|
||||
this.primes = primes;
|
||||
@ -51,7 +51,7 @@ public class QuineMcCluskey {
|
||||
public QuineMcCluskey(Expression expression) throws ExpressionException {
|
||||
ContextFiller context = new ContextFiller(expression);
|
||||
variables = context.getVariables();
|
||||
rows = new ArrayList<>();
|
||||
rows = new TableRows();
|
||||
fillTableWith(new BoolTableExpression(expression, context));
|
||||
primes = new ArrayList<>();
|
||||
}
|
||||
@ -73,7 +73,6 @@ public class QuineMcCluskey {
|
||||
add(i, value.equals(ThreeStateValue.dontCare));
|
||||
}
|
||||
}
|
||||
Collections.sort(rows);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -129,27 +128,29 @@ public class QuineMcCluskey {
|
||||
|
||||
|
||||
QuineMcCluskey simplifyStep() {
|
||||
ArrayList<TableRow> newRows = new ArrayList<>();
|
||||
for (int i = 0; i < rows.size() - 1; i++)
|
||||
for (int j = i + 1; j < rows.size(); j++) {
|
||||
TableRows newRows = new TableRows();
|
||||
|
||||
TableRow r1 = rows.get(i);
|
||||
TableRow r2 = rows.get(j);
|
||||
for (ArrayList<TableRow> list : rows.listIterable())
|
||||
for (int i = 0; i < list.size() - 1; i++)
|
||||
for (int j = i + 1; j < list.size(); j++) {
|
||||
|
||||
int index = checkCompatible(r1, r2);
|
||||
if (index >= 0) {
|
||||
// can optimize;
|
||||
TableRow newRow = new TableRow(r1);
|
||||
newRow.setToOptimized(index);
|
||||
newRow.addSource(r1.getSource());
|
||||
newRow.addSource(r2.getSource());
|
||||
TableRow r1 = list.get(i);
|
||||
TableRow r2 = list.get(j);
|
||||
|
||||
r1.setUsed();
|
||||
r2.setUsed();
|
||||
int index = checkCompatible(r1, r2);
|
||||
if (index >= 0) {
|
||||
// can optimize;
|
||||
TableRow newRow = new TableRow(r1);
|
||||
newRow.setToOptimized(index);
|
||||
newRow.addSource(r1.getSource());
|
||||
newRow.addSource(r2.getSource());
|
||||
|
||||
newRows.add(newRow);
|
||||
r1.setUsed();
|
||||
r2.setUsed();
|
||||
|
||||
newRows.add(newRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<TableRow> np = new ArrayList<TableRow>();
|
||||
np.addAll(primes);
|
||||
@ -161,13 +162,13 @@ public class QuineMcCluskey {
|
||||
}
|
||||
|
||||
QuineMcCluskey removeDuplicates() {
|
||||
ArrayList<TableRow> newRows = new ArrayList<TableRow>();
|
||||
TableRows newRows = new TableRows();
|
||||
for (TableRow r : rows) {
|
||||
int i = newRows.indexOf(r);
|
||||
if (i < 0) {
|
||||
TableRow i = newRows.findRow(r);
|
||||
if (i == null) {
|
||||
newRows.add(r);
|
||||
} else {
|
||||
newRows.get(i).addSource(r.getSource());
|
||||
i.addSource(r.getSource());
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,12 +186,8 @@ public class QuineMcCluskey {
|
||||
}
|
||||
|
||||
private int checkCompatible(TableRow r1, TableRow r2) {
|
||||
for (int i = 0; i < r1.size(); i++) {
|
||||
if (r1.get(i) == TableItem.optimized || r2.get(i) == TableItem.optimized) {
|
||||
if (!r1.get(i).equals(r2.get(i)))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (r1.getOptimizedFlags() != r2.getOptimizedFlags())
|
||||
return -1;
|
||||
|
||||
int difIndex = -1;
|
||||
for (int i = 0; i < r1.size(); i++) {
|
||||
@ -207,7 +204,12 @@ public class QuineMcCluskey {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ArrayList<TableRow> newList = new ArrayList<TableRow>();
|
||||
for (TableRow r : rows) {
|
||||
newList.add(r);
|
||||
}
|
||||
Collections.sort(newList);
|
||||
for (TableRow r : newList) {
|
||||
sb.append(r.toString());
|
||||
sb.append("\n");
|
||||
}
|
||||
@ -240,7 +242,7 @@ public class QuineMcCluskey {
|
||||
* @param variables the variables to use to build the expression
|
||||
* @return the expression
|
||||
*/
|
||||
public static Expression addAnd(Expression e, ArrayList<TableRow> rows, ArrayList<Variable> variables) {
|
||||
public static Expression addAnd(Expression e, Iterable<TableRow> rows, ArrayList<Variable> variables) {
|
||||
for (TableRow r : rows) {
|
||||
Expression n = r.getExpression(variables);
|
||||
if (e == null)
|
||||
|
@ -22,8 +22,9 @@ import static de.neemann.digital.analyse.expression.Operation.and;
|
||||
public class TableRow implements Comparable<TableRow> {
|
||||
|
||||
private final TableItem[] items;
|
||||
private boolean used = false;
|
||||
private final TreeSet<Integer> source;
|
||||
private boolean used = false;
|
||||
private long optimizedFlags;
|
||||
|
||||
/**
|
||||
* Copies the given table row
|
||||
@ -34,10 +35,11 @@ public class TableRow implements Comparable<TableRow> {
|
||||
this(tr.size());
|
||||
for (int i = 0; i < size(); i++)
|
||||
items[i] = tr.get(i);
|
||||
optimizedFlags = tr.optimizedFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new tyble row
|
||||
* Creates a new table row
|
||||
*
|
||||
* @param cols number of columns
|
||||
*/
|
||||
@ -52,7 +54,7 @@ public class TableRow implements Comparable<TableRow> {
|
||||
* @param cols the number of columns
|
||||
* @param bitValue the value representing the bits in the row
|
||||
* @param index the index of the original source row
|
||||
* @param dontCare dont care
|
||||
* @param dontCare true if don't care
|
||||
*/
|
||||
public TableRow(int cols, int bitValue, int index, boolean dontCare) {
|
||||
this(cols);
|
||||
@ -70,7 +72,7 @@ public class TableRow implements Comparable<TableRow> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The item at the given indes
|
||||
* The item at the given index
|
||||
*
|
||||
* @param index the comumns index
|
||||
* @return the value
|
||||
@ -80,12 +82,23 @@ public class TableRow implements Comparable<TableRow> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given idex to optimized
|
||||
* Sets the given index to optimized
|
||||
*
|
||||
* @param index the columns index
|
||||
*/
|
||||
public void setToOptimized(int index) {
|
||||
items[index] = TableItem.optimized;
|
||||
optimizedFlags |= 1L << index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the optimized flags.
|
||||
* All Variables which are deleted/optimized in this row are marked by a one bit at their position.
|
||||
*
|
||||
* @return the flags
|
||||
*/
|
||||
public long getOptimizedFlags() {
|
||||
return optimizedFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -151,7 +164,7 @@ public class TableRow implements Comparable<TableRow> {
|
||||
|
||||
@Override
|
||||
public int compareTo(TableRow tableRow) {
|
||||
return Integer.compare(countOnes(), tableRow.countOnes());
|
||||
return toString().compareTo(tableRow.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
124
src/main/java/de/neemann/digital/analyse/quinemc/TableRows.java
Normal file
124
src/main/java/de/neemann/digital/analyse/quinemc/TableRows.java
Normal file
@ -0,0 +1,124 @@
|
||||
package de.neemann.digital.analyse.quinemc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Set of rows stored in a special way to make comparisons faster
|
||||
*
|
||||
* @author hneemann
|
||||
*/
|
||||
class TableRows implements Iterable<TableRow> {
|
||||
private final TreeMap<Long, ArrayList<TableRow>> rows;
|
||||
private int size;
|
||||
|
||||
TableRows() {
|
||||
rows = new TreeMap<>();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void add(TableRow tableRow) {
|
||||
long flags = tableRow.getOptimizedFlags();
|
||||
getList(flags).add(tableRow);
|
||||
size++;
|
||||
}
|
||||
|
||||
private ArrayList<TableRow> getList(long flags) {
|
||||
ArrayList<TableRow> list = rows.get(flags);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
rows.put(flags, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
rows.clear();
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public void addAll(TableRows newRows) {
|
||||
for (Map.Entry<Long, ArrayList<TableRow>> e : newRows.rows.entrySet()) {
|
||||
ArrayList<TableRow> values = e.getValue();
|
||||
getList(e.getKey()).addAll(values);
|
||||
size += values.size();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row stored in this list which is equal to the given row
|
||||
*
|
||||
* @param r the row to look for
|
||||
* @return the row found
|
||||
*/
|
||||
TableRow findRow(TableRow r) {
|
||||
ArrayList<TableRow> list = rows.get(r.getOptimizedFlags());
|
||||
|
||||
if (list == null)
|
||||
return null;
|
||||
|
||||
int i = list.indexOf(r);
|
||||
if (i < 0)
|
||||
return null;
|
||||
else
|
||||
return list.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<TableRow> iterator() {
|
||||
return new RowIterator(rows.values().iterator());
|
||||
}
|
||||
|
||||
public Iterable<ArrayList<TableRow>> listIterable() {
|
||||
return rows.values();
|
||||
}
|
||||
|
||||
|
||||
public TableRow get(int i) {
|
||||
for (Map.Entry<Long, ArrayList<TableRow>> e : rows.entrySet()) {
|
||||
ArrayList<TableRow> list = e.getValue();
|
||||
if (i < list.size())
|
||||
return list.get(i);
|
||||
else
|
||||
i -= list.size();
|
||||
}
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
private class RowIterator implements Iterator<TableRow> {
|
||||
private final Iterator<ArrayList<TableRow>> listIter;
|
||||
private Iterator<TableRow> itemIter;
|
||||
|
||||
RowIterator(Iterator<ArrayList<TableRow>> iterator) {
|
||||
listIter = iterator;
|
||||
itemIter = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
while (itemIter == null && listIter.hasNext()) {
|
||||
itemIter = listIter.next().iterator();
|
||||
if (!itemIter.hasNext())
|
||||
itemIter = null;
|
||||
}
|
||||
return itemIter != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableRow next() {
|
||||
TableRow next = itemIter.next();
|
||||
if (!itemIter.hasNext())
|
||||
itemIter = null;
|
||||
return next;
|
||||
}
|
||||
}
|
||||
}
|
@ -31,14 +31,15 @@ public class QuineMcCluskeyTest extends TestCase {
|
||||
Expression e = or(and(a, and(c, d)), or(and(not(c), not(d)), and(not(b), c)));
|
||||
QuineMcCluskey t = new QuineMcCluskey(e);
|
||||
|
||||
assertEquals("0000,1\n" +
|
||||
assertEquals(
|
||||
"0000,1\n" +
|
||||
"0010,2\n" +
|
||||
"0011,3\n" +
|
||||
"0100,4\n" +
|
||||
"1000,5\n" +
|
||||
"0011,3\n" +
|
||||
"1010,6\n" +
|
||||
"1011,7\n" +
|
||||
"1100,8\n" +
|
||||
"1011,7\n" +
|
||||
"1111,9\n", t.toString());
|
||||
|
||||
}
|
||||
@ -53,25 +54,28 @@ public class QuineMcCluskeyTest extends TestCase {
|
||||
QuineMcCluskey t = new QuineMcCluskey(e).simplifyStep();
|
||||
assertFalse(t.isFinished());
|
||||
|
||||
assertEquals("00-0,1,2\n" +
|
||||
"0-00,1,4\n" +
|
||||
assertEquals(
|
||||
"-000,1,5\n" +
|
||||
"-010,2,6\n" +
|
||||
"-011,3,7\n" +
|
||||
"-100,4,8\n" +
|
||||
"0-00,1,4\n" +
|
||||
"00-0,1,2\n" +
|
||||
"001-,2,3\n" +
|
||||
"-010,2,6\n" +
|
||||
"-100,4,8\n" +
|
||||
"1-00,5,8\n" +
|
||||
"1-11,7,9\n" +
|
||||
"10-0,5,6\n" +
|
||||
"1-00,5,8\n" +
|
||||
"-011,3,7\n" +
|
||||
"101-,6,7\n" +
|
||||
"1-11,7,9\n", t.toString());
|
||||
"101-,6,7\n",
|
||||
t.toString());
|
||||
|
||||
t = t.simplifyStep();
|
||||
assertFalse(t.isFinished());
|
||||
|
||||
assertEquals("-0-0,1,2,5,6\n" +
|
||||
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" +
|
||||
"--00,1,4,5,8\n" +
|
||||
"-01-,2,3,6,7\n" +
|
||||
"-01-,2,3,6,7\n", t.toString());
|
||||
|
||||
@ -82,8 +86,9 @@ public class QuineMcCluskeyTest extends TestCase {
|
||||
t = t.removeDuplicates();
|
||||
assertFalse(t.isFinished());
|
||||
|
||||
assertEquals("-0-0,1,2,5,6\n" +
|
||||
assertEquals(
|
||||
"--00,1,4,5,8\n" +
|
||||
"-0-0,1,2,5,6\n" +
|
||||
"-01-,2,3,6,7\n", t.toString());
|
||||
|
||||
t = t.simplifyStep();
|
||||
@ -94,8 +99,8 @@ public class QuineMcCluskeyTest extends TestCase {
|
||||
primes = t.getPrimes();
|
||||
assertEquals(4, primes.size());
|
||||
assertEquals("1-11,7,9", primes.get(0).toString());
|
||||
assertEquals("-0-0,1,2,5,6", primes.get(1).toString());
|
||||
assertEquals("--00,1,4,5,8", primes.get(2).toString());
|
||||
assertEquals("-0-0,1,2,5,6", primes.get(2).toString());
|
||||
assertEquals("--00,1,4,5,8", primes.get(1).toString());
|
||||
assertEquals("-01-,2,3,6,7", primes.get(3).toString());
|
||||
|
||||
Expression exp = t.getExpression();
|
||||
|
@ -83,7 +83,7 @@ public class Gal16V8JEDECExporterTest extends TestCase {
|
||||
"QF2194*\r\n" +
|
||||
"G0*\r\n" +
|
||||
"F0*\r\n" +
|
||||
"L256 10111110110111011111111111111111*\r\n" +
|
||||
"L256 10111110110111011111111111111111*\r\n" + // fuses are created with WinCUPL 5.0
|
||||
"L288 10111101111011111111111111111111*\r\n" +
|
||||
"L320 01111110111011101111111111111111*\r\n" +
|
||||
"L352 01111101111111011111111111111111*\r\n" +
|
||||
|
Loading…
x
Reference in New Issue
Block a user