Skip to content
Snippets Groups Projects
Select Git revision
  • master
1 result

csvCReader.py

Blame
  • symboCalc.py 6.73 KiB
    # Jack Eckert
    
    # dependencies
    import math
    from typing import Any
    
    # base class for functions
    
    # arg is the argument of the function, which by default is the identity function represented
    # by the string 'x'. Any string will work and acts as a marker to allow the program to identify
    # the identity function.
    
    # coef is the coefficient of the function, should always be an integer or float and by default
    # is one. 
    class BaseFunction():
        def __init__(self, coef=None, arg=None):
            if coef == None:
                self.__coefficient = 1
            else:
                self.__coefficient = coef
            
            if arg == None:
                self.__argument = 'x'
            else:
                self.__argument = arg
    
        def getArg(self):
            return self.__argument
        
        def setArg(self, new):
            self.__argument = new
    
        def getCoef(self):
            return self.__coefficient
        
        def setCoef(self, new):
            self.__coefficient = new
    
        # used to consolidate an outside constant (k) into the function's coefficient
        def integrateCoef(self, k):
            self.__coefficient *= k
    
        def __neg__(self):
            return type(self)(-self.getCoef(), self.getArg())
    
        def __eq__(self, other):
            if not(isinstance(other, type(self))):
                return False
            return (self.getArg() == other.getArg() and self.getCoef() == other.getCoef())
    
        def __str__(self):
            if self.getCoef() == 1:
                coefficientString = ''
            elif self.getCoef() == -1:
                coefficientString = '-'
            else:
                coefficientString = round(self.getCoef(), 3)
            return coefficientString
        
        def __repr__(self):
            return str(self)
    
        def derive(self, shell):
            if isinstance(self.getArg(), str):
                return shell
            else:
                return [shell.getArg().derive(), shell]
    
    # power function, i.e. a function raised to a constant power.
    class Power(BaseFunction):
        def __init__(self, coef=None, arg=None, exp=1):
            super().__init__(coef, arg)
            self.__exponent = exp
    
        def getExp(self):
            return self.__exponent
        
        def setExp(self):
            return self.__exponent
        
        def __neg__(self):
            return type(self)(-self.getCoef(), self.getArg(), self.getExp())
        
        def __eq__(self, other):
            return (super().__eq__(other) and self.getExp() == other.getExp())
        
        def __ne__(self, other):
            return not(self.__eq__(other))
        
        def __str__(self):
            coefficientString = super().__str__()
    
            # parentheses formatting
            if not(isinstance(self.getArg(), str)):
                argumentString = f"({self.getArg()})"
            else:
                argumentString = self.getArg()
    
            # exponent formatting
            if self.getExp() == 1:
                return f"{coefficientString}{argumentString}"
    
            return f"{coefficientString}{argumentString}^{self.getExp()}"
    
        def derive(self):
            # base framework for the derivative, n * f(x)^(n - 1)
            if self.getExp() == 1:
                shell = self.getCoef()
            else:
                shell = Power(self.getCoef() * self.getExp(), self.getArg(), self.getExp() - 1)
    
            # derivation
            return super().derive(shell)
            
    # exponential function, i.e. a constant raised to a function power.
    class Exponential(BaseFunction):
        def __init__(self, coef=None, arg=None, base=math.e):
            super().__init__(coef, arg)
            if base != math.e:
                if isinstance(self.getArg(), str):
                    self.setArg(Power(math.log(base)))
                else:
                    self.integrateCoef(math.log(base))
            self.__base = base
    
        def getBase(self):
            return self.__base
        
        def setBase(self, new):
            self.__base = new
    
        def __neg__(self):
            return type(self)(-self.getCoef(), self.getArg(), self.getBase())
    
        def __str__(self):
            coefficientString = super().__str__()
            return f"{coefficientString}exp({self.getArg()})"
        
        def __eq__(self, other):
            return (super().__eq__(other) and self.getBase() == other.getBase())
        
        def derive(self):
            shell = self
            return super().derive(shell)
    
    # sine function  
    class Sine(BaseFunction):
        def __init__(self, coef=None, arg=None):
            super().__init__(coef, arg)
    
        def __str__(self):
            coefficientString = super().__str__()
            return f"{coefficientString}sin({self.getArg()})"
        
        def derive(self):
            shell = Cosine(self.getCoef(), self.getArg())
            return super().derive(shell)
    
    # cosine function 
    class Cosine(BaseFunction):
        def __init__(self, coef=None, arg=None):
            super().__init__(coef, arg)
    
        def __str__(self):
            coefficientString = super().__str__()
            return f"{coefficientString}cos({self.getArg()})"
        
        def derive(self):
            shell = -Sine(self.getCoef(), self.getArg())
            return super().derive(shell)
    
    class Equation():
        def __init__(self, eqList):
            self.__eqList = eqList
            for i, term in enumerate(self.__eqList):
                if not(isinstance(term, list)):
                    self.__eqList[i] = [term]
    
        def __iter__(self):
            self.index = -1
            return self
        
        def __next__(self):
            if self.index < len(self.__eqList) - 1:
                self.index += 1
                return self.__eqList[self.index]
            else:
                raise StopIteration
    
        def getEqList(self):
            return self.__eqList
        
        def setEqList(self, new):
            self.__eqList = new
    
        def __getitem__(self, i):
            return self.__eqList[i]
        
        def __setitem__(self, i, new):
            self.__eqList[i] = new
    
        def addTerm(self, new):
            if not(isinstance(new, list)):
                new = [new]
            self.__eqList.append(new)
    
        def removeAt(self, i):
            del self.__eqList[i]
    
        def __str__(self):
            strList = []
            for term in self:
                termString = ''
                for seg in term:
                    termString += f"({seg})"
                strList.append(termString)
            return " + ".join(strList)
        
        def __mul__(self, k):
            copy = Equation(self.__eqList)
            for term in copy:
                term.insert(0, k)
            return copy
        
        def __rmul__(self, k):
            copy = Equation(self.__eqList)
            for term in copy:
                term.insert(0, k)
            return copy
        
        def __add__(self, k):
            copy = Equation(self.__eqList)
            copy.addTerm(k)
            return copy
    
        def __radd__(self, k):
            copy = Equation(self.__eqList)
            copy.addTerm(k)
            return copy
        
        def __sub__(self, k):
            return self + -k
        
        def __rsub__(self, k):
            return -self + k
        
        #TODO
        def simplify(self):
            pass
    
    # Testing
    if __name__ == "__main__":
        eq1 = Equation([[Power(exp=2), Cosine()], Sine()])
        print(eq1 - Cosine())