美文网首页
实现表达式求导

实现表达式求导

作者: 星光下的胖子 | 来源:发表于2021-04-17 19:10 被阅读0次

    思路^_^

    1.创建表达式类(Exp、Const、Variable),并实现eval(计算表达式的值)和deriv(求导)操作。
    # 1.1 定义表达式
    class Exp(object):
        def eval(self, **kwargs):  # 计算表达式的值
            pass
        
        def deriv(self, x):  # 计算表达式的导数
            pass
        
        def __add__(self, other):  # 运算符重载 e1 + e2
            return Add(self, other).simplify()
        
        def __sub__(self, other):  # 运算符重载 e1 - e2
            return Sub(self, other).simplify()
        
        def __mul__(self, other):  # 运算符重载 e1 * e2
            return Mul(self, other).simplify()
        
        def __truediv__(self, other):  # 运算符重载 e1 / e2
            return TrueDiv(self, other).simplify()
        
        def __neg__(self):  # 运算符重载 - e1
            return Neg(self).simplify()
        
        def __pow__(self, power):  # 运算符重载 e1 ** e2
            return Pow(self, power).simplify()
        
        def __ln__(self):  # 自定义的ln运算符
            return Ln(self).simplify()
    
    # 1.2 定义常量表达式
    class Const(Exp):
        def __init__(self, value):
            self.value = value
            
        def eval(self, **kwargs):  # 计算表达式的值
            return self.value
        
        def deriv(self, x):  # 计算表达式的导数
            return Const(0)
        
        def __repr__(self):  # print时自动调用
            return f"{self.value}"
    
    # 1.3 定义变量表达式
    class Variable(Exp):
        def __init__(self, name):
            self.name = name
            
        def eval(self, **kwargs):  # 计算表达式的值
            if self.name in kwargs:
                return kwargs[self.name]
            raise NameError(f"name {self.name} is not found")
        
        def deriv(self, x):  # 计算表达式的导数
            name = self.get_param_name(x)
            return Const(1 if name == self.name else 0)
        
        def __repr__(self):  # print时自动调用
            return self.name
        
        def get_param_name(self, x):
            if isinstance(x, Variable):
                return x.name
            if isinstance(x, str):
                return x
            raise TypeError(f"{x} is neither Variable nor str")
    
    2.实现表达式的简单操作:加运算、取负运算、减运算、乘运算、除运算。
    # 2.1 简单操作——加运算
    class Add(Exp):
        def __init__(self, left, right):
            self.left = left
            self.right = right
            
        def eval(self, **kwargs):
            return self.left.eval(**kwargs) + self.right.eval(**kwargs)
        
        def deriv(self, x):
            return self.left.deriv(x) + self.right.deriv(x)
        
        def __repr__(self):  # 为了可读性,判断是否要加括号()
            if isinstance(self.left, (Const, Variable)):
                if isinstance(self.right, Const):
                    if self.right.value < 0:
                        return f"{self.left} - {-self.right.value}"
                    else:
                        return f"{self.left} + {self.right}"
                elif isinstance(self.right, Variable):
                    return f"{self.left} + {self.right}"
                else:
                    return f"{self.left} + ({self.right})"
            elif isinstance(self.right, (Const, Variable)):
                if isinstance(self.right, Const) and self.right.value < 0:
                    return f"({self.left}) - {-self.right.value}"
                else:
                    return f"({self.left}) + {self.right}"
            else:
                return f"({self.left}) + ({self.right})"
        
        def simplify(self):  # 简化表达式
            if isinstance(self.left, Const):
                if self.left.value == 0:
                    return self.right
                if isinstance(self.right, Const):
                    return Const(self.left.value + self.right.value)
            elif isinstance(self.right, Const) and self.right.value == 0:
                return self.left
            return self
    
    # 2.2 简单操作——取负运算
    class Neg(Exp):
        def __init__(self, exp):
            self.exp = exp
            
        def eval(self, **kwargs):
            return - self.exp.eval(**kwargs)
        
        def deriv(self, x):
            return - self.exp.deriv(x)
        
        def __repr__(self):  # 为了可读性,判断是否要加括号()
            if isinstance(self.exp, Const):
                return f"{-self.exp.value}"
            if isinstance(self.exp, Variable):
                return f"-{self.exp}"
            return f"(-{self.exp})"
        
        def simplify(self):  # 简化表达式
            if isinstance(self.exp, Const):
                return Const(-self.exp.value)
            return self
    
    # 2.3 简单操作——减运算
    class Sub(Exp):
        def __init__(self, left, right):
            self.left = left
            self.right = right
            
        def eval(self, **kwargs):
            return self.left.eval(**kwargs) - self.right.eval(**kwargs)
        
        def deriv(self, x):
            return self.left.deriv(x) - self.right.deriv(x)
        
        def __repr__(self):  # 为了可读性,判断是否要加括号()
            if isinstance(self.left, (Const, Variable)):
                if isinstance(self.right, Const):
                    if self.right.value < 0:
                        return f"{self.left} + {-self.right.value}"
                    else:
                        return f"{self.left} - {self.right}"
                elif isinstance(self.right, Variable):
                    return f"{self.left} - {self.right}"
                else:
                    return f"{self.left} - ({self.right})"
            elif isinstance(self.right, (Const, Variable)):
                if isinstance(self.right, Const) and self.right.value < 0:
                    return f"({self.left}) + {-self.right.value}"
                else:
                    return f"({self.left}) - {self.right}"
            else:
                return f"({self.left}) - ({self.right})"
        
        def simplify(self):  # 简化表达式
            if isinstance(self.left, Const):
                if self.left.value == 0:
                    return - self.right
                if isinstance(self.right, Const):
                    return Const(self.left.value - self.right.value)
            elif isinstance(self.right, Const) and self.right.value == 0:
                return self.left
            return self
    
    # 2.4 简单操作——乘运算
    class Mul(Exp):
        def __init__(self, left, right):
            self.left = left
            self.right = right
            
        def eval(self, **kwargs):
            return self.left.eval(**kwargs) * self.right.eval(**kwargs)
        
        def deriv(self, x):
            u, v = self.left, self.right
            # (uv)‘=u‘v + uv'
            return u.deriv(x) * v + u * v.deriv(x)
        
        def __repr__(self):  # 为了可读性,判断是否要加括号()
            if isinstance(self.left, (Const, Variable)):
                if isinstance(self.right, Const):
                    if self.right.value < 0:
                         return f"{self.left} * ({self.right.value})"
                    else:
                        return f"{self.left} * {self.right}"
                elif isinstance(self.right, Variable):
                    return f"{self.left} * {self.right}"
                else:
                    return f"{self.left} * ({self.right})"
            elif isinstance(self.right, (Const, Variable)):
                if isinstance(self.right, Const) and self.right.value < 0:
                    return f"({self.left}) * ({self.right.value})"
                else:
                    return f"({self.left}) * {self.right}"
            else:
                return f"({self.left}) * ({self.right})"
        
        def simplify(self):  # 简化表达式
            if isinstance(self.left, Const):
                if self.left.value == 0:
                    return Const(0)
                if self.left.value == 1:
                    return self.right
                if isinstance(self.right, Const):
                    return Const(self.left.value * self.right.value)
            elif isinstance(self.right, Const):
                if self.right.value == 0:
                    return Const(0)
                if self.right.value == 1:
                    return self.left
            return self
    
    # 2.5 简单操作——除运算
    class TrueDiv(Exp):
        def __init__(self, left, right):
            self.left = left
            self.right = right
            
        def eval(self, **kwargs):
            return self.left.eval(**kwargs) / self.right.eval(**kwargs)
        
        def deriv(self, x):
            u, v = self.left, self.right
            # (u/v)‘=(u‘v - uv')/(v*v)
            return (u.deriv(x) * v - u * v.deriv(x)) / (v * v)
        
        def __repr__(self):  # 为了可读性,判断是否要加括号()
            if isinstance(self.left, (Const, Variable)):
                if isinstance(self.right, Const):
                    if self.right.value < 0:
                         return f"{self.left} / ({self.right.value})"
                    else:
                        return f"{self.left} / {self.right}"
                elif isinstance(self.right, Variable):
                    return f"{self.left} / {self.right}"
                else:
                    return f"{self.left} / ({self.right})"
            elif isinstance(self.right, (Const, Variable)):
                if isinstance(self.right, Const) and self.right.value < 0:
                    return f"({self.left}) / ({self.right.value})"
                else:
                    return f"({self.left}) / {self.right}"
            else:
                return f"({self.left}) / ({self.right})"
        
        def simplify(self):  # 简化表达式
            if isinstance(self.left, Const):
                if self.left.value == 0:
                    return Const(0)
                if isinstance(self.right, Const):
                    return Const(self.left.value / self.right.value)
            elif isinstance(self.right, Const):
                if self.right.value == 0:
                    raise ZeroDivisionError("division by zero")
                if self.right.value == 1:
                    return self.left
            return self
    
    3.添加复杂操作:对数运算、幂运算。
    # 3.1 复杂操作——对数运算
    import math
    
    # 自定义ln运算
    def ln(exp):
        return exp.__ln__()
    
    class Ln(Exp):
        def __init__(self, antilog):
            self.antilog = antilog  # 真数
            
        def eval(self, **kwargs):
            # math.log(x, [base=math.e])
            x = self.antilog.eval(**kwargs)
            if x <= 0:
                raise ValueError("the antilog must be greater than zero")
            return math.log(x)
        
        def deriv(self, x):
            # (lnf)‘=f‘/f
            return self.antilog.deriv(x) / self.antilog
        
        def __repr__(self):  # 为了可读性,判断是否要加括号()
            if isinstance(self.antilog, (Const, Variable)):
                return f"ln{self.antilog}"
            return f"ln({self.antilog})"
        
        def simplify(self):  # 简化表达式
            if isinstance(self.antilog, Const) and self.antilog.value <= 0:
                raise ValueError("the antilog must be greater than zero")
            return self
    
    # 3.2 复杂操作——幂运算
    class Pow(Exp):
        def __init__(self, base, power):
            self.base = base
            self.power = power
            
        def eval(self, **kwargs):
            return self.base.eval(**kwargs) ** self.power.eval(**kwargs)
        
        def deriv(self, x):
            f, g = self.base, self.power
            # (f^g)‘=f^g*(g‘*ln(f) + g*f‘/f)
            if g.deriv(x) == 0:
                return f ** g * (g * f.deriv(x) / f)
            return f ** g * (g.deriv(x) * ln(f) + g * f.deriv(x) / f)
        
        def __repr__(self):  # 为了可读性,判断是否要加括号()
            if isinstance(self.base, Variable) or (isinstance(self.base, Const) and self.base.value >= 0):
                if isinstance(self.power, Const):
                    if self.power.value < 0:
                        return f"{self.base} ** ({self.power.value})"
                    else:
                        return f"{self.base} ** {self.power}"
                elif isinstance(self.power, Variable):
                    return f"{self.base} ** {self.power}"
                else:
                    return f"{self.base} ** ({self.power})"
            elif isinstance(self.power, (Const, Variable)):
                if isinstance(self.power, Const) and self.power.value < 0:
                    return f"({self.base}) ** ({self.power.value})"
                else:
                    return f"({self.base}) ** {self.power}"
            else:
                return f"({self.base}) ** ({self.power})"
        
        def simplify(self):  # 简化表达式
            if isinstance(self.base, Const):
                if self.base.value == 0:
                    return Const(0)
                elif self.base.value == 1:
                    return Const(1)
    #             elif self.base.value < 0:
    #                 raise ValueError("the base cannot be less than zero")
                elif isinstance(self.power, Const):
                    return Const(self.base.value ** self.power.value)
            elif isinstance(self.power, Const):
                if self.power.value == 0:
                    return Const(1)
                if self.power.value == 1:
                    return self.base
            return self
    

    相关文章

      网友评论

          本文标题:实现表达式求导

          本文链接:https://www.haomeiwen.com/subject/abkplltx.html