2016-12-10 6 views
0

Ich muss eine Aufgabe in Python 3.4 programmieren, die Folgendes erfordert: - Das Programm fordert den Benutzer auf, ein Datenmodell einzugeben, das von mehreren Untermodellen in Form einer Zeichenfolge erstellt wird die folgenden:Evaluieren Sie ein vom Benutzer als Python-Funktion eingegebenes Modell

# the program ask : 
please input the submodel1 
# user will input: 
A = a*x + b*y*exp(3*c/d*x) 
# then the program ask : 
-> please input the submodel2 
# user will input: 
B = e*x + f*y*exp(3*h/d*x) 
# then the program ask : 
-> please input the main model: 
# user will input: 
Y = A*x - exp(B**2/y) 

dann nehmen sie das Programm diese Modelle (Strings) und führt einige Operationen auf ihnen wie Kurvenanpassung des Hauptmodells vorhandenen Daten und Plot-Ergebnisse mit den Parametern Werte zeigt. Die Idee hier ist, dem Benutzer die Freiheit zu geben, das Modell zur Laufzeit auszuwählen, ohne es als Funktion innerhalb der App programmieren zu müssen. mein Problem hier besteht in der Umwandlung oder Interpretation der Zeichenfolge als eine Python-Funktion, die Wert zurückgibt. Ich erforschte Lösung wie die Funktion eval(), aber ich bin auf der Suche nach einer Lösung, die wie in der Matlab

func = sym('string') 
func = matlabfunction(func) 

, die eine anonyme Funktion erstellt, die Sie mit leicht Hoffnung umgehen können ich mich klar gemacht, wenn überhaupt eine weitere Klarstellung erforderlich bitte lassen Sie mich wissen, die Lösung sollte mit python 3.4 Vielen Dank im Voraus

Antwort

0

Sie Parse-kompatibel sein nutzen ab: https://pypi.python.org/pypi/parse und trainieren Sie Ihren Parser mathematische Ausdrücke zu erkennen, finden Sie in diesem Beispiel (python27) :
http://www.nerdparadise.com/tech/python/parsemath/

# A really simple expression evaluator supporting the 
# four basic math functions, parentheses, and variables. 

class Parser: 
    def __init__(self, string, vars={}): 
     self.string = string 
     self.index = 0 
     self.vars = { 
      'pi' : 3.141592653589793, 
      'e' : 2.718281828459045 
      } 
     for var in vars.keys(): 
      if self.vars.get(var) != None: 
       raise Exception("Cannot redefine the value of " + var) 
      self.vars[var] = vars[var] 

    def getValue(self): 
     value = self.parseExpression() 
     self.skipWhitespace() 
     if self.hasNext(): 
      raise Exception(
       "Unexpected character found: '" + 
       self.peek() + 
       "' at index " + 
       str(self.index)) 
     return value 

    def peek(self): 
     return self.string[self.index:self.index + 1] 

    def hasNext(self): 
     return self.index < len(self.string) 

    def skipWhitespace(self): 
     while self.hasNext(): 
      if self.peek() in ' \t\n\r': 
       self.index += 1 
      else: 
       return 

    def parseExpression(self): 
     return self.parseAddition() 

    def parseAddition(self): 
     values = [self.parseMultiplication()] 
     while True: 
      self.skipWhitespace() 
      char = self.peek() 
      if char == '+': 
       self.index += 1 
       values.append(self.parseMultiplication()) 
      elif char == '-': 
       self.index += 1 
       values.append(-1 * self.parseMultiplication()) 
      else: 
       break 
     return sum(values) 

    def parseMultiplication(self): 
     values = [self.parseParenthesis()] 
     while True: 
      self.skipWhitespace() 
      char = self.peek() 
      if char == '*': 
       self.index += 1 
       values.append(self.parseParenthesis()) 
      elif char == '/': 
       div_index = self.index 
       self.index += 1 
       denominator = self.parseParenthesis() 
       if denominator == 0: 
        raise Exception(
         "Division by 0 kills baby whales (occured at index " + 
         str(div_index) + 
         ")") 
       values.append(1.0/denominator) 
      else: 
       break 
     value = 1.0 
     for factor in values: 
      value *= factor 
     return value 

    def parseParenthesis(self): 
     self.skipWhitespace() 
     char = self.peek() 
     if char == '(': 
      self.index += 1 
      value = self.parseExpression() 
      self.skipWhitespace() 
      if self.peek() != ')': 
       raise Exception(
        "No closing parenthesis found at character " 
        + str(self.index)) 
      self.index += 1 
      return value 
     else: 
      return self.parseNegative() 

    def parseNegative(self): 
     self.skipWhitespace() 
     char = self.peek() 
     if char == '-': 
      self.index += 1 
      return -1 * self.parseParenthesis() 
     else: 
      return self.parseValue() 

    def parseValue(self): 
     self.skipWhitespace() 
     char = self.peek() 
     if char in '.': 
      return self.parseNumber() 
     else: 
      return self.parseVariable() 

    def parseVariable(self): 
     self.skipWhitespace() 
     var = '' 
     while self.hasNext(): 
      char = self.peek() 
      if char.lower() in '_abcdefghijklmnopqrstuvwxyz': 
       var += char 
       self.index += 1 
      else: 
       break 

     value = self.vars.get(var, None) 
     if value == None: 
      raise Exception(
       "Unrecognized variable: '" + 
       var + 
       "'") 
     return float(value) 

    def parseNumber(self): 
     self.skipWhitespace() 
     strValue = '' 
     decimal_found = False 
     char = '' 

     while self.hasNext(): 
      char = self.peek()    
      if char == '.': 
       if decimal_found: 
        raise Exception(
         "Found an extra period in a number at character " + 
         str(self.index) + 
         ". Are you European?") 
       decimal_found = True 
       strValue += '.' 
      elif char in '': 
       strValue += char 
      else: 
       break 
      self.index += 1 

     if len(strValue) == 0: 
      if char == '': 
       raise Exception("Unexpected end found") 
      else: 
       raise Exception(
        "I was expecting to find a number at character " + 
        str(self.index) + 
        " but instead I found a '" + 
        char + 
        "'. What's up with that?") 

     return float(strValue) 

def evaluate(expression, vars={}): 
    try: 
     p = Parser(expression, vars) 
     value = p.getValue() 
    except Exception as (ex): 
     msg = ex.message 
     raise Exception(msg) 

    # Return an integer type if the answer is an integer 
    if int(value) == value: 
     return int(value) 

    # If Python made some silly precision error 
    # like x.99999999999996, just return x + 1 as an integer 
    epsilon = 0.0000000001 
    if int(value + epsilon) != int(value): 
     return int(value + epsilon) 
    elif int(value - epsilon) != int(value): 
     return int(value) 

    return value 

print evaluate("1 + 2 * 3") 
print evaluate("(1 + 2) * 3") 
print evaluate("-(1 + 2) * 3") 
print evaluate("(1-2)/3.0 + 0.0000") 
print evaluate("1 + pi/4") 
print evaluate("(a + b)/c", { 'a':1, 'b':2, 'c':3 }) 
print evaluate("(x + e * 10)/10", { 'x' : 3 }) 
print evaluate("1.0/3 * 6") 
print evaluate("(1 - 1 + -1) * pi") 
print evaluate("pi * e") 
+0

Vielen Dank Hamza, es ist diese Art von Lösung, die ich suche, ich hoffe, mehr Antworten zu sehen, bevor ich einen akzeptiere, trotzdem gab mir das einen starken Startpunkt danke – Hzine

+0

@hamza hebal könnte Text relevant für die Antwort hinzufügen. Wenn die Links verschwinden würden, hätte diese Antwort keinen Wert. Vielen Dank. – rapvelopment

0

lmfit (http://lmfit.github.io/lmfit-py/) eine ExpressionModel, die Ihnen nützlich sein könnten:

import numpy as np 
import matplotlib.pyplot as plt 
from lmfit.models import ExpressionModel 

# make fake data 
x = np.linspace(-10, 10, 201) 
amp, cen, wid = 3.4, 1.8, 0.5 

y = amp * np.exp(-(x-cen)**2/(2*wid**2))/(np.sqrt(2*np.pi)*wid) 
y += np.random.normal(size=len(x), scale=0.01) 

# create model from expression 
model= ExpressionModel("amp * exp(-(x-cen)**2 /(2*wid**2))/(sqrt(2*pi)*wid)") 

# fit data to that model 
result = model.fit(y, x=x, amp=5, cen=5, wid=1) 

# show results 
print(result.fit_report()) 
plt.plot(x, y,   'bo') 
plt.plot(x, result.init_fit, 'k--') 
plt.plot(x, result.best_fit, 'r-') 
plt.show() 

Dieser verwendet asteval (http://newville.github.io/asteval) und unterstützt so eine relativ reiche Teilmenge von Python Syntax und numpy Konstanten und ufuncs, einschließlich sqrt, exp, sin, pi, und so weiter.

+0

Danke Newville, das ist fantastisch für die meisten Fälle und es funktionierte auf vielen von mir, in meinem Fall sollte ich einen angepassten Parser verwenden, sonst wird dies die beste Antwort sein, Danke – Hzine

Verwandte Themen