Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Hello, @ericrozon! Before answering your question, I would like to make you note that return is a sentence, not a function. That is, you should write something like return x instead of return(x). That being said, I can't think of any potential problem that could arise from using return(x), except that it can cause a momentarily raised eyebrow on somebody reading your code (like it happened to me.) A second observation is that b = var(b) is not syntactically correct, since the correct form actually is b = var('b'). That WILL cause problems. Finally, One last suggestion would be to avoid using the ring RR to define your matrix, since that can cause rounding errors.

Anyway, concerning your question, the problem seems to be the following: Sage is interpreting your variable b not as the independent variable of your function f, but as a symbolic constant. Basically, the problem comes from your function mat: feeding it b tries to create a symbolic matrix, which is impossible, since you declared its elements to be on the numerical ring RR. If you delete the RR as I suggested above, mat will try to create a symbolic matrix (that is allowed in that case, because Sage defaults to the symbolic ring SR), which will have symbolic eigenvalues, and you cannot compute the max of symbolic values

You can solve your problem simply doing a few modifications. Define the function

def g(x):
    return f(x) - 3

and call find_root on it. Alternatively, you could also define your f to return r - 3. I am going to use this second approach for this code:

def is_essentially_real(x):
    if x.imag() == 0:
        return True # changed
    else:
        return False # changed

def get_leading_eigenvalue(L):
    evals = L.eigenvalues()
    moduli = [e.n() for e in evals if is_essentially_real(e)]
    moduli = [e for e in moduli if e >= 0]
    r = max(moduli)
    return r # changed

def mat(b):
    M = matrix(2, 2, [1, b, 1, 2]) # changed: removed the RR ring
    return M # changed

def f(b):
    M = mat(b)
    r = get_leading_eigenvalue(M)
    return r - 3 # changed: subtracted 3

find_root(f, 1, 3) # no more error

This returns the root 1.9999999999999996 (pretty close!). You will notice that I marked every change I made to your code.

I hope this helps!