Let's improve the linear algebra tutor
Code Interpreter made a good first attempt but there's a lot we can improve
Yesterday I wrote a post about how I got Code Interpreter to create a Python-based tutor for learning the rudiments of linear algebra. While it was a very impressive initial effort, it needs some work. The script has a number of limitations, which need to be rectified, if we are to build a robust tutor.
I am going to identify those limitations in this post, and provide Code Interpreter’s suggestions for overcoming the first two. (Otherwise this post would be overly long.) This is a great example of how iteratively working with ChatGPT + Code Interpreter can yield even better results than merely relying on its first output.
The limitations of our first tutor
The script is a basic tutorial for teaching linear algebra concepts. It uses a class called ‘LinearAlgebraTutor’
which offers various methods to teach topics such as vectors, matrices, scalar multiplication, matrix addition and subtraction, and more.
Following is an outline of the limitations I’ve identified1:
User Input Handling:
The script takes a user input, but does not validate or handle incorrect inputs.
There’s no option to exit or go back to the main menu.
No interaction with the user other than selecting a topic; no exercises of quizzes to assess understanding.
Code Structure:
The teaching methods are outside the class and should be inside the class to access via
‘self’
.The
‘start’
method contains an‘if-elif’
chain for topic selection, which can become unwieldy as more topics are added.Lack of separation between logic and presentation: the print statements are mixed with mathematical operations.
Content Limitations:
The teaching is mostly theoretical, with no visual aids, such as plots or interactive components, to enhance understanding.
Limited examples and no provision for the user to experiment with custom inputs or see step-by-step solutions.
Error Handling:
No error handling for operations that might fail, such as matrix inversion for singular matrices.
No checks for vector or matrix dimensions where needed, such as in matrix multiplication or cross product.
Suggestions to overcome Limitations2
User Input Handling:
Implement input validation to ensure users enter a valid choice.
Add options to exit the tutorial or return to the main menu.
Introduce exercises or quizzes to gauge understanding and engagement.
Code Structure:
Move the teaching methods inside the
‘LinearAlgebraTutor’
class.Replace the
‘if-elif’
chain with a dictionary mapping to methods or a switch-like structure.Separate the logic and presentation by creating methods for mathematical operations and print statements.
Content Enhancements:
Include visual aids such as plots to demonstrate vectors, matrices, and transformations.
Provide interactive examples that allow users to input custom values and see results.
Expand the curriculum to include more advanced topics and practical applications of linear algebra.
Error Handling:
Implement error handling for operations that might fail, such as using
‘try-except’
blocks.Include checks for vector and matrix dimensions where necessary to ensure compatability for operations.
Some solutions
Modifying the script for user input handling:
Validate the user’s input to ensure they select a valid option.
Add an option to exit the tutorial or return to the main menu.
Provide a loop to allow continuous interaction until the user decides to exit.
Code:
class LinearAlgebraTutor:
# Other methods remain the same
def start(self):
while True:
print("Welcome to the Linear Algebra Tutor!")
print("Please choose a topic:")
print("1. Vectors")
print("2. Matrices")
print("3. Scalar Multiplication")
print("4. Matrix Addition and Subtraction")
print("5. Matrix Multiplication")
print("6. Dot Product")
print("7. Cross Product")
print("8. Determinants")
print("9. Eigenvalues and Eigenvectors")
print("10. Matrix Inversion")
print("11. Matrix Transposition")
print("12. Exit")
topic = input("Please enter a number between 1 and 12: ")
if topic.isdigit():
topic = int(topic)
if topic == 1:
self.teach_vectors()
elif topic == 2:
self.teach_matrices()
# continue with other elif statements for other topics
elif topic == 12:
print("Thank you for using the Linear Algebra Tutor. Goodbye!")
break
else:
print("Invalid choice. Please enter a number between 1 and 12.")
else:
print("Invalid input. Please enter a numerical value.")
What this does:
The
‘while True:’
loop ensures that the user can continue selecting topics until they choose to exit.The
‘isdigit()’
method checks if the user’s input is a numerical value, preventing non-numeric inputs.A new option “12.Exit” has been added, allowing the user to exit the tutorial.
If the user enters an invalid number (outside the range 1-12), they receive an error message.
Improving the code structure:
Move Teaching Methods Inside the Class
The teaching methods must be part of the
‘LinearAlgebraTutor’
class to be called via‘self’
. This encapsulates the functionality within the class.
Replace the
‘if-elif’
Chain with a Dictionary MappingThe chain of
‘if-elif’
statements can become unwieldy as more topics are added. By using a dictionary to map the topics to methods, we can simplify the code.
Separate Logic and Presentation
Create separate methods for mathematical operations and print statements. This separation of concerns makes the code more modular and easier to maintain.
class LinearAlgebraTutor:
def __init__(self):
# Define a dictionary that maps topic numbers to methods
self.topic_mapping = {
1: self.teach_vectors,
2: self.teach_matrices,
# Continue mapping other topics
}
def start(self):
while True:
print("Welcome to the Linear Algebra Tutor!")
# Menu options
print("12. Exit")
topic = input("Please enter a number between 1 and 12: ")
if topic.isdigit():
topic = int(topic)
if 1 <= topic <= 11:
# Call the corresponding method based on user input
self.topic_mapping[topic]()
elif topic == 12:
print("Thank you for using the Linear Algebra Tutor. Goodbye!")
break
else:
print("Invalid choice. Please enter a number between 1 and 12.")
else:
print("Invalid input. Please enter a numerical value.")
def teach_vectors(self):
# Separate method for vector operations
self.print_vector_intro()
v = self.create_vector([1, 2, 3])
u = self.create_vector([4, 5, 6])
self.add_vectors(v, u)
def print_vector_intro(self):
print("\n--- Vectors ---")
# Continue with introductory text
def create_vector(self, values):
return np.array(values)
def add_vectors(self, v, u):
print("v + u = ", np.add(v, u))
# Continue with other methods for other topics
Explanation:
Dictionary mapping: The
‘topic_mapping’
dictionary in the constructor links topics to methods, allowing for a concise and scalable way to handle topic selection.Separation of Concerns: By separating the logic and presentation, the code is more maintainable. For example,
‘teach_vectors’
now delegates printing to‘print_vector_intro’
and vector operations to separate methods.Encapsulation: All teaching methods are now encapsulated within the class, ensuring a coherent design.
Summary
The first attempt at creating a linear algebra tutor was, while impressive given the simple prompt provided, insufficent and poorly structured. It would have been of little use to a student, in part because of the limitations identified above. However, once we identified those limitations, we can iteratively work with Chat GPT + Code Interpreter to improve upon the idea. Iterative improvements with ChatGPT (whether combined with Code Interpreter or not) are an extraordinarily powerful way to rapidly generate fairly sophisticated output from generative AI. And, as the saying goes, today’s AI is the worst you’ll ever use.
Let me clarify this statement. I identified a variety of limitations to the script, and subsequently asked Code Interpreter to review it and provide me with a list of limitations. These two lists matched nearly perfectly, which I think says a lot about how much Python I have learned since I started to use Code Interpreter to write me various scripts. What you are reading in this section is a synthesis of my thoughts and Code Interpreter’s. But as I say, Code Interpreter identified the same limitations that I did.
I provide some suggestions for the first two limitations, however, please note that these suggestions were created entirely by Code Interpreter, and not me. The distinction between identifying a limitation and proposing a solution to remedy that limitation ought to be obvious!
These were all provided by Code Interpreter.