def setUp(self): # a = VariedCoefficient(A=1) # b = VariedCoefficient(B=1) self.term1 = SimpleTerm(TermTypes.POLYNOMIAL, -5, 1) self.term2 = SimpleTerm(TermTypes.EXPONENTIAL, 3, 3) self.term3 = SimpleTerm(TermTypes.POLYNOMIAL, 4, 3) self.term4 = SimpleTerm(TermTypes.SINE, 2, 8)
def setUp(self): a = VariedCoefficient(A=1) b = VariedCoefficient(B=1) self.term1 = AddTerm([MultiplyTerm([SimpleTerm(TermTypes.POLYNOMIAL, b, 0), SimpleTerm(TermTypes.POLYNOMIAL, 1, 0)]), SimpleTerm(TermTypes.POLYNOMIAL, a, 0), SimpleTerm(TermTypes.POLYNOMIAL, 6, 0), SimpleTerm(TermTypes.POLYNOMIAL, b + 5, 1)])
def get_signature(self): signature = {} # KEY: term, VALUE: count for subterm in self.terms: if not ((subterm.term_type == TermTypes.POLYNOMIAL) and (subterm.power == 0)): subterm_sig = SimpleTerm(subterm.term_type, 1, subterm.power) AbstractTerm.increment_map(signature, subterm_sig, 1) return signature
def __rmul__(self, other): from main.multiplyterm import MultiplyTerm from main.simpleterm import SimpleTerm, TermTypes if isinstance(other, numbers.Number): return MultiplyTerm( [self, SimpleTerm(TermTypes.POLYNOMIAL, other, 0)]) else: raise TypeError( "Multiplying SimpleTerm with thing that is not a number or term" )
def simplify(self): from main.multiplyterm import MultiplyTerm # "Flatten" any weird nested AddTerms. tmp_terms = [term.simplify() for term in self.terms] # Possibly redundant terms = [] for term in tmp_terms: if isinstance(term, AddTerm): terms = terms + term.terms else: terms.append(term) # REAL simplest case: Only one term. if len(terms) == 1: return terms[0] term_signatures = {} # Signature, coef for term in terms: term = term.simplify() # Simplify again after breaking up nested add terms signature = {} # KEY: term, VALUE: count coef = 0 if isinstance(term, MultiplyTerm): coef = term.get_coefficient_term().multiple signature = term.get_signature() elif isinstance(term, SimpleTerm): coef = term.multiple signature[SimpleTerm(term.term_type, 1, term.power)] = 1 else: raise ValueError("Term Type not recognized!") frozen_key = frozenset(signature.items()) AbstractTerm.increment_map(term_signatures, frozen_key, coef) retvals = [] for signature in term_signatures: const_val = term_signatures[signature] if not (const_val == 0): # print(const_val) const_term = SimpleTerm(TermTypes.POLYNOMIAL, const_val, 0) retvals.append(MultiplyTerm([const_term] + list(dict(signature)))) return AddTerm(retvals)
def solve_homogenous(self): self.homogenous_solutions = [None, None] a = self.coefs.variables[Equation.Y_PP] b = self.coefs.variables[Equation.Y_P] c = self.coefs.variables[Equation.Y] bsq_4ac = b**2 - 4 * c * a if bsq_4ac > 0: # Standard two exponential solutions root1 = (-b + math.sqrt(bsq_4ac)) / (2 * a) root2 = (-b - math.sqrt(bsq_4ac)) / (2 * a) self.homogenous_solutions[0] = SimpleTerm( TermTypes.EXPONENTIAL, VariedCoefficient(**{Equation.C1: 1}), root1) self.homogenous_solutions[1] = SimpleTerm( TermTypes.EXPONENTIAL, VariedCoefficient(**{Equation.C2: 1}), root2) elif bsq_4ac < 0: # Periodic solution b_2a = -b / (2 * a) freq_term = math.sqrt(-bsq_4ac) / (2 * a) self.homogenous_solutions[0] = MultiplyTerm([ SimpleTerm(TermTypes.EXPONENTIAL, VariedCoefficient(**{Equation.C1: 1}), b_2a), SimpleTerm(TermTypes.SINE, 1, freq_term) ]) self.homogenous_solutions[1] = MultiplyTerm([ SimpleTerm(TermTypes.EXPONENTIAL, VariedCoefficient(**{Equation.C2: 1}), b_2a), SimpleTerm(TermTypes.COSINE, 1, freq_term) ]) else: # Repeated roots b_2a = -b / (2 * a) self.homogenous_solutions[0] = SimpleTerm( TermTypes.EXPONENTIAL, VariedCoefficient(**{Equation.C1: 1}), b_2a) self.homogenous_solutions[1] = MultiplyTerm([ SimpleTerm(TermTypes.POLYNOMIAL, VariedCoefficient(**{Equation.C2: 1}), 1), SimpleTerm(TermTypes.EXPONENTIAL, 1, b_2a) ]) self.homogenous_solutions = list( [soln.simplify() for soln in self.homogenous_solutions])
def __split_expression(terms): coefficient = functools.reduce(lambda x, y: x * y.multiple, terms, 1) exp_accum = 0 polynom_accum = 0 sin_cos_terms = [] for term in terms: if (term.term_type == TermTypes.SINE) or (term.term_type == TermTypes.COSINE): sin_cos_terms.append(SimpleTerm(term.term_type, 1, term.power)) elif term.term_type == TermTypes.POLYNOMIAL: polynom_accum += term.power elif term.term_type == TermTypes.EXPONENTIAL: exp_accum += term.power else: raise ValueError("Illegal Term Type!") return coefficient, polynom_accum, exp_accum, sin_cos_terms
def simplify(self): # Simplify, and "Flatten" any weird nested MultiplyTerms. tmp_terms = [term.simplify() for term in self.terms] terms = [] # coef = self.coefficient # print(coef) for term in tmp_terms: if isinstance(term, MultiplyTerm): terms = terms + term.terms # coef *= term.coefficient else: terms.append(term) # REAL simplest case: Only one term. if len(terms) == 1: return terms[0] # * coef # Stupid add terms screwing everything up add_terms = [term.terms for term in terms if isinstance(term, AddTerm)] other_terms = [term for term in terms if not isinstance(term, AddTerm)] # Split up the "other terms" into core components coefficient, polynom_accum, exp_accum, sin_cos_terms = MultiplyTerm.__split_expression( other_terms) # coefficient *= coef if len(add_terms) == 0: accumulated_terms = [ SimpleTerm(TermTypes.POLYNOMIAL, coefficient, 0) ] if not (polynom_accum == 0): accumulated_terms.append( SimpleTerm(TermTypes.POLYNOMIAL, 1, polynom_accum)) if not (exp_accum == 0): accumulated_terms.append( SimpleTerm(TermTypes.EXPONENTIAL, 1, exp_accum)) if (len(accumulated_terms) == 1) and (len(sin_cos_terms) == 0): return accumulated_terms[0] return MultiplyTerm(accumulated_terms + sin_cos_terms) retvals = [] for combo in itertools.product(*add_terms): mult_tmp = MultiplyTerm(list(combo)).simplify() tmp_coef, tmp_polynom_accum, tmp_exp_accum, tmp_sin_cos_terms = \ MultiplyTerm.__split_expression(mult_tmp.terms) total_coefficient = coefficient * tmp_coef if total_coefficient == 0: continue total_polynom_accum = polynom_accum + tmp_polynom_accum total_exp_accum = exp_accum + tmp_exp_accum total_sin_cos_terms = sin_cos_terms + tmp_sin_cos_terms accumulated_terms = [ SimpleTerm(TermTypes.POLYNOMIAL, total_coefficient, 0) ] if not (total_polynom_accum == 0): accumulated_terms.append( SimpleTerm(TermTypes.POLYNOMIAL, 1, total_polynom_accum)) if not (total_exp_accum == 0): accumulated_terms.append( SimpleTerm(TermTypes.EXPONENTIAL, 1, total_exp_accum)) if (len(accumulated_terms) == 1) and (len(total_sin_cos_terms) == 0): retvals.append(accumulated_terms[0]) else: retvals.append( MultiplyTerm(accumulated_terms + total_sin_cos_terms)) if len(retvals) == 0: return SimpleTerm(TermTypes.POLYNOMIAL, 0, 0) return AddTerm(retvals).simplify()
def init_solutions(self): self.solve_homogenous() homogenous_signatures = [ solution.get_signature() for solution in self.homogenous_solutions ] # for term in homogenous_signatures: # for blah in term: # print(blah, term[blah]) # print() # # print(term) self.var_num = ord('A') self.specific_solutions = [] for term in self.terms.terms: solution_terms = [] subterms = term.terms for subterm in subterms: if not isinstance(subterm, SimpleTerm): raise ValueError( "Solution init error: Terms not simplified correctly!") term_type = subterm.term_type if term_type == TermTypes.POLYNOMIAL: polynom_terms = [] for i in range(subterm.power + 1): polynom_terms.append( SimpleTerm(TermTypes.POLYNOMIAL, 1, i)) solution_terms.append(AddTerm(polynom_terms)) elif term_type == TermTypes.EXPONENTIAL: solution_terms.append( SimpleTerm(TermTypes.EXPONENTIAL, 1, subterm.power)) elif (term_type == TermTypes.SINE) or term_type == TermTypes.COSINE: solution_terms.append( AddTerm([ SimpleTerm(TermTypes.SINE, 1, subterm.power), SimpleTerm(TermTypes.COSINE, 1, subterm.power) ])) solution_form = MultiplyTerm(solution_terms) solution_form = solution_form.simplify() names = [] repeats = 0 for polyterm in solution_form.terms: # Check for solutions that are already part of the general solution for signature in homogenous_signatures: if polyterm.get_signature() == signature: repeats += 1 name = self.__get_next_available_name() names.append(name) coef = VariedCoefficient(**{name: 1}) if isinstance(polyterm, SimpleTerm): polyterm.multiple = coef continue if not isinstance(polyterm, MultiplyTerm): raise ValueError( "Solving error: Failed to simplify properly") polyterm.get_coefficient_term().multiple = coef # Multiply by t^s if not (repeats == 0): solution_form = ( solution_form * SimpleTerm(TermTypes.POLYNOMIAL, 1, repeats)).simplify() self.specific_solutions.append((solution_form, term, names))
# from main.variedcoefficient import VariedCoefficient from main.simpleterm import SimpleTerm, TermTypes # from main.addterm import AddTerm from main.multiplyterm import MultiplyTerm from main.equation import Equation # x = VariedCoefficient("A") # x = x * 2 * 7 # print(x) # term1 = SimpleTerm(TermTypes.EXPONENTIAL, 3, 2) term2 = SimpleTerm(TermTypes.POLYNOMIAL, -5, 2) term4 = MultiplyTerm([ SimpleTerm(TermTypes.COSINE, 1, 2), SimpleTerm(TermTypes.POLYNOMIAL, 1, 1) ]).simplify() term5 = SimpleTerm(TermTypes.SINE, 3, 2) # print(term1) # print(term2) # print(term5) # print(term5.derivative()) # print(term5.simplify()) eqn1 = Equation(coef_list=[1, 0, 1], term_list=[term4, term5]) # eqn1 = Equation(coef_list=[1, 1, 1], term_list=[term2]) eqn1.init_solutions() print(eqn1) eqn1.solve_all_specific() print(eqn1.specific_solutions[0])