Ask Your Question
1

Root systems algorithm: "TypeError: 'str' object is not callable"

asked 2020-08-19 22:54:59 +0200

SarahDi gravatar image

updated 2020-09-24 22:59:31 +0200

slelievre gravatar image

I am rather new to Sage and formal language.

I am running the following code which works fine with a slighty simpler version (where the variables p1, p2, ..., p5 in the function letsapply are fixed).

Here is the original function that works fine:

def letsapply(listg, alist):
    mylistg = listg
    mylistg.reverse()
    for si in mylistg:
        if si == 's1':
            alist = map(s1, alist)
        elif si == 's2':
            alist = map(s2, alist)
        elif si == 's3':
            alist = map(s3, alist)
        elif si == 's4':
            alist = map(s4, alist)
        elif si == 's5':
            alist = map(s5, alist)
        elif si == 's6':
            alist = map(s6, alist)
        else:
            print("Wrong input in letsapply!!")
    alistt = [tuple(v) for v in alist]
    alistts = set(alistt)
    return alistts

Below, I am getting the following

TypeError: 'str' object is not callable

Could anyone help me fix this? Thanks a lot!

e = RootSystem(['E',6]).ambient_space()
Roots = e.roots()

a1 = vector((1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2, 1/2))
a2 = vector((1, 1, 0, 0, 0, 0, 0, 0))
a3 = vector((-1, 1, 0, 0, 0, 0, 0, 0))
a4 = vector((0, -1, 1, 0, 0, 0, 0, 0))
a5 = vector((0, 0, -1, 1, 0, 0, 0, 0))
a6 = vector((0, 0, 0, -1, 1, 0, 0, 0))

Lini = [a1, a2, a3, a4, a5]

# alist is the set of all projections of roots in E6

myR = [vector(v) for v in Roots]

def proj(t, ai):
    myLone = vector(ai)
    result= t - myLone.dot_product(t) / (ai.dot_product(ai))*myLone
    return result

myL = [proj(x, a6) for x in myR]

def si(t, projai):
      myLone = projai
      result = t- 2*myLone.dot_product(t)/(projai.dot_product(projai))*myLone
      return result

def decompose(g, mylength):
    # g is a str(aa) where aa belongs to list(WeylGroup ...)
    listg = [g[3*i]+ g[3*i+1] for i in range(0, mylength)]
    return listg

def letsapply(listg, alist, p1, p2, p3, p4, p5):
    mylistg = listg
    mylistg.reverse()
    for si in mylistg:
        if si == 's1':
            alist = map(lambda w: si(w, p1), alist)
        elif si == 's2':
            alist = map(lambda w: si(w, p2), alist)
        elif si == 's3':
            alist = map(lambda w: si(w, p3), alist)
        elif si == 's4':
            alist = map(lambda w: si(w, p4), alist)
        elif si == 's5':
            alist = map(lambda w: si(w, p5), alist)
        else:
            print("Wrong input in letsapply!!")
    alistt = [tuple(v) for v in alist]
    alistts = set(alistt)
    return alistts

def main():
    W = WeylGroup(["A", 5], prefix="s")
    listW = list(W)
    # We remove the first element which is 1:
    listW.pop(0)
    listWdecomposed = [decompose(str(g), g.length()) for g in listW]

    e = RootSystem(['E',6]).ambient_space()
    Roots = e.roots()
    ## get all projections of roots in E6
    myR = [vector(v) for v in Roots]
    myL = [proj(x, a6) for x in myR]
    print("myL =", myL)

    # produce all combinaisons in myL of five vectors,
    # and apply the procedure to them: the procedure consists first in writing
    # the Weyl group associated to any five elements in myL (call any : myLel),
    # then applying these elements si to myLel

    myLlist= Combinations(myL, 5).list()
    for myLel in myLlist:
        [proja1, proja2, proja3, proja4, proja5] = myLel
    res = set(tuple(v) for v in myLel)
    for listg in listWdecomposed:
        res = res.union(letsapply(listg, myLel, proja1, proja2, proja3, proja4, proja5))
        # Reconvert
        res = [vector(v) for v in res]
        res.sort()
    if len(res)< 30:
        return(len(res), res)
    else:
        print("too many vectors in this subspace")
    return 0
    main()
edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
1

answered 2020-08-20 00:30:07 +0200

Emmanuel Charpentier gravatar image

Your code self-contradicts. Take this sample :

for si in mylistg:
    if si == 's1':
        alist = map(s1, alist)

The second line triggers the execution of the third if the test succeeds, i. e if si is a string.

But the third line then tries to map the function si to the elements of alist.

You can't have it both ways : si can't be simultaneously a string and a function...

You have to choose to have your cake or to eat it...

A possible solution is to make mylistg a list of functions, and have allowed_s a list of permissible values. You code snippet would become (something like)

alisttt=[list(map(lambda v:u(v), alist)) for u in mylistg if u in allowed_s]

with possible seasonings to prepare the arguments and return the result in pleasant form.

HTH,

Historical (paleontological) note : Common Lisp, allowing you to attach both a value and a function to the same symbol, would have allowed such a ... thing ... Not Python.

edit flag offensive delete link more

Comments

Hi, the si applied is the si defined here:

myP = [proj(x, a6) for x in Lini]
 [proja1, proja2, proja3, proja4, proja5] = myP
    def si(t, projai):
            myLone = projai
            result = t- 2*myLone.dot_product(t)/(projai.dot_product(projai))*myLone
            return result
SarahDi gravatar imageSarahDi ( 2020-08-20 09:45:08 +0200 )edit

This code along with the main function below work fine:

def main():
    W = WeylGroup(["A", 5], prefix="s")
    listW = list(W)
    # We remove the first element which is 1:
    listW.pop(0)
    listWdecomposed = [decompose(str(g), g.length()) for g in listW]
    res = set(tuple(v) for v in myP)

    for listg in listWdecomposed:
        res = res.union(letsapply(listg, myP))

    # On reconvertit :
    res = [vector(v) for v in res]
    res.sort()
    return(len(res), res)

Now, I am trying to do a loop where I apply this function 'main' to the list of all sets of five random vectors in myL, this is why I have added the p1,p2... in the letsapply function.

SarahDi gravatar imageSarahDi ( 2020-08-20 09:51:44 +0200 )edit

If I understand you correctly, you oscillate between the generators of W (here s1, s2, s3, s4, s5) and their string representations (i. e. "s1", "s2", "s3", "s4", "s5"). Your function decompose is an attempt to get to the "factors" of a (non-trivial) element of W in terms of these generators.

Let's keep it simple, stay in W and do not fiddle with string representation madness :

sage: W=WeylGroup(["A",5], prefix="s")                                          
sage: def decompose(w): 
....:     S=w.parent().gens() 
....:     return [S[u-1] for u in w.reduced_word()] 
....:                                                                           
sage: all([bool(w==product(decompose(w))) for w in W[1:]])                      
True

HTH,

Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2020-08-20 14:20:39 +0200 )edit
1

OK, I'm dense, and wasn't clear the first time around.

In your function letsapply, the snippet :

for si in mylistg:
    if si == 's1':
        alist = map(s1, alist)

defines si to be a local variable (with a string value coming from mylistg). This variable hides the global definition of the function si, which is no longer reachable, hence the dreaded string not callable message.

Rename your bloody loop variable !

Is that clearer ?

Now,

  • Messing with string representations of objects is still objectionable. Use the natural bases and natural representation of your objects.

  • A Python dictionary whose keys are the elements of the basis of your objects and whose value would be the associated functions would be both clearer and more natural.

Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2020-08-20 17:56:40 +0200 )edit

Cool. Merci :)

SarahDi gravatar imageSarahDi ( 2020-08-25 11:51:27 +0200 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2020-08-19 22:54:59 +0200

Seen: 870 times

Last updated: Sep 24 '20