def test_custom_functions(self): parser = Parser() def testFunction0(): return 13 def testFunction1(a): return 2 * a + 9 def testFunction2(a, b): return 2 * a + 3 * b # zero argument functions don't currently work # self.assertEqual(parser # .parse('testFunction()') # .evaluate({"testFunction":testFunction0}),13) self.assertExactEqual( parser.parse('testFunction(x)').evaluate({ "x": 2, "testFunction": testFunction1 }), 13) self.assertExactEqual( parser.parse('testFunction(x , y)').evaluate({ "x": 2, "y": 3, "testFunction": testFunction2 }), 13) # Add some "built-in" functions def mean(*xs): return sum(xs) / len(xs) parser.functions['mean'] = mean def counter(initial): class nonlocals: x = initial def count(increment): nonlocals.x += increment return nonlocals.x return count parser.functions['count'] = counter(0) self.assertEqual(parser.parse("mean(xs)").variables(), ["xs"]) self.assertEqual(parser.parse("mean(xs)").symbols(), ["mean", "xs"]) self.assertEqual( parser.evaluate("mean(xs)", variables={"xs": [1, 2, 3]}), 2) self.assertExactEqual( parser.evaluate("count(num)", variables={"num": 5}), 5) self.assertExactEqual( parser.evaluate("count(num)", variables={"num": 5}), 10)
class Expression(Serializable): def __init__(self, ex: str): ex = str(ex) self._string = ex self._expression = Parser().parse(ex.replace('**', '^')) @property def string(self): return self._string def variables(self): return self._expression.variables() def evaluate(self, parameters): if USE_NUMEXPR: return numexpr.evaluate(self._string, global_dict={}, local_dict=parameters) else: return self._expression.evaluate(parameters) def get_serialization_data(self, serializer: 'Serializer'): return dict(type='Expression', expression=self._string) @staticmethod def deserialize(serializer: 'Serializer', **kwargs): return Expression(kwargs['expression']) @property def identifier(self): return None
class Expression(Serializable): def __init__(self, ex: str) -> None: self.__string = str(ex) # type: str self.__expression = Parser().parse(ex.replace("**", "^")) # type: py_expression_eval.Expression @property def string(self) -> str: return self.__string def variables(self) -> Iterable[str]: return self.__expression.variables() def evaluate(self, **kwargs) -> float: if USE_NUMEXPR: return numexpr.evaluate(self.__string, global_dict={}, local_dict=kwargs) else: return self.__expression.evaluate(kwargs) def get_serialization_data(self, serializer: "Serializer") -> Dict[str, Any]: return dict(type="Expression", expression=self.__string) @staticmethod def deserialize(serializer: "Serializer", **kwargs) -> Serializable: return Expression(kwargs["expression"]) @property def identifier(self) -> Optional[str]: return None
def _evaluate(cls, layers, formula): """ Parse a string into an arithmetic expression. Parameters ---------- layers : list List of `Layer` objects that correspond to the given variables. formula : str A string describing the arithmetic operations to perform. """ parser = Parser() for layer in layers: formula = formula.replace(layer.name, layer.name.replace(" ", "_")) layer_vars = {layer.name.replace(" ", "_"): layer for layer in layers} try: expr = parser.parse(formula) except Exception as e: logging.error(e) return # Extract variables expr_vars = expr.variables() # Get the intersection of the sets of variables listed in the # expression and layer names of the current layer list union_set = set(layer_vars.keys()).intersection(set(expr_vars)) if len(union_set) != 0: logging.error( "Mis-match between current layer list and expression:" "%s", union_set) try: result = parser.evaluate(expr.simplify({}).toString(), layer_vars) result._dispersion = np.copy(layers[0]._dispersion) result._dispersion_unit = Unit(layers[0]._dispersion_unit) # Make sure layer name is unique i = 1 for layer in layers: if layer.name == result.name: result.name = result.name + "{}".format(i) i += 1 except Exception as e: logging.error("While evaluating formula: %s", e) return return result
def _evaluate(cls, models, formula): """ Parse a string into an arithmetic expression. Parameters ---------- models : list List of `Layer` objects that correspond to the given variables. formula : str A string describing the arithmetic operations to perform. """ try: parser = Parser() expr = parser.parse(formula) except: return # Extract variables vars = expr.variables() # List the models in the same order as the variables sorted_models = [m for v in vars for m in models if m.name == v] if len(sorted_models) > len(vars): logging.error("Incorrect model arithmetic formula: the number " "of models does not match the number of variables.") return elif len(sorted_models) < len(vars): extras = [ x for x in vars if x not in [y.name for y in sorted_models] ] for extra in extras: matches = re.findall('([\+\*\-\/]?\s?{})'.format(extra), formula) for match in matches: formula = formula.replace(match, "") try: expr = parser.parse(formula) vars = expr.variables() except: logging.error("An error occurred.") return try: result = parser.evaluate( expr.simplify({}).toString(), dict(pair for pair in zip(vars, sorted_models))) return result except (AttributeError, TypeError) as e: logging.error("Incorrectly formatted model formula: %s", e)
def _evaluate(cls, layers, formula): """ Parse a string into an arithmetic expression. Parameters ---------- layers : list List of `Layer` objects that correspond to the given variables. formula : str A string describing the arithmetic operations to perform. """ parser = Parser() for layer in layers: formula = formula.replace(layer.name, layer.name.replace(" ", "_")) try: expr = parser.parse(formula) except Exception as e: logging.error(e) return # Extract variables vars = expr.variables() # List the models in the same order as the variables # sorted_layers = [next(l for v in vars for l in layers # if l.name.replace(" ", "_") == v)] # sorted_layers = [l for v in vars for l in layers # if l.name.replace(" ", "_") == v] sorted_layers = [] for v in vars: for l in layers: if l.name.replace(" ", "_") == v: sorted_layers.append(l) break if len(sorted_layers) != len(vars): logging.error("Incorrect layer arithmetic formula: the number " "of layers does not match the number of variables.") try: result = parser.evaluate( expr.simplify({}).toString(), dict(pair for pair in zip(vars, sorted_layers))) result._dispersion = sorted_layers[0]._dispersion result.dispersion_unit = sorted_layers[0].dispersion_unit except Exception as e: logging.error("While evaluating formula: {}".format(e)) return return result
def test_custom_functions(self): parser = Parser() def testFunction0(): return 13 def testFunction1(a): return 2*a+9 def testFunction2(a,b): return 2*a+3*b # zero argument functions don't currently work # self.assertEqual(parser # .parse('testFunction()') # .evaluate({"testFunction":testFunction0}),13) self.assertExactEqual(parser .parse('testFunction(x)') .evaluate({"x":2,"testFunction":testFunction1}),13) self.assertExactEqual(parser .parse('testFunction(x , y)') .evaluate({"x":2,"y":3,"testFunction":testFunction2}),13) # Add some "built-in" functions def mean(*xs): return sum(xs) / len(xs) parser.functions['mean'] = mean def counter(initial): class nonlocals: x = initial def count(increment): nonlocals.x += increment return nonlocals.x return count parser.functions['count'] = counter(0) self.assertEqual(parser.parse("mean(xs)").variables(), ["xs"]) self.assertEqual(parser.parse("mean(xs)").symbols(), ["mean", "xs"]) self.assertEqual(parser.evaluate("mean(xs)", variables={"xs": [1, 2, 3]}), 2) self.assertExactEqual(parser.evaluate("count(inc)", variables={"inc": 5}), 5) self.assertExactEqual(parser.evaluate("count(inc)", variables={"inc": 5}), 10)
class Evaluator: def __init__(self, func='x'): self.parser = Parser() self.expr = self.parser.parse(func) def toString(self): self.expr.toString() def getVariableList(self): return self.expr.variables() def evaluate(self, vars): return self.parser.evaluate(self.expr.toString(), vars)
def saveAnswers(json_indices, jsondata, output_path): output = open(output_path, 'w') parser = Parser() for d in jsondata: if int(d['id']) in json_indices: #print(str(d['ans']) + '\n') answer = answer.replace('%', ' / 100') try: answer = parser.evaluate(answer, variables=None) except: pass output.write(str(d['ans']) + '\n') output.close()
def __init__(self, expression, sample_points): """Initialize the Evaluator :param expression: string of a math expression :param sample_points: list of sample points (tuples) """ expression = Parser().parse(expression) variables = expression.variables() super().__init__(len(variables), 1) self.inputs = sample_points inputs_dicts = [ dict(zip(variables, sample_point)) for sample_point in sample_points ] self.outputs = [ expression.evaluate(input_dict) for input_dict in inputs_dicts ]
def create_dataset(filename, expression, start, end, n_data=2000): """Evaluate given expression and create a dataset from this function with noise.""" data = [] x = np.linspace(start, end, n_data ) parser = Parser() expr = parser.parse(expression) variable = expr.variables() for i in x: data.append([i, parser.evaluate(expression, {variable[0]: i})]) data = np.array(data) row,col = data.shape noise =np.random.RandomState(721).normal(0, 1, n_data) data[:,1] = data[:,1] + noise f = open(filename, '+w') for i in range(row): f.write('{:.3f},{:.3f}\n'.format(data[i,0],data[i,1])) f.close()
def solve(equation, variables): """ Given an equation and variables, solves the equation if possible. If not possible to solve equation, returns 'no answer' """ for key in variables.keys(): equation = equation.replace(key, variables[key]) equation = equation.strip('x =') equation = equation.strip() print('equation:', equation) print('variables:', variables) parser = Parser() #print(re.search('[[a-z]]', equation)) if re.search('[[a-z]]', equation) is not None: answer = 'no answer' else: try: print('equation:', equation) equation.replace('%', ' / 100') answer = parser.evaluate(equation, variables=None) print('answer:', answer) except (OverflowError, ZeroDivisionError): answer = float('inf') return answer
def eval(fx, a): parser = Parser() return parser.evaluate(str(fx), {'x': float(a)})
class ParserTestCase(unittest.TestCase): def setUp(self): self.parser = Parser() def test_parser(self): parser = Parser() #parser and variables self.assertEqual(parser.parse('lulu(x,y)').variables(), ['lulu','x','y']) #evaluate self.assertEqual(parser.parse('1').evaluate({}), 1) self.assertEqual(parser.parse('a').evaluate({'a': 2}), 2) self.assertEqual(parser.parse('2 * 3').evaluate({}), 6) self.assertEqual(parser.parse(u'2 \u2219 3').evaluate({}), 6) self.assertEqual(parser.parse(u'2 \u2022 3').evaluate({}), 6) self.assertEqual(parser.parse('2 ^ x').evaluate({'x': 3}), 8) self.assertEqual(parser.parse('x < 3').evaluate({'x': 3}), False) self.assertEqual(parser.parse('x < 3').evaluate({'x': 2}), True) self.assertEqual(parser.parse('x <= 3').evaluate({'x': 3}), True) self.assertEqual(parser.parse('x <= 3').evaluate({'x': 4}), False) self.assertEqual(parser.parse('x > 3').evaluate({'x': 4}), True) self.assertEqual(parser.parse('x >= 3').evaluate({'x': 3}), True) self.assertEqual(parser.parse('2 * x + 1').evaluate({'x': 3}), 7) self.assertEqual(parser.parse('2 + 3 * x').evaluate({'x': 4}), 14) self.assertEqual(parser.parse('(2 + 3) * x').evaluate({'x': 4}), 20) self.assertEqual(parser.parse('2-3^x').evaluate({'x': 4}), -79) self.assertEqual(parser.parse('-2-3^x').evaluate({'x': 4}), -83) self.assertEqual(parser.parse('-3^x').evaluate({'x': 4}), -81) self.assertEqual(parser.parse('(-3)^x').evaluate({'x': 4}), 81) self.assertEqual(parser.parse('2*x + y').evaluate({'x': 4, 'y': 1}), 9) self.assertEqual(parser.parse("x||y").evaluate({'x': 'hello ', 'y': 'world'}), 'hello world') self.assertEqual(parser.parse("'x'||'y'").evaluate({}), 'xy') self.assertEqual(parser.parse("'x'=='x'").evaluate({}), True) self.assertEqual(parser.parse("(a+b)==c").evaluate({'a': 1, 'b': 2, 'c': 3}), True) self.assertEqual(parser.parse("(a+b)!=c").evaluate({'a': 1, 'b': 2, 'c': 3}), False) self.assertEqual(parser.parse("(a^2-b^2)==((a+b)*(a-b))").evaluate({'a': 4859, 'b': 13150}), True) self.assertEqual(parser.parse("(a^2-b^2+1)==((a+b)*(a-b))").evaluate({'a': 4859, 'b': 13150}), False) self.assertEqual(parser.parse("x/((x+y))").simplify({}).evaluate({'x':1, 'y':1}), 0.5) #functions self.assertEqual(parser.parse('pyt(2 , 0)').evaluate({}),2) self.assertEqual(parser.parse("concat('Hello',' ','world')").evaluate({}),'Hello world') #external function self.assertEqual(parser.parse('testFunction(x , y)').evaluate({"x":2,"y":3,"testFunction":testFunction}),13) # test substitute expr = parser.parse('2 * x + 1') expr2 = expr.substitute('x', '4 * x') # ((2*(4*x))+1) self.assertEqual(expr2.evaluate({'x': 3}), 25) # test simplify expr = parser.parse('x * (y * atan(1))').simplify({'y': 4}) self.assertIn('x*3.141592', expr.toString()) self.assertEqual(expr.evaluate({'x': 2}), 6.283185307179586) # test toString with string constant expr = parser.parse("'a'=='b'") self.assertIn("'a'=='b'",expr.toString()) expr = parser.parse("concat('a\n','\n','\rb')=='a\n\n\rb'") self.assertEqual(expr.evaluate({}),True) expr = parser.parse("a==''") self.assertEqual(expr.evaluate({'a':''}),True) #test toString with an external function expr=parser.parse("myExtFn(a,b,c,1.51,'ok')") self.assertEqual(expr.substitute("a",'first').toString(),"myExtFn(first,b,c,1.51,'ok')") # test variables expr = parser.parse('x * (y * atan(1))') self.assertEqual(expr.variables(), ['x', 'y']) self.assertEqual(expr.simplify({'y': 4}).variables(), ['x']) # list operations self.assertEqual(parser.parse('a, 3').evaluate({'a': [1, 2]}), [1, 2, 3]) def test_consts(self): # self.assertEqual(self.parser.parse("PI ").variables(), [""]) self.assertEqual(self.parser.parse("PI").variables(), []) self.assertEqual(self.parser.parse("PI ").variables(), []) self.assertEqual(self.parser.parse("E ").variables(), []) self.assertEqual(self.parser.parse(" E").variables(), []) self.assertEqual(self.parser.parse("E").variables(), []) self.assertEqual(self.parser.parse("E+1").variables(), []) self.assertEqual(self.parser.parse("E / 1").variables(), []) self.assertEqual(self.parser.parse("sin(PI)+E").variables(), []) def test_parsing_e_and_pi(self): self.assertEqual(self.parser.parse('Pie').variables(), ["Pie"]) self.assertEqual(self.parser.parse('PIe').variables(), ["PIe"]) self.assertEqual(self.parser.parse('Eval').variables(), ["Eval"]) self.assertEqual(self.parser.parse('Eval1').variables(), ["Eval1"]) self.assertEqual(self.parser.parse('EPI').variables(), ["EPI"]) self.assertEqual(self.parser.parse('PIE').variables(), ["PIE"]) self.assertEqual(self.parser.parse('Engage').variables(), ["Engage"]) self.assertEqual(self.parser.parse('Engage * PIE').variables(), ["Engage", "PIE"]) self.assertEqual(self.parser.parse('Engage_').variables(), ["Engage_"]) self.assertEqual(self.parser.parse('Engage1').variables(), ["Engage1"]) self.assertEqual(self.parser.parse('E1').variables(), ["E1"]) self.assertEqual(self.parser.parse('PI2').variables(), ["PI2"]) self.assertEqual(self.parser.parse('(E1 + PI)').variables(), ["E1"]) self.assertEqual(self.parser.parse('E1_').variables(), ["E1_"]) self.assertEqual(self.parser.parse('E_').variables(), ["E_"]) def test_evaluating_consts(self): self.assertEqual(self.parser.evaluate("Engage1", variables={"Engage1": 2}), 2) self.assertEqual(self.parser.evaluate("Engage1 + 1", variables={"Engage1": 1}), 2)
def preprocess(question, equation, sni_model, fields, use_sni=True): """ Returns preprocessed version of question and equation using sni_model and fields """ # handle %'s question = question.replace('%', ' % ') # handle fractions parser = Parser() fractions = re.findall('\(\d+\)/\(\d+\)', question) fractions = np.append(fractions, re.findall('\(\d+/\d+\)', question)) for i, fraction in enumerate(fractions): #question = question.replace(fraction, str(sys.maxsize - i)) #equation = equation.replace(fraction, str(sys.maxsize - i)) question = question.replace( fraction, str(parser.evaluate(fraction, variables=None))) equation = equation.replace( fraction, str(parser.evaluate(fraction, variables=None))) # handle numbers with units question = re.sub(r'(\d+)([A-z]{1,2})', r'\1 \2', question) # seperate equation at operators equation = equation.replace('[', ' ( ') equation = equation.replace(']', ' ) ') equation = equation.replace('+', ' + ') equation = equation.replace('+', ' + ') equation = equation.replace('-', ' - ') equation = equation.replace('*', ' * ') equation = equation.replace('/', ' / ') equation = equation.replace('(', ' ( ') equation = equation.replace(')', ' ) ') equation = equation.replace('=', ' = ') equation = equation.replace('^', ' ^ ') # reduce %'s #equation = equation.replace('%', ' / 100 ') equation = re.sub(r'(\d*.{0,1}\d+)%', r'(\1 / 100 )', equation) # preprocess question equation = equation.split() question = question.split() # prepend and postpend null tokens to question to allow for sni window size # of three question = ['null', 'null', 'null'] + question + ['null', 'null', 'null'] # prevent inplace changes on question question_copy = [t for t in question] #print('question_copy:', question_copy) # replace significant numbers in question and equation i = 0 variable_values = dict() for j, token in enumerate(question): if isFloat(token): example = question_copy[j - 3:j + 4] ex = data.Example.fromlist([' '.join(example), ''], fields) dataset = data.Dataset([ex], fields) inp = None iterator = data.Iterator(dataset, batch_size=1) iterator.repeat = False for batch in iterator: inp = batch.text.t() if (not use_sni) or (use_sni and isSignificant(inp, sni_model)): #if (use_sni and isSignificant(inp, sni_model)) or (not use_sni): for symbol in equation: if symbol == token: equation[equation.index(symbol)] = '[' + chr(97 + i) + ']' character = '[' + chr(97 + i) + ']' variable_values[character] = token for q in question: if q == token: question[question.index(q)] = '[' + chr(97 + i) + ']' i += 1 # remove pre/postpended null tokens from question question = question[3:-3] question = ' '.join(question) + '\n' equation = ' '.join(equation) + '\n' return question, equation, variable_values
class VirtualMeter(Contract): """ Module that manages a virtual meter""" def __init__(self, private_key, abi_file, address, endpoint, formula): with open(abi_file) as f: abi = json.load(f)['abi'] super().__init__(private_key, address, abi, endpoint) # Check if meter is active active = self.contract.functions.isActive(self.account.address).call() if not active: raise NotAMeter('Check that the meter is enabled by the operator') # Get meter ID and connect to the monitoring server meter_id = self.contract.functions.getCurrentMeterData( self.account.address).call()[0] meter_id = meter_id.split(b'\0', 1)[0].decode('ascii') self.meter_id = getattr(MeterNames, meter_id) # Replace formula with ELT(x) calls. self.formula = Parser().parse(formula.replace('x', '*')) self.logger = configure_logging(self.meter_id) info = 'Initialized!' self.logger.info(green(info)) def start_pinging(self): (last_reading, reading) = (0, 0) while True: # Meter loops forever last_reading = reading (reading, timestamp) = \ self.calculate_reading() # Wait until we get a new reading # Perhaps make a call to monitoring server every 15 mins? while (reading == last_reading): self.logger.warning(red('Sleeping until new reading')) time.sleep(20) (reading, timestamp) = \ self.calculate_reading() self.ping(reading, timestamp) info = 'Pinged {} kWh at t={}'.format(reading, timestamp) self.logger.info(green(info)) def calculate_reading(self): """ Utilizes Abstract Syntax Trees to parse an equation and evaluate ELT readings or Coefficients github.com/Axiacore/py-expression-eval """ args = dict() coefficients = vars(Coefficients) meters = [m for m in self.formula.variables() if not m.startswith('F')] for var in self.formula.variables(): # If it's a known coefficient get it from the constants list if var in coefficients: args[var] = getattr(Coefficients, var) # If it's an ELT or KMZ, get it from the blockchain else: info = 'Fetching reading for => {}'.format(var) self.logger.debug(green(info)) addr = self.contract.functions.meterAddressById( normalize(var)).call() data = self.contract.functions.getCurrentMeterData(addr).call() reading = data[1] args[var] = reading timestamp = data[2] info = 'Arguments to be evaluated => {}'.format(args) self.logger.debug(yellow(info)) reading = self.formula.evaluate(args) return reading, timestamp def ping(self, reading, timestamp): """ Takes reading and timestamp and creates a raw transaction call to `ping` at the target contract """ args = [int(reading), int(timestamp)] self.sign_and_send(self.contract.functions.ping, args)
class ParserTestCase(unittest.TestCase): def setUp(self): self.parser = Parser() def assertExactEqual(self, a, b): self.assertEqual(type(a), type(b)) self.assertEqual(a, b) def test_parser(self): parser = Parser() # parser and variables self.assertEqual(parser.parse('pow(x,y)').variables(), ['x', 'y']) self.assertEqual(parser.parse('pow(x,y)').symbols(), ['pow', 'x', 'y']) # but '"a b"' can *not* be used as a variable self.assertEqual( parser.parse('"a b"*2').evaluate({'"a b"': 2}), "a ba b") # unless parse configured to allow double quoted variables (i.e. allow multi-word vars) parser2 = Parser( string_literal_quotes=("'")) # only single, not double! self.assertEqual(parser2.parse('"a b"*2').evaluate({'"a b"': 2}), 4) # evaluate self.assertExactEqual(parser.parse('1').evaluate({}), 1) self.assertExactEqual(parser.parse('a').evaluate({'a': 2}), 2) self.assertExactEqual(parser.parse('2 * 3').evaluate({}), 6) self.assertExactEqual(parser.parse(u'2 \u2219 3').evaluate({}), 6) self.assertExactEqual(parser.parse(u'2 \u2022 3').evaluate({}), 6) self.assertExactEqual(parser.parse('2 ^ x').evaluate({'x': 3}), 8.0) self.assertExactEqual(parser.parse('2 ** x').evaluate({'x': 3}), 8.0) self.assertExactEqual( parser.parse('-1.E2 ** x + 2.0E2').evaluate({'x': 1}), 100.0) self.assertEqual(parser.parse('x < 3').evaluate({'x': 3}), False) self.assertEqual(parser.parse('x < 3').evaluate({'x': 2}), True) self.assertEqual(parser.parse('x <= 3').evaluate({'x': 3}), True) self.assertEqual(parser.parse('x <= 3').evaluate({'x': 4}), False) self.assertEqual(parser.parse('x > 3').evaluate({'x': 4}), True) self.assertEqual(parser.parse('x >= 3').evaluate({'x': 3}), True) self.assertExactEqual(parser.parse('2 * x + 1').evaluate({'x': 3}), 7) self.assertExactEqual(parser.parse('2 + 3 * x').evaluate({'x': 4}), 14) self.assertExactEqual( parser.parse('(2 + 3) * x').evaluate({'x': 4}), 20) self.assertExactEqual(parser.parse('2-3^x').evaluate({'x': 4}), -79.0) self.assertExactEqual(parser.parse('-2-3^x').evaluate({'x': 4}), -83.0) self.assertExactEqual(parser.parse('-3^x').evaluate({'x': 4}), -81.0) self.assertExactEqual(parser.parse('(-3)^x').evaluate({'x': 4}), 81.0) self.assertExactEqual(parser.parse('2-3**x').evaluate({'x': 4}), -79.0) self.assertExactEqual( parser.parse('-2-3**x').evaluate({'x': 4}), -83.0) self.assertExactEqual(parser.parse('-3**x').evaluate({'x': 4}), -81.0) self.assertExactEqual(parser.parse('(-3)**x').evaluate({'x': 4}), 81.0) self.assertExactEqual( parser.parse('2*x + y').evaluate({ 'x': 4, 'y': 1 }), 9) self.assertEqual( parser.parse("x||y").evaluate({ 'x': 'hello ', 'y': 'world' }), 'hello world') self.assertEqual(parser.parse("'x'||'y'").evaluate({}), 'xy') self.assertEqual(parser.parse("'x'=='x'").evaluate({}), True) self.assertEqual( parser.parse("(a+b)==c").evaluate({ 'a': 1, 'b': 2, 'c': 3 }), True) self.assertEqual( parser.parse("(a+b)!=c").evaluate({ 'a': 1, 'b': 2, 'c': 3 }), False) self.assertEqual( parser.parse("(a^2-b^2)==((a+b)*(a-b))").evaluate({ 'a': 4859, 'b': 13150 }), True) self.assertEqual( parser.parse("(a^2-b^2+1)==((a+b)*(a-b))").evaluate({ 'a': 4859, 'b': 13150 }), False) self.assertEqual( parser.parse("(a**2-b**2)==((a+b)*(a-b))").evaluate({ 'a': 4859, 'b': 13150 }), True) self.assertEqual( parser.parse("(a**2-b**2+1)==((a+b)*(a-b))").evaluate({ 'a': 4859, 'b': 13150 }), False) self.assertExactEqual( parser.parse("x/((x+y))").simplify({}).evaluate({ 'x': 1, 'y': 1 }), 0.5) self.assertExactEqual( parser.parse('origin+2.0').evaluate({'origin': 1.0}), 3.0) # logical expressions self.assertExactEqual( parser.parse('a and b').evaluate({ 'a': True, 'b': False }), False) self.assertExactEqual( parser.parse('a and not b').evaluate({ 'a': True, 'b': False }), True) self.assertExactEqual( parser.parse('a or b').evaluate({ 'a': True, 'b': False }), True) self.assertExactEqual( parser.parse('a xor b').evaluate({ 'a': True, 'b': True }), False) # check precedents: AND should evaluate before OR self.assertExactEqual( parser.parse('a or b and not a').evaluate({ 'a': True, 'b': False }), True) # in operations self.assertExactEqual( parser.parse('"ab" in ("ab", "cd")').evaluate({}), True) self.assertExactEqual( parser.parse('"ee" in ("ab", "cd")').evaluate({}), False) self.assertExactEqual( parser.parse('1 in (1, 2, 3)').evaluate({}), True) self.assertExactEqual( parser.parse('"ab" in ("ab", "cd") and 1 in (1,2,3)').evaluate({}), True) self.assertExactEqual( parser.parse('"word" in "word in sentence"').evaluate({}), True) # functions self.assertExactEqual(parser.parse('pyt(2 , 0)').evaluate({}), 2.0) self.assertEqual( parser.parse("concat('Hello',' ','world')").evaluate({}), 'Hello world') self.assertExactEqual( parser.parse('if(a>b,5,6)').evaluate({ 'a': 8, 'b': 3 }), 5) self.assertExactEqual( parser.parse('if(a,b,c)').evaluate({ 'a': None, 'b': 1, 'c': 3 }), 3) self.assertExactEqual( parser.parse('if(random(1)>1,1,0)').evaluate({}), 0) # log with base or natural log self.assertExactEqual(parser.parse('log(16,2)').evaluate({}), 4.0) self.assertExactEqual(parser.parse('log(E^100)').evaluate({}), 100.0) self.assertExactEqual(parser.parse('log(E**100)').evaluate({}), 100.0) # test substitute expr = parser.parse('2 * x + 1') expr2 = expr.substitute('x', '4 * x') # ((2*(4*x))+1) self.assertExactEqual(expr2.evaluate({'x': 3}), 25) # test simplify expr = parser.parse('x * (y * atan(1))').simplify({'y': 4}) self.assertIn('x*3.141592', expr.toString()) self.assertExactEqual(expr.evaluate({'x': 2}), 6.283185307179586) # test toString with string constant expr = parser.parse("'a'=='b'") self.assertIn("'a'=='b'", expr.toString()) self.assertIn("'a'=='b'", "%s" % expr) expr = parser.parse("concat('a\n','\n','\rb')=='a\n\n\rb'") self.assertEqual(expr.evaluate({}), True) expr = parser.parse("a==''") self.assertEqual(expr.evaluate({'a': ''}), True) # test toString with an external function expr = parser.parse("myExtFn(a,b,c,1.51,'ok')") self.assertEqual( expr.substitute("a", 'first').toString(), "myExtFn(first,b,c,1.51,'ok')") # test variables expr = parser.parse('x * (y * atan(1))') self.assertEqual(expr.variables(), ['x', 'y']) self.assertEqual(expr.simplify({'y': 4}).variables(), ['x']) # list operations self.assertEqual( parser.parse('a, 3').evaluate({'a': [1, 2]}), [1, 2, 3]) def test_consts(self): # self.assertEqual(self.parser.parse("PI ").variables(), [""]) self.assertEqual(self.parser.parse("PI").variables(), []) self.assertEqual(self.parser.parse("PI ").variables(), []) self.assertEqual(self.parser.parse("E ").variables(), []) self.assertEqual(self.parser.parse(" E").variables(), []) self.assertEqual(self.parser.parse("E").variables(), []) self.assertEqual(self.parser.parse("E+1").variables(), []) self.assertEqual(self.parser.parse("E / 1").variables(), []) self.assertEqual(self.parser.parse("sin(PI)+E").variables(), []) def test_parsing_e_and_pi(self): self.assertEqual(self.parser.parse('Pie').variables(), ["Pie"]) self.assertEqual(self.parser.parse('PIe').variables(), ["PIe"]) self.assertEqual(self.parser.parse('Eval').variables(), ["Eval"]) self.assertEqual(self.parser.parse('Eval1').variables(), ["Eval1"]) self.assertEqual(self.parser.parse('EPI').variables(), ["EPI"]) self.assertEqual(self.parser.parse('PIE').variables(), ["PIE"]) self.assertEqual(self.parser.parse('Engage').variables(), ["Engage"]) self.assertEqual( self.parser.parse('Engage * PIE').variables(), ["Engage", "PIE"]) self.assertEqual(self.parser.parse('Engage_').variables(), ["Engage_"]) self.assertEqual(self.parser.parse('Engage1').variables(), ["Engage1"]) self.assertEqual(self.parser.parse('E1').variables(), ["E1"]) self.assertEqual(self.parser.parse('PI2').variables(), ["PI2"]) self.assertEqual(self.parser.parse('(E1 + PI)').variables(), ["E1"]) self.assertEqual(self.parser.parse('E1_').variables(), ["E1_"]) self.assertEqual(self.parser.parse('E_').variables(), ["E_"]) def test_evaluating_consts(self): self.assertExactEqual( self.parser.evaluate("Engage1", variables={"Engage1": 2}), 2) self.assertExactEqual( self.parser.evaluate("Engage1 + 1", variables={"Engage1": 1}), 2) def test_custom_functions(self): parser = Parser() def testFunction0(): return 13 def testFunction1(a): return 2 * a + 9 def testFunction2(a, b): return 2 * a + 3 * b # zero argument functions don't currently work # self.assertEqual(parser # .parse('testFunction()') # .evaluate({"testFunction":testFunction0}),13) self.assertExactEqual( parser.parse('testFunction(x)').evaluate({ "x": 2, "testFunction": testFunction1 }), 13) self.assertExactEqual( parser.parse('testFunction(x , y)').evaluate({ "x": 2, "y": 3, "testFunction": testFunction2 }), 13) # Add some "built-in" functions def mean(*xs): return sum(xs) / len(xs) parser.functions['mean'] = mean def counter(initial): class nonlocals: x = initial def count(increment): nonlocals.x += increment return nonlocals.x return count parser.functions['count'] = counter(0) self.assertEqual(parser.parse("mean(xs)").variables(), ["xs"]) self.assertEqual(parser.parse("mean(xs)").symbols(), ["mean", "xs"]) self.assertEqual( parser.evaluate("mean(xs)", variables={"xs": [1, 2, 3]}), 2) self.assertExactEqual( parser.evaluate("count(num)", variables={"num": 5}), 5) self.assertExactEqual( parser.evaluate("count(num)", variables={"num": 5}), 10) def test_custom_functions_with_inline_strings(self): parser = Parser() expr = parser.parse("func(1, \"func(2, 4)\")") self.assertEqual(expr.variables(), ['func']) expr = parser.parse("func(1, 'func(2, 4)')") self.assertEqual(expr.variables(), ['func']) parser2 = Parser(string_literal_quotes=("'")) expr = parser2.parse("func(1, \"func(2, 4)\")") self.assertEqual(expr.variables(), ['func', "\"func(2, 4)\""]) expr = parser2.parse("func(1, 'func(2, 4)')") self.assertEqual(expr.variables(), ['func']) def test_custom_functions_substitute_strings(self): def func(var, str): if str == "custom text": return 1 if str == "foo": return 2 return 0 parser = Parser() expr = parser.parse("func(1, \"custom text\")") self.assertEqual(expr.evaluate({"func": func}), 1) parser = Parser(string_literal_quotes=("'")) expr = parser.parse("func(1, \"custom text\")") self.assertEqual( expr.evaluate({ "func": func, "\"custom text\"": "foo" }), 2) def test_decimals(self): parser = Parser() self.assertExactEqual( parser.parse(".1").evaluate({}), parser.parse("0.1").evaluate({})) self.assertExactEqual( parser.parse(".1*.2").evaluate({}), parser.parse("0.1*0.2").evaluate({})) self.assertExactEqual(parser.parse(".5^3").evaluate({}), float(0.125)) self.assertExactEqual(parser.parse("16^.5").evaluate({}), 4.0) self.assertExactEqual(parser.parse(".5**3").evaluate({}), float(0.125)) self.assertExactEqual(parser.parse("16**.5").evaluate({}), 4.0) self.assertExactEqual(parser.parse("8300*.8").evaluate({}), 6640.0) self.assertExactEqual(parser.parse("1E3*2.0").evaluate({}), 2000.0) self.assertExactEqual(parser.parse("-1e3*2.0").evaluate({}), -2000.0) self.assertExactEqual( parser.parse("-1E3*2.E2").evaluate({}), -200000.0) with self.assertRaises(ValueError): parser.parse("..5").evaluate({}) def test_to_string(self): parser = Parser() self.assertEqual( parser.parse("-12 * a + -2").toString(), '(((-12)*a)+(-2))')
def generate_graph(self, graph_file, print_edges = False, flow = 0): """ Reads the .net file and return it's infos. The infos are: function(s) node(s) arc(s) edge(s) od(s) It should be following the specification from: https://wiki.inf.ufrgs.br/Network_files_specification It returns a list of vertices(V), a list of edges(E) and a list of OD(ODlist) Tests: >>> Experiment(8, './networks/OW10_1/OW10_1.net', 1, 'OW').\ generate_graph('./networks/OW10_1/OW10_1.net') #doctest:+NORMALIZE_WHITESPACE (['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M'], ['A-B', 'B-A', 'A-C', \ 'C-A', 'A-D', 'D-A', 'B-D', 'D-B', 'B-E', 'E-B', 'C-D', 'D-C', 'C-F', 'F-C', 'C-G', 'G-C',\ 'D-E', 'E-D', 'D-G', 'G-D', 'D-H', 'H-D', 'E-H', 'H-E', 'F-G', 'G-F', 'F-I', 'I-F', 'G-H',\ 'H-G', 'G-J', 'J-G', 'G-K', 'K-G', 'H-K', 'K-H', 'I-J', 'J-I', 'I-L', 'L-I', 'J-K', 'K-J',\ 'J-L', 'L-J', 'J-M', 'M-J', 'K-M', 'M-K'], [('A', 'L', 600), ('A', 'M', 400),\ ('B', 'L', 300), ('B', 'M', 400)]) In order: The vertice list, edge list and the OD list. Vertices -> ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M'] Edges -> ['A-B', 'B-A', 'A-C', 'C-A', 'A-D', 'D-A', 'B-D', 'D-B', 'B-E', 'E-B', 'C-D', 'D-C', 'C-F', 'F-C', 'C-G', 'G-C', 'D-E', 'E-D', 'D-G', 'G-D', 'D-H', 'H-D', 'E-H', 'H-E', 'F-G', 'G-F', 'F-I', 'I-F', 'G-H', 'H-G', 'G-J', 'J-G', 'G-K', 'K-G', 'H-K', 'K-H', 'I-J', 'J-I', 'I-L', 'L-I', 'J-K', 'K-J', 'J-L', 'L-J', 'J-M', 'M-J', 'K-M', 'M-K'] OD -> [('A', 'L', 600), ('A', 'M', 400), ('B', 'L', 300), ('B', 'M', 400)] """ vertices = [] edges = [] functions = {} od_list = [] for line in open(graph_file, 'r'): taglist = string.split(line) if taglist[0] == 'function': variables = [] variables = taglist[2].replace("(", "") variables = variables.replace(")", "") variables = variables.split(",") functions[taglist[1]] = [taglist[3], variables] elif taglist[0] == 'node': vertices.append(Node(taglist[1])) elif taglist[0] == 'dedge' or taglist[0] == 'edge': constants = [] cost_formula = "" freeflow_cost = 0 constant_acc = 0 if len(taglist) > 5: i = 5 while i <= (len(taglist) - 1): constants.append(taglist[i]) i += 1 parser = Parser() ##[4] is function name.[0] is expression exp = parser.parse(functions[taglist[4]][0]) LV = exp.variables() buffer_LV = [] for l in LV: if l not in functions[taglist[4]][1]: constant_acc += 1 buffer_LV.append(l) #check if the formula has any parameters(variables) flag = False for v in functions[taglist[4]][1]: if v in LV: flag = True buffer_dic = {} i = 0 for index in range(constant_acc): buffer_dic[buffer_LV[index]] = float(constants[index]) i = 1 if not flag: freeflow_cost = exp.evaluate(buffer_dic) cost_formula = str(freeflow_cost) elif is_number(functions[taglist[4]][0]): freeflow_cost = float(functions[taglist[4]][0]) cost_fomula = functions[taglist[4]][0] else: exp = exp.simplify(buffer_dic) cost_formula = exp.toString() exp = Parser() cost_formula2 = "(" + cost_formula + ") + flow" exp = exp.parse(cost_formula2) freeflow_cost = exp.evaluate({'f': 0, 'flow': flow}) # Hardcoded edges.append(Edge(taglist[2], taglist[3], freeflow_cost, cost_formula)) if taglist[0] == 'edge': edges.append(Edge(taglist[3], taglist[2], freeflow_cost, cost_formula)) else: cost_formula = "" freeflow_cost = 0 parser = Parser() if is_number(functions[taglist[4]][0]): cost_formula = functions[taglist[4]][0] freeflow_cost = float(functions[taglist[4]][0]) else: exp = parser.parse(functions[taglist[4]][0]) cost_formula = exp.toString() cost_formula2 = "(" + cost_formula + ") + flow" exp = exp.parse(cost_formula2) freeflow_cost = exp.evaluate({'f': 0, 'flow': flow}) # hardcoded edges.append(Edge(taglist[2], taglist[3], freeflow_cost, cost_formula)) edges.append(Edge(taglist[3], taglist[2], freeflow_cost, cost_formula)) elif taglist[0] == 'od': od_list.append((taglist[2], taglist[3], int(taglist[4]))) ''' Print edges but there are too many lines to be printed!! ''' if print_edges: for e in edges: print("Edge " + str(e.start) + "-" + str(e.end) + " has length: " + str(e.length)) return vertices, edges, od_list
from py_expression_eval import Parser import numpy as np import copy with open( '../tests/train_best_models/saved_models/classifier_basic/answers.txt' ) as f: preds = np.array(f.readlines()) with open('../tencent/data/working/basic/answers.txt') as f: tgts = np.array(f.readlines()) parser = Parser() for i, line in enumerate(preds): output = None try: output = float(line) output = parser.evaluate(output, variables=None) except (ValueError, TypeError): output = line.strip() preds[i] = output for i, line in enumerate(tgts): output = None try: output = line.replace('%', ' / 100') #output = float(line) output = parser.evaluate(output, variables=None) except: # (ValueError,TypeError): output = line.strip() tgts[i] = output #print(preds) #print(tgts)
class ParserTestCase(unittest.TestCase): def setUp(self): self.parser = Parser() def test_parser(self): parser = Parser() #parser and variables self.assertEqual(parser.parse('lulu(x,y)').variables(), ['lulu','x','y']) #evaluate self.assertEqual(parser.parse('2 * 3').evaluate({}), 6) self.assertEqual(parser.parse('2 ^ x').evaluate({'x': 3}), 8) self.assertEqual(parser.parse('2 * x + 1').evaluate({'x': 3}), 7) self.assertEqual(parser.parse('2 + 3 * x').evaluate({'x': 4}), 14) self.assertEqual(parser.parse('(2 + 3) * x').evaluate({'x': 4}), 20) self.assertEqual(parser.parse('2-3^x').evaluate({'x': 4}), -79) self.assertEqual(parser.parse('-2-3^x').evaluate({'x': 4}), -83) self.assertEqual(parser.parse('-3^x').evaluate({'x': 4}), -81) self.assertEqual(parser.parse('(-3)^x').evaluate({'x': 4}), 81) self.assertEqual(parser.parse('2*x + y').evaluate({'x': 4, 'y': 1}), 9) self.assertEqual(parser.parse("x||y").evaluate({'x': 'hello ', 'y': 'world'}), 'hello world') self.assertEqual(parser.parse("'x'||'y'").evaluate({}), 'xy') self.assertEqual(parser.parse("'x'=='x'").evaluate({}), True) self.assertEqual(parser.parse("(a+b)==c").evaluate({'a': 1, 'b': 2, 'c': 3}), True) self.assertEqual(parser.parse("(a+b)!=c").evaluate({'a': 1, 'b': 2, 'c': 3}), False) self.assertEqual(parser.parse("(a^2-b^2)==((a+b)*(a-b))").evaluate({'a': 4859, 'b': 13150}), True) self.assertEqual(parser.parse("(a^2-b^2+1)==((a+b)*(a-b))").evaluate({'a': 4859, 'b': 13150}), False) #functions self.assertEqual(parser.parse('pyt(2 , 0)').evaluate({}),2) self.assertEqual(parser.parse("concat('Hello',' ','world')").evaluate({}),'Hello world') #external function self.assertEqual(parser.parse('testFunction(x , y)').evaluate({"x":2,"y":3,"testFunction":testFunction}),13) # test substitute expr = parser.parse('2 * x + 1') expr2 = expr.substitute('x', '4 * x') # ((2*(4*x))+1) self.assertEqual(expr2.evaluate({'x': 3}), 25) # test simplify expr = parser.parse('x * (y * atan(1))').simplify({'y': 4}) self.assertIn('x*3.141592', expr.toString()) self.assertEqual(expr.evaluate({'x': 2}), 6.283185307179586) # test toString with string constant expr = parser.parse("'a'=='b'") self.assertIn("'a'=='b'",expr.toString()) expr = parser.parse("concat('a\n','\n','\rb')=='a\n\n\rb'") self.assertEqual(expr.evaluate({}),True) #test toString with an external function expr=parser.parse("myExtFn(a,b,c,1.51,'ok')") self.assertEqual(expr.substitute("a",'first').toString(),"myExtFn(first,b,c,1.51,'ok')") # test variables expr = parser.parse('x * (y * atan(1))') self.assertEqual(expr.variables(), ['x', 'y']) self.assertEqual(expr.simplify({'y': 4}).variables(), ['x']) def test_consts(self): # self.assertEqual(self.parser.parse("PI ").variables(), [""]) self.assertEqual(self.parser.parse("PI").variables(), []) self.assertEqual(self.parser.parse("PI ").variables(), []) self.assertEqual(self.parser.parse("E ").variables(), []) self.assertEqual(self.parser.parse(" E").variables(), []) self.assertEqual(self.parser.parse("E").variables(), []) self.assertEqual(self.parser.parse("E+1").variables(), []) self.assertEqual(self.parser.parse("E / 1").variables(), []) self.assertEqual(self.parser.parse("sin(PI)+E").variables(), []) def test_parsing_e_and_pi(self): self.assertEqual(self.parser.parse('Pie').variables(), ["Pie"]) self.assertEqual(self.parser.parse('PIe').variables(), ["PIe"]) self.assertEqual(self.parser.parse('Eval').variables(), ["Eval"]) self.assertEqual(self.parser.parse('Eval1').variables(), ["Eval1"]) self.assertEqual(self.parser.parse('EPI').variables(), ["EPI"]) self.assertEqual(self.parser.parse('PIE').variables(), ["PIE"]) self.assertEqual(self.parser.parse('Engage').variables(), ["Engage"]) self.assertEqual(self.parser.parse('Engage * PIE').variables(), ["Engage", "PIE"]) self.assertEqual(self.parser.parse('Engage_').variables(), ["Engage_"]) self.assertEqual(self.parser.parse('Engage1').variables(), ["Engage1"]) self.assertEqual(self.parser.parse('E1').variables(), ["E1"]) self.assertEqual(self.parser.parse('PI2').variables(), ["PI2"]) self.assertEqual(self.parser.parse('(E1 + PI)').variables(), ["E1"]) self.assertEqual(self.parser.parse('E1_').variables(), ["E1_"]) self.assertEqual(self.parser.parse('E_').variables(), ["E_"]) def test_evaluating_consts(self): self.assertEqual(self.parser.evaluate("Engage1", variables={"Engage1": 2}), 2) self.assertEqual(self.parser.evaluate("Engage1 + 1", variables={"Engage1": 1}), 2)
class ParserTestCase(unittest.TestCase): def setUp(self): self.parser = Parser() def assertExactEqual(self, a, b): self.assertEqual(type(a), type(b)) self.assertEqual(a, b) def test_parser(self): parser = Parser() #parser and variables self.assertEqual(parser.parse('pow(x,y)').variables(), ['x','y']) self.assertEqual(parser.parse('pow(x,y)').symbols(), ['pow','x','y']) #checking if '"a b"' could be a variable (using it in sql) self.assertEqual(parser.parse('"a b"*2').evaluate({'"a b"':2}),4) #evaluate self.assertExactEqual(parser.parse('1').evaluate({}), 1) self.assertExactEqual(parser.parse('a').evaluate({'a': 2}), 2) self.assertExactEqual(parser.parse('2 * 3').evaluate({}), 6) self.assertExactEqual(parser.parse(u'2 \u2219 3').evaluate({}), 6) self.assertExactEqual(parser.parse(u'2 \u2022 3').evaluate({}), 6) self.assertExactEqual(parser.parse('2 ^ x').evaluate({'x': 3}), 8.0) self.assertExactEqual(parser.parse('2 ** x').evaluate({'x': 3}), 8.0) self.assertExactEqual(parser.parse('-1.E2 ** x + 2.0E2').evaluate({'x': 1}), 100.0) self.assertEqual(parser.parse('x < 3').evaluate({'x': 3}), False) self.assertEqual(parser.parse('x < 3').evaluate({'x': 2}), True) self.assertEqual(parser.parse('x <= 3').evaluate({'x': 3}), True) self.assertEqual(parser.parse('x <= 3').evaluate({'x': 4}), False) self.assertEqual(parser.parse('x > 3').evaluate({'x': 4}), True) self.assertEqual(parser.parse('x >= 3').evaluate({'x': 3}), True) self.assertExactEqual(parser.parse('2 * x + 1').evaluate({'x': 3}), 7) self.assertExactEqual(parser.parse('2 + 3 * x').evaluate({'x': 4}), 14) self.assertExactEqual(parser.parse('(2 + 3) * x').evaluate({'x': 4}), 20) self.assertExactEqual(parser.parse('2-3^x').evaluate({'x': 4}), -79.0) self.assertExactEqual(parser.parse('-2-3^x').evaluate({'x': 4}), -83.0) self.assertExactEqual(parser.parse('-3^x').evaluate({'x': 4}), -81.0) self.assertExactEqual(parser.parse('(-3)^x').evaluate({'x': 4}), 81.0) self.assertExactEqual(parser.parse('2-3**x').evaluate({'x': 4}), -79.0) self.assertExactEqual(parser.parse('-2-3**x').evaluate({'x': 4}), -83.0) self.assertExactEqual(parser.parse('-3**x').evaluate({'x': 4}), -81.0) self.assertExactEqual(parser.parse('(-3)**x').evaluate({'x': 4}), 81.0) self.assertExactEqual(parser.parse('2*x + y').evaluate({'x': 4, 'y': 1}), 9) self.assertEqual(parser.parse("x||y").evaluate({'x': 'hello ', 'y': 'world'}), 'hello world') self.assertEqual(parser.parse("'x'||'y'").evaluate({}), 'xy') self.assertEqual(parser.parse("'x'=='x'").evaluate({}), True) self.assertEqual(parser.parse("(a+b)==c").evaluate({'a': 1, 'b': 2, 'c': 3}), True) self.assertEqual(parser.parse("(a+b)!=c").evaluate({'a': 1, 'b': 2, 'c': 3}), False) self.assertEqual(parser.parse("(a^2-b^2)==((a+b)*(a-b))").evaluate({'a': 4859, 'b': 13150}), True) self.assertEqual(parser.parse("(a^2-b^2+1)==((a+b)*(a-b))").evaluate({'a': 4859, 'b': 13150}), False) self.assertEqual(parser.parse("(a**2-b**2)==((a+b)*(a-b))").evaluate({'a': 4859, 'b': 13150}), True) self.assertEqual(parser.parse("(a**2-b**2+1)==((a+b)*(a-b))").evaluate({'a': 4859, 'b': 13150}), False) self.assertExactEqual(parser.parse("x/((x+y))").simplify({}).evaluate({'x':1, 'y':1}), 0.5) self.assertExactEqual(parser.parse('origin+2.0').evaluate({'origin': 1.0}), 3.0) #functions self.assertExactEqual(parser.parse('pyt(2 , 0)').evaluate({}), 2.0) self.assertEqual(parser.parse("concat('Hello',' ','world')").evaluate({}),'Hello world') self.assertExactEqual(parser.parse('if(a>b,5,6)').evaluate({'a':8,'b':3}),5) self.assertExactEqual(parser.parse('if(a,b,c)').evaluate({'a':None,'b':1,'c':3}),3) #log with base or natural log self.assertExactEqual(parser.parse('log(16,2)').evaluate({}), 4.0) self.assertExactEqual(parser.parse('log(E^100)').evaluate({}), 100.0) self.assertExactEqual(parser.parse('log(E**100)').evaluate({}), 100.0) # test substitute expr = parser.parse('2 * x + 1') expr2 = expr.substitute('x', '4 * x') # ((2*(4*x))+1) self.assertExactEqual(expr2.evaluate({'x': 3}), 25) # test simplify expr = parser.parse('x * (y * atan(1))').simplify({'y': 4}) self.assertIn('x*3.141592', expr.toString()) self.assertExactEqual(expr.evaluate({'x': 2}), 6.283185307179586) # test toString with string constant expr = parser.parse("'a'=='b'") self.assertIn("'a'=='b'",expr.toString()) self.assertIn("'a'=='b'", "%s" % expr) expr = parser.parse("concat('a\n','\n','\rb')=='a\n\n\rb'") self.assertEqual(expr.evaluate({}),True) expr = parser.parse("a==''") self.assertEqual(expr.evaluate({'a':''}),True) #test toString with an external function expr=parser.parse("myExtFn(a,b,c,1.51,'ok')") self.assertEqual(expr.substitute("a",'first').toString(),"myExtFn(first,b,c,1.51,'ok')") # test variables expr = parser.parse('x * (y * atan(1))') self.assertEqual(expr.variables(), ['x', 'y']) self.assertEqual(expr.simplify({'y': 4}).variables(), ['x']) # list operations self.assertEqual(parser.parse('a, 3').evaluate({'a': [1, 2]}), [1, 2, 3]) def test_consts(self): # self.assertEqual(self.parser.parse("PI ").variables(), [""]) self.assertEqual(self.parser.parse("PI").variables(), []) self.assertEqual(self.parser.parse("PI ").variables(), []) self.assertEqual(self.parser.parse("E ").variables(), []) self.assertEqual(self.parser.parse(" E").variables(), []) self.assertEqual(self.parser.parse("E").variables(), []) self.assertEqual(self.parser.parse("E+1").variables(), []) self.assertEqual(self.parser.parse("E / 1").variables(), []) self.assertEqual(self.parser.parse("sin(PI)+E").variables(), []) def test_parsing_e_and_pi(self): self.assertEqual(self.parser.parse('Pie').variables(), ["Pie"]) self.assertEqual(self.parser.parse('PIe').variables(), ["PIe"]) self.assertEqual(self.parser.parse('Eval').variables(), ["Eval"]) self.assertEqual(self.parser.parse('Eval1').variables(), ["Eval1"]) self.assertEqual(self.parser.parse('EPI').variables(), ["EPI"]) self.assertEqual(self.parser.parse('PIE').variables(), ["PIE"]) self.assertEqual(self.parser.parse('Engage').variables(), ["Engage"]) self.assertEqual(self.parser.parse('Engage * PIE').variables(), ["Engage", "PIE"]) self.assertEqual(self.parser.parse('Engage_').variables(), ["Engage_"]) self.assertEqual(self.parser.parse('Engage1').variables(), ["Engage1"]) self.assertEqual(self.parser.parse('E1').variables(), ["E1"]) self.assertEqual(self.parser.parse('PI2').variables(), ["PI2"]) self.assertEqual(self.parser.parse('(E1 + PI)').variables(), ["E1"]) self.assertEqual(self.parser.parse('E1_').variables(), ["E1_"]) self.assertEqual(self.parser.parse('E_').variables(), ["E_"]) def test_evaluating_consts(self): self.assertExactEqual(self.parser.evaluate("Engage1", variables={"Engage1": 2}), 2) self.assertExactEqual(self.parser.evaluate("Engage1 + 1", variables={"Engage1": 1}), 2) def test_custom_functions(self): parser = Parser() def testFunction0(): return 13 def testFunction1(a): return 2*a+9 def testFunction2(a,b): return 2*a+3*b # zero argument functions don't currently work # self.assertEqual(parser # .parse('testFunction()') # .evaluate({"testFunction":testFunction0}),13) self.assertExactEqual(parser .parse('testFunction(x)') .evaluate({"x":2,"testFunction":testFunction1}),13) self.assertExactEqual(parser .parse('testFunction(x , y)') .evaluate({"x":2,"y":3,"testFunction":testFunction2}),13) # Add some "built-in" functions def mean(*xs): return sum(xs) / len(xs) parser.functions['mean'] = mean def counter(initial): class nonlocals: x = initial def count(increment): nonlocals.x += increment return nonlocals.x return count parser.functions['count'] = counter(0) self.assertEqual(parser.parse("mean(xs)").variables(), ["xs"]) self.assertEqual(parser.parse("mean(xs)").symbols(), ["mean", "xs"]) self.assertEqual(parser.evaluate("mean(xs)", variables={"xs": [1, 2, 3]}), 2) self.assertExactEqual(parser.evaluate("count(inc)", variables={"inc": 5}), 5) self.assertExactEqual(parser.evaluate("count(inc)", variables={"inc": 5}), 10) def test_decimals(self): parser = Parser() self.assertExactEqual(parser.parse(".1").evaluate({}), parser.parse("0.1").evaluate({})) self.assertExactEqual(parser.parse(".1*.2").evaluate({}), parser.parse("0.1*0.2").evaluate({})) self.assertExactEqual(parser.parse(".5^3").evaluate({}), float(0.125)) self.assertExactEqual(parser.parse("16^.5").evaluate({}), 4.0) self.assertExactEqual(parser.parse(".5**3").evaluate({}), float(0.125)) self.assertExactEqual(parser.parse("16**.5").evaluate({}), 4.0) self.assertExactEqual(parser.parse("8300*.8").evaluate({}), 6640.0) self.assertExactEqual(parser.parse("1E3*2.0").evaluate({}), 2000.0) self.assertExactEqual(parser.parse("-1e3*2.0").evaluate({}), -2000.0) self.assertExactEqual(parser.parse("-1E3*2.E2").evaluate({}), -200000.0) with self.assertRaises(ValueError): parser.parse("..5").evaluate({})
class ParserTestCase(unittest.TestCase): def setUp(self): self.parser = Parser() def test_parser(self): parser = Parser() #parser and variables self.assertEqual(parser.parse('pow(x,y)').variables(), ['x', 'y']) self.assertEqual(parser.parse('pow(x,y)').symbols(), ['pow', 'x', 'y']) #checking if '"a b"' could be a variable (using it in sql) self.assertEqual(parser.parse('"a b"*2').evaluate({'"a b"': 2}), 4) #evaluate self.assertEqual(parser.parse('1').evaluate({}), 1) self.assertEqual(parser.parse('a').evaluate({'a': 2}), 2) self.assertEqual(parser.parse('2 * 3').evaluate({}), 6) self.assertEqual(parser.parse(u'2 \u2219 3').evaluate({}), 6) self.assertEqual(parser.parse(u'2 \u2022 3').evaluate({}), 6) self.assertEqual(parser.parse('2 ^ x').evaluate({'x': 3}), 8) self.assertEqual(parser.parse('x < 3').evaluate({'x': 3}), False) self.assertEqual(parser.parse('x < 3').evaluate({'x': 2}), True) self.assertEqual(parser.parse('x <= 3').evaluate({'x': 3}), True) self.assertEqual(parser.parse('x <= 3').evaluate({'x': 4}), False) self.assertEqual(parser.parse('x > 3').evaluate({'x': 4}), True) self.assertEqual(parser.parse('x >= 3').evaluate({'x': 3}), True) self.assertEqual(parser.parse('2 * x + 1').evaluate({'x': 3}), 7) self.assertEqual(parser.parse('2 + 3 * x').evaluate({'x': 4}), 14) self.assertEqual(parser.parse('(2 + 3) * x').evaluate({'x': 4}), 20) self.assertEqual(parser.parse('2-3^x').evaluate({'x': 4}), -79) self.assertEqual(parser.parse('-2-3^x').evaluate({'x': 4}), -83) self.assertEqual(parser.parse('-3^x').evaluate({'x': 4}), -81) self.assertEqual(parser.parse('(-3)^x').evaluate({'x': 4}), 81) self.assertEqual(parser.parse('2*x + y').evaluate({'x': 4, 'y': 1}), 9) self.assertEqual( parser.parse("x||y").evaluate({ 'x': 'hello ', 'y': 'world' }), 'hello world') self.assertEqual(parser.parse("'x'||'y'").evaluate({}), 'xy') self.assertEqual(parser.parse("'x'=='x'").evaluate({}), True) self.assertEqual( parser.parse("(a+b)==c").evaluate({ 'a': 1, 'b': 2, 'c': 3 }), True) self.assertEqual( parser.parse("(a+b)!=c").evaluate({ 'a': 1, 'b': 2, 'c': 3 }), False) self.assertEqual( parser.parse("(a^2-b^2)==((a+b)*(a-b))").evaluate({ 'a': 4859, 'b': 13150 }), True) self.assertEqual( parser.parse("(a^2-b^2+1)==((a+b)*(a-b))").evaluate({ 'a': 4859, 'b': 13150 }), False) self.assertEqual( parser.parse("x/((x+y))").simplify({}).evaluate({ 'x': 1, 'y': 1 }), 0.5) #functions self.assertEqual(parser.parse('pyt(2 , 0)').evaluate({}), 2) self.assertEqual( parser.parse("concat('Hello',' ','world')").evaluate({}), 'Hello world') self.assertEqual( parser.parse('if(a>b,5,6)').evaluate({ 'a': 8, 'b': 3 }), 5) self.assertEqual( parser.parse('if(a,b,c)').evaluate({ 'a': None, 'b': 1, 'c': 3 }), 3) # test substitute expr = parser.parse('2 * x + 1') expr2 = expr.substitute('x', '4 * x') # ((2*(4*x))+1) self.assertEqual(expr2.evaluate({'x': 3}), 25) # test simplify expr = parser.parse('x * (y * atan(1))').simplify({'y': 4}) self.assertIn('x*3.141592', expr.toString()) self.assertEqual(expr.evaluate({'x': 2}), 6.283185307179586) # test toString with string constant expr = parser.parse("'a'=='b'") self.assertIn("'a'=='b'", expr.toString()) self.assertIn("'a'=='b'", "%s" % expr) expr = parser.parse("concat('a\n','\n','\rb')=='a\n\n\rb'") self.assertEqual(expr.evaluate({}), True) expr = parser.parse("a==''") self.assertEqual(expr.evaluate({'a': ''}), True) #test toString with an external function expr = parser.parse("myExtFn(a,b,c,1.51,'ok')") self.assertEqual( expr.substitute("a", 'first').toString(), "myExtFn(first,b,c,1.51,'ok')") # test variables expr = parser.parse('x * (y * atan(1))') self.assertEqual(expr.variables(), ['x', 'y']) self.assertEqual(expr.simplify({'y': 4}).variables(), ['x']) # list operations self.assertEqual( parser.parse('a, 3').evaluate({'a': [1, 2]}), [1, 2, 3]) def test_consts(self): # self.assertEqual(self.parser.parse("PI ").variables(), [""]) self.assertEqual(self.parser.parse("PI").variables(), []) self.assertEqual(self.parser.parse("PI ").variables(), []) self.assertEqual(self.parser.parse("E ").variables(), []) self.assertEqual(self.parser.parse(" E").variables(), []) self.assertEqual(self.parser.parse("E").variables(), []) self.assertEqual(self.parser.parse("E+1").variables(), []) self.assertEqual(self.parser.parse("E / 1").variables(), []) self.assertEqual(self.parser.parse("sin(PI)+E").variables(), []) def test_parsing_e_and_pi(self): self.assertEqual(self.parser.parse('Pie').variables(), ["Pie"]) self.assertEqual(self.parser.parse('PIe').variables(), ["PIe"]) self.assertEqual(self.parser.parse('Eval').variables(), ["Eval"]) self.assertEqual(self.parser.parse('Eval1').variables(), ["Eval1"]) self.assertEqual(self.parser.parse('EPI').variables(), ["EPI"]) self.assertEqual(self.parser.parse('PIE').variables(), ["PIE"]) self.assertEqual(self.parser.parse('Engage').variables(), ["Engage"]) self.assertEqual( self.parser.parse('Engage * PIE').variables(), ["Engage", "PIE"]) self.assertEqual(self.parser.parse('Engage_').variables(), ["Engage_"]) self.assertEqual(self.parser.parse('Engage1').variables(), ["Engage1"]) self.assertEqual(self.parser.parse('E1').variables(), ["E1"]) self.assertEqual(self.parser.parse('PI2').variables(), ["PI2"]) self.assertEqual(self.parser.parse('(E1 + PI)').variables(), ["E1"]) self.assertEqual(self.parser.parse('E1_').variables(), ["E1_"]) self.assertEqual(self.parser.parse('E_').variables(), ["E_"]) def test_evaluating_consts(self): self.assertEqual( self.parser.evaluate("Engage1", variables={"Engage1": 2}), 2) self.assertEqual( self.parser.evaluate("Engage1 + 1", variables={"Engage1": 1}), 2) def test_custom_functions(self): parser = Parser() def testFunction0(): return 13 def testFunction1(a): return 2 * a + 9 def testFunction2(a, b): return 2 * a + 3 * b # zero argument functions don't currently work # self.assertEqual(parser # .parse('testFunction()') # .evaluate({"testFunction":testFunction0}),13) self.assertEqual( parser.parse('testFunction(x)').evaluate({ "x": 2, "testFunction": testFunction1 }), 13) self.assertEqual( parser.parse('testFunction(x , y)').evaluate({ "x": 2, "y": 3, "testFunction": testFunction2 }), 13) # Add some "built-in" functions def mean(*xs): return sum(xs) / len(xs) parser.functions['mean'] = mean def counter(initial): class nonlocals: x = initial def count(increment): nonlocals.x += increment return nonlocals.x return count parser.functions['count'] = counter(0) self.assertEqual(parser.parse("mean(xs)").variables(), ["xs"]) self.assertEqual(parser.parse("mean(xs)").symbols(), ["mean", "xs"]) self.assertEqual( parser.evaluate("mean(xs)", variables={"xs": [1, 2, 3]}), 2) self.assertEqual(parser.evaluate("count(inc)", variables={"inc": 5}), 5) self.assertEqual(parser.evaluate("count(inc)", variables={"inc": 5}), 10) def test_decimals(self): parser = Parser() self.assertEqual( parser.parse(".1").evaluate({}), parser.parse("0.1").evaluate({})) self.assertEqual( parser.parse(".1*.2").evaluate({}), parser.parse("0.1*0.2").evaluate({})) self.assertEqual(parser.parse(".5^3").evaluate({}), float(0.125)) self.assertEqual(parser.parse("16^.5").evaluate({}), 4) self.assertEqual(parser.parse("8300*.8").evaluate({}), 6640) with self.assertRaises(ValueError): parser.parse("..5").evaluate({}) def test_to_string(self): parser = Parser() self.assertEqual( parser.parse("-12 * a + -2").toString(), '(((-12.0)*a)+(-2.0))')
class ParserTestCase(unittest.TestCase): def setUp(self): self.parser = Parser() def test_parser(self): parser = Parser() #parser and variables self.assertEqual(parser.parse('lulu(x,y)').variables(), ['lulu','x','y']) #evaluate self.assertEqual(parser.parse('2 * 3').evaluate({}), 6) self.assertEqual(parser.parse('2 ^ x').evaluate({'x': 3}), 8) self.assertEqual(parser.parse('2 * x + 1').evaluate({'x': 3}), 7) self.assertEqual(parser.parse('2 + 3 * x').evaluate({'x': 4}), 14) self.assertEqual(parser.parse('(2 + 3) * x').evaluate({'x': 4}), 20) self.assertEqual(parser.parse('2-3^x').evaluate({'x': 4}), -79) self.assertEqual(parser.parse('-2-3^x').evaluate({'x': 4}), -83) self.assertEqual(parser.parse('-3^x').evaluate({'x': 4}), -81) self.assertEqual(parser.parse('(-3)^x').evaluate({'x': 4}), 81) self.assertEqual(parser.parse('2*x + y').evaluate({'x': 4, 'y': 1}), 9) self.assertEqual(parser.parse("x||y").evaluate({'x': 'hello ', 'y': 'world'}), 'hello world') self.assertEqual(parser.parse("'x'||'y'").evaluate({}), 'xy') #functions self.assertEqual(parser.parse('pyt(2 , 0)').evaluate({}),2) self.assertEqual(parser.parse("concat('Hello',' ','world')").evaluate({}),'Hello world') #external function self.assertEqual(parser.parse('testFunction(x , y)').evaluate({"x":2,"y":3,"testFunction":testFunction}),13) # test substitute expr = parser.parse('2 * x + 1') expr2 = expr.substitute('x', '4 * x') # ((2*(4*x))+1) self.assertEqual(expr2.evaluate({'x': 3}), 25) # test simplify expr = parser.parse('x * (y * atan(1))').simplify({'y': 4}) self.assertIn('x*3.141592', expr.toString()) self.assertEqual(expr.evaluate({'x': 2}), 6.283185307179586) # test variables expr = parser.parse('x * (y * atan(1))') self.assertEqual(expr.variables(), ['x', 'y']) self.assertEqual(expr.simplify({'y': 4}).variables(), ['x']) def test_consts(self): # self.assertEqual(self.parser.parse("PI ").variables(), [""]) self.assertEqual(self.parser.parse("PI").variables(), []) self.assertEqual(self.parser.parse("PI ").variables(), []) self.assertEqual(self.parser.parse("E ").variables(), []) self.assertEqual(self.parser.parse(" E").variables(), []) self.assertEqual(self.parser.parse("E").variables(), []) self.assertEqual(self.parser.parse("E+1").variables(), []) self.assertEqual(self.parser.parse("E / 1").variables(), []) self.assertEqual(self.parser.parse("sin(PI)+E").variables(), []) def test_parsing_e_and_pi(self): self.assertEqual(self.parser.parse('Pie').variables(), ["Pie"]) self.assertEqual(self.parser.parse('PIe').variables(), ["PIe"]) self.assertEqual(self.parser.parse('Eval').variables(), ["Eval"]) self.assertEqual(self.parser.parse('Eval1').variables(), ["Eval1"]) self.assertEqual(self.parser.parse('EPI').variables(), ["EPI"]) self.assertEqual(self.parser.parse('PIE').variables(), ["PIE"]) self.assertEqual(self.parser.parse('Engage').variables(), ["Engage"]) self.assertEqual(self.parser.parse('Engage * PIE').variables(), ["Engage", "PIE"]) self.assertEqual(self.parser.parse('Engage_').variables(), ["Engage_"]) self.assertEqual(self.parser.parse('Engage1').variables(), ["Engage1"]) self.assertEqual(self.parser.parse('E1').variables(), ["E1"]) self.assertEqual(self.parser.parse('PI2').variables(), ["PI2"]) self.assertEqual(self.parser.parse('(E1 + PI)').variables(), ["E1"]) self.assertEqual(self.parser.parse('E1_').variables(), ["E1_"]) self.assertEqual(self.parser.parse('E_').variables(), ["E_"]) def test_evaluating_consts(self): self.assertEqual(self.parser.evaluate("Engage1", variables={"Engage1": 2}), 2) self.assertEqual(self.parser.evaluate("Engage1 + 1", variables={"Engage1": 1}), 2)
def preprocess(question, equation): """ Returns preprocessed version of question and equation """ # handle %'s question = question.replace('%', ' % ') # handle fractions parser = Parser() fractions = re.findall('\(\d+\)/\(\d+\)', question) fractions = np.append(fractions, re.findall('\(\d+/\d+\)', question)) for i, fraction in enumerate(fractions): #question = question.replace(fraction, str(sys.maxsize - i)) #equation = equation.replace(fraction, str(sys.maxsize - i)) question = question.replace( fraction, str(parser.evaluate(fraction, variables=None))) equation = equation.replace( fraction, str(parser.evaluate(fraction, variables=None))) # handle numbers with units question = re.sub(r'(\d+)([A-z]{1,2})', r'\1 \2', question) # seperate equation at operators print('equation (before):', equation) equation = equation.replace('[', ' ( ') equation = equation.replace(']', ' ) ') equation = equation.replace('+', ' + ') equation = equation.replace('+', ' + ') equation = equation.replace('-', ' - ') equation = equation.replace('*', ' * ') equation = equation.replace('/', ' / ') equation = equation.replace('(', ' ( ') equation = equation.replace(')', ' ) ') equation = equation.replace('=', ' = ') equation = equation.replace('^', ' ^ ') # reduce %'s equation = equation.replace('%', ' / 100 ') # Preprocess Question question = question.split() question = np.append(['null', 'null', 'null'], question) question = np.append(question, ['null', 'null', 'null']) numbers = np.array([token for token in question if isFloat(token)]) # or float(token) == 2)]) _, indices = np.unique(numbers, return_index=True) numbers = numbers[np.sort(indices)] equation = np.array([token.strip() for token in equation.split(' ')]) examples = [] print('equation:', equation) for i, number in enumerate(numbers): index = np.where(question == number)[0][0] src = question[index - 3:index + 4] src = ' '.join(src) if number.strip() in equation: examples = np.append(examples, [src + '\t' + 'yes']) print('example:', src + '\t' + 'yes') else: examples = np.append(examples, [src + '\t' + 'no']) print('example:', src + '\t' + 'no') return examples
class numericalMethod(ABC): __metaclass__ = ABCMeta # Input data targetExpression = 'x^2 + 47' a = -1 b = 1 delta = 0.01 eps = 0.001 # Output data solution = [] N = 0 solutionEval = [] x_ = 0 Q_ = 0 def __init__(self, targetFunction, a, b, delta, eps): self.targetExpression = targetFunction self.a = a self.b = b self.delta = delta self.eps = eps self.solution.clear() self.solutionEval.clear() self.expression = Parser().parse(self.targetExpression) def Q(self, x): return self.expression.evaluate({'x': x}) def printExpression(self): print('Q(x) = ' + self.targetExpression) def initPlot(self, namePlot, step): x = np.arange(self.a, self.b + step, step) y = [] for args in x: y.append(self.Q(args)) plt.figure(namePlot) plt.xlabel('x') plt.ylabel('Q(x)') plt.plot(x, y, label=self.targetExpression) plt.legend() return plt def showFunction(self): self.initPlot('Target function', 0.01).show() def showNumericalMethod(self): newPlot = self.initPlot('Work of the numerical method', 0.01) for values in self.solution: newPlot.plot(values[1], values[3], 'go') newPlot.plot(values[2], values[4], 'go') newPlot.plot(self.x_, self.Q_, 'rs', label='optimum') newPlot.show() def showTable(self): print(tabulate(self.solution, headers=['№ iter', 'a', 'b', 'Q(a)', 'Q(b)'], tablefmt='orgtbl')) def showReference(self): print('->Input:') print('--->Q(x) = ' + self.targetExpression) print('--->[a, b] = [', self.a, ',', self.b, ']') print('--->delta = ', self.delta) print('--->eps = ', self.eps) print('->Output:') print('--->Iterations: ', self.N) print('--->Evaluation of the solution: ', self.solutionEval) print('--->x* = ', self.x_) print('--->Q(x*) = ', self.Q_) @abstractmethod def numericalSolution(self): pass