/******************************************************************************* * Copyright (c) 2009 Elliott Baron * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Elliott Baron - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.codan.extension; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; public class QuineMcCluskeySimplifier { protected ITruthTable truthTable; protected List> implicantCover; private Map, List>> implications; public QuineMcCluskeySimplifier(ITruthTable tt) { this.truthTable = tt; List> minterms = tt.getMinterms(); List> inputMinterms = new ArrayList>(minterms); List> primeImplicants = new ArrayList>(minterms); boolean change = true; while (change && minterms.size() > 1) { // Iterate until we achieve a steady state change = false; Queue> primary = new LinkedList>(); primary.addAll(minterms); while (!primary.isEmpty()) { // Iterate through all combinations Minterm one = primary.remove(); Queue> secondary = new LinkedList>(); secondary.addAll(minterms); while (!secondary.isEmpty()) { Minterm two = secondary.remove(); Minterm combined = one.combineTerms(two); if (combined != null) { if (!minterms.contains(combined)) { change = true; minterms.add(combined); } // Combined one and two so neither are prime implicants primeImplicants.remove(one); primeImplicants.remove(two); if (!primeImplicants.contains(combined)) { primeImplicants.add(combined); } } } } } implications = new HashMap, List>>(); for (Minterm implicant : primeImplicants) { implications.put(implicant, new ArrayList>()); for (Minterm minterm : inputMinterms) { if (implicant.implies(minterm)) { implications.get(implicant).add(minterm); } } } implicantCover = new ArrayList>(); // remove minterms which are implied by an essential implicant List> mintermsCopy = new ArrayList>(inputMinterms); for (Minterm minterm : mintermsCopy) { Minterm implicant = null; int numImplications = 0; for (Minterm pi : primeImplicants) { List> impl = implications.get(pi); if (impl.contains(minterm)) { implicant = pi; numImplications++; } } // essential implicant if (numImplications == 1) { inputMinterms.removeAll(implications.get(implicant)); if (!implicantCover.contains(implicant)) { implicantCover.add(implicant); } } } // Remove essential implicants from our list primeImplicants.removeAll(implicantCover); // find a cover for the remaining minterms while (inputMinterms.size() > 0) { Minterm maxImplicant = null; for (Minterm pi : primeImplicants) { if (maxImplicant == null || implications.get(pi).size() >= implications.get(maxImplicant).size()) { maxImplicant = pi; } } inputMinterms.removeAll(implications.get(maxImplicant)); primeImplicants.remove(maxImplicant); implicantCover.add(maxImplicant); } } public List> getImplicantCover() { return implicantCover; } public List> getImplications(Minterm primeImplicant) { return implications.get(primeImplicant); } }