first commit
This commit is contained in:
205
quine.py
Normal file
205
quine.py
Normal file
@@ -0,0 +1,205 @@
|
||||
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
|
||||
Reference in New Issue
Block a user