X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_utils.py;h=81b5634bc921736b0d007f3df04013d0dc6df265;hb=7bb608efc474092b1c26286924c8d91a1bf51aaa;hp=38e75761dab0394f3aa5e6e3016aed7c0edebbc8;hpb=839b90b46009aeb42d2615884972949664d154ad;p=sage.d.git diff --git a/mjo/eja/eja_utils.py b/mjo/eja/eja_utils.py index 38e7576..81b5634 100644 --- a/mjo/eja/eja_utils.py +++ b/mjo/eja/eja_utils.py @@ -2,6 +2,96 @@ from sage.functions.other import sqrt from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector +def _change_ring(x, R): + r""" + Change the ring of a vector, matrix, or a cartesian product of + those things. + + SETUP:: + + sage: from mjo.eja.eja_utils import _change_ring + + EXAMPLES:: + + sage: v = vector(QQ, (1,2,3)) + sage: m = matrix(QQ, [[1,2],[3,4]]) + sage: _change_ring(v, RDF) + (1.0, 2.0, 3.0) + sage: _change_ring(m, RDF) + [1.0 2.0] + [3.0 4.0] + sage: _change_ring((v,m), RDF) + ( + [1.0 2.0] + (1.0, 2.0, 3.0), [3.0 4.0] + ) + sage: V1 = cartesian_product([v.parent(), v.parent()]) + sage: V = cartesian_product([v.parent(), V1]) + sage: V((v, (v, v))) + ((1, 2, 3), ((1, 2, 3), (1, 2, 3))) + sage: _change_ring(V((v, (v, v))), RDF) + ((1.0, 2.0, 3.0), ((1.0, 2.0, 3.0), (1.0, 2.0, 3.0))) + + """ + try: + return x.change_ring(R) + except AttributeError: + try: + from sage.categories.sets_cat import cartesian_product + if hasattr(x, 'element_class'): + # x is a parent and we're in a recursive call. + return cartesian_product( [_change_ring(x_i, R) + for x_i in x.cartesian_factors()] ) + else: + # x is an element, and we want to change the ring + # of its parent. + P = x.parent() + Q = cartesian_product( [_change_ring(P_i, R) + for P_i in P.cartesian_factors()] ) + return Q(x) + except AttributeError: + # No parent for x + return x.__class__( _change_ring(x_i, R) for x_i in x ) + +def _scale(x, alpha): + r""" + Scale the vector, matrix, or cartesian-product-of-those-things + ``x`` by ``alpha``. + + This works around the inability to scale certain elements of + Cartesian product spaces, as reported in + + https://trac.sagemath.org/ticket/31435 + + ..WARNING: + + This will do the wrong thing if you feed it a tuple or list. + + SETUP:: + + sage: from mjo.eja.eja_utils import _scale + + EXAMPLES:: + + sage: v = vector(QQ, (1,2,3)) + sage: _scale(v,2) + (2, 4, 6) + sage: m = matrix(QQ, [[1,2],[3,4]]) + sage: M = cartesian_product([m.parent(), m.parent()]) + sage: _scale(M((m,m)), 2) + ([2 4] + [6 8], [2 4] + [6 8]) + + """ + if hasattr(x, 'cartesian_factors'): + P = x.parent() + return P(tuple( _scale(x_i, alpha) + for x_i in x.cartesian_factors() )) + else: + return x*alpha + + def _all2list(x): r""" Flatten a vector, matrix, or cartesian product of those things @@ -160,18 +250,16 @@ def gram_schmidt(v, inner_product=None): R = v[0].base_ring() - # Define a scaling operation that can be used on tuples. - # Oh and our "zero" needs to belong to the right space. - scale = lambda x,alpha: x*alpha + # Our "zero" needs to belong to the right space for sum() to work. zero = v[0].parent().zero() - if hasattr(v[0], 'cartesian_factors'): - P = v[0].parent() - scale = lambda x,alpha: P(tuple( x_i*alpha - for x_i in x.cartesian_factors() )) + sc = lambda x,a: a*x + if hasattr(v[0], 'cartesian_factors'): + # Only use the slow implementation if necessary. + sc = _scale def proj(x,y): - return scale(x, (inner_product(x,y)/inner_product(x,x))) + return sc(x, (inner_product(x,y)/inner_product(x,x))) # First orthogonalize... for i in range(1,len(v)): @@ -188,6 +276,6 @@ def gram_schmidt(v, inner_product=None): # them here because then our subalgebra would have a bigger field # than the superalgebra. for i in range(len(v)): - v[i] = scale(v[i], ~norm(v[i])) + v[i] = sc(v[i], ~norm(v[i])) return v