summaryrefslogtreecommitdiffstats
path: root/org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/QuineMcCluskeySimplifier.java
blob: d3630284d8b843b5d041df20941a1e451cb09d63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*******************************************************************************
 * 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<E> {
	protected List<Minterm<E>> minterms;
	protected List<E> variables;
	protected List<Minterm<E>> implicantCover;
	
	public QuineMcCluskeySimplifier(ITruthTable<E> tt) {
		minterms = tt.getMinterms();
		variables = tt.getVariables();
		List<Minterm<E>> inputMinterms = new ArrayList<Minterm<E>>(minterms);
		List<Minterm<E>> primeImplicants = new ArrayList<Minterm<E>>(minterms);
				
		boolean change = true;
		while (change && minterms.size() > 1) { // Iterate until we achieve a steady state
			change = false;
			Queue<Minterm<E>> primary = new LinkedList<Minterm<E>>();
			primary.addAll(minterms);			
			while (!primary.isEmpty()) { // Iterate through all combinations
				Minterm<E> one = primary.remove();			
				Queue<Minterm<E>> secondary = new LinkedList<Minterm<E>>();
				secondary.addAll(minterms);
				while (!secondary.isEmpty()) {
					Minterm<E> two = secondary.remove();
					Minterm<E> 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);
						}
					}
				}
			}
		}
		
		// Determine which prime implicants cover which original minterms
		Map<Minterm<E>, List<Minterm<E>>> implications = new HashMap<Minterm<E>, List<Minterm<E>>>();
		for (Minterm<E> implicant : primeImplicants) {
			implications.put(implicant, new ArrayList<Minterm<E>>());
			for (Minterm<E> minterm : inputMinterms) {
				if (implicant.implies(minterm)) {
					implications.get(implicant).add(minterm);
				}
			}
		}
		
		implicantCover = new ArrayList<Minterm<E>>();
		// remove minterms which are implied by an essential implicant
		List<Minterm<E>> mintermsCopy = new ArrayList<Minterm<E>>(inputMinterms);
		for (Minterm<E> minterm : mintermsCopy) {
			Minterm<E> implicant = null;
			int numImplications = 0;
			for (Minterm<E> pi : primeImplicants) {
				List<Minterm<E>> 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<E> maxImplicant = null;
			for (Minterm<E> 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<Minterm<E>> getImplicantCover() {
		return implicantCover;
	}

}