Commit 16a63a41 authored by mrk022's avatar mrk022
Browse files

can follow user steps up until fraction reduction

parent c37c1241
# Equation Tree class
# AI Final Project
# Takes an equation of the form x + 3 = 5 + x and makes this into an equation tree
# this means = is in root and each expression is a tree on either side
# currently only works for addition and two variables on each side of equation
class EquationTreeNode:
def __init__(self, value, parent=None):
self.value = value
self.left = None
self.right = None
self.parent = parent
def setLeft(self, newNode):
self.left = newNode
def setRight(self, newNode):
self.right = newNode
def addLeftNode(self, newNode):
self.left = newNode
newNode.parent = self
def addRightNode(self, newNode):
self.right = newNode
newNode.parent = self
def splitExpression(self, expression):
expressions = expression.split("+")
leftNode = EquationTreeNode(expressions[0])
rightNode = EquationTreeNode(expressions[1])
self.addLeftNode(leftNode)
self.addRightNode(rightNode)
'''def main():
equation = "3x+5=2+2x"
expressions = equation.split("=")
rootNode = EquationTreeNode("=", None)
leftNode = EquationTreeNode("+")
rootNode.addLeftNode(leftNode)
splitExpression(expressions[0], leftNode)
rightNode = EquationTreeNode("+")
rootNode.addRightNode(rightNode)
splitExpression(expressions[1], rightNode)
print(rootNode.value)
print(rootNode.left.value, rootNode.right.value)
print(rootNode.left.left.value, rootNode.left.right.value, rootNode.right.left.value, rootNode.right.right.value)
main() '''
\ No newline at end of file
......@@ -28,12 +28,17 @@ class EquationTree:
self.inorder(node.right)
def evaluate(self, parent, left):
# can simplify this to call helper function
if left:
if parent.left.canEval():
print("parent.left.left is ", parent.left.left.value)
print("parent.left.right is ", parent.left.right)
if isinstance(parent.left.left, NumNode):
print("num node")
print("evaluating", parent.left.eval())
newNode = NumNode(parent.left.eval())
else:
print("variable node")
print("evaluating", parent.left.eval())
newNode = VariableNode(str(parent.left.eval()) + "x")
parent.left = newNode
......@@ -113,14 +118,20 @@ class PlusNode:
self.value = "+"
def canEval(self):
if isinstance(self.left, VariableNode) == isinstance(self.right,VariableNode):
if isinstance(self.left, VariableNode) and isinstance(self.right,VariableNode):
return True
return False
elif isinstance(self.left, NumNode) and isinstance(self.right, NumNode):
return True
else:
return False
def getInverse(self):
return MinusNode(None,None)
def eval(self):
#print("left value ", self.left)
#print(isinstance(self.left, NumNode))
#print("right value ", self.right.value())
return self.left.eval() + self.right.eval()
......@@ -134,9 +145,12 @@ class MinusNode:
self.value = "-"
def canEval(self):
if isinstance(self.left, VariableNode) == isinstance(self.right,VariableNode):
if isinstance(self.left, VariableNode) and isinstance(self.right,VariableNode):
return True
elif isinstance(self.left, NumNode) and isinstance(self.right, NumNode):
return True
return False
else:
return False
def getInverse(self):
return PlusNode(None, None)
......@@ -353,6 +367,12 @@ def main():
equationTree.printTree()
equationTree.get_expression()
'''
print("old node should be 2, is ", oldNum.value)
print("moved node should be 7, is ", moveNode.value)
print("new op is ", newOp.value)
'''
if __name__ == "__main__":
main()
\ No newline at end of file
import ccm
import re
from ccm.lib.actr import *
#from expressionTree import EquationTreeNode
import tree
import queue
......@@ -11,27 +10,40 @@ class TutorState:
self.expressions = equation.split("=")
self.tree = tree.generate_tree(equation)
def move_constants_right(self):
def move_values(self, left, constants):
moveNode = None
node = self.tree.root.left
newOp = None
q = queue.Queue()
if left: # if moving values from right to left
node = self.tree.root.right
q.enqueue(self.tree.root.left)
else: # if moving values from left to right
node = self.tree.root.left
q.enqueue(self.tree.root.right)
if constants: # if moving constants
nodeType = tree.NumNode
emptyNode = tree.VariableNode("0x")
else: # if moving variables
nodeType = tree.VariableNode
emptyNode = tree.NumNode(0)
print("node is ", node)
if isinstance(node, tree.PlusNode) or isinstance(node, tree.MinusNode):
# if plus or minus node
if node.canEval() == False:
# if can't evaluate children, need to move one
newOp = node.getInverse()
if isinstance(node.left, tree.NumNode):
if isinstance(node.left, nodeType):
moveNode = node.left
node.left = tree.VariableNode("0x")
elif isinstance(node.right,tree.NumNode):
node.left = emptyNode
elif isinstance(node.right, nodeType):
moveNode = node.right
node.right = tree.VariableNode("0x")
q = queue.Queue()
q.enqueue(self.tree.root.right)
node.right = emptyNode
moved = False
while not q.isEmpty() and not moved:
currentNode = q.front()
print("currentNode is ", currentNode.value)
if currentNode.left != None:
if isinstance(currentNode.left, tree.NumNode):
if isinstance(currentNode.left, nodeType):
oldNum = currentNode.left
currentNode.left = newOp
currentNode.left.left = oldNum
......@@ -39,27 +51,43 @@ class TutorState:
moved = True
q.enqueue(currentNode.left)
if currentNode.right != None and not moved:
if isinstance(currentNode.right, tree.NumNode):
if isinstance(currentNode.right, nodeType):
oldNum = currentNode.right
currentNode.right = newOp
currentNode.right.left = oldNum
currentNode.right.right = moveNode
moved = True
q.enqueue(currentNode.right)
if isinstance(currentNode, nodeType) and not moved:
oldNum =currentNode
print("old node should be 2, is ", oldNum.value)
print("moved node should be 7, is ", moveNode.value)
print("new op is ", newOp.value)
if left:
self.tree.root.left = newOp
self.tree.root.left.left = oldNum
self.tree.root.left.right = moveNode
else:
self.tree.root.right = newOp
self.tree.root.right.left = oldNum
self.tree.root.right.right = moveNode
moved=True
q.dequeue()
self.combine_like_terms(True) # will need to change this to just combine variables 4x + 0x
# will need to change this to just combine variables 4x + 0x
if left: self.combine_like_terms(False)
else : self.combine_like_terms(True)
return self.tree.get_expression()
#self.tree.printTree()
#self.tree.get_expression()
def combine_like_terms(self, left):
self.tree.get_expression()
print("COMBINING LIKE TERMS")
if left:
print("evaluating left side")
self.tree.evaluate(self.tree.root, True)
else:
print("evaluating right side")
self.tree.evaluate(self.tree.root, False)
self.tree.get_expression()
return self.tree.get_expression()
class UserState(ccm.Model): #ccm.ProductionSystem
......@@ -72,11 +100,6 @@ class UserState(ccm.Model): #ccm.ProductionSystem
self.oldEquation = None
self.sides = self.getLeftandRightVals()
self.constantCount = self.getConstantCount()
#self.generate_tree()
#self.moveconstants = ["4x=5x+2-7","4x+7-2=5x", "7-2=1x", "-1x+7-2=0"]
#self.movevariables = ["7=5x-4x+2", "4x-5x+7=2"]
#self.addconstants = ["4x=5x-5","4x+5=5x"]
#self.addvariables = ["7=1x+2", "-1x+7=2"]
self.state = None
self.end = False
......@@ -90,13 +113,15 @@ class UserState(ccm.Model): #ccm.ProductionSystem
self.sides = self.getLeftandRightVals()
oldConstantCount = self.constantCount
self.constantCount = self.getConstantCount()
#self.state = self.get_state(oldConstantCount)
self.state = self.get_state(oldConstantCount)
#print("state is ", self.state)
return oldConstantCount
#return oldConstantCount
def getLeftandRightVals(self):
expressions = self.equation.split("=")
leftVars = None
rightVars = None
try:
leftVars = re.split("[+-]", expressions[0])
rightVars = re.split("[+-]", expressions[1])
......@@ -114,53 +139,57 @@ class UserState(ccm.Model): #ccm.ProductionSystem
for value in self.sides[0]:
if self.isConstant(value):
constantsOnLeft += 1
else:
elif 'x' in value:
variablesOnLeft += 1
for value in self.sides[1]:
if self.isConstant(value):
constantsOnRight += 1
else:
elif 'x' in value:
variablesOnRight += 1
return [variablesOnLeft, constantsOnLeft, variablesOnRight, constantsOnRight]
print("There are ", variablesOnLeft, " variables on the left and ", constantsOnLeft, " constants on the left")
print("There are ", variablesOnRight, " variables on the right and ", constantsOnRight, " constants on the right")
def isConstant(self, value):
if 'x' in value:
print(value)
if not value.isdigit():
return False
return True
def get_state(self, oldConstantCount):
# based on number of variables constants on each side of the equation, the agent guesses which state the user is moving to
print("old constant count ", oldConstantCount)
print("self.constantcount ", self.constantCount)
print("old: ", oldConstantCount)
print("new: ", self.constantCount)
if oldConstantCount[0] != self.constantCount[0] and oldConstantCount[2] != self.constantCount[2]:
# if not same number of variables as before for both sides then moved variables
print("variables were moved")
self.state = "move_variables"
self.state = "move_variables 1"
elif oldConstantCount[0] != self.constantCount[0] or oldConstantCount[2] != self.constantCount[2]:
print("variables were added")
self.state = "add_variables"
if oldConstantCount[0] > self.constantCount[0]: self.state = "add_variables 1"
else: self.state = "add_variables 0"
elif oldConstantCount[1] != self.constantCount[1] and oldConstantCount[3] != self.constantCount[3]:
print("constants were moved")
self.state = "move_constants"
if oldConstantCount[1] < self.constantCount[1]: #moving constants to left
self.state = "move_constants 1"
else:
self.state = "move_constants 0"
elif oldConstantCount[1] != self.constantCount[1] or oldConstantCount[3] != self.constantCount[3]:
print("constants were added")
self.state = "add_constants"
if oldConstantCount[1] > self.constantCount[1]:
self.state = "add_constants 1"
else:
self.state = "add_constants 0"
else:
print("nothing triggered")
# need to do this for division and simplifying fraction
return self.state
def moveConstants(self):
'''def moveConstants(self):
print("Constants moved to one side of equation")
self.state = "move_constants"
def moveVariables(self):
print("Variables moved to one side of equation")
self.state = "move_variables"
self.state = "move_variables"''' # dont think i need these functions anymore
# look at how to structure UserState () to not run every function
......@@ -174,43 +203,41 @@ class IntelligentTutor(ACTR):
#tutor.combine_like_terms(True)
def init():
cc = user.get_input()
user.get_input()
print("USER STATE IS ", user.state) # need to get user input to translate to state
goal.set(user.get_state(cc)) #
goal.set(user.state) #get_state(cc)
def moved_constants(goal="move_constants ?left"): #true if moving constants left
tutorEq = tutor.move_values(bool(int(left)), True)
print("user equation ",user.equation)
goal.set("check_state " + tutorEq)
def add_constants(goal= "add_constants ?left"):
tutorEq = tutor.combine_like_terms(bool(int(left)))
print("user equation ",user.equation)
goal.set("check_state " + tutorEq)
def moved_variables(goal="move_variables ?left"):
tutorEq = tutor.move_values(bool(int(left)), False)
print("user equation ",user.equation)
goal.set("check_state " + tutorEq)
def add_variables(goal = "add_variables ?left"):
tutorEq = tutor.combine_like_terms(bool(int(left)))
print("user equation", user.equation)
goal.set("check_state " + tutorEq)
def moved_constants(goal="move_constants"): #user="ready:True"
tutorEq = tutor.move_constants_right()
def check_state(goal = "check_state ?tutorEq"):
if tutorEq == user.equation:
user.get_input()
goal.set(user.state)
else:
print("INVALID")
goal.set("end_process")
#if it is invalid then move to invalid state, and return correct state we found in that function
#print("constants")
#goal.set("add_constants")
def add_constants(goal= "add_constants"):
# use tree functionality to add constants, pass in expression with two constants to expression tree and solve
# generate new correct equation based on this result
# check if user input is the same as what we caluclated
# if it is correct then
user.get_input()
goal.set(user.state)
# if it is invalid then move to the invalid state
def moved_variables(goal="move_variables"):
#user.moveVariables()
print("variables")
goal.set("add_variables")
goal.set("invalid_state " + tutorEq)
def add_variables(goal = "add_variables"):
print("add")
goal.set("end_process")
def incorrect_state(goal = "invalid state"):
print("You have entered an invalid state. We anticipated the correct step to be: \n Please continue solving the problem with the corrected equation above.")
def incorrect_state(goal = "invalid_state ?tutorEqn"):
print("You have entered an invalid state. We anticipated the correct step to be: ", tutorEqn, "\nPlease continue solving the problem with the corrected equation.")
# need to print what correct state would have been
user.equation = tutorEqn
user.get_input()
goal.set(user.state)
......@@ -223,8 +250,6 @@ class EmptyEnvironment(ccm.Model):
def main():
#eqn = "3x + 4 = 0"
env_name = EmptyEnvironment()
agent_name = IntelligentTutor()
env_name.agent = agent_name
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment