Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #89099 > unrolled thread

Need opinions on P vs NP

Started byPaddy <paddy3118@gmail.com>
First post2015-04-17 18:19 -0700
Last post2015-04-18 01:08 -0700
Articles 5 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  Need opinions on P vs NP Paddy <paddy3118@gmail.com> - 2015-04-17 18:19 -0700
    Re: Need opinions on P vs NP Ian Kelly <ian.g.kelly@gmail.com> - 2015-04-17 20:33 -0600
      Re: Need opinions on P vs NP Paddy <paddy3118@gmail.com> - 2015-04-17 22:11 -0700
    Re: Need opinions on P vs NP wxjmfauth@gmail.com - 2015-04-18 00:08 -0700
      Re: Need opinions on P vs NP Paddy <paddy3118@gmail.com> - 2015-04-18 01:08 -0700

#89099 — Need opinions on P vs NP

FromPaddy <paddy3118@gmail.com>
Date2015-04-17 18:19 -0700
SubjectNeed opinions on P vs NP
Message-ID<f2e51cb7-dbcf-4679-baf3-9b006b82e08c@googlegroups.com>
Having just seen Raymond's talk on Beyond PEP-8 here: https://www.youtube.com/watch?v=wf-BqAjZb8M, it reminded me of my own recent post where I am soliciting opinions from non-newbies on the relative Pythonicity of different versions of a routine that has non-simple array manipulations.

The blog post: http://paddy3118.blogspot.co.uk/2015/04/pythonic-matrix-manipulation.html

The first, (and original), code sample:

def cholesky(A):
    L = [[0.0] * len(A) for _ in range(len(A))]
    for i in range(len(A)):
        for j in range(i+1):
            s = sum(L[i][k] * L[j][k] for k in range(j))
            L[i][j] = sqrt(A[i][i] - s) if (i == j) else \
                      (1.0 / L[j][j] * (A[i][j] - s))
    return L


The second equivalent code sample:

def cholesky2(A):
    L = [[0.0] * len(A) for _ in range(len(A))]
    for i, (Ai, Li) in enumerate(zip(A, L)):
        for j, Lj in enumerate(L[:i+1]):
            s = sum(Li[k] * Lj[k] for k in range(j))
            Li[j] = sqrt(Ai[i] - s) if (i == j) else \
                      (1.0 / Lj[j] * (Ai[j] - s))
    return L


The third:

def cholesky3(A):
    L = [[0.0] * len(A) for _ in range(len(A))]
    for i, (Ai, Li) in enumerate(zip(A, L)):
        for j, Lj in enumerate(L[:i]):
            #s = fsum(Li[k] * Lj[k] for k in range(j))
            s = fsum(Lik * Ljk for Lik, Ljk in zip(Li, Lj[:j]))
            Li[j] = (1.0 / Lj[j] * (Ai[j] - s))
        s = fsum(Lik * Lik for Lik in Li[:i])
        Li[i] = sqrt(Ai[i] - s)
    return L

My blog post gives a little more explanation, but I have yet to receive any comments on relative Pythonicity.

[toc] | [next] | [standalone]


#89105

FromIan Kelly <ian.g.kelly@gmail.com>
Date2015-04-17 20:33 -0600
Message-ID<mailman.389.1429324454.12925.python-list@python.org>
In reply to#89099
On Fri, Apr 17, 2015 at 7:19 PM, Paddy <paddy3118@gmail.com> wrote:
> Having just seen Raymond's talk on Beyond PEP-8 here: https://www.youtube.com/watch?v=wf-BqAjZb8M, it reminded me of my own recent post where I am soliciting opinions from non-newbies on the relative Pythonicity of different versions of a routine that has non-simple array manipulations.
>
> The blog post: http://paddy3118.blogspot.co.uk/2015/04/pythonic-matrix-manipulation.html
>
> The first, (and original), code sample:
>
> def cholesky(A):
>     L = [[0.0] * len(A) for _ in range(len(A))]
>     for i in range(len(A)):
>         for j in range(i+1):
>             s = sum(L[i][k] * L[j][k] for k in range(j))
>             L[i][j] = sqrt(A[i][i] - s) if (i == j) else \
>                       (1.0 / L[j][j] * (A[i][j] - s))
>     return L
>
>
> The second equivalent code sample:
>
> def cholesky2(A):
>     L = [[0.0] * len(A) for _ in range(len(A))]
>     for i, (Ai, Li) in enumerate(zip(A, L)):
>         for j, Lj in enumerate(L[:i+1]):
>             s = sum(Li[k] * Lj[k] for k in range(j))
>             Li[j] = sqrt(Ai[i] - s) if (i == j) else \
>                       (1.0 / Lj[j] * (Ai[j] - s))
>     return L
>
>
> The third:
>
> def cholesky3(A):
>     L = [[0.0] * len(A) for _ in range(len(A))]
>     for i, (Ai, Li) in enumerate(zip(A, L)):
>         for j, Lj in enumerate(L[:i]):
>             #s = fsum(Li[k] * Lj[k] for k in range(j))
>             s = fsum(Lik * Ljk for Lik, Ljk in zip(Li, Lj[:j]))
>             Li[j] = (1.0 / Lj[j] * (Ai[j] - s))
>         s = fsum(Lik * Lik for Lik in Li[:i])
>         Li[i] = sqrt(Ai[i] - s)
>     return L
>
> My blog post gives a little more explanation, but I have yet to receive any comments on relative Pythonicity.

I prefer the first version. You're dealing with mathematical formulas
involving matrices here, so subscripting seems appropriate, and
enumerating out rows and columns just feels weird to me.

That said, I also prefer how the third version pulls the last column
of each row out of the inner loop instead of using a verbose
conditional expression that you already know will be false for every
column except the last one. Do that in the first version, and I think
you've got it.

[toc] | [prev] | [next] | [standalone]


#89108

FromPaddy <paddy3118@gmail.com>
Date2015-04-17 22:11 -0700
Message-ID<43f7a201-5b3e-48f9-b216-feeea306dac6@googlegroups.com>
In reply to#89105
On Saturday, 18 April 2015 03:34:57 UTC+1, Ian  wrote:
> On Fri, Apr 17, 2015 at 7:19 PM, Paddy <paddy3118@..l.com> wrote:
> > Having just seen Raymond's talk on Beyond PEP-8 here: https://www.youtube.com/watch?v=wf-BqAjZb8M, it reminded me of my own recent post where I am soliciting opinions from non-newbies on the relative Pythonicity of different versions of a routine that has non-simple array manipulations.
> >
> > The blog post: http://paddy3118.blogspot.co.uk/2015/04/pythonic-matrix-manipulation.html
> >
> > The first, (and original), code sample:
> >
> > def cholesky(A):
> >     L = [[0.0] * len(A) for _ in range(len(A))]
> >     for i in range(len(A)):
> >         for j in range(i+1):
> >             s = sum(L[i][k] * L[j][k] for k in range(j))
> >             L[i][j] = sqrt(A[i][i] - s) if (i == j) else \
> >                       (1.0 / L[j][j] * (A[i][j] - s))
> >     return L
> >
> >
> > The second equivalent code sample:
> >
> > def cholesky2(A):
> >     L = [[0.0] * len(A) for _ in range(len(A))]
> >     for i, (Ai, Li) in enumerate(zip(A, L)):
> >         for j, Lj in enumerate(L[:i+1]):
> >             s = sum(Li[k] * Lj[k] for k in range(j))
> >             Li[j] = sqrt(Ai[i] - s) if (i == j) else \
> >                       (1.0 / Lj[j] * (Ai[j] - s))
> >     return L
> >
> >
> > The third:
> >
> > def cholesky3(A):
> >     L = [[0.0] * len(A) for _ in range(len(A))]
> >     for i, (Ai, Li) in enumerate(zip(A, L)):
> >         for j, Lj in enumerate(L[:i]):
> >             #s = fsum(Li[k] * Lj[k] for k in range(j))
> >             s = fsum(Lik * Ljk for Lik, Ljk in zip(Li, Lj[:j]))
> >             Li[j] = (1.0 / Lj[j] * (Ai[j] - s))
> >         s = fsum(Lik * Lik for Lik in Li[:i])
> >         Li[i] = sqrt(Ai[i] - s)
> >     return L
> >
> > My blog post gives a little more explanation, but I have yet to receive any comments on relative Pythonicity.
> 
> I prefer the first version. You're dealing with mathematical formulas
> involving matrices here, so subscripting seems appropriate, and
> enumerating out rows and columns just feels weird to me.
> 
> That said, I also prefer how the third version pulls the last column
> of each row out of the inner loop instead of using a verbose
> conditional expression that you already know will be false for every
> column except the last one. Do that in the first version, and I think
> you've got it.

But shouldn't the maths transcend the slight change in representation? A programmer in the J language might have a conceptually neater representation of the same thing due to its grounding in arrays (maybe) and for a J representation it would become J-thonic. In Python, it is usual to iterate over collections and also to use enumerate where we must have indices. 

Could it be that there is a also a strong pull in the direction of using indices because that is what is predominantly given in the way matrix maths is likely to be expressed mathematically? A case of "TeX likes indices so we should too"?

[toc] | [prev] | [next] | [standalone]


#89114

Fromwxjmfauth@gmail.com
Date2015-04-18 00:08 -0700
Message-ID<734ce510-16d7-4ccb-9fd1-8e0db646114b@googlegroups.com>
In reply to#89099
Le samedi 18 avril 2015 03:19:40 UTC+2, Paddy a écrit :
> Having just seen Raymond's talk on Beyond PEP-8 here: https://www.youtube.com/watch?v=wf-BqAjZb8M, it reminded me of my own recent post where I am soliciting opinions from non-newbies on the relative Pythonicity of different versions of a routine that has non-simple array manipulations.
> 
> The blog post: http://paddy3118.blogspot.co.uk/2015/04/pythonic-matrix-manipulation.html
> 
> The first, (and original), code sample:
> 
> def cholesky(A):
>     L = [[0.0] * len(A) for _ in range(len(A))]
>     for i in range(len(A)):
>         for j in range(i+1):
>             s = sum(L[i][k] * L[j][k] for k in range(j))
>             L[i][j] = sqrt(A[i][i] - s) if (i == j) else \
>                       (1.0 / L[j][j] * (A[i][j] - s))
>     return L
> 
> 
> The second equivalent code sample:
> 
> def cholesky2(A):
>     L = [[0.0] * len(A) for _ in range(len(A))]
>     for i, (Ai, Li) in enumerate(zip(A, L)):
>         for j, Lj in enumerate(L[:i+1]):
>             s = sum(Li[k] * Lj[k] for k in range(j))
>             Li[j] = sqrt(Ai[i] - s) if (i == j) else \
>                       (1.0 / Lj[j] * (Ai[j] - s))
>     return L
> 
> 
> The third:
> 
> def cholesky3(A):
>     L = [[0.0] * len(A) for _ in range(len(A))]
>     for i, (Ai, Li) in enumerate(zip(A, L)):
>         for j, Lj in enumerate(L[:i]):
>             #s = fsum(Li[k] * Lj[k] for k in range(j))
>             s = fsum(Lik * Ljk for Lik, Ljk in zip(Li, Lj[:j]))
>             Li[j] = (1.0 / Lj[j] * (Ai[j] - s))
>         s = fsum(Lik * Lik for Lik in Li[:i])
>         Li[i] = sqrt(Ai[i] - s)
>     return L
> 
> My blog post gives a little more explanation, but I have yet to receive any comments on relative Pythonicity.

========

def cholesky999(A):
    n = len(A)
    L = [[0.0] * n for i in range(n)]
    for i in range(n):
        for j in range(i+1):
            s = 0.0
            for k in range(j):
                s += L[i][k] * L[j][k]
            if i == j:
                L[i][j] = sqrt(A[i][i] - s)
            else:
                L[i][j] = (1.0 / L[j][j] * (A[i][j] - s))
    return L

Simple, clear, logical, consistant.

[toc] | [prev] | [next] | [standalone]


#89118

FromPaddy <paddy3118@gmail.com>
Date2015-04-18 01:08 -0700
Message-ID<23cb60d6-1cdf-4b77-a523-f0b187a49be0@googlegroups.com>
In reply to#89114
On Saturday, 18 April 2015 08:09:06 UTC+1, wxjm...@gmail.com  wrote:
> Le samedi 18 avril 2015 03:19:40 UTC+2, Paddy a écrit :
> > Having just seen Raymond's talk on Beyond PEP-8 here: https://www.youtube.com/watch?v=wf-BqAjZb8M, it reminded me of my own recent post where I am soliciting opinions from non-newbies on the relative Pythonicity of different versions of a routine that has non-simple array manipulations.
> > 
> > The blog post: http://paddy3118.blogspot.co.uk/2015/04/pythonic-matrix-manipulation.html
> > 
> > The first, (and original), code sample:
> > 
> > def cholesky(A):
> >     L = [[0.0] * len(A) for _ in range(len(A))]
> >     for i in range(len(A)):
> >         for j in range(i+1):
> >             s = sum(L[i][k] * L[j][k] for k in range(j))
> >             L[i][j] = sqrt(A[i][i] - s) if (i == j) else \
> >                       (1.0 / L[j][j] * (A[i][j] - s))
> >     return L
> > 
> > 
> > The second equivalent code sample:
> > 
> > def cholesky2(A):
> >     L = [[0.0] * len(A) for _ in range(len(A))]
> >     for i, (Ai, Li) in enumerate(zip(A, L)):
> >         for j, Lj in enumerate(L[:i+1]):
> >             s = sum(Li[k] * Lj[k] for k in range(j))
> >             Li[j] = sqrt(Ai[i] - s) if (i == j) else \
> >                       (1.0 / Lj[j] * (Ai[j] - s))
> >     return L
> > 
> > 
> > The third:
> > 
> > def cholesky3(A):
> >     L = [[0.0] * len(A) for _ in range(len(A))]
> >     for i, (Ai, Li) in enumerate(zip(A, L)):
> >         for j, Lj in enumerate(L[:i]):
> >             #s = fsum(Li[k] * Lj[k] for k in range(j))
> >             s = fsum(Lik * Ljk for Lik, Ljk in zip(Li, Lj[:j]))
> >             Li[j] = (1.0 / Lj[j] * (Ai[j] - s))
> >         s = fsum(Lik * Lik for Lik in Li[:i])
> >         Li[i] = sqrt(Ai[i] - s)
> >     return L
> > 
> > My blog post gives a little more explanation, but I have yet to receive any comments on relative Pythonicity.
> 
> ========
> 
> def cholesky999(A):
>     n = len(A)
>     L = [[0.0] * n for i in range(n)]
>     for i in range(n):
>         for j in range(i+1):
>             s = 0.0
>             for k in range(j):
>                 s += L[i][k] * L[j][k]
>             if i == j:
>                 L[i][j] = sqrt(A[i][i] - s)
>             else:
>                 L[i][j] = (1.0 / L[j][j] * (A[i][j] - s))
>     return L
> 
> Simple, clear, logical, consistant.

And so most Pythonic? Maybe so.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web