From: Antonio Jimenez Pastor Date: Tue, 29 Jan 2019 16:02:56 +0000 (+0100) Subject: Advanced a bit more in lazyDDRing X-Git-Url: http://git.risc.jku.at/gitweb/?a=commitdiff_plain;h=31b57819616e4f2afeef86b8cff72bdb7d109387;p=ajpastor%2Fdiff_defined_functions.git Advanced a bit more in lazyDDRing Added a file to manipulate sequence as functions over the integers. --- diff --git a/ajpastor/dd_functions/ddExamples.py b/ajpastor/dd_functions/ddExamples.py index 3e5b8f6..f398724 100644 --- a/ajpastor/dd_functions/ddExamples.py +++ b/ajpastor/dd_functions/ddExamples.py @@ -1149,8 +1149,8 @@ def GenericHypergeometricFunction(num=[],den=[],init=_sage_const_1 ): if(not((numerator,denominator,initial) in __CACHED_HYPERGEOMETRIC)): ## Building differential operator get_op = lambda p : destiny_ring.element(p).equation; - op_num = prod(get_op([el,x]) for el in numerator,x); - op_den = prod(get_op([el-_sage_const_1 ,x]) for el in denominator, get_op([_sage_const_0 ,x])); + op_num = prod((get_op([el,x]) for el in numerator),x); + op_den = prod((get_op([el-_sage_const_1 ,x]) for el in denominator), get_op([_sage_const_0 ,x])); op = op_num - op_den; f = destiny_ring.element(op); diff --git a/ajpastor/dd_functions/lazyDDRing.py b/ajpastor/dd_functions/lazyDDRing.py index be70a16..04d2b1b 100644 --- a/ajpastor/dd_functions/lazyDDRing.py +++ b/ajpastor/dd_functions/lazyDDRing.py @@ -15,6 +15,8 @@ from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing as is from ajpastor.lazy.conversion import ConversionSystem; from ajpastor.dd_functions.ddFunction import *; +from ajpastor.misc.matrix import differential_movement; + #################################################################################################### #################################################################################################### ### ELEMENT CLASS @@ -352,7 +354,7 @@ class LazyDDRing (UniqueRepresentation, ConversionSystem, IntegralDomain): v = vector(self, v); ## Going to a root with the vector - v,dest = self.__pullup_vector(v, current); + v,const,dest = self.__pullup_vector(v, self.__poly_ring().zero(), current); ## Returning the appropriate polynomial using the final vector return self.__vector_to_poly(v, dest); @@ -365,11 +367,16 @@ class LazyDDRing (UniqueRepresentation, ConversionSystem, IntegralDomain): self.__add_function(element, gen=True); self.__r_graph.add_edge((element, root, relation)); - return self.__map_to_vars[element]; + # Removing root as a generator + index = self.__gens.index(self.__gen[self.__map_to_vars[root]]); + for i in range(self.__trans[root][1].nrows()): + self.__gens.pop(index); + + return self.__gen[self.__map_to_vars[element]]; ## Otherwise, we add the element to the variables and return it self.__add_function(element, gen=True); - return self.__map_to_vars[element]; + return self.__gen[self.__map_to_vars[element]]; ################################################################################################ ### Other Methods for LazyRing @@ -393,22 +400,11 @@ class LazyDDRing (UniqueRepresentation, ConversionSystem, IntegralDomain): self.__gens = []; self.__map_of_derivatives = {}; + def derivative(self, el, times=1): + raise NotImplementedError("method derivative not implemented"); + def get_derivative(self, el): - if(el in self.__map_of_derivatives): - return self.__map_of_derivatives[el]; - - if(el in self.__constants): - return _sage_const_0 ; - else: - try: - el = self.poly_ring()(el); - if(el in self.poly_ring().gens()): - new_poly = self.to_poly(self.map_of_vars()[str(el)].derivative()); - self.__map_of_derivatives[el] = new_poly; - return new_poly; - except: - pass; - raise ValueError("Method 'get_derivative' can only be summoned with variables.\nGot: %s -- %s" %(el, el.parent())); + raise NotImplementedError("method get_derivative not implemented"); ################################################################################################ ### Other Integral Domain methods @@ -521,7 +517,35 @@ class LazyDDRing (UniqueRepresentation, ConversionSystem, IntegralDomain): ################################################################################################ ### Private methods - ################################################################################################ + ################################################################################################ + def __pullup_vector(self, vector, constant, current): + if(self.__r_graph.in_degree(current) == 0): + return (vector, constant, current); + + ## Getting all data for this case + cR = self.__poly_field; + edge = self.__r_graph.incoming_edges(current)[0]; + C = self.__trans[edge[0]][1]; + trans_const = self.__trans[edge[0]][0]; + relation = edge[2]; + + ## Computing the derivatives of current in his father vector space + ivectors = [vector(cR, [0 for i in range(relation[0])] + [1] + [0 for i in range(relation[0]+1,self.__trans[current][1].nrows())])]; + extra_cons = [relation[1][1]]; + + for i in range(len(vector)): + extra_cons += [ivectors[-1][-1]*trans_const]; + ivectors += [differential_movement(C, ivectors[-1], self.derivative)]; + + res_vector = sum([vector(cR,[vector[i]*ivectors[i][j] for j in range(len(ivectors[i]))]) for i in range(len(vector))]); + res_constant = sum([vector[i]*extra_cons[i] for i in range(len(vector))], constant); + + return self.__pollup_vector(res_vector, res_constant, edge[0]); + + def __vector_to_poly(self, vector, current): + gen_index = self.__map_to_vars[current]; + return sum(vector[i]*self.__gen[gen_index+i] for i in range(len(vector)) if vector[i] != 0); + def __add_function(self, f, gen=False): ## We look for relations with the derivatives of itself derivatives = [f.derivative(times=i) for i in range(f.getOrder())]; @@ -559,7 +583,7 @@ class LazyDDRing (UniqueRepresentation, ConversionSystem, IntegralDomain): for i in range(order): self.__gens += [self.__gen[self.__used]]; self.__map_of_vars[self.__gens[-1]] = current; - self.__map_to_vars[current] = self.__gens[-1]; + self.__map_to_vars[current] = self.__used; self.__used += 1; current = current.derivative(); diff --git a/ajpastor/misc/sequence_manipulation.py b/ajpastor/misc/sequence_manipulation.py new file mode 100644 index 0000000..ce1b403 --- /dev/null +++ b/ajpastor/misc/sequence_manipulation.py @@ -0,0 +1,66 @@ + +################################################################################ +################################################################################ +################################################################################ +## Sequence operations +def addition(f,g): + return lambda n : f(n)+g(n); + +def hadamard_product(f,g): + return lambda n : f(n)*g(n); + +def cauchy_product(f,g): + return lambda n : sum(f(m)*g(n-m) for m in range(n+1)); + +def composition(f,g): + if(g(0) != 0): + raise ValueError("Impossible compose with g(0) != 0"); + def _composition(n): + if(n == 0): + return f(0); + result = 0; + current = g; + for k in range(1,n+1): + result += f(k)*current(n); + current = cauchy_product(current, g) + return result; + return _composition; + +def egf_ogf(f): + ''' + Method that receives a sequence in the form of a black-box function + and return a sequence h(n) such that egf(f) = ogf(h). + ''' + return lambda n: f(n)/factorial(n); + +def ogf_egf(f): + ''' + Method that receives a sequence in the form of a black-box function + and return a sequence h(n) such that egf(h) = ogf(f). + ''' + return lambda n: f(n)*factorial(n); + +def inv_lagrangian(f): + if(f(0) != 0): + raise ValueError("Power serie not invertible"); + if(f(1) == 0): + raise NotImplementedError("Case with order higher than 1 not implemented"); + f = egf_ogf(f); + def _inverse(n): + if(n == 0): + return 0; + elif(n == 1): + return 1/f(1); + else: + result = 0; + for k in range(1,n): + poly = bell_polynomial(n-1,k); + #print poly; + variables = poly.variables(); + #print variables; + extra = (-1)^k*falling_factorial(n+k-1,k); + result += extra*poly(**{str(variables[i]):f(i+1)/((i+1)*f(1)) for i in range(len(v +ariables))}); + return (1/((f(1)^n)*factorial(n))) * result; + return ogf_egf(_inverse); + diff --git a/releases/diff_defined_functions__0.6.zip b/releases/diff_defined_functions__0.6.zip index eecea87..009625c 100644 Binary files a/releases/diff_defined_functions__0.6.zip and b/releases/diff_defined_functions__0.6.zip differ diff --git a/releases/old/diff_defined_functions__0.6__19.01.29_17:02:54.zip b/releases/old/diff_defined_functions__0.6__19.01.29_17:02:54.zip new file mode 100644 index 0000000..009625c Binary files /dev/null and b/releases/old/diff_defined_functions__0.6__19.01.29_17:02:54.zip differ