-
Notifications
You must be signed in to change notification settings - Fork 19
/
Quine McCluskey.py
182 lines (164 loc) · 7.29 KB
/
Quine McCluskey.py
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# Quine McCluskey algorithm for minimizing logical expressions
# Author: Suman Adhikari
def mul(x,y): # Multiply 2 minterms
res = []
for i in x:
if i+"'" in y or (len(i)==2 and i[0] in y):
return []
else:
res.append(i)
for i in y:
if i not in res:
res.append(i)
return res
def multiply(x,y): # Multiply 2 expressions
res = []
for i in x:
for j in y:
tmp = mul(i,j)
res.append(tmp) if len(tmp) != 0 else None
return res
def refine(my_list,dc_list): # Removes don't care terms from a given list and returns refined list
res = []
for i in my_list:
if int(i) not in dc_list:
res.append(i)
return res
def findEPI(x): # Function to find essential prime implicants from prime implicants chart
res = []
for i in x:
if len(x[i]) == 1:
res.append(x[i][0]) if x[i][0] not in res else None
return res
def findVariables(x): # Function to find variables in a meanterm. For example, the minterm --01 has C' and D as variables
var_list = []
for i in range(len(x)):
if x[i] == '0':
var_list.append(chr(i+65)+"'")
elif x[i] == '1':
var_list.append(chr(i+65))
return var_list
def flatten(x): # Flattens a list
flattened_items = []
for i in x:
flattened_items.extend(x[i])
return flattened_items
def findminterms(a): #Function for finding out which minterms are merged. For example, 10-1 is obtained by merging 9(1001) and 11(1011)
gaps = a.count('-')
if gaps == 0:
return [str(int(a,2))]
x = [bin(i)[2:].zfill(gaps) for i in range(pow(2,gaps))]
temp = []
for i in range(pow(2,gaps)):
temp2,ind = a[:],-1
for j in x[0]:
if ind != -1:
ind = ind+temp2[ind+1:].find('-')+1
else:
ind = temp2[ind+1:].find('-')
temp2 = temp2[:ind]+j+temp2[ind+1:]
temp.append(str(int(temp2,2)))
x.pop(0)
return temp
def compare(a,b): # Function for checking if 2 minterms differ by 1 bit only
c = 0
for i in range(len(a)):
if a[i] != b[i]:
mismatch_index = i
c += 1
if c>1:
return (False,None)
return (True,mismatch_index)
def removeTerms(_chart,terms): # Removes minterms which are already covered from chart
for i in terms:
for j in findminterms(i):
try:
del _chart[j]
except KeyError:
pass
mt = [int(i) for i in input("Enter the minterms: ").strip().split()]
dc = [int(i) for i in input("Enter the don't cares(If any): ").strip().split()]
mt.sort()
minterms = mt+dc
minterms.sort()
size = len(bin(minterms[-1]))-2
groups,all_pi = {},set()
# Primary grouping starts
for minterm in minterms:
try:
groups[bin(minterm).count('1')].append(bin(minterm)[2:].zfill(size))
except KeyError:
groups[bin(minterm).count('1')] = [bin(minterm)[2:].zfill(size)]
# Primary grouping ends
#Primary group printing starts
print("\n\n\n\nGroup No.\tMinterms\tBinary of Minterms\n%s"%('='*50))
for i in sorted(groups.keys()):
print("%5d:"%i) # Prints group number
for j in groups[i]:
print("\t\t %-20d%s"%(int(j,2),j)) # Prints minterm and its binary representation
print('-'*50)
#Primary group printing ends
# Process for creating tables and finding prime implicants starts
while True:
tmp = groups.copy()
groups,m,marked,should_stop = {},0,set(),True
l = sorted(list(tmp.keys()))
for i in range(len(l)-1):
for j in tmp[l[i]]: # Loop which iterates through current group elements
for k in tmp[l[i+1]]: # Loop which iterates through next group elements
res = compare(j,k) # Compare the minterms
if res[0]: # If the minterms differ by 1 bit only
try:
groups[m].append(j[:res[1]]+'-'+j[res[1]+1:]) if j[:res[1]]+'-'+j[res[1]+1:] not in groups[m] else None # Put a '-' in the changing bit and add it to corresponding group
except KeyError:
groups[m] = [j[:res[1]]+'-'+j[res[1]+1:]] # If the group doesn't exist, create the group at first and then put a '-' in the changing bit and add it to the newly created group
should_stop = False
marked.add(j) # Mark element j
marked.add(k) # Mark element k
m += 1
local_unmarked = set(flatten(tmp)).difference(marked) # Unmarked elements of each table
all_pi = all_pi.union(local_unmarked) # Adding Prime Implicants to global list
print("Unmarked elements(Prime Implicants) of this table:",None if len(local_unmarked)==0 else ', '.join(local_unmarked)) # Printing Prime Implicants of current table
if should_stop: # If the minterms cannot be combined further
print("\n\nAll Prime Implicants: ",None if len(all_pi)==0 else ', '.join(all_pi)) # Print all prime implicants
break
# Printing of all the next groups starts
print("\n\n\n\nGroup No.\tMinterms\tBinary of Minterms\n%s"%('='*50))
for i in sorted(groups.keys()):
print("%5d:"%i) # Prints group number
for j in groups[i]:
print("\t\t%-24s%s"%(','.join(findminterms(j)),j)) # Prints minterms and its binary representation
print('-'*50)
# Printing of all the next groups ends
# Process for creating tables and finding prime implicants ends
# Printing and processing of Prime Implicant chart starts
sz = len(str(mt[-1])) # The number of digits of the largest minterm
chart = {}
print('\n\n\nPrime Implicants chart:\n\n Minterms |%s\n%s'%(' '.join((' '*(sz-len(str(i))))+str(i) for i in mt),'='*(len(mt)*(sz+1)+16)))
for i in all_pi:
merged_minterms,y = findminterms(i),0
print("%-16s|"%','.join(merged_minterms),end='')
for j in refine(merged_minterms,dc):
x = mt.index(int(j))*(sz+1) # The position where we should put 'X'
print(' '*abs(x-y)+' '*(sz-1)+'X',end='')
y = x+sz
try:
chart[j].append(i) if i not in chart[j] else None # Add minterm in chart
except KeyError:
chart[j] = [i]
print('\n'+'-'*(len(mt)*(sz+1)+16))
# Printing and processing of Prime Implicant chart ends
EPI = findEPI(chart) # Finding essential prime implicants
print("\nEssential Prime Implicants: "+', '.join(str(i) for i in EPI))
removeTerms(chart,EPI) # Remove EPI related columns from chart
if(len(chart) == 0): # If no minterms remain after removing EPI related columns
final_result = [findVariables(i) for i in EPI] # Final result with only EPIs
else: # Else follow Petrick's method for further simplification
P = [[findVariables(j) for j in chart[i]] for i in chart]
while len(P)>1: # Keep multiplying until we get the SOP form of P
P[1] = multiply(P[0],P[1])
P.pop(0)
final_result = [min(P[0],key=len)] # Choosing the term with minimum variables from P
final_result.extend(findVariables(i) for i in EPI) # Adding the EPIs to final solution
print('\n\nSolution: F = '+' + '.join(''.join(i) for i in final_result))
input("\nPress enter to exit...")