Welcome, guest | Sign In | My Account | Store | Cart

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

Python, 180 lines
  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>

6 comments

David S. de Lis 17 years, 10 months ago  # | flag

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:

# 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!

Stephan Diehl (author) 17 years, 10 months ago  # | flag

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) &amp; Set(b)

more readable.

Zed Lopez 17 years, 1 month ago  # | flag

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.

Stephan Diehl (author) 17 years, 1 month ago  # | flag

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.

Zed Lopez 17 years ago  # | flag

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 "&lt;stdin&gt;", 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.

Christos Georgiou 15 years, 8 months ago  # | flag

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.