Files
quine/quine.py
2017-09-19 20:41:56 -04:00

205 lines
5.5 KiB
Python

from math import ceil
from math import log
def quine(truth, dontcare=None, bits=0):
if dontcare is None:
dontcare = []
if bits == 0:
bits = int(ceil(log(max(truth + dontcare),2)))
d = [None] * bits
getterms = truth + dontcare
#collect all terms
nextcol = [[] for i in range(bits+1)]
for item in getterms:
tmp = item
tru = ['0'] * bits
for i in range(bits-1, -1, -1):
if tmp >= 2**i:
tmp -= 2**i
tru[i] = '1'
asterm = term(tru)
nextcol[asterm.group] += [asterm]
d[0] = nextcol
#print(d)
#return d
for col in range(bits-1):
nextcol = [[] for i in range(bits-col+1)]
for group in range(bits-col):
for item1 in d[col][group]:
for item2 in d[col][group+1]:
if item1.match(item2):
asterm = item1.merge(item2)
item1.prime = False
item2.prime = False
if asterm not in nextcol[group]:
nextcol[group] += [asterm]
d[col+1] = nextcol
return d
pimp = term.allprime(d)
#return pimp
defdict = {}
for i in truth:
defdict[i] = False
ptable = [None] * len(pimp)
#return ptable
for i in range(len(pimp)):
ptable[i] = defdict.copy()
for min in truth:
ptable[i][min] = min in pimp[i].mins
#return ptable
prevess = []
ess = []
covered = set([])
while True:
for min in [x for x in truth if x not in covered]:
terms = []
for i in range(len(ptable)):
if ptable[i][min]:
terms += [i]
#print(terms)
if len(terms) == 1:
#print('test')
ess += [pimp[terms[0]]]
#print(ess)
del ptable[terms[0]]
del pimp[terms[0]]
#print(ess)
# for i in ptable:
# del i[min]
#print(ess)
covered.add(min)
break
if ess == prevess:
break
prevess = ess
notcovered = [x for x in truth if x not in covered]
#for
return pimp, ess, ptable, covered, notcovered
def tovhdl(terms):
asstr = ''
for i in range(len(terms)):
asstr += 'T(%d) <= ' % i
strt = 0
while True:
if terms[i].truth[strt] == '1':
asstr += chr(65+strt) + ' '
break
elif terms[i].truth[strt] == '0':
asstr += 'not ' + chr(65+strt) + ' '
break
strt += 1
for j in range(strt+1,len(terms[i].truth)):
if terms[i].truth[j] == 'x':
continue
asstr += ' and '
if terms[i].truth[j] == '0':
asstr += 'not '
asstr += chr(j+65)
asstr += ';\n'
return asstr
def getexpansion(terms):
asstr = []
for term in terms:
m = ''
for i in range(len(term.truth)):
if term.truth[i] == 'x':
continue
m += chr(65+i)
if term.truth[i] == '0':
m += "'"
asstr.append(m)
fstring = ''
for i in range(len(terms)-1):
fstring += asstr[i] + ' + '
fstring += asstr[-1]
return fstring
def petterms():
pass
class term:
def __init__(self, truth):
self.truth = truth
self.group = sum([1 if i == '1' else 0 for i in self.truth])
dc = []
num = 0
for i in range(len(self.truth)):
if self.truth[i] == '1':
num += 2**i
elif self.truth[i] == 'x':
dc += [2**i]
vals = [num]
for term in dc:
vals += [val + term for val in vals]
self.mins = vals
self.prime = True
def __eq__(self, other):
return self.truth == other.truth
def match(self, other):
if len(self.truth) != len(other.truth):
raise ValueError('truth values must have equal length')
cnt = 0
for i in range(len(self.truth)):
if self.truth[i] == 'x' and other.truth[i] == 'x':
continue
elif self.truth[i] == 'x' or other.truth[i] == 'x':
return False
elif self.truth[i] != other.truth[i]:
cnt += 1
return cnt == 1
#never use without verifying terms match first
def merge(self, other):
if len(self.truth) != len(other.truth):
raise ValueError('truth values must have equal length')
newtruth = ['0'] * len(self.truth)
for i in range(len(self.truth)):
if self.truth[i] == other.truth[i] != 'x':
newtruth[i] = self.truth[i]
else:
newtruth[i] = 'x'
return term(newtruth)
@staticmethod
def allterms(lst):
if isinstance(lst, term):
return set(lst.mins)
else:
mins = set()
for i in lst:
mins.update(set(term.allterms(i)))
return mins
@staticmethod
def allprime(lst):
if isinstance(lst, term):
return [lst] if lst.prime else []
else:
terms = []
for item in lst:
terms += term.allprime(item)
return terms