This lets treat you a python sets.Set as a scalar (number,string,...) The german linux magazine featured an article about the PERL module "Quantum::Superpositions": http://www.linux-magazin.de/Artikel/ausgabe/2003/12/perl/perl.html This sounded like fun and I implemented it in Python (probably not everything). Perl code lines: over 700 Python code lines: 100
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 | from sets import Set
import operator
import inspect
class Superposition(Set):
def __init__(self,*argl):
super(Superposition,self).__init__(self)
for arg in argl:
if isinstance(arg,Set):
self |= arg
elif isinstance(arg,list) or isinstance(arg,tuple):
self |= Set(arg)
else:
self.add(arg)
def eigenstates(self):
return list(self)
def _cartesian(self,other,op,order=True):
if order:
if isinstance(other,Superposition):
s = self.__class__([op(x,y) for x in self for y in other])
else:
s = self.__class__([op(x,other) for x in self])
else:
if isinstance(other,Superposition):
s = self.__class__([op(y,x) for x in self for y in other])
else:
s = self.__class__([op(other,x) for x in self])
return s
def __add__(self,other):
return self._cartesian(other,operator.add)
__radd__ = __add__
def __sub__(self,other):
return self._cartesian(other,operator.sub)
def __rsub__(self,other):
return self._cartesian(other,operator.sub,False)
def __mod__(self,other):
return self._cartesian(other,operator.mod)
def __rmod__(self,other):
return self._cartesian(other,operator.mod,False)
def __mul__(self,other):
return self._cartesian(other,operator.mul)
__rmul__ = __mul__
def __div__(self,other):
return self._cartesian(other,operator.div)
def __rdiv__(self,other):
return self._cartesian(other,operator.div,False)
def _comp(self,other,op):
return self.__class__([x for x in self if op(x,other)])
def __eq__(self,other):
return self._comp(other,operator.eq)
def __lt__(self,other):
return self._comp(other,operator.lt)
def __le__(self,other):
return self._comp(other,operator.le)
def __gt__(self,other):
return self._comp(other,operator.gt)
def __ge__(self,other):
return self._comp(other,operator.ge)
def __ne__(self,other):
if isinstance(other,Superposition):
return self.__class__([x for x in self if x not in other])
else:
return self._comp(other,operator.ne)
class Any(Superposition):pass
class All(Superposition):
def _comp(self,other,op):
r = super(All,self)._comp(other,op)
if len(r) == len(self):
return r
else:
return All()
def __eq__(self,other):
if isinstance(other,Set):
r = Set(self) & other
if len(r) == len(self):
return All(r)
else:
return All()
elif len(self) == 1 and self.eigenstates()[0] == other:
print 'in elif'
return All(self)
else:
return All()
if __name__ == '__main__':
a = Superposition(1,2,3)
b = Superposition(2,3,4)
print 'a =',a
print 'b =',b
print 'a+b',a+b
print 'a-b',a-b
print 'b-a',b-a
print 'a*b',a*b
print 'a/b',a/b
print 'b/a',b/a
print 'a == 1',a==1
print 'a == 2',a==2
print 'a == b',a==b
print 'a != b',a!=b
print 'b != a',b!=a
print 'a < 2',a<2
print 'a > 2',a>2
print 'a <= 2',a<=2
print 'a >= 2',a>=2
print 'a < b',a<b
print 'a > b',a>b
print
a = All(1,2,3)
b = All(2,3,4)
print '== All =='
print
print 'a == 1',a==1
print 'a == 2',a==2
print 'a == b',a==b
print 'a == a',a==a
print 'a != b',a!=b
print 'b != a',b!=a
print 'a < 2',a<2
print 'a < 4',a<4
print 'a > 2',a>2
print 'a > 0',a>0
print 'a <= 3',a<=3
print 'a >= 2',a>=2
print 'a < b',a<b
print 'a > b',a>b
print 'a > a',a>a
print 'a >= a',a>=a
print 'All(7,8,9) <= Any(5,6,7)', All(7,8,9) <= Any(5,6,7)
print 'All(5,6,7) <= Any(7,8,9)', All(5,6,7) <= Any(7,8,9)
print 'Any(6,7,8) <= All(7,8,9)', Any(6,7,8) <= All(7,8,9)
print 'MIN: Any(6,7,8) <= All(6,7,8)', Any(6,7,8) <= All(6,7,8)
print 'MAX: Any(6,7,8) >= All(6,7,8)', Any(6,7,8) >= All(6,7,8)
import math
print 'PRIMES range(4,20)', [x for x in range(4,20) if x % All([i for i in xrange(2,int(math.sqrt(x))+1)]) != 0]
def isprimenumber(num):
return bool(num % All([i for i in xrange(2,int(math.sqrt(num))+1)]) != 0)
def isprime(num):
if isinstance(num,Superposition):
return bool([x for x in num.eigenstates() if isprimenumber(x) ])
else:
return isprimenumber(num)
def hastwin(num):
return isprime(num) and isprime(num+Any(+2,-2))
print 'isprime(7)',isprime(7)
print 'isprime(10)',isprime(10)
print 'hastwin(7)',hastwin(7)
print 'hastwin(23)',hastwin(23)
print '== Strings =='
a = Any('a','b','c')
print "a = Any('a','b','c')"
print "a + '_test'",a + '_test'
|
While this has of course nothing to do with quantum physics, there are some usefull things that can be done with it. There are two classes defined: "All" and "Any". The constructor takes any number of scalars and/or Superposition instances. These items are the possible states. When doing scalar operations on such objects, the operation is delegated to its possible states. The difference between "Any" and "All" lays in the use of comparison operators: As the names suggest, the comparison must be true for all elements in "All" while it is enough to be true for one element in "Any". The comparison operation return no boolean values but Any or All instances (this is for you to see, which elements compared true)
While this has of course nothing to do with quantum physics, there are some usefull things that can be done with it. There are two classes defined: "All" and "Any". The constructor takes any number of scalars and/or Superposition instances. These items are the possible states. When doing scalar operations on such objects, the operation is delegated to its possible states. The difference between "Any" and "All" lays in the use of comparison operators: As the names suggest, the comparison must be true for all elements in "All" while it is enough to be true for one element in "Any". The comparison operation return no boolean values but Any or All instances (this is for you to see, which elements compared true)
Some tasks that can be done with this:
<pre>
>>> l = range(5,15)
>>> Any(l) <= All(l) #Minimum
Any([5])
>>> Any(l) >= All(l) #Maximum
Any([14])
>>> import math
>>> # checking if a number is prime
>>> num = 7
>>> num % All([i for i in xrange(2,int(math.sqrt(num))+1)]) != 0
All([1])
>>> num = 10
>>> num % All([i for i in xrange(2,int(math.sqrt(num))+1)]) != 0
All([])
>>>
</pre>
Excellent. Perl's Quantum::Superpositions is a superb package, and its functionality will be a core aspect of scalars in Perl 6.
Besides what's been stated in this module (I am not sure it does Q::S 100% but it returns the result of comparisons, when Q::S only returns a boolean result, an improvement I'll let the author know of), it allows you to make thins like this:
Without it, those ifs would have had to be explicit fors, checking every option against the others, explicitely. Being implicit in the Any/All classes, it makes for easier to read code. And if makes room for a possible optimization if those loops can be run in parallel, it's not the case, but it could be...
Certainly a great module and it's great having it in Python as well. Top quality!
Thanks you liked it!!! I'm quite sure that the P::S package does not return boolean values as well, because I took that feature out of P::S's docstring (and it made sense to me).
Myself, I would have used sets directly with your example.So, in a way, it's more a thing of personal taste if one finds
or
more readable.
Perl's Quantum::Superposition is so much longer because it does more. This is very cool. But the code-lines comparison to Perl's module is entirely unfair. Perl's lets you configure existing functions (including built-in core functions) to accept and return values in superposition _without modifying those functions_. I wonder if that would be possible in Python.
Further, the fewer than 650 lines between the beginning of the module and the beginning of its POD include comments, and the author's style uses a lot more whitespace than necessary, both in blank lines and in putting his {'s on their own lines. But those are small points compared to the fact that most of the code is devoted to dealing with passing and receiving values in superposition to and from other functions.
Point taken. Hope you are not too offended. The comparison is unfair and I have to admit that I know nothing about Perl internals. The way Python works, it is just not neccessary to change the interpreter. This solution will work with any other Python construct, be it builtin or not.
Actually, I think you misunderstand my point. Perl's allows this:
This produces
As opposed to:
which produces:
That's what the bulk of Perl's Quantum::Superpositions is going to -- allowing the transparent passing of superposition objects into and out of existing functions, even built-ins, without those functions needing any awareness-in-advance that superposition objects even exist. Unless you omitted this from your documentation and I've grossly misread your code, this is not possible with your (admittedly shorter) module.
And Quantum::Superpositions doesn't "modify the interpreter" to do it.
Alex Martelli seems to find explicit for's clearer, though... re: """Without it, those ifs would have had to be explicit fors, checking every option against the others, explicitely."""
This message:
http://mail.python.org/pipermail/python-list/2003-February/148311.html
is about a similar module (at least re the Any, All predicates --that one was implemented using generators delegating comparisons etc to the members of the iterable). You can follow the thread.