Commit 449c84ec authored by mrk022's avatar mrk022
Browse files

got tree working better, need to tie in with RBES noe

parent 6180fd72
......@@ -4,11 +4,89 @@
import queue
class EquationTree:
def __init__(self):
self.root = EqualsNode()
self.root.left = None
self.root.right = None
def updateNode(self, parent, left, newNode):
if left: parent.left = newNode
else: parent.right = newNode
self.printTree()
def get_expression(self):
self.output = ""
self.inorder(self.root)
print("output is: ", self.output)
return self.output
def inorder(self, node):
if node:
self.inorder(node.left)
self.output += str(node.value)
self.inorder(node.right)
def evaluate(self, parent, left):
if left:
if parent.left.canEval():
if isinstance(parent.left.left, NumNode):
print("evaluating", parent.left.eval())
newNode = NumNode(parent.left.eval())
else:
print("evaluating", parent.left.eval())
newNode = VariableNode(str(parent.left.eval()) + "x")
parent.left = newNode
elif parent.left.left != None and parent.left.left.canEval():
self.evaluate(parent.left, True)
elif parent.left.right != None and parent.left.right.canEval():
self.evaluate(parent.left, False)
else:
if parent.right.canEval():
if isinstance(parent.right.left, NumNode):
print("evaluating", parent.right.eval())
newNode = NumNode(parent.right.eval())
else:
print("evaluating", parent.right.eval())
newNode = VariableNode(str(parent.right.eval()) + "x")
parent.right = newNode
elif parent.right.left != None and parent.right.left.canEval():
self.evaluate(parent.right, True)
elif parent.right.right != None and parent.right.right.canEval():
self.evaluate(parent.right, False)
def printTree(self):
q = queue.Queue()
q.enqueue(self.root)
while not q.isEmpty():
currentNode = q.front()
if currentNode.left != None:
b = Branch()
q.enqueue(b)
q.enqueue(currentNode.left)
if currentNode.right != None:
q.enqueue(currentNode.right)
print(q.dequeue().value, end =' ')
class Branch:
def __init__(self):
self.value = "\n"
self.left = None
self.right = None
class EqualsNode:
def __init__(self):
self.value = "="
class TimesNode:
def __init__(self, left, right):
self.left = left
self.right = right
self.value = "*"
def eval(self):
'''if check_if_variables(str(self.left.eval()), str(self.right.eval())) == "both_vars":
v1 = str(self.left.eval()).split("x")[0]
......@@ -32,7 +110,16 @@ class PlusNode:
def __init__(self, left, right):
self.left = left
self.right = right
self.value = "+"
def canEval(self):
if isinstance(self.left, VariableNode) == isinstance(self.right,VariableNode):
return True
return False
def getInverse(self):
return MinusNode(None,None)
def eval(self):
return self.left.eval() + self.right.eval()
......@@ -44,6 +131,15 @@ class MinusNode:
def __init__(self,left, right):
self.left = left
self.right = right
self.value = "-"
def canEval(self):
if isinstance(self.left, VariableNode) == isinstance(self.right,VariableNode):
return True
return False
def getInverse(self):
return PlusNode(None, None)
def eval(self):
return self.left.eval() - self.right.eval()
......@@ -53,21 +149,31 @@ class MinusNode:
class NumNode:
def __init__(self, num):
self.num = num
self.value = num
self.left = None
self.right = None
def eval(self):
return self.num
return self.value
def canEval(self):
return False # not an operator
def inorder(self):
return str(self.num)
return str(self.value)
class VariableNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def eval(self):
# get value before x
return float(self.value.split("x")[0])
return int(self.value.split("x")[0])
def canEval(self):
return False #not an operator
def inorder(self):
return str(self.eval())
......@@ -99,7 +205,7 @@ def E(q):
output = VariableNode(token)
# make a different class for variable node
else:
output = NumNode(float(token))
output = NumNode(int(token))
#except:
# print("Not a valid operation, need variables of like terms")
# output = NumNode(float(0))
......@@ -138,9 +244,62 @@ def infix_to_prefix(formula):
a = exp_stack.pop()
b = exp_stack.pop()
exp_stack.append( op+" "+b+" "+a )
print exp_stack[-1]
print(exp_stack[-1])
return exp_stack[-1]
def add_to_tree(q, root, left):
if not q.isEmpty():
token = q.dequeue()
operator = False
if token == "+":
newNode = PlusNode(None, None)
operator = True
elif token == "*":
newNode = TimesNode(None, None)
operator = True
elif token == "-":
newNode = MinusNode(None, None)
operator = True
elif "x" in token:
newNode = VariableNode(token)
else:
newNode = NumNode(int(token))
if left: root.left = newNode
else: root.right = newNode
if operator:
add_to_tree(q, newNode, True)
add_to_tree(q, newNode, False)
return newNode
def generate_tree(equation):
t = EquationTree()
expressions = equation.split("=")
x1 = infix_to_prefix(expressions[0])
x2 = infix_to_prefix(expressions[1])
lst1 = x1.split()
q1 = queue.Queue()
lst2 = x2.split()
q2 = queue.Queue()
for token in lst1:
q1.enqueue(token)
add_to_tree(q1, t.root, True) # add expression tree to left side of equation tree
for token in lst2:
q2.enqueue(token)
add_to_tree(q2, t.root, False) # add expression tree to right side of equation tree
t.printTree()
return t
def eval_tree(expression):
'''x = NumNode(5)
......@@ -174,8 +333,25 @@ def split_equation(equation):
return expressions
def main():
exp = split_equation("4x * 3x + 2")
x = eval_tree(exp[0])
#exp = split_equation("4x * 3x + 2")
#x = eval_tree(exp[0])
'''eqTree = EquationTree()
x1 = VariableNode("4x")
x2 = NumNode(3)
x3 = NumNode(2)
x4 = NumNode(7)
t = PlusNode(x1,x2)
t2 = PlusNode(x3,x4)
eqTree.root.left = t
eqTree.root.right = t2
eqTree.printTree()'''
equationTree = generate_tree("4x + 3 = 2 + 7")
print(equationTree.root.left.canEval())
print(equationTree.root.right.canEval())
newNode = NumNode(equationTree.root.right.eval())
equationTree.updateNode(equationTree.root, False, newNode)
equationTree.printTree()
equationTree.get_expression()
if __name__ == "__main__":
......
......@@ -2,11 +2,63 @@ import ccm
import re
from ccm.lib.actr import *
#from expressionTree import EquationTreeNode
from tree import *
import tree
import queue
class StepGenerator:
class TutorState:
def __init__(self,equation):
self.equation = equation
self.expressions = equation.split("=")
self.tree = tree.generate_tree(equation)
def move_constants_right(self):
moveNode = None
node = self.tree.root.left
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):
moveNode = node.left
node.left = tree.VariableNode("0x")
elif isinstance(node.right,tree.NumNode):
moveNode = node.right
node.right = tree.VariableNode("0x")
q = queue.Queue()
q.enqueue(self.tree.root.right)
moved = False
while not q.isEmpty() and not moved:
currentNode = q.front()
if currentNode.left != None:
if isinstance(currentNode.left, tree.NumNode):
oldNum = currentNode.left
currentNode.left = newOp
currentNode.left.left = oldNum
currentNode.left.right = moveNode
moved = True
q.enqueue(currentNode.left)
if currentNode.right != None and not moved:
if isinstance(currentNode.right, tree.NumNode):
oldNum = currentNode.right
currentNode.right = newOp
currentNode.right.left = oldNum
currentNode.right.right = moveNode
moved = True
q.enqueue(currentNode.right)
q.dequeue()
#self.tree.printTree()
#self.tree.get_expression()
def combine_like_terms(self, left):
self.tree.get_expression()
print("COMBINING LIKE TERMS")
if left:
self.tree.evaluate(self.tree.root, True)
else:
self.tree.evaluate(self.tree.root, False)
self.tree.get_expression()
class UserState(ccm.Model): #ccm.ProductionSystem
#moveConstants = "0" # move constants is 0 when need to move them, 1 when move variables, 2 when neither
......@@ -15,6 +67,7 @@ class UserState(ccm.Model): #ccm.ProductionSystem
def __init__(self, equation):
ccm.Model.__init__(self)
self.equation = equation
self.oldEquation = None
self.sides = self.getLeftandRightVals()
self.constantCount = self.getConstantCount()
#self.generate_tree()
......@@ -26,19 +79,29 @@ class UserState(ccm.Model): #ccm.ProductionSystem
self.end = False
def get_input(self):
user_step = input("Please enter your next step: ") #figure out what user step means
outputString = "Equation is currently: " + str(self.equation) + "\nWhat is your next step? "
user_step = input(outputString) #figure out what user step means
# call some get_state() function comparing user step to what state should be
oldEquation = self.equation
self.oldEquation = self.equation
self.equation = user_step
newSides = self.getLeftandRightVals()
self.state = self.get_state(newSides)
ready = True
return user_step
oldSides = self.sides
self.sides = self.getLeftandRightVals()
oldConstantCount = self.constantCount
self.constantCount = self.getConstantCount()
#self.state = self.get_state(oldConstantCount)
#print("state is ", self.state)
return oldConstantCount
def getLeftandRightVals(self):
expressions = self.equation.split("=")
leftVars = re.split("[+-]", expressions[0])
rightVars = re.split("[+-]", expressions[1])
try:
leftVars = re.split("[+-]", expressions[0])
rightVars = re.split("[+-]", expressions[1])
except:
print("INVALID INPUT, try again")
self.equation=self.oldEquation
self.get_input()
return [leftVars, rightVars]
def getConstantCount(self):
......@@ -67,17 +130,25 @@ class UserState(ccm.Model): #ccm.ProductionSystem
return False
return True
def get_state(self, newSides):
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
if newSides[0] != self.sides[0] and newSides[2] != newSides[2]:
print("old constant count ", oldConstantCount)
print("self.constantcount ", 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"
elif newSides[0] != self.sides[0] or newSides[2] != newSides[2]:
elif oldConstantCount[0] != self.constantCount[0] or oldConstantCount[2] != self.constantCount[2]:
print("variables were added")
self.state = "add_variables"
elif newSides[1] != self.sides[1] and newSides[3] != newSides[3]:
elif oldConstantCount[1] != self.constantCount[1] and oldConstantCount[3] != self.constantCount[3]:
print("constants were moved")
self.state = "move_constants"
elif newSides[1] != self.sides[1] or newSides[3] != newSides[3]:
elif oldConstantCount[1] != self.constantCount[1] or oldConstantCount[3] != self.constantCount[3]:
print("constants were added")
self.state = "add_constants"
else:
print("nothing triggered")
# need to do this for division and simplifying fraction
def moveConstants(self):
......@@ -94,15 +165,21 @@ class UserState(ccm.Model): #ccm.ProductionSystem
class IntelligentTutor(ACTR):
goal = Buffer()
user = UserState("4x+7=5x+2")
tutor = TutorState("4x + 3 = 2x + 7")
tutor.move_constants_right()
tutor.combine_like_terms(False)
tutor.combine_like_terms(True)
def init():
user.get_input()
goal.set(user.state)
cc = user.get_input()
print("USER STATE IS ", user.state) # need to get user input to translate to state
goal.set("move_constants") #user.get_state(cc)
def moved_constants(goal="move_constants"): #user="ready:True"
#execute move constants on current equation
#check if user input is the same as what we expect
#if so then
print("here??")
user.get_input()
goal.set(user.state)
#if it is invalid then move to invalid state, and return correct state we found in that function
......
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