Struggling To Test My Code For Keywords

from sympy import *
import random
lambda1 = Symbol('lambda_i')
kw3 = {"I","*I","I/2","*I/2","*I:","I:","sqrt"}
merror = bool
merror == True
n = random.randrange(2, 3, 1)
def mgenerator():
    A = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
    B = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
    return (A,B)
mA, mB = mgenerator()
def matrices():
    MC = mA*mB
    eq55 = Eq(lambda1,(MC).eigenvals())
    P, D = MC.diagonalize()
    return (MC, eq55, P, D)
def mtest():
    mC, mE, mP, mD = matrices()
    if mC.is_diagonalizable() and not any(kw in str(mE) for kw in kw3):
            merror == False
            return merror
    else:
        mA, mB = mgenerator()
        mC, mE, mP, mD = matrices()
        return (mA, mB, mC, mE, mP, mD)
while merror == True:
    mtest()
if merror == False:
    #do stuff 

For some reason I am not able to test my code and run the rest of it. I do not want to generate eigenvectors that include any square roots or complex numbers. Right now, one version of the code works but requires me to execute it a few time to generate the whole problem set.

I am getting a headache from trying to understand the difference between static and dynamic generated variables in matrix forms. Passing these variables through defined functions is also mind-boggling.

I am trying to generate static matrices and test them for conditionals. If they fail the test I want to generate new matrices and test them continuously until they pass the test and I can run the rest of my code.

I accomplished working testing functinos for a similar project integrated in the full code which is the calculus problem generator above the linear algebra problem generator.

Working Code
Updating Working Code That Is Currently Broken
As you can see between the two, the lower half is getting revised and condensed with nicer testing but I am struggling to get the outputs I want that don’t include complex numbers or square roots.
Twitter @Noeo1234)

This is two independent calls to mgenerator, which means that n is generated twice and could theoretically be different (but see below). You can unpack the result of a single call with mA, mB = mgenerator()

However this is not important right now, because you are generating n = random.randrange(2, 3, 1). Because randrange does not include the upper bound (like range in general), this will always be 2.

It seems like you might want to review Python syntax, particularly how to unpack tuples.

I temporarily changed from random.randrange(2, 4, 1) to random.randrange(2, 3, 1)
as a debugging strategy (making it simpler to get the simple right). Eventually I want to generate both 2x2 and 3x3 matrices when I can get the test for 2x2 matrices right.

Exactly what do you expect should happen when these lines of code run?

Probably redundant, but adding merror = bool seemed to fix something while coding.

merror = bool creates a boolean variable.
merror == True specifies the truth value of the boolean variable merror

I used = for creating the variable and == for assigning it a numerical value (1,0) (i.e; True/False).

I will try deleting merror == True

No, it assigns the built-in function bool to the name merror.

No, it tests whether the variable merror (which is the function bool) is equal to True, and does nothing with the result.

This is not how Python works. == is a test for equality, it is not assignment.

Maybe it is better to then change merror == False to merror = False inside def mtest():

I will also try deleting merror = bool and merror == True and replace with merror = True

Current code I am working with (trying not to edit OP):

from sympy import *
import random
lambda1 = Symbol('lambda_i')
kw3 = {"I","*I","I/2","*I/2","*I:","I:","sqrt"}
merror = True
n = random.randrange(2, 3, 1) 
def mgenerator():
    A = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
    B = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
    return (A,B)
def matrices():
    mA, mB = mgenerator()
    MC = mA*mB
    eq55 = Eq(lambda1,(MC).eigenvals())
    if MC.is_diagonalizable():
        P, D = MC.diagonalize()
        return (MC, eq55, P, D)
def mtest():
    mC, mE, mP, mD = matrices()
    if mC.is_diagonalizable() and not any(kw in str(mE) for kw in kw3):
            merror = False
            return merror
    else:
        mA, mB = mgenerator()
        mC, mE, mP, mD = matrices()
        return (mA, mB, mC, mE, mP, mD)
while merror == True:
    mtest()
print(merror)
if merror == False:
     #do stuff

Execution returns:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_17839/3028806082.py in <module>
    186         display(Eq(P1,mP**-1,evaluate=False))
    187         display(Eq(Eq(PD*P1,mP*mD*mP**-1,evaluate=False),C,evaluate=False))
--> 188 linear_algebra()
    189 print("\n")
    190 print("\n")

/tmp/ipykernel_17839/3028806082.py in linear_algebra()
    146             return (mA, mB, mC, mE, mP, mD)
    147     while merror == True:
--> 148         mtest()
    149     print(merror)
    150     if merror == False:

/tmp/ipykernel_17839/3028806082.py in mtest()
    137             return (MC, eq55, P, D)
    138     def mtest():
--> 139         mC, mE, mP, mD = matrices()
    140         if mC.is_diagonalizable() and not any(kw in str(mE) for kw in kw3):
    141                 merror = False

TypeError: cannot unpack non-iterable NoneType object

Does this mean James’ reply is not a solution since these are non-iterable NoneType objects?

Maybe I am messing up in

    def matrices():
        mA, mB = mgenerator()
        MC = mA*mB
        eq55 = Eq(lambda1,(MC).eigenvals())
        if MC.is_diagonalizable():
            P, D = MC.diagonalize()
            return (MC, eq55, P, D)

By failing to check if the matrix is diagonalizable. I will try to split the functions up so variables are not created before assignments.

Error free execution with

from sympy import *
import random     
lambda1 = Symbol('lambda_i')
kw3 = {"I","*I","I/2","*I/2","*I:","I:","sqrt"}
merror = True
n = random.randrange(2, 3, 1) 
def mgenerator():
    A = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
    B = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
    return (A,B)
def matrices():
    mA, mB = mgenerator()
    MC = mA*mB
    eq55 = Eq(lambda1,MC.eigenvals())
    if MC.is_diagonalizable():
        P, D = MC.diagonalize()
    else:
        P,D = MC, MC  #placeholder
    return mA, mB, P, D
def mtest():
    mC, mE, mP, mD = matrices()
    if mC.is_diagonalizable() and not any(kw in str(mE) for kw in kw3):
            merror = False
            return merror
    else:
        mA, mB = mgenerator()
        mC, mE, mP, mD = matrices()
        return (mA, mB, mC, mE, mP, mD)
while merror == True:
    mtest()
print(merror)
if merror == False:
    # do stuff

Still failing to pass the mtest() and generate any outputs, though.

Splitting up functions is a good idea. I would also recommend that if you want to assume that the output of a function has a certain type (e.g. that it is a tuple of a given length), you should make sure that the function always returns that type. If a function completes execution without any return statement, it will return None, and this is the error you were seeing.

2 Likes

Making progress.

from sympy import *
import random
def linear_algebra():
    lambda1 = Symbol('lambda_i')
    kw3 = {"I","*I","I/2","*I/2","*I:","I:","sqrt"}
    merror = True
    n = random.randrange(2, 3, 1) 
    def Amgen():
        A = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
        return A
    def Bmgen():
        B = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
        return B
    def diagonalizer():
        mA, mB = Amgen(),Bmgen()
        C = mA*mB
        P,D = [0,0]
        eq55 = Eq(lambda1,C.eigenvals())
        if C.is_diagonalizable():
            P, D = C.diagonalize()
        else:
            mA, mB = Amgen(),Bmgen()
            C = mA*mB
            diagonalizer()
        eq55 = Eq(lambda1,C.eigenvals())
        return P, D,eq55
    def mstest():
        mE = diagonalizer()[2]
        if not any(kw in str(mE) for kw in kw3):
                merror = False
                return merror
        else:
            Amgen()
            Bmgen()
            diagonalizer()
            mstest()
    #while mtest()[1] == True:
    #    mtest()
    print(mstest())
    if mstest() == False:
        # do stuff
        print("yay!")
linear_algebra()

returns several different outputs.
None yay!

or

none

or

false

or

False yay!

Will try to add a check for type None and none. Probably something like if not type(None) or not type(none)

This outputs either False yay! or None.

from sympy import *
import random
def linear_algebra():
    lambda1 = Symbol('lambda_i')
    kw3 = {"I","*I","I/2","*I/2","*I:","I:","sqrt"}
    merror = True
    #n = random.randrange(2, 3, 1) 
    n = 2
    def Amgen():
        A = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
        return A
    def Bmgen():
        B = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
        return B
    def diagonalizer():
        mA, mB = Amgen(),Bmgen()
        C = mA*mB
        P,D = [0,0]
        eq55 = Eq(lambda1,C.eigenvals())
        if C.is_diagonalizable():
            P, D = C.diagonalize()
        else:
            mA, mB = Amgen(),Bmgen()
            C = mA*mB
            diagonalizer()
        eq55 = Eq(lambda1,C.eigenvals())
        return P, D,eq55
    def mstest():
        mE = diagonalizer()[2]
        if not any(kw in str(mE) for kw in kw3):
                merror = False
                return merror
        else:
            Amgen()
            Bmgen()
            diagonalizer()
            mstest()
    #while mtest()[1] == True:
    #    mtest()
    merror2 = mstest()
    print(merror2)
    if merror2 == False :
        # do stuff
        print("yay!")
        
linear_algebra()

This prints some amount of Nones until a False, yay!. Might be a solution.

from sympy import *
import random
def linear_algebra():
    lambda1 = Symbol('lambda_i')
    kw3 = {"I","*I","I/2","*I/2","*I:","I:","sqrt"}
    merror = True
    #n = random.randrange(2, 3, 1) 
    n = 2
    def Amgen():
        A = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
        return A
    def Bmgen():
        B = randMatrix(n,n,percent=100,min=0, max=3,symmetric=False)
        return B
    def diagonalizer():
        mA, mB = Amgen(),Bmgen()
        C = mA*mB
        P,D = [0,0]
        eq55 = Eq(lambda1,C.eigenvals())
        if C.is_diagonalizable():
            P, D = C.diagonalize()
        else:
            mA, mB = Amgen(),Bmgen()
            C = mA*mB
            diagonalizer()
        eq55 = Eq(lambda1,C.eigenvals())
        return P, D,eq55
    def mstest():
        mE = diagonalizer()[2]
        if not any(kw in str(mE) for kw in kw3):
                merror = False
                return merror
        else:
            Amgen()
            Bmgen()
            diagonalizer()
            mstest()
    #while mtest()[1] == True:
    #    mtest()
    merror2 = mstest()
    print(merror2)
    if merror2 == False and type(merror2) != None:
        # do stuff
        print("yay!")  
    else:
        linear_algebra()
linear_algebra()

Link To Fixed Code

Think I got a stable version with a working keyword tester finally.

Only thing is, with all the tests, the search space is too large for 3x3 matrices now unless there are any performance boosts I could discover. At least it works for 2x2s!

Thank you all for your help!