####### Output before python code in CoCalc #######
Creating a Boolean polynomial ring with 3 generators which will act as two state random variables.
The generators of the Boolean Polynomial Ring, BPR
Defining X0, X1, X2
lp term order
Generators for the probability polynomials over QQ
Defining x0, x1, x2
lp term order
Probabilities (heads) of the 3 generators taken as distinguishable (unfair) coin tosses. These are independent probabilities, and do not sum to 1.0
+----------------+--------------+--------------+--------------+
| generators | P(X0) = x0 | P(X1) = x1 | P(X2) = x2 |
+================+==============+==============+==============+
| prob. of heads | 0.558991 | 0.067929 | 0.917864 |
+----------------+--------------+--------------+--------------+
| coin toss 1 | 0 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 2 | 1 | 1 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 3 | 1 | 1 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 4 | 1 | 1 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 5 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 6 | 0 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 7 | 0 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 8 | 0 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 9 | 0 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 10 | 0 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 11 | 0 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 12 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 13 | 1 | 1 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 14 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 15 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 16 | 0 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 17 | 0 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 18 | 1 | 1 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 19 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 20 | 1 | 0 | 0 |
+----------------+--------------+--------------+--------------+
| coin toss 21 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 22 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 23 | 0 | 0 | 0 |
+----------------+--------------+--------------+--------------+
| coin toss 24 | 1 | 0 | 0 |
+----------------+--------------+--------------+--------------+
| coin toss 25 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 26 | 0 | 0 | 0 |
+----------------+--------------+--------------+--------------+
| coin toss 27 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 28 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| coin toss 29 | 1 | 0 | 0 |
+----------------+--------------+--------------+--------------+
| coin toss 30 | 1 | 0 | 1 |
+----------------+--------------+--------------+--------------+
| freq. of heads | 0.633333 | 0.166667 | 0.833333 |
+----------------+--------------+--------------+--------------+
The number of atoms is 8 = 2**3 generators. The generator probabilities induce the following probability scheme for the 8 atoms.
Aprob
[0.034853, 0.003119, 0.478225, 0.042795, 0.027497, 0.002461, 0.377289, 0.033762]
Total probability (just checking)
1.0
Table of atoms and monomials. With the exception of the 0th atom and monomial the rest are not equal.
+-----+-------+----------------------+-------------+
| # | bin | atoms | monomials |
+=====+=======+======================+=============+
| 0 | 000 | (X0+0)*(X1+0)*(X2+0) | X0*X1*X2 |
+-----+-------+----------------------+-------------+
| 1 | 001 | (X0+0)*(X1+0)*(X2+1) | X0*X1 |
+-----+-------+----------------------+-------------+
| 2 | 010 | (X0+0)*(X1+1)*(X2+0) | X0*X2 |
+-----+-------+----------------------+-------------+
| 3 | 011 | (X0+0)*(X1+1)*(X2+1) | X0 |
+-----+-------+----------------------+-------------+
| 4 | 100 | (X0+1)*(X1+0)*(X2+0) | X1*X2 |
+-----+-------+----------------------+-------------+
| 5 | 101 | (X0+1)*(X1+0)*(X2+1) | X1 |
+-----+-------+----------------------+-------------+
| 6 | 110 | (X0+1)*(X1+1)*(X2+0) | X2 |
+-----+-------+----------------------+-------------+
| 7 | 111 | (X0+1)*(X1+1)*(X2+1) | 1 |
+-----+-------+----------------------+-------------+
An example Boolean polynomial:
myBP
X0*X1 + X0*X2 + X0
Monomial vector
MonVec
(X0*X1*X2, X0*X1, X0*X2, X0, X1*X2, X1, X2, 1)
Polynomial vector
Mvect = (MGA*Avect)mod 2, Mvect is 0-1 vector with a 1 corresponding to each monomial in the Bollean polynomial, 0 otherwise
(0, 1, 1, 1, 0, 0, 0, 0)
Atom vector
Avect = (MGA*Mvect)mod 2
(1, 0, 0, 1, 0, 0, 0, 0)
Multigrade And matrix, it's totally unimodular over ZZ, and it's an involution(self inverse) mod 2
MGA =
[1 1 1 1 1 1 1 1]
[0 1 0 1 0 1 0 1]
[0 0 1 1 0 0 1 1]
[0 0 0 1 0 0 0 1]
[0 0 0 0 1 1 1 1]
[0 0 0 0 0 1 0 1]
[0 0 0 0 0 0 1 1]
[0 0 0 0 0 0 0 1]
Inverse of Multigrade And matrix in ZZ, QQ, or RR
MGAinv
[ 1 -1 -1 1 -1 1 1 -1]
[ 0 1 0 -1 0 -1 0 1]
[ 0 0 1 -1 0 0 -1 1]
[ 0 0 0 1 0 0 0 -1]
[ 0 0 0 0 1 -1 -1 1]
[ 0 0 0 0 0 1 0 -1]
[ 0 0 0 0 0 0 1 -1]
[ 0 0 0 0 0 0 0 1]
Monomial probabilities(which do not sum to 1.0)
but the last term is the sum of all atom probabilities = 1.0
Mprob = Aprob*MGA
[0.034853, 0.037972, 0.513078, 0.558991, 0.062349, 0.067929, 0.917864, 1.0]
Generators for the probability polynomial or formula over RR
Pvect = MGAinv*Avect, the coefficients of the probability polynomial or formula
[2.0, -1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0]
Monoms, monomials over RR
Probability polynomial when Boolean Ring generators are independent two state random variables
ProbPoly = Pvect*Monoms
2*x0*x1*x2 - x0*x1 - x0*x2 + x0
Probability formula whether or not the generators are independent,
P(X0*X1 + X0*X2 + X0) = 2*P(X0*X1*X2) - P(X0*X1) - P(X0*X2) + P(X0)
In this example with independent generators the numerical probability (using the dot product of vectors), P(X0*X1 + X0*X2 + X0) =
Pvect*Mprob =
0.0776473245971981
or Avect*Aprob =
0.0776473245971982
An example where the generators are not independent is constructed by creating a probability schema for the atoms arbitrarily
Probability schema for the atoms, PS =
[0.129868, 0.168863, 0.102342, 0.08467, 0.058265, 0.092064, 0.169314, 0.194614]
Monomial probabilities
MP = PS*MGA =
[0.129868, 0.298731, 0.23221, 0.485743, 0.188133, 0.44906, 0.459789, 1.0]
In this example with non-independent generators the numerical probability, P(X0*X1 + X0*X2 + X0) =
Pvect*MP =
0.214538569850260
Avect*PS =
0.214538569850260
###########################################################################################################################################
from tabulate import tabulate
load('ProbRecurse.py')
load('Prob.py')
load('ProbM.py')
load('ProbM2.py')
load('ProbScheme.py')
load('IndProbSchema.py')
KDELTA = lambda A, B: A.parent(A == B)
NOT = lambda A: A.parent(1) + A
XOR = lambda A, B: A + B
OR = lambda A, B: A + B + A*B
IF = lambda A, B: A.parent(1) + A + A*B
IFF = lambda A, B: A.parent(1) + A + B
AND = lambda A, B: A*B
NAND = lambda A, B: A.parent(1) + A*B
NOR = lambda A, B: A.parent(1) + A + B + A*B
FORALL = lambda mylist: reduce(AND, mylist)
EXISTS = lambda mylist: reduce(OR, mylist)
UNIQUE = lambda mylist: reduce(XOR,[FORALL([A + NOT(KDELTA(A,B)) for A in mylist]) for B in mylist])
nn = 3 # of generators of Boolean Algebra
print('Creating a Boolean polynomial ring with '+str(nn)+ ' generators which will act as two state random variables.')
print(' ')
aa = 2**nn # number of atoms in the Boolean Algebra
BPR = BooleanPolynomialRing(nn,'X',order='lp')
print('The generators of the Boolean Polynomial Ring, BPR')
BPR.inject_variables()
BPR.term_order()
mypoly=BPR(1)
for ii in range(0,len(BPR.gens())):
mypoly=mypoly*(BPR(1) + BPR.gen(ii))
print(' ')
CPR = PolynomialRing(QQ,nn,'x',order='lp') # probability polynomials over QQ
print('Generators for the probability polynomials over QQ')
CPR.inject_variables()
CPR.term_order()
newpoly = CPR(1)
for ii in range(0,len(CPR.gens())):
newpoly = newpoly*(CPR(1) + CPR.gen(ii)) # to create all possible monomials in CPR
print(' ')
IPS=IndProbSchema(nn)
print("Probabilities (heads) of the "+str(nn)+" generators taken as distinguishable (unfair) coin tosses. These are independent probabilities, and do not sum to 1.0")
prbheads = [round(x,6) for x in IPS[0]]
hdata = []
headsdata = ['prob. of heads']
headers=['generators']
cola=['left']
trials = 30
cointoss = matrix(ZZ,30,nn,0)
frequency = vector([0.0]*nn)
for ii in range(nn):
headsdata.append(str(round(prbheads[ii],6)))
headers.append('P(' + str(BPR.gens()[ii]) + ') = ' + str(CPR.gens()[ii]))
cola.append('center')
hdata.append(headsdata)
for ii in range(trials):
trialrow = ['coin toss '+ str(ii+1)]
for jj in range(nn):
if random() <= prbheads[jj]:
cointoss[ii,jj] = 1
trialrow.append('1')
else:
trialrow.append('0')
frequency[jj] = frequency[jj] + cointoss[ii,jj]
hdata.append(trialrow)
frequency = frequency/trials
trialrow = ['freq. of heads']
for jj in range(nn):
trialrow.append(round(frequency[jj],6))
hdata.append(trialrow)
print(tabulate(hdata, headers=headers, tablefmt="grid", colalign=cola))
print(' ')
print('The number of atoms is '+str(aa)+' = 2**'+str(nn)+' generators. The generator probabilities induce the following probability scheme for the '+str(aa)+' atoms.')
print('Aprob')
[round(x,6) for x in IPS[1]]
print(' ')
mysum=0
for ii in range(aa):
mysum=mysum+IPS[1][ii]
print("Total probability (just checking)")
round(mysum,6)
print(' ')
print('Table of atoms and monomials. With the exception of the 0th atom and monomial the rest are not equal.')
AMdata = []
for ii in range(aa):
rowAM = []
mystring = '0'*(nn-len(bin(ii)[2:]))+bin(ii)[2:]
mystring2 = ''
for jj in range(nn):
mystring2 = mystring2 + '*(' + str(BPR.gen(jj)) + '+' + mystring[jj] +')'
rowAM.append(str(ii))
rowAM.append(mystring)
rowAM.append(mystring2[1:])
rowAM.append(str(mypoly.monomials()[ii]))
AMdata.append(rowAM)
#print(str(ii)+' '+ mystring +' ' + mystring2[1:] + ' ' + str(mypoly.monomials()[ii]))
print(tabulate(AMdata, headers=('#','bin','atoms', 'monomials'), tablefmt="grid", colalign=('center','center','center','left')))
print(' ')
###############################################################################################
# should abort this with error, if too many variables in polynomial
myBP = X0*X1 + X0*X2 + X0
###############################################################################################
print('An example Boolean polynomial:')
print(' ')
print('myBP')
myBP
print(' ')
Mvect = [0]*aa
for y in myBP.monomials():
for jj in range(len(mypoly.monomials())):
if y==mypoly.monomials()[jj]:
Mvect[jj]=1
MGAinv = matrix(ZZ,[1])
for ii in range(1,nn+1):
MGAinv = block_matrix(ZZ,2,2,[MGAinv,-MGAinv,0,MGAinv],subdivide=False) # creating inverse of multigrade operator 'AND' matrix MGA
# modulo 2 it's an involution however...
# MGA and MGAinv are upper triangular, MGA is like Sierpinski triangle see
# https://commons.wikimedia.org/wiki/File:Multigrade_operator_AND.svg
# over ZZ it is totally unimodular
MGA = MGAinv%2
Mvect=vector(Mvect)
print('Monomial vector')
print('MonVec')
print(str(vector(mypoly.monomials())))
print(' ')
print('Polynomial vector')
print('Mvect = (MGA*Avect)mod 2, Mvect is 0-1 vector with a 1 corresponding to each monomial in the Bollean polynomial, 0 otherwise')
Mvect
print(' ')
Avect = MGA*Mvect%2
print('Atom vector')
print('Avect = (MGA*Mvect)mod 2')
Avect
print(' ')
print("Multigrade And matrix, it's totally unimodular over ZZ, and it's an involution(self inverse) mod 2")
print('MGA =')
MGA
print(' ')
print('Inverse of Multigrade And matrix in ZZ, QQ, or RR')
print('MGAinv')
MGAinv
Pvect = MGAinv*Avect
print(' ')
Mprob=IPS[1]*MGA
print('Monomial probabilities(which do not sum to 1.0)')
print('but the last term is the sum of all atom probabilities = 1.0')
print('Mprob = Aprob*MGA')
[round(x,6) for x in Mprob]
print(' ')
print('Generators for the probability polynomial or formula over RR')
print(' ')
print('Pvect = MGAinv*Avect, the coefficients of the probability polynomial or formula')
[round(x,6) for x in Pvect]
print(' ')
print('Monoms, monomials over RR')
Monoms = vector(newpoly.monomials())
print(' ')
print('Probability polynomial when Boolean Ring generators are independent two state random variables')
print('ProbPoly = Pvect*Monoms')
Pvect*Monoms
print(' ')
ProbExpr = ''
for ii in range(aa):
if Pvect[ii] > 1: mystr = ' + '+str(Pvect[ii])+'*'
if Pvect[ii] == 1: mystr = str(' + ')
if Pvect[ii] == -1: mystr = str(' - ')
if Pvect[ii] < -1: mystr = ' - '+str(abs(Pvect[ii]))+'*'
if Pvect[ii] != 0: ProbExpr = ProbExpr + mystr+'P('+ str(mypoly.monomials()[ii])+')'
if ProbExpr[1] == '+' : ProbExpr = ProbExpr[3:]
if ProbExpr[1] == '-' : ProbExpr = '-' + ProbExpr[3:]
print('Probability formula whether or not the generators are independent,')
print('P('+str(myBP)+') = ' + ProbExpr)
print(' ')
print("In this example with independent generators the numerical probability (using the dot product of vectors), P("+str(myBP)+") = ")
print('Pvect*Mprob =')
Pvect*Mprob
print('or Avect*Aprob =')
IPS[1]*Avect
print(' ')
print('An example where the generators are not independent is constructed by creating a probability schema for the atoms arbitrarily')
PS = ProbScheme(nn)
print('Probability schema for the atoms, PS =')
[round(x,6) for x in PS]
print(' ')
MP=PS*MGA
print('Monomial probabilities')
print('MP = PS*MGA =')
[round(x,6) for x in MP]
print(' ')
print('In this example with non-independent generators the numerical probability, P('+str(myBP)+') = ')
print('Pvect*MP =')
Pvect*MP
print('Avect*PS =')
Avect*PS