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

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 close merge delete

Sort by » oldest newest most voted

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.

more

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

( 2020-08-20 02:45:08 -0600 )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.

( 2020-08-20 02:51:44 -0600 )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,

( 2020-08-20 07:20:39 -0600 )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.

( 2020-08-20 10:56:40 -0600 )edit

Cool. Merci :)

( 2020-08-25 04:51:27 -0600 )edit