# This file was *autogenerated* from the file ./lazyRing.sage
from sage.all_cmdline import * # import sage library
-_sage_const_2 = Integer(2); _sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_20 = Integer(20)
from sage.rings.ring import IntegralDomain;
from sage.structure.element import IntegralDomainElement;
from sage.categories.integral_domains import IntegralDomains;
from ajpastor.lazy.conversion import ConversionSystem;
from ajpastor.dd_functions.ddFunction import *;
+from ajpastor.misc.ring_w_sequence import Ring_w_Sequence;
from ajpastor.misc.matrix import differential_movement;
####################################################################################################
self.__poly = parent.poly_ring()(el);
except:
try:
- self.__poly = parent.poly_field()(str(el));
+ self.__poly = parent.poly_field()(el);
except:
self.__raw = parent.base()(el);
self.__poly = self.parent().to_poly(self.__raw);
### Arithmetics methods
################################################################################################
def _add_(self, other):
- if(isinstance(other, _LazyDDFunction)):
- try:
- return _LazyDDFunction(self.parent(), self.poly()+self.parent()(other).poly());
- except NotImplementedError as e:
- pass;
-
- return NotImplemented;
+ try:
+ return _LazyDDFunction(self.parent(), self.poly()+self.parent()(other).poly());
+ except:
+ return NotImplemented;
def _sub_(self,other):
return self.__add__(-other);
try:
return _LazyDDFunction(self.parent(), -self.poly());
except NotImplementedError:
- pass;
+ return NotImplemented;
- return NotImplemented;
-
def _mul_(self,other):
- if(isinstance(other, _LazyDDFunction)):
- try:
- return _LazyDDFunction(self.parent(), self.poly()*self.parent()(other).poly());
- except NotImplementedError as e:
- pass;
-
- return NotImplemented;
+ try:
+ return _LazyDDFunction(self.parent(), self.poly()*self.parent()(other).poly());
+ except:
+ return NotImplemented;
def _div_(self,other):
- if(isinstance(other, _LazyDDFunction)):
- try:
- return _LazyDDFunction(self.parent(), self.parent().poly_field()(self.poly())/self.parent().poly_field()(self.parent()(other).poly()));
- except NotImplementedError as e:
- pass;
-
- return NotImplemented;
+ try:
+ return _LazyDDFunction(self.parent(), self.poly()/self.parent()(other).poly());
+ except:
+ return NotImplemented;
def _pow_(self,i):
try:
'''
Method that a common divisor of 'self' and the input
'''
- if(len(input) > _sage_const_1):
+ if(len(input) > 1):
return self.gcd(input);
return _LazyDDFunction(self.parent(), gcd([self.poly()]+[self.parent()(el).poly() for el in input]));
'''
Method that a common multiple of 'self' and the input
'''
- if(len(input) > _sage_const_1 ):
+ if(len(input) > 1 ):
return self.gcd(input);
return _LazyDDFunction(self.parent(), lcm([self.poly()]+[self.parent()(el).poly() for el in input]));
except NotImplementedError:
factors = pol.factor(proof=False);
except:
- factors = [(pol,_sage_const_1 )];
+ factors = [(pol,1 )];
for factor in factors:
- result = (self.parent().to_real(factor[_sage_const_0 ]) == _sage_const_0 );
+ result = (self.parent().to_real(factor[0 ]) == 0 );
if(result):
- self.parent().add_relations(factor[_sage_const_0 ]);
+ self.parent().add_relations(factor[0 ]);
break;
+ if(result):
+ self.__poly = self.parent().poly_ring().zero();
+
return result;
@cached_method
Element = _LazyDDFunction;
- def __init__(self, base, constants=QQ, var_name="z" category=None):
+ def __init__(self, base, constants=QQ, var_name="z", category=None):
'''
Implementation of a Covnersion System using InfinitePolynomialRing as a basic structure.
self.__constants = constants;
self.__poly_ring = InfinitePolynomialRing(constants, names=[var_name]);
+ self.__poly_field = self.__poly_ring.fraction_field();
self.__gen = self.__poly_ring.gens()[0];
self.__used = 0;
self.__map_of_derivatives = {}; # Map for each variable to its derivative (as a polynomial)
## Casting and Coercion system
- self.base().register_conversion(LDRSimpleMorphism(self, self.base()));
+ self.base().register_conversion(LDRSimpleMorphism(self, self.base()));
+
+ ## Adding the 'x' as a basic variable in the ring
+ self(DFinite.element([0,0,1],[0,1],name="x"));
################################################################################################
### Implementing methods of ConversionSystem
try:
built = element.built();
if(not (built is None)):
- if(built[_sage_const_0 ] == "derivative"):
- if(not(element in built[_sage_const_1 ])):
- integral = self(built[_sage_const_1 ][_sage_const_0 ]);
- if(not (integral.poly().is_monomial() and integral.poly().degree() == _sage_const_1 )):
- return self(built[_sage_const_1 ][_sage_const_0 ]).derivative().poly();
- elif(built[_sage_const_0 ] == "polynomial"):
+ if(built[0 ] == "derivative"):
+ if(not(element in built[1 ])):
+ integral = self(built[1 ][0 ]);
+ if(not (integral.poly().is_monomial() and integral.poly().degree() == 1 )):
+ return self(built[1 ][0 ]).derivative().poly();
+ elif(built[0 ] == "polynomial"):
## We check we do not have infinite recursion
- if(not element in built[_sage_const_1 ][_sage_const_1 ].values()):
+ if(not element in built[1 ][1 ].values()):
## We have some building information
- polys = {key : self.to_poly(built[_sage_const_1 ][_sage_const_1 ][key]) for key in built[_sage_const_1 ][_sage_const_1 ]};
- return built[_sage_const_1 ][_sage_const_0 ](**polys);
+ polys = {key : self.to_poly(built[1 ][1 ][key]) for key in built[1 ][1 ]};
+ return built[1 ][0 ](**polys);
except AttributeError:
pass;
## Otherwise we look for a linear relation between the element and the variables
## Breath-search for a linear relation
- roots = [el for el in self.__r_graph.vertices() if self.__r_graph.in_degree() == 0];# Getting roots
+ roots = [el for el in self.__r_graph if self.__r_graph.in_degree(el) == 0];# Getting roots
from collections import deque;
to_search = deque(roots); # Initializing the queue
while(len(to_search) > 0):
to_search.append(edge[1]);
# Visiting the current node
- relation = self.__find_relation(element, current);
+ relation = self.__find_relation(element, current, self.__trans[current][1].nrows());
if(not (relation is None)):
## If it is not just the function, create a new node for future relations
if(relation[0] != 0):
## Creating the vector in the current level
v = [0 for i in range(self.__trans[current][1].nrows())];
- v[relation[0]] = relation[1];
- v = vector(self, v);
+ v[relation[0]] = relation[1][0];
+ v = vector(self.poly_field(), v);
## Going to a root with the vector
- v,const,dest = self.__pullup_vector(v, self.__poly_ring().zero(), current);
+ v,const,dest = self.__pullup_vector(v, relation[1][1], current);
## Returning the appropriate polynomial using the final vector
- return self.__vector_to_poly(v, dest);
+ return self.__vector_to_poly(v, dest)+const;
## At this point, no direct relation was found. We look for relation between element and the roots
for root in roots:
self.__add_function(element, gen=True);
self.__r_graph.add_edge((element, root, relation));
+ # Adding the relation for future simplifications
+ rel = self.__gen[root] - relation[1][1]*self.__gen[self.__map_to_vars[element]+relation[0]] - relation[1][1];
+ self.add_relations(rel);
+
# 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()):
def element(self, X):
return self(X);
+ def gens(self):
+ return self.__gens;
+
+ def ngens(self):
+ return len(self.__gens);
+
################################################################################################
### Other Ring methods
################################################################################################
################################################################################################
def _coerce_map_from_(self, S):
coer = None;
- if(isinstance(S, LazyRing)):
+ if(isinstance(S, LazyDDRing)):
coer = self.base()._coerce_map_from_(S.base());
+ elif(S == self.poly_ring() or S == self.poly_field()):
+ coer = True;
elif(S == self.base()):
coer = True;
else:
return (not(coer is False) and not(coer is None));
def _element_constructor_(self, *args, **kwds):
- if(len(args) < _sage_const_1 ):
- print args
+ if(len(args) < 1 ):
raise ValueError("Impossible to build an element without arguments");
- i = _sage_const_0 ;
- if(len(args) >= _sage_const_2 ):
- if(not (args[_sage_const_0 ] is self)):
+ i = 0 ;
+ if(len(args) >= 2 ):
+ if(not (args[0 ] is self)):
raise ValueError("RIOKO: What the .... are you sending to this method?");
- i = _sage_const_1 ;
+ i = 1 ;
X = args[i];
try:
order = f.getOrder();
relation = None;
- for i in range(f.getOrder(),0,-1):
- n_relation = self.__find_relation(derivatives[i], derivatives[:i-1], _debug);
+ for i in range(f.getOrder()-1,0,-1):
+ n_relation = self.__find_relation(derivatives[i], derivatives[:i]);
if(not (n_relation is None)):
- order = i-1;
+ order = i;
relation = n_relation;
else:
break;
new_row = [companion[i][j] for j in range(order)];
if(i == relation[0]):
new_row[-1] = relation[1][0];
- C += [[companion[i][j] for j in range(k-1)] + []];
+ C += [new_row];
C = Matrix(self,C);
- self.__trans[f] = (relation[1],C);
+ self.__trans[f] = (relation[1][1],C);
else:
- self.__trans[f] = (self.zero(),Matrix(self, f.equation.companion()));
+ self.__trans[f] = (self.poly_ring().zero(),Matrix(self, f.equation.companion()));
## Adding f as a vertex (edges must be added outside this function)
self.__r_graph.add_vertex(f);
return;
- def __find_relation(self, g,f):
- '''
- Method that get the relation between g and a f. If possible, it computes the derivatives up to
- some order of f and check relations with them.
-
- It returns a tuple (k,res) where:
- - k: the first index which we found a relation
- - res: the relation (see __find_linear_relation to see how such relation is expressed).
-
- Then the following statement is always True:
- g == f[k]*res[0] + res[1]
- '''
- if(is_DDFunction(f)):
- f = [f.derivative(times=i) for i in range(f.getOrder())];
-
- for k in range(d):
- res = __find_linear_relation(g,f[k]);
- if(not (res is None)):
- return (k,res);
-
- return None;
-
-def __find_linear_relation(f,g):
- '''
- This method receives two DDFunctions and return two constants (c,d) such that f = cg+d.
- None is return if those constants do not exist.
- '''
- if(not (is_DDFunction(f) and is_DDFunction(g))):
- raise TypeError("find_linear_relation: The functions are not DDFunctions");
-
- ## Simplest case: some of the functions are constants is a constant
- if(f.is_constant):
- return (f.parent().zero(), f(0));
- elif(g.is_constant):
+ def __find_relation(self, g,f,d=None):
+ '''
+ Method that get the relation between g and a f. If possible, it computes
+ the derivatives up to some order of f and check relations with them.
+
+ It returns a tuple (k,res) where
+ - k: the first index which we found a relation
+ - res: the relation (see __find_linear_relation to see how such
+ relation is expressed).
+
+ Then the following statement is always True
+ g == f[k]*res[0] + res[1]
+
+ INPUT:
+ - g: Function we want to see the relation
+ - f: Function or list of functions where we look for relations
+ - d: Optional parameter to limit
+ '''
+ if(is_DDFunction(f)): # If f is a function, computing the derivatives
+ f = [f.derivative(times=i) for i in range(f.getOrder())];
+ if(not(d is None)):
+ f = f[:d]; # Limiting the list with the optional parameter d
+
+ for k in range(len(f)):
+ res = self.__find_linear_relation(g,f[k]);
+ if(not (res is None)):
+ return (k,res);
+
return None;
- try:
- of = 1; og = 1;
- while(f.getSequenceElement(of) == 0): of += 1;
- while(g.getSequenceElement(og) == 0): og += 1;
-
- if(of == og):
- c = f.getSequenceElement(of)/g.getSequenceElement(og);
- d = f(0) - c*g(0);
+ def __find_linear_relation(self, f,g):
+ '''
+ This method receives two DDFunctions and return two constants (c,d)
+ such that f = cg+d. None is return if those constants do not exist.
+ '''
+ if(not (is_DDFunction(f) and is_DDFunction(g))):
+ raise TypeError("find_linear_relation: The functions are not DDFunctions");
+
+ ## Simplest case: some of the functions are constants is a constant
+ if(f.is_constant):
+ return (f.parent().zero(), f(0));
+ elif(g.is_constant):
+ return None;
+
+ try:
+ of = 1; og = 1;
+ while(f.getSequenceElement(of) == 0): of += 1;
+ while(g.getSequenceElement(og) == 0): og += 1;
- if(f == c*g + d):
- return (c,d);
- except Exception:
- pass;
-
- return None;
+ if(of == og):
+ c = f.getSequenceElement(of)/g.getSequenceElement(og);
+ d = f(0) - c*g(0);
+
+ if(f == c*g + d):
+ return (c,d);
+ except Exception:
+ pass;
+
+ return None;
####################################################################################################
####################################################################################################
class LazyDDRingFunctor (ConstructionFunctor):
def __init__(self):
ID = IntegralDomains();
- self.rank = _sage_const_20 ;
+ self.rank = 20 ;
super(LazyDDRingFunctor, self).__init__(ID,ID);
### Methods to implement