def ProbM(myBP): # myBP is a boolean polynomial being converted to probabilty expression1# myBP.parent().term_order() must be 'lp'2if type(myBP) == sage.rings.integer.Integer:3if myBP%2 == 0:4return QQ(0)5else:6return QQ(1)7mystr = str(myBP.variables()) # converting all uppers to lower and lowers to uppercase I SEE A BUG HERE!!!!!! mixed upper and lower var names sort differently8NewGens=""9for ii in range(len(mystr)):10if mystr[ii] == mystr[ii].upper():11NewGens = NewGens + mystr[ii].lower()12else:13NewGens = NewGens + mystr[ii].upper() # if boolean variable XcGGt1u then, prob var is xCggT1U etc. Mixed case generators are a problem - they sort differently14NewGens = NewGens[1:len(NewGens) - 1] # generators for probabilty polynomial assuming boolean generators are independent15if len(myBP.variables()) == 1:16NewGens = NewGens.replace(',','')17NewGens.replace(' ','')18CPR = PolynomialRing(QQ,len(myBP.variables()),NewGens,order=myBP.parent().term_order()) #myBP.parent().term_order()19CPR.inject_variables()20nn = myBP.nvariables() # number of generators in boolean polynomial21atoms = 2**nn # number of atoms in corresponding boolean algebra22# should abort this with error, if too many variables in polynomial23mypoly=myBP.parent(1)24for ii in range(0,len(myBP.parent().gens())):25mypoly = mypoly*(myBP.parent(1) + myBP.parent().gen(ii))26Mvect = [0]*atoms27for y in myBP.monomials():28for jj in range(len(mypoly.monomials())):29if y==mypoly.monomials()[jj]:30Mvect[jj]=131#Mvect = [0]*atoms # This loop only works when CPR term_order is 'invlex'32#for jj in range(len(myBP.monomials())):33# mm = 034# for kk in range(len(myBP.monomials()[jj].variables())):35# mm = mm + 2**myBP.variables().index(myBP.monomials()[jj].variables()[kk])36# Mvect[mm] = 137#Mvect.reverse()38# Mvect order for instance is (X111,X110,X101,X100,X011,X010,X001,X000) has two nonequiv intepretations39# as monomials or atoms example was for three variables40Mvect = vector(Mvect)41MGinv = matrix(ZZ,[1])42for ii in range(1,nn+1):43MGinv = block_matrix(ZZ,2,2,[MGinv,-MGinv,0,MGinv],subdivide=False) # creating inverse of multigrade operator 'AND' matrix MG44# modulo 2 it's an involution however...45# MG and MGinv are upper triangular, MG is like Sierpinski triangle see46# https://commons.wikimedia.org/wiki/File:Multigrade_operator_AND.svg47Avect = (MGinv*Mvect)%248Pvect = MGinv*Avect # convert from boolean ring (mons) to boolean algebra (atoms) then to probability polynomial49# ((MGinv*Mvect)%2) is the atoms vector equivalent to the monnomials vector Mvect50# Pvect are the coefficients of prob poly in CPR51# CPR.term_order() = myBP.parent().term_order()52newpoly = CPR(1)53for ii in range(0,len(CPR.gens())):54newpoly = newpoly*(CPR(1) + CPR.gen(ii)) # to create all possible monomials in CPR55return Pvect*vector(newpoly.monomials()) # inner product of the two vectors to create prob poly5657