Fixed small error in Log
authorAntonio Jimenez Pastor <ajpastor@risc.uni-linz.ac.at>
Mon, 1 Oct 2018 14:06:01 +0000 (16:06 +0200)
committerAntonio Jimenez Pastor <ajpastor@risc.uni-linz.ac.at>
Mon, 1 Oct 2018 14:06:01 +0000 (16:06 +0200)
Fixed error in toDiffAlgebraic

Added the power with power series.

ajpastor/dd_functions/ddExamples.py
ajpastor/dd_functions/ddFunction.py
ajpastor/dd_functions/toDiffAlgebraic.py
releases/diff_defined_functions__0.6.zip
releases/old/diff_defined_functions__0.6__18.10.01_16:05:59.zip [new file with mode: 0644]

index 611cf38..14b6b86 100644 (file)
@@ -295,7 +295,7 @@ def Log(input, ddR = None):
         This function can be converted into symbolic expressions.
     '''
     if(is_DDFunction(input)):
-        return Log(x+_sage_const_1 )(input);
+        return Log(x+_sage_const_1 )(input-1);
     f,dR = __decide_parent(input, ddR);
     
     evaluate = lambda p : dR.getSequenceElement(p,_sage_const_0 );
index 59f1415..340f954 100644 (file)
@@ -1894,16 +1894,23 @@ class DDFunction (IntegralDomainElement):
         return super(DDFunction,self).__div__(self.__check_symbolic(other));
         
     def __radd__(self, other):
-        return super(DDFunction,self).__add__(self.__check_symbolic(other));
+        return super(DDFunction,self).__radd__(self.__check_symbolic(other));
         
     def __rsub__(self, other):
-        return (-self) + self.__check_symbolic(other);
+        return super(DDFunction,self).__rsub__(self.__check_symbolic(other));
         
     def __rmul__(self, other):
-        return super(DDFunction,self).__mul__(self.__check_symbolic(other));
+        return super(DDFunction,self).__rmul__(self.__check_symbolic(other));
         
     def __rdiv__(self, other):
-        return self.inverse * self.__check_symbolic(other);
+        return super(DDFunction,self).__rdiv__(self.__check_symbolic(other));
+        
+    def __rpow__(self, other):
+        try:
+            print "__rpow__ was called";
+            return self.parent().to_depth(1)(other)**self;
+        except:
+            return NotImplemented;
         
     def __iadd__(self, other):
         return super(DDFunction,self).__add__(self.__check_symbolic(other));
@@ -1974,20 +1981,39 @@ class DDFunction (IntegralDomainElement):
                     except Exception:
                         raise ZeroDivisionError("Impossible to compute the inverse");
                     return inverse.__pow__(-other);
-            else: ## Trying a power on the basic field
-                try:
-                    newDDRing = DDRing(self.parent());
-                    other = self.parent().base_ring()(other);
-                    self.__pows[other] = newDDRing.element([(-other)*f.derivative(),f], [el**other for el in f.getInitialValueList(1 )], check_init=False);
+            else: ## Trying a generic power
+                if(is_DDFunction(other) or other in self.parent()):
+                    if(self(x=0) != 1):
+                        raise ValueError("The base of exponentiation must have initial value 1");
+                    from ajpastor.dd_functions.ddExamples import Log;
+                    lf = Log(self);
+                    
+                    R = sage.categories.pushout.pushout(other.parent(), lf.parent());
+                    g = R(other); lf = R(lf);
+                    R = R.to_depth(R.depth()+1);
+                    
+                    if((g(x=0) != 0)):                    
+                        raise ValueError("The exponent must have initial value 0");
                     
                     newName = None;
-                    if(not(self.__name is None)):
-                        newName = DinamicString("(_1)^%s" %(other), self.__name);
-                    self.__pows[other].__name = newName;
-                except TypeError:
-                    raise TypeError("Impossible to compute (%s)^(%s) within the basic field %s" %(f.getInitialValue(0 ), other, f.parent().base_ring()));
-                except ValueError:
-                    raise NotImplementedError("Powering to an element of %s not implemented" %(other.parent()));
+                    if((not is_DDFunction(g)) or (g._DDFunction__name is not None)):
+                        newName = DinamicString("(_1)^(_2)", [self.__name, repr(other)]);
+                    
+                    self.__pows[other] = R.element([-(lf*other).derivative(),1],[1],name=newName);
+                else:
+                    try:
+                        newDDRing = DDRing(self.parent());
+                        other = self.parent().base_ring()(other);
+                        self.__pows[other] = newDDRing.element([(-other)*f.derivative(),f], [el**other for el in f.getInitialValueList(1 )], check_init=False);
+                        
+                        newName = None;
+                        if(not(self.__name is None)):
+                            newName = DinamicString("(_1)^%s" %(other), self.__name);
+                        self.__pows[other].__name = newName;
+                    except TypeError:
+                        raise TypeError("Impossible to compute (%s)^(%s) within the basic field %s" %(f.getInitialValue(0 ), other, f.parent().base_ring()));
+                    except ValueError:
+                        raise NotImplementedError("Powering to an element of %s not implemented" %(other.parent()));
         return self.__pows[other];
         
             
index 56f42fd..273ab79 100644 (file)
@@ -35,13 +35,34 @@ def get_InfinitePolynomialRingVaribale(parent, gen, number):
     
 #### TODO: Review this function
 def infinite_derivative(element, times=1, var=x):
-    if(times in ZZ and times > 1):
+    '''
+        Method that takes an element and compute its times-th derivative
+        with respect to the variable given by var.
+        
+        If the element is not in a InfinitePolynomialRing then the method
+        'derivative' of the object will be called. Otherwise this method
+        returns the derivative following the rules:
+            - The coefficients of the polynomial ring are differentiated using
+            a recursive call to this method (usually this leads to a call of the
+            method '.derivative' of that coefficient).
+            - Any variable "#_n" appearing in the InfinitePolynomialRing has
+            as derivative the variable "#_{n+1}", i.e., the same name but with
+            one higher index.
+    '''
+    if(not ((times in ZZ) and times >=0)):
+        raise ValueError("The argument 'times' must be a non-negative integer");
+    elif(times > 1): # Recursive call
         return infinite_derivative(infinite_derivative(element, times-1))
+    elif(times == 0): # Empty call
+        return element;
+        
+    ## Call with times = 1
     try:
         parent = element.parent();
     except AttributeError:
         return 0;
     
+    ## Simple call: not an InfinitePolynomialRing
     if(not is_InfinitePolynomialRing(parent)):
         try:
             try:
@@ -50,27 +71,42 @@ def infinite_derivative(element, times=1, var=x):
                 return element.derivative();
         except AttributeError:
             return parent.zero();
+            
+    ## IPR call
+    ## Symbolic case?
+    if(sage.symbolic.ring.is_SymbolicExpressionRing(parent.base())):
+        raise TypeError("Base ring for the InfinitePolynomialRing not valid (found SymbolicRing)");
+    ### Monomial case
     if(element.is_monomial()):
+        ## Case of degree 1 (add one to the index of the variable)
         if(len(element.variables()) == 1 and element.degree() == 1):
             g,n = get_InfinitePolynomialRingGen(parent, element, True);
             return get_InfinitePolynomialRingVaribale(parent, g,n+1);
+        ## Case of higher degree
         else:
-            degrees = element.degrees();
+            # Computing the variables in the monomial and their degrees (in order)
             variables = element.variables();
             degrees = [element.degree(v) for v in variables];
+            variables = [parent(v) for v in variables]
             ## Computing the common factor
-            com_factor = prod([variables[i]**(degrees[i]-1) for i in range(len(degrees)) if degrees[i] > 0]);
-            ## Computing the derivative for each variable
-            each_sum = [
-                degrees[i]*infinite_derivative(parent(variables[i]))*prod(
-                    variables[j] for j in range(len(variables)) if ((i != j) and (degrees[j] > 0)))
-                for i in range(len(variables)) if degrees[i] > 0];
+            com_factor = prod([variables[i]**(degrees[i]-1) for i in range(len(degrees))]);
+            ## Computing the derivative of each variable
+            der_variables = [infinite_derivative(parent(v)) for v in variables];
+            
+            ## Computing the particular part for each summand
+            each_sum = [];
+            for i in range(len(variables)):
+                if(degrees[i] > 0):
+                    part_prod = prod([variables[j] for j in range(len(variables)) if j != i]);
+                    each_sum += [degrees[i]*infinite_derivative(parent(variables[i]))*part_prod];
             
+            ## Computing the final result
             return com_factor*sum(each_sum);
+    ### Non-monomial case
     else:
         coefficients = element.coefficients();
-        monomials = element.monomials();
-        return sum([infinite_derivative(coefficients[i])*monomials[i] + parent(coefficients[i])*infinite_derivative(parent(monomials[i])) for i in range(len(monomials))]);
+        monomials = [parent(el) for el in element.monomials()];
+        return sum([infinite_derivative(coefficients[i])*monomials[i] + coefficients[i]*infinite_derivative(monomials[i]) for i in range(len(monomials))]);
     
 def fromInfinityPolynomial_toFinitePolynomial(poly):
     if(not is_InfinitePolynomialRing(poly.parent())):
index 53eb465..c4cca1b 100644 (file)
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__18.10.01_16:05:59.zip b/releases/old/diff_defined_functions__0.6__18.10.01_16:05:59.zip
new file mode 100644 (file)
index 0000000..c4cca1b
Binary files /dev/null and b/releases/old/diff_defined_functions__0.6__18.10.01_16:05:59.zip differ