|
Description:
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
Source: Text Source
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'
Discussion:
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:
>>> 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([])
>>>
|
|
Add comment
|
|
Number of comments: 6
Excellent, David S. de Lis, 2004/02/03
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:
# example
from Superposition import *
allowedTtys = ['tty1', 'tty2', 'stty10']
allowedApps = ['admin', 'remote', 'web']
def login(user, userApp, userTty, userApps):
if Any(userApps) == Any(allowedApps):
if userTty == Any(allowedTtys):
print("GRANTED: user %s connected to %s running %s" % (user, userTty, userApp))
else:
print("ERROR: user %s not allowed to attach to secured Tty %s" % (user, userTty))
else:
print("ERROR: user %s not allowed to run %s" % (user, userApp))
login('foouser', 'web', 'tty1', ['web', 'proxy'])
login('baruser', 'hack', 'tty1', ['hack', 'install', 'backup'])
login('bazuser', 'admin', 'stty6', ['admin'])
# result:
GRANTED: user foouser connected to tty1 running web
ERROR: user baruser not allowed to run hack
ERROR: user bazuser not allowed to attach to secured Tty stty6
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!
Add comment
Stephan Diehl, 2004/02/08
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
Any(a) == Any(b)
or
Set(a) & Set(b)
more readable.
Add comment
Alex Martelli seems to find explicit for's clearer, though..., Christos Georgiou, 2006/03/12
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.
Add comment
Perl's Quantum::Superposition is so much longer because it does more, Zed Lopez, 2004/10/20
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.
Add comment
Point taken, Stephan Diehl, 2004/10/28
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.
Add comment
Zed Lopez, 2004/11/30
Actually, I think you misunderstand my point. Perl's allows this:
use Quantum::Superpositions UNARY => ["CORE::oct"];
my $s1 = any('123', '456', '765');
my $o1 = oct($s1);
print join ' ', eigenstates($o1), "\n";
This produces
501 302 83
As opposed to:
from Superposition import Any, All
s1 = Any('123','456','765')
o1 = oct(s1)
which produces:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: oct() argument can't be converted to oct
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.
Add comment
|
|
|