Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Python Optimization

7 views
Skip to first unread message

mukesh tiwari

unread,
Feb 14, 2010, 11:53:15 AM2/14/10
to
Hello everyone. I am new to python and previously i did programming in
c/c++.Could some one please help me to improve the run time for this
python program as i don't have idea how to optimized this code.This
code also seems to be more unpythonic so how to make it look like more
pythonic . I am trying for this problem(https://www.spoj.pl/problems/
FACT1/).
Thank you

# To change this template, choose Tools | Templates
# and open the template in the editor.

__author__="Mukesh Tiwari"
__date__ ="$Feb 10, 2010 1:35:26 AM$"


import random
from Queue import Queue


def gcd(a,b):
while b:
a,b=b,a%b
return a

def rabin_miller(p,t=1):
if(p<2):
return False
if(p!=2 and p%2==0):
return False
s=p-1
while(s%2==0):
s>>=1
for i in xrange(t):
a=random.randrange(p-1)+1
temp=s
mod=pow(a,temp,p)
while(temp!=p-1 and mod!=1 and mod!=p-1):
mod=(mod*mod)%p
temp=temp*2
if(mod!=p-1 and temp%2==0):
return False
return True
def brent(n):
if(n%2==0):
return 2;

x,c,m=random.randrange(0,n),random.randrange(1,n),random.randrange(1,n)
y,r,q=x,1,1
g,ys=0,0
while(True):
x=y
for i in range(r):
y,k=(y*y+c)%n,0
while(True):
ys=y
for i in range(min(m,r-k)):
y,q=(y*y+c)%n,q*abs(x-y)%n
g,k=gcd(q,n),k+m
if(k>= r or g>1):break
r=2*r
if(g>1):break
if(g==n):
while(True):
ys,g=(x*x+c)%n,gcd(abs(x-ys),n)
if(g>1):break
return g


def factor(n):
Q_1,Q_2=Queue(),[]
Q_1.put(n)
while(not Q_1.empty()):
l=Q_1.get()
if(rabin_miller(l)):
Q_2.append(l)
continue
d=brent(l)
if(d==l):Q_1.put(l)
else:
Q_1.put(d)
Q_1.put(l/d)
return Q_2

if __name__ == "__main__":
while(True):
n=int(raw_input())
if(n==0):break
L=factor(n)
L.sort()
#print L
i=0
s=""
while(i<len(L)):
cnt=L.count(L[i])
#print "%d^%d"%(L[i],cnt)
s+=str(L[i])+"^"+str(cnt)+" "
i+=cnt
print s[:-1]

Mark Lawrence

unread,
Feb 14, 2010, 12:12:32 PM2/14/10
to pytho...@python.org

A good starting point is
http://wiki.python.org/moin/PythonSpeed/PerformanceTips

HTH.

Mark Lawrence

Mark Dickinson

unread,
Feb 14, 2010, 12:48:11 PM2/14/10
to
On Feb 14, 4:53 pm, mukesh tiwari <mukeshtiwari.ii...@gmail.com>
wrote:

> Hello everyone. I am new to python and previously i did programming in
> c/c++.Could some one please help me to improve the run time for this
> python program as i don't have idea how to optimized this code.
> [...]

How much of a speedup do you need? Are we talking about orders of
magnitude (in which case you might want to consider using something
like the Multiple Polynomial Quadratic Sieve method instead, or as
well), or just a few percent?

(1) Have you profiled the code to see where it's spending most of its
time? This is an essential first step.

(2) Obvious things: use range rather than xrange in your loops. Make
sure that all heavily used variables/functions are local to the
function you're using them in. E.g., you use range, min and abs in
the middle of the 'brent' function. Instead, start the brent function
by setting _abs, _range, _min = abs, range, min, and then use _abs,
_range, etc. instead. Lookups of local variables are faster than
globals.

(3) In the inner loop:

for i in range(min(m,r-k)):
y,q=(y*y+c)%n,q*abs(x-y)%n

you can get probably rid of the abs call. It *might* also help to
avoid the tuple packing/unpacking (but see (1)). You could try doing
a couple of steps at a time instead of one (i.e., unroll the loop a
little bit); one advantage is that you probably don't need to bother
reducing q modulo n at every step; every other step would be good
enough. Depending on the relative speed of multiplication and
reduction, and the sizes of the integers involved, this might save
time.

(4) Have you tried using Montgomery reduction in the Brent method?
The inner loop of that method involves two reductions modulo n, which
may well be where the biggest bottleneck is. But see (1). The other
obvious bottleneck is the gcd method; if profiling shows that that's
the case, there might be ways to speed that up, too. (E.g., use a
binary gcd algorithm, or use Lehmer's method.)

Good luck!
--
Mark

Aahz

unread,
Feb 14, 2010, 1:03:21 PM2/14/10
to
In article <363498c7-3575-4f1e...@q16g2000yqq.googlegroups.com>,

Mark Dickinson <dick...@gmail.com> wrote:
>
>(2) Obvious things: use range rather than xrange in your loops.

Um, what? You meant the reverse, surely?
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

"At Resolver we've found it useful to short-circuit any doubt and just
refer to comments in code as 'lies'. :-)"

Steve Howell

unread,
Feb 14, 2010, 1:41:35 PM2/14/10
to
On Feb 14, 9:48 am, Mark Dickinson <dicki...@gmail.com> wrote:
> On Feb 14, 4:53 pm, mukesh tiwari <mukeshtiwari.ii...@gmail.com>
> wrote:
>
> > Hello everyone. I am new to python and previously i did programming in
> > c/c++.Could some one please help me to improve the run time for this
> > python program as i don't have idea how to optimized this code.
> > [...]
>
> How much of a speedup do you need?  Are we talking about orders of
> magnitude (in which case you might want to consider using something
> like the Multiple Polynomial Quadratic Sieve method instead, or as
> well), or just a few percent?
>
> (1) Have you profiled the code to see where it's spending most of its
> time?  This is an essential first step.
>

I ditto the profiling recommendation.

http://docs.python.org/library/profile.html

It might also be useful to time your algorithm for n=10, 100, 1000,
10000, etc., to get a better sense of how the overall algorithm
behaves.

Mark Dickinson

unread,
Feb 14, 2010, 2:35:35 PM2/14/10
to
On Feb 14, 6:03 pm, a...@pythoncraft.com (Aahz) wrote:
> In article <363498c7-3575-4f1e-ad53-d9cd10c8d...@q16g2000yqq.googlegroups.com>,

> Mark Dickinson  <dicki...@gmail.com> wrote:
>
> >(2) Obvious things: use range rather than xrange in your loops.  
>
> Um, what?  You meant the reverse, surely?

Er, yes I did. Thanks!

--
Mark

Mark Dickinson

unread,
Feb 14, 2010, 2:52:51 PM2/14/10
to
On Feb 14, 4:53 pm, mukesh tiwari <mukeshtiwari.ii...@gmail.com>
wrote:
> Hello everyone. I am new to python and previously i did programming in
> c/c++.Could some one please help me to improve the run time for this
> python program as i don't have idea how to optimized this code.This
> code also seems to be more unpythonic so how to make it look like more
> pythonic . I am trying for this problem(https://www.spoj.pl/problems/
> FACT1/).
> Thank you

One other thing: in the 'brent' function, you're setting m to
randrange(1, n). What's the purpose of this? It looks to me as
though m controls the number of Pollard-Rho iterations that are
clumped together at one time (before doing a gcd operation), and using
a random number for this doesn't make a lot of sense to me.

--
Mark

Steve Howell

unread,
Feb 14, 2010, 3:07:41 PM2/14/10
to

The randomness also makes the algorithm a little buggy.

I tried this input:

37^5 41^5

Usually I get the right answer. Other times I get this:

37^5 41^3 1681^1

And occasionally it appears to get into an infinite loop, which
definitely could be a cause of "slowness." :)


mukesh tiwari

unread,
Feb 15, 2010, 12:08:30 PM2/15/10
to

Thank you all for help. I will try to improve these short comings.

Paul Boddie

unread,
Feb 16, 2010, 10:38:24 AM2/16/10
to
On 14 Feb, 19:41, Steve Howell <showel...@yahoo.com> wrote:
>
> I ditto the profiling recommendation.
>
> http://docs.python.org/library/profile.html

(To the original inquirer...) Try this, too:

http://wiki.python.org/moin/PythonSpeed/Profiling

If you have the tools, it's a lot easier than scanning through tables
of times.

Paul

0 new messages