def checkFunction_math(self, raw): """ Returns whether a string contains a valid mathematical expression :param raw: string which contains mathematical expression :return: boolean """ try: f = eq.Expression(raw, ['x', 'A', 'B']) # TODO: need a better method for checking if functions are valid than a simple point evaluation # although this works in most cases most of the time it seems. f(x=0, A=0, B=0) # Value and Type errors are thrown when the string can't be converted to a function via Equation library except TypeError: logging.error( "Attempted to parse text that is not a function, or with improperly labelled parameters" ) return False # TODO: It would be nice to automatically detect any parameters, regardless of if they are labelled A or B, and # Zero division errors are still functions, i.e. 1/x except ZeroDivisionError: logging.warning( "Function defined which is unbounded at the origin") return True else: return True
def fitnessfunction(): s = input("Enter the equation you want to find minimum for:") f = Equation.Expression(s, ["x", "y"]) range = [] s = list(map(int, input("Enter range of values [a,b] for x:").split())) range.append(s) s = list(map(int, input("Enter range of values [a,b] for y:").split())) range.append(s) return [f, range]
def evaluate(self, value): # f could be defined as a class attribute but would require storing the Expression object in memory. # by declaring it locally it is thrown away and we only need store the text it is derived from. # This saves memory overhead at the cost of run-time performance in evaluating functions try: f = eq.Expression(self.raw, ["x", "A", "B"]) result = f(x=value, A=self.A, B=self.B) except ValueError: logging.error("Failed to evaluate function call") return None else: return result
def ternary(self, compound, limits): """ generate a search list for the ternary compound """ vars = compound.vars eqs = [ Equation.Expression(ele.comp, compound.vars) for ele in compound.elements ] eles = [ele.name for ele in compound.elements] composition_format = "{:.2f}".join(eles) + "{:.2f}" concentrations = np.stack(list(tri_grid(self.n, *limits)), axis=0) formula = [composition_format.format(*row) for row in concentrations] fake_df = pd.DataFrame({ "formula": formula, "x": concentrations[:, 0], "y": concentrations[:, 1], "z": concentrations[:, 2] }) return self.generate(fake_df)
def _calculate(self, x: str): # re_parser = '([^\(;]*\(.*?\)|[^;]*) ?; ?' # regex_split = ";(?!(?:[^(]*\([^)]*\))*[^()]*\))" x = x.strip() splitexp = "[*+%/^-](?!(?:[^(]*\([^)]*\))*[^()]*\))" x_exprs = re.split(splitexp, x) x_ops = re.findall(splitexp, x) splitops = SpreadSheet._split_ops(x) x_exprs = splitops[0] x_ops = splitops[1] if len(x_exprs) > 1 and not [i in x for i in ["<", "=", ">"]].count(True): for i, e in enumerate(x_exprs): x_exprs[i] = str(self._calculate(e)) i = 1 for op in x_ops: x_exprs.insert(i, op) i = i + 2 x = "".join(x_exprs) if x.startswith("ABS("): x = x[4:-1] x = SpreadSheet._calculate(self, x) assert isinstance(x, (int, float)) return math.fabs(x) elif x.startswith("FLOOR("): x = x[6:-1] x = SpreadSheet._calculate(self, x) assert isinstance(x, (int, float)) return math.floor(x) elif x.startswith("CEILING("): x = x[8:-1] x = SpreadSheet._calculate(self, x) assert isinstance(x, (int, float)) return math.ceil(x) elif x.startswith("SIN("): x = x[4:-1] x = SpreadSheet._calculate(self, x) assert isinstance(x, (int, float)) return math.sin(x) elif x.startswith("COS("): x = x[4:-1] x = SpreadSheet._calculate(self, x) assert isinstance(x, (int, float)) return math.cos(x) elif x.startswith("TAN("): x = x[4:-1] x = SpreadSheet._calculate(self, x) assert isinstance(x, (int, float)) return math.tan(x) elif x.startswith("LOG("): x = x[4:-1] args_ = SpreadSheet._split_semicolon(x) assert 1 <= len(args_) <= 2 x = args_[0] if len(args_) == 2: y = args_[1] else: y = "10" x, y = SpreadSheet._calculate(self, x),\ SpreadSheet._calculate(self, y) assert isinstance(x and y, (int, float)) return math.log(x, y) elif x.startswith("POW("): x = x[4:-1] args_ = SpreadSheet._split_semicolon(x) assert len(args_) == 2 x = args_[0] y = args_[1] x, y = SpreadSheet._calculate(self, x),\ SpreadSheet._calculate(self, y) assert isinstance(x and y, (int, float)) return math.pow(x, y) elif x.startswith("IF("): x = x[3:-1] args_ = SpreadSheet._split_semicolon(x) assert len(args_) == 3 x = args_[0] if x.__contains__('(') and not x.startswith('('): x = SpreadSheet._split_if(x) x1 = x[0] x2 = x[2] x1 = SpreadSheet._calculate(self, x1) x2 = SpreadSheet._calculate(self, x2) x = str(x1) + x[1] + str(x2) y = args_[1] z = args_[2] x = SpreadSheet._calculate(self, x) if x: state = SpreadSheet._calculate(self, y) else: state = SpreadSheet._calculate(self, z) if state == 1: state = "TRUE" elif state == 0: state = "FALSE" return state elif x.startswith("SUM("): x = x[4:-1] args_ = SpreadSheet._split_semicolon(x) sum_ = 0 for arg in args_: arg = SpreadSheet._calculate(self, arg) assert isinstance(arg, (int, float, tuple)) if isinstance(arg, tuple): for i in range(arg[0][0], arg[1][0] + 1): for j in range(arg[0][1], arg[1][1] + 1): y = self._getcellat(i, j).getvalue() assert isinstance(y, (int, float)) sum_ += y else: sum_ += arg return sum_ elif x.startswith("COUNTIF("): x = x[8:-1] args_ = SpreadSheet._split_semicolon(x) assert len(args_) == 2 x = args_[0] y = args_[1] x, y = SpreadSheet._calculate(self, x),\ SpreadSheet._calculate(self, y) assert isinstance(x, tuple) and len(x) == 2 count = 0 for i in range(x[0][0], x[1][0] + 1): for j in range(x[0][1], x[1][1] + 1): if self._getcellat(i, j).getvalue() == y: count += 1 return count elif x.startswith("AVERAGE("): x = x[8:-1] args_ = SpreadSheet._split_semicolon(x) sum_ = 0 count = 0 for arg in args_: arg = SpreadSheet._calculate(self, arg) assert isinstance(arg, (int, float, tuple)) if isinstance(arg, tuple): for i in range(arg[0][0], arg[1][0] + 1): for j in range(arg[0][1], arg[1][1] + 1): y = self._getcellat(i, j).getvalue() assert isinstance(y, (int, float)) sum_ += y count += 1 else: sum_ += arg count += 1 avg = sum_ / max(count, 1) # float("%.3f" % avg) return round(avg, 3) else: try: return float(x) except ValueError: pass if x.startswith(("'", '"')) and x.endswith(("'", '"')): return x[1:-1] elif x.__contains__(":"): return SpreadSheet.parserangeaddr(x) else: if x.startswith("(") and x.endswith(")"): x = x[1:-1] eqstr = x eq = re.sub("[A-Z]+[0-9]+", lambda m: self._convert(m), eqstr) eq = eq.replace("SIN(", "sin(") eq = eq.replace("COS(", "cos(") eq = eq.replace("TAN(", "tan(") eq = eq.replace("ABS(", "abs(") return Equation.Expression(eq)()