Ask Your Question

Simon King's profile - activity

2018-09-22 09:51:09 +0100 received badge  Good Answer (source)
2014-09-30 03:24:03 +0100 received badge  Enlightened (source)
2014-09-30 03:24:03 +0100 received badge  Good Answer (source)
2014-08-27 00:45:18 +0100 received badge  Good Answer (source)
2014-08-20 15:22:11 +0100 received badge  Nice Answer (source)
2014-06-12 08:00:16 +0100 received badge  Nice Answer (source)
2012-04-15 05:42:33 +0100 answered a question Error in looking at source code

This is a known problem: See trac ticket #11913. Unfortunately, the problem isn't resolved yet.

Two possible workarounds:

  1. If you do "click to the left of this block", then the complete source is shown. I don't know what happens if the doc string contains several tracebacks, though.
  2. Use the command line version of Sage: The problem is specific to the Notebook.
2012-03-22 13:44:58 +0100 commented question Non-commutative ring with inverses

I think that sage-combinat-devel would be even better than sage-devel or sage-algebra (though the latter would make sense as well). Actually, yesterday I did post on sage-combinat-devel, in order to point people to this question. After all, Noud had already asked on sage-support, but didn't get a good answer (sorry for that).

2012-03-18 13:48:40 +0100 received badge  Nice Answer (source)
2012-03-16 10:20:35 +0100 answered a question save definitions

Saving functions is a general problem with Python (and Python is Sage's language). But Sage provides a partial solution in the modules sage.misc.fpickle. That module contains a function pickle_function, that translates a given function into a string (and then you can save the string). And it also contains a function unpickle_function, that translates that string into a function.

Example:

sage: from sage.misc.fpickle import pickle_function, unpickle_function
sage: def my_func(x): return x^2
....: 
sage: tmp = tmp_filename()
sage: save(pickle_function(my_func), tmp)
sage: recovered_function = unpickle_function(load(tmp))
sage: recovered_function(5)
25

pickle_function does have limitations (as explained in the docs), but perhaps it is enough for your application?

2012-03-14 07:09:20 +0100 received badge  Enthusiast
2012-03-13 11:14:31 +0100 received badge  Nice Answer (source)
2012-03-12 16:11:17 +0100 answered a question How to save a function in sage

I think the answer crucially depends on what you mean by the word "function".

It could be a Python or Cython function, either defined in an interactive session or in a module. It could be a symbolic expression, or perhaps could be a polynomial, which are sometimes mistaken for a function.

Symbolic function is easy to pickle:

sage: f(x) = x^2
sage: type(f)
<type 'sage.symbolic.expression.Expression'>
sage: tmp = tmp_filename()
sage: save(f,tmp)
sage: load(tmp)
x^2

Similarly, a polynomial is easy to pickle:

sage: P.<x> = QQ[]
sage: p = x^2
sage: type(p)
<type 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>
sage: save(p,tmp)
sage: load(tmp)
x^2

However, if you are really talking about a Python function (e.g., a lambda function), then there is a general problem: You can't easily pickle Python functions defined in an interactive session. And Python is Sage's programming language.

sage: def f(x):
....:     return x
....: 
sage: save(f,tmp)
---------------------------------------------------------------------------
PicklingError                             Traceback (most recent call last)

/home/simon/SAGE/sage-5.0.beta7/devel/sage-main/<ipython console> in <module>()

/home/simon/SAGE/sage-5.0.beta7/local/lib/python2.7/site-packages/sage/structure/sage_object.so in sage.structure.sage_object.save (sage/structure/sage_object.c:8647)()

PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed

However, if you define the same function in some Python module, then pickling would work.

And what do you mean by the "contents" of a function?

Do you mean, you have a Python function and want to see its code?

Then again, if it is defined in a module, then it works easily: If you have any object X (function or anything else) in Sage, then you can try to see its code by appending two question marks and hitting return (or shift-return in the Sage notebook). And with edit(X,'vim') (inserting another editor name if you don't like vim), then you could actually edit the code.

But if the function is only defined in an interactive session, then Python can not find the code.

2012-03-01 09:09:57 +0100 received badge  Nice Answer (source)
2012-03-01 05:13:00 +0100 answered a question Show the polynomials in the Groebner Basis as they are found

After you reformulated your question, it seems to me that what you want to do is test "radical membership" of some of the x_i. That's to say: You want to know whether there is some integer n such that x_i^n belongs to the ideal.

Actually, the Gröbner basis of an ideal is not enough to solve that radical membership! In Singular, radical membership can be tested as explained here.

That functionality is provided by some library of Singular. If you want to do the same in Sage, without using a Singular sub-process, you can meanwhile do as follows:

First, we define some ideal, and show that the Gröbner basis does not immediately show that some power of y vanishes:

sage: P.<x,y> = QQ[]
sage: I = P*[x*y^3+y^5, x*y^6]
sage: I.groebner_basis()
[x^3*y^3, x^2*y^4, y^5 + x*y^3]

Next, we import some stuff that is needed to benefit from Singular library functions in Sage, load the library, define the Singular function, and test for radical membership of y in I:

sage: from sage.libs.singular import lib, singular_function
sage: lib("tropical.lib")
sage: rad_mem = singular_function("radicalMemberShip")
sage: rad_mem(y,I)
   skipping text from `parameter`
1

I don't know where the text "skipping text ..." comes from - anyway, the answer of the function is 1, and that means that indeed some power of y belongs to I. Let us verify it:

sage: y in I
False
sage: y^2 in I
False
sage: y^3 in I
False
sage: y^7 in I
False
sage: y^8 in I
True

However, no power of x belongs to I:

sage: rad_mem(x,I)
0

I hope this is enough to solve your problem. In particular, I believe that looking at some protocol output of slimgb would certainly not solve your problem: As demonstrated above, the Gröbner basis does, in general, not directly provide the radical membership information for variables).

Also, as much as I know, there is no option to make slimgb or std or another Singular function make print the polynomials being considered.

2012-02-29 16:28:54 +0100 answered a question Show the polynomials in the Groebner Basis as they are found

Do you know the degree of the polynomial you are looking for? Then it might make sense to compute a truncated Gröbner basis out to that degree -- in particular if your polynomial system happens to be homogeneous.

2012-02-28 18:11:20 +0100 commented question inverse of a polynomial modulo another polynomial

Burcin, xgcd doesn't work. It fails with a type error, "cannot coerce nonconstant polynomial".

2012-01-18 02:13:21 +0100 answered a question Faugère's F4 Algorithm

As much as I know, there are only toy implementations of F5 in Sage (and I don't recall how it is available) - that's to say, they are good for educational purposes, but it would be much more efficient to use the default ways of computing Gröbner bases.

Note that Michael Brickenstein's "slimgb" (which is often used in Singular and thus also in Sage) is sometimes referred to as a version of F4. If you create a multivariate ideal J and want to compute its Gröbner basis with a particular algorithm, you can use something like

J.groebner_basis(algorithm='slimgb')
2012-01-14 08:58:58 +0100 commented question sage and nohup

Concerning `*`: Why don't you use the editor to format code like code?

2012-01-13 05:26:52 +0100 received badge  Editor (source)
2012-01-13 05:22:26 +0100 answered a question How can I construct graded algebras?

Since you ask for graded algebras, but refer to the category of graded modules: Which of the two do you need?

General remarks on Sage's category framework

I recommend that you study my public worksheet on categories and coercion.

First of all, the purpose of categories in Sage is not to construct a specific object in that category. It is more or less the other way around: You implement something and inform Sage that it belongs to some category. For example, let someone implement a Python class MyModuleClass whose instances are graded modules. Then, MyModuleClass.__init__ should make sure that the instance is declared as an object of the category of graded modules over the given base ring.

It is possible that some instances of MyModuleClass actually are algebras and not just modules. For example, the set of m by n matrices over a ring R is often just an R-module, but it is an R-algebra if m==n. In that situation, it is not needed that you sub-class MyModuleClass, but you can simply choose a different category during initialisation.

Why is that useful?

  • Sometimes one needs to test whether a given object X is an R-module or not. Then, you can simply test it by "if X in Modules(R): <do something>".
  • The categories in Sage can provide generic code that is available to all objects of that category - it is not needed that you implement these methods by yourself. For example, the category of commutative additive semigroups provides a method called summation(...), and it is available to the rational field, since it belongs to a sub-category:

    sage: QQ.summation.__module__
    'sage.categories.commutative_additive_semigroups'
    
  • In order to belong to a certain category, an object has to satisfy certain algebraic axioms. For example, elements of a commutative ring can be multiplied, and the result does not depend on the multiplication order. The category framework provides some basic tests (of course, it can't be exhaustive) that your implementation is sane:

    sage: TestSuite(QQ).run(verbose=True)
    running ._test_additive_associativity() . . . pass
    running ._test_an_element() . . . pass
    running ._test_associativity() . . . pass
    running ._test_category() . . . pass
    running ._test_distributivity() . . . pass
    running ._test_elements() . . .
      Running the test suite of self.an_element()
      running ._test_category() . . . pass
      running ._test_eq() . . . pass
      running ._test_not_implemented_methods() . . . pass
      running ._test_pickling() . . . pass
      pass
    running ._test_elements_eq() . . . pass
    running ._test_eq() . . . pass
    running ._test_not_implemented_methods() . . . pass
    running ._test_one() . . . pass
    running ._test_pickling() . . . pass
    running ._test_prod() . . . pass
    running ._test_some_elements() . . . pass
    running ._test_zero() . . . pass
    

So, the category framework helps to implement an algebraic structure. However, it is not the location of the actual implementation.

Where to find actual implementations

If you want to find out what modules or algebras are currently implemented in Sage, then look into sage.modules or sage.algebras (The links are to the relevant chapters of the documentation).

You will find that there are non-commutative algebras, whereas the modules currently available in Sage are only over commutative rings. However, this will change in upcoming versions (hopefully in sage-5.0): Singular, which is a computer algebra system used by Sage for polynomial arithmetic ... (more)

2012-01-09 14:37:52 +0100 answered a question Does or will Sage support the Visual Python module?

As I said in a comment above: It is not recommended to install some package in one python installation (e.g., some system-wide installation) and then import it into a totally different installation (e.g., the Sage installation).

It is important to keep in mind that Sage includes "batteries": It includes Python, it includes GAP, it includes Maxima, Singular, you name it. Hence, when you want to use a specific Python package in Sage then you should install it in Sage's Python, and nowhere else.

Hence, open a Sage shell (if sage is in your path then do "sage -sh"), and then do whatever is needed to install the package. Namely, in the Sage shell, "python" and "gap" and "singular" will automatically be Sage's versions, not the system-wide versions.

2012-01-09 03:53:46 +0100 commented answer Does or will Sage support the Visual Python module?

Too bad, I thought I can have line breaks in a comment. Anyway: In order to install any new Python module in Sage, just open a Sage shell (i.e., if "sage" is the command for launching an interactive Sage session, do "sage -sh"). In that shell, the commands "singular", "gap", "python" and so on will refer to Sage's own versions of Singular, GAP and python. Hence, in the Sage shell, you'd just do whatever needed to install the package, and then it will automatically be in the right version of Python.

2012-01-09 03:50:18 +0100 commented answer Does or will Sage support the Visual Python module?

Note that Sage has its own Python. Hence, rather than using "visual" from the global Python version on your machine (which may be a different version than Sage's Python!), I think it would be better to install the visual module into Sage's Python

2012-01-03 01:44:45 +0100 answered a question intermediate algebra

I am posting this as an answer and not as an comment, since I believe a weak point of askSage is the fact that it is too easy to no notice a comment (at least this is what happened to me on several occasions).

I am not sure what you mean by "intermediate algebra", and in fact you did not ask a question.

Is your question "How can one solve an arbitrary equation in one variable numerically (in complex numbers)?" or "How can one solve an arbitrary equation in one variable symbolically?" or "How can one solve an arbitrary linear equation over an arbitrary field?" or "For homework, I have to find z such that 3+z-13=z+2; what is the solution to that equation?"?

The answer will depend on the question.

2011-12-09 17:02:30 +0100 commented answer determine consistency of nonlinear system of equations

But be warned that computing the (Krull) dimension of an ideal requires a Gröbner basis computation (that's done internally), which, depending on the problem, might be very very difficult. My experience is that it is always worth trying, but the OP shouldn't be too disappointed if it doesn't work.

2011-12-09 15:38:51 +0100 received badge  Nice Answer (source)
2011-11-25 10:52:42 +0100 answered a question Basis of invariant polynomial system

Hooray, there is SAGBI bases in Sage! Namely, Singular provides them. See singular manual

It is not totally staight forward to use it in Sage, because your base ring is a function field, and even though Singular itself can deal with it, lib_singular (which is used for many polynomial rings) cannot handle it, yet.

So, you could try it via the pexpect interface (see the Sage reference manual):

sage: R.<S0,S1,S2,S3,S4,S5> = QQ[]
sage: P.<X0,X1,X2, Y0,Y1,Y2> = Frac(R)[]
sage: I = P * [
X0  + Y0 - S0,
X0 *  X1  + Y0 *  Y1   -     S1,
X0* ( X1^2 + 2 * X2 )+ Y0* ( Y1^2 + 2* Y2 )-   2* S2,
X0* ( X1^3 + 6 * X2* X1 )+ Y0 *( Y1^3 + 6* Y2 *Y1 )  -   6 *S3,
X0* ( X1^4 + 12* X2* X1^2 + 12* X2^2 )+ Y0 *( Y1^4 + 12* Y2* Y1^2 + 12* Y2^2 )-  24* S4,
X0* ( X1^5 + 20* X2* X1^3 + 60* X2^2* X1 )  + Y0 *( Y1^5 + 20 *Y2* Y1^3 + 60* Y2^2 *Y1 )  - 120* S5]
sage: PI = singular(I)
sage: PI
X0+Y0+(-S0),
X0*X1+Y0*Y1+(-S1),
X0*X1^2+Y0*Y1^2+2*X0*X2+2*Y0*Y2+(-2*S2),
X0*X1^3+Y0*Y1^3+6*X0*X1*X2+6*Y0*Y1*Y2+(-6*S3),
X0*X1^4+Y0*Y1^4+12*X0*X1^2*X2+12*Y0*Y1^2*Y2+12*X0*X2^2+12*Y0*Y2^2+(-24*S4),
X0*X1^5+Y0*Y1^5+20*X0*X1^3*X2+20*Y0*Y1^3*Y2+60*X0*X1*X2^2+60*Y0*Y1*Y2^2+(-120*S5)
sage: singular.LIB("sagbi.lib")
sage: G = PI.sagbi()

However, it doesn't seem to be an easy problem - I give no guarantee that it will soon finish. Also, it seems that it can not be used with a degree bound; at least, the Singular manual does not mention it.

2011-11-25 09:53:35 +0100 answered a question Basis of invariant polynomial system

If you just want to compute a truncated Gröbner basis of your system (say, out to degree 7), then it's easy:

sage: R.<S0,S1,S2,S3,S4,S5> = QQ[]
sage: P.<X0,X1,X2, Y0,Y1,Y2> = Frac(R)[]
sage: P
Multivariate Polynomial Ring in X0, X1, X2, Y0, Y1, Y2 over Fraction Field of Multivariate Polynomial Ring in S0, S1, S2, S3, S4, S5 over Rational Field
sage: I = P * [
....: X0  + Y0 - S0,
....: X0 *  X1  + Y0 *  Y1   -     S1,
....: X0* ( X1^2 + 2 * X2 )+ Y0* ( Y1^2 + 2* Y2 )-   2* S2,
....: X0* ( X1^3 + 6 * X2* X1 )+ Y0 *( Y1^3 + 6* Y2 *Y1 )  -   6 *S3,
....: X0* ( X1^4 + 12* X2* X1^2 + 12* X2^2 )+ Y0 *( Y1^4 + 12* Y2* Y1^2 + 12* Y2^2 )-  24* S4,
....: X0* ( X1^5 + 20* X2* X1^3 + 60* X2^2* X1 )  + Y0 *( Y1^5 + 20 *Y2* Y1^3 + 60* Y2^2 *Y1 )  - 120* S5]
sage: I
Ideal (X0 + Y0 - S0, X0*X1 + Y0*Y1 - S1, X0*X1^2 + Y0*Y1^2 + 2*X0*X2 + 2*Y0*Y2 - 2*S2, X0*X1^3 + Y0*Y1^3 + 6*X0*X1*X2 + 6*Y0*Y1*Y2 - 6*S3, X0*X1^4 + Y0*Y1^4 + 12*X0*X1^2*X2 + 12*Y0*Y1^2*Y2 + 12*X0*X2^2 + 12*Y0*Y2^2 - 24*S4, X0*X1^5 + Y0*Y1^5 + 20*X0*X1^3*X2 + 20*Y0*Y1^3*Y2 + 60*X0*X1*X2^2 + 60*Y0*Y1*Y2^2 - 120*S5) of Multivariate Polynomial Ring in X0, X1, X2, Y0, Y1, Y2 over Fraction Field of Multivariate Polynomial Ring in S0, S1, S2, S3, S4, S5 over Rational Field
sage: %time G = I.groebner_basis(deg_bound = 7)
CPU times: user 0.17 s, sys: 0.01 s, total: 0.18 s
Wall time: 0.46 s
sage: len(G)
18

However, Note two things:

"Usual Gröbner bases" will always destroy the symmetry of your original equations. I am afraid it seems that there is no SAGBI basis in Sage. I wish it was.

Also note that the result is, in general, not a "Gröbner basis out to degree n" but a "truncated Gröbner basis". Namely, while computing the Gröbner basis, all polynomials with leading monomial of degree greater than n will simply be discarded of. But for inhomogeneous systems (like yours) it could happen that the s-polynomial of two polynomials of degree > n have a leading monomial of degree smaller than n. Hence, the truncation will lose information.

2011-11-24 18:23:05 +0100 commented answer Basis of invariant polynomial system

Hi Volker, I think the OP's problem is not "given a finite group action, compute a minimal generating set of the invariant ring". But just to put that straight: Hironaka decomposition is not needed to compute minimal generating sets, at least in the "classical" (non-modular) case. I introduced a more direct algorithm, that is implemented in Singular since a couple of years. At that time, it clearly outperformed what was in Magma. Meanwhile, Magma uses that algorithm as well.

2011-11-23 11:29:21 +0100 answered a question Sage crashes when inverting a large matrix - alternatives?

Please provide a concrete example, perhaps by providing a link to a worksheet or so.

I just tried (using sage-4.7.2):

sage: MS = MatrixSpace(QQ, 50)
sage: A = MS.random_element()
sage: %time B = ~A
CPU times: user 0.23 s, sys: 0.00 s, total: 0.23 s
Wall time: 0.38 s

So, 50x50 over QQ really doesn't seem to be a challenge, and thus it would be interesting to know what you did exactly.

2011-10-28 10:24:59 +0100 received badge  Commentator
2011-10-28 10:24:59 +0100 commented answer perfomance: GAP code vs SAGE code

Ouch, I sometimes forget how clever Cython is. I knew that Cython doesn't loop if one has `for i in range(N): pass`, but I thought that the assignement `j=i` would prevent it!

2011-10-27 14:52:18 +0100 answered a question perfomance: GAP code vs SAGE code

My previous example exposed a case in which it is better to do low-level stuff inside Singular/GAP/Magma/... sub-processes.

I guess I also owe you an example that shows how much faster Python and Cython are. Consider an almost empty loop:

sage: singular.eval('int i')
'int i;'
sage: singular.eval('int j')
'int j;'
sage: def test1():
....:     singular.eval('for (i=1;i<=100000;i++){j=i;}')
....:     
sage: def test2():
....:     for i in range(1,100001):
....:         j = i
....:         
sage: def test3():
....:     for i in xrange(1,100001):
....:         j = i
....:         
sage: cython("""
....: def test4():
....:     cdef int i
....:     cdef int j
....:     for i from 1<=i<=100000:
....:         j = i
....: """)
sage: %timeit test1()
5 loops, best of 3: 445 ms per loop
sage: %timeit test2()
125 loops, best of 3: 4.74 ms per loop
sage: %timeit test3()
125 loops, best of 3: 3.27 ms per loop
sage: %timeit test4()
625 loops, best of 3: 126 ns per loop

You see, if such basic things are concerned, Python is much faster than Singular (I don't know how fast GAP is), and Cython much faster than Python.

2011-10-27 04:27:03 +0100 answered a question perfomance: GAP code vs SAGE code

Hi there!

Concerning "slowness of the interface": That ist a general problem for the pexpect-interfaces. The idea of these interfaces is that Sage pretends to be a user who is interactively working with a GAP/Singular/Magma/... session. So, Sage sends strings that GAP/Singular/Magma interpretes as commands; then Sage waits for the result; when they appear, the strings printed by GAP/Singular/Magma are transferred back to Sage and interpreted.

Of course, this has one big disadvantage: Communication with a sub-process by ascii strings and parsing of printed results has a huge overhead. Therefore, when using such pexpect interfaces, it is sometimes needed to do, for example, a loop in Singular, even though a loop in Sage (using Cython, at least) is much faster.

I give you some examples using the Singular pexpect interface:

sage: P.<x,y,z> = QQ[]
sage: sP = singular(P)
sage: M = singular.matrix(100,100,0)
sage: def test1(M):
....:     for i in range(1,101):
....:         for j in range(1,101):
....:             M[i,j] = singular(i)*singular(j)
....:
sage: def test2(M):
....:     for i in range(1,101):
....:         for j in range(1,101):
....:             M[i,j] = i*j
....:
sage: def test3(M):
....:     singular.eval('int i')
....:     singular.eval('int j')
....:     singular.eval('for (i=1;i<=100;i++){for (j=1;j<=100;j++){%s[i,j]=i*j;}}'%M.name())
....:

The three functions are equivalent:

sage: M = singular.matrix(100,100,0)
sage: test1(M)
sage: N = singular.matrix(100,100,0)
sage: test2(N)
sage: O = singular.matrix(100,100,0)
sage: test3(O)
sage: list(M)==list(N)==list(O)
True

However the running times are vastly different, since the first two functions use the interface very inefficiently:

sage: M = singular.matrix(100,100,0)
sage: %time test1(M)
CPU times: user 8.50 s, sys: 1.96 s, total: 10.46 s
Wall time: 10.57 s
sage: M = singular.matrix(100,100,0)
sage: %time test2(M)
CPU times: user 4.44 s, sys: 1.06 s, total: 5.50 s
Wall time: 5.65 s
sage: M = singular.matrix(100,100,0)
sage: %time test3(M)
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.14 s

The overhead of a pexpect interface can be completely avoided by using a C library instead. In the case of Singular, such library is available: libSingular. But, as Volker said, LibGAP is not totally ready, yet.

After stating so many negative things about pexpect, you might wonder why it exists. In fact, the pexpect approach has at least two advantages:

  • The same interface (after modifying certain details: "What is the prompt?", "How is equality tested?" and so on) can be used for interacting with any command line program. In particular, we can offer a pexpect interface to Magma and Maple, but it would be illegal to include them in Sage as C libraries
  • It gives you full access to all ...
(more)
2011-10-14 14:26:48 +0100 received badge  Nice Answer (source)
2011-10-14 02:56:31 +0100 answered a question pickling extension classes

Even when you had a Python class,

loads(dumps(a))==a
would not evaluate as true, because the objects loads(dumps(a)) is a new object, thus, id(loads(dumps(a))) will differ from id(a).

So, if one sees your problem as a Python/Cython problem, then there are two parts of your problem (which are mostly answered by the documentation of Python, by the way). If you work in Sage, some related tools are available, so that your problem has a third part.

The first part is comparison of objects. For that purpose, Python (and Cython) use methods such as __cmp__ and __richcmp__ (see Python docs). If they are not provided, comparison will simply compare id(...).

The second part is pickling/serialisation. Python offers different serialisation protocols (again: see Python docs).

If you have Python classes, you may use the first protocol, which relies on methods like __getstate__, __setstate__, __getinitargs__, __getnewargs__. But for extension classes you have to use the second protocol: You need to provide a __reduce__ method, returning a function f and arguments args to that function, so that f(*args) will return (a copy of) the original object.

Here is the third part of your problem: You work in Sage. You know that they say "we don't re-invent the wheel, we build the car". Thus, it makes sense to use Sage's infrastructure, rather than programming everything from scratch.

For example, when you want to create a class whose instances are "unique" (meaning: A loads(dumps(...)) copy of the instance will not only be equal but identical with the instance), you can simply inherit from sage.structure.unique_representation.UniqueRepresentation. In more complicated cases (or with Cython classes), you can also use sage.structure.factory.UniqueFactory, which does not seem to appear in the reference manual, but you can of course still browse its documentation in a Sage session.

If your intension is to implement algebraic structures, you are likely to derive your classes from sage.structure.element.Element or sage.structure.parent.Parent (or from existing sub-classes; also see this worksheet). In that case, you should look into the source code, near to the __cmp__ and __richcmp__ methods: You will find comments that explain what methods you should provide for comparison.

2011-09-19 06:32:08 +0100 received badge  Good Answer (source)
2011-09-06 22:10:43 +0100 received badge  Nice Answer (source)
2011-09-05 04:11:18 +0100 answered a question Learning Python for Sage

Even in Python 2.7, you could import the print function from the future Python:

sage: from __future__ import print_function
sage: print("stuff stuff", end = " ")
stuff stuff sage: print("stuff stuff", end = " \n@\n")
stuff stuff 
@
sage:
2011-08-24 03:10:20 +0100 commented answer Timing cached functions

If one uses the @cached_method decorator, then one can clear the cache: `a.my_great_cached_method.clear_cache()`. If one uses it in the commands that are passed to "timeit", one could avoid to measure the time spent for creating the matrix, hence, getting more accurate results.

2011-08-18 16:33:04 +0100 commented answer Can sage tweet?

That said, it seems that e-mailing does not work. Just for fun, I tried to send me an e-mail from Sage. There was a warning concerning the use of a deprecated module, and the e-mail has not arrived. Moreover, the doc string of the "email" function is broken (wrong formatting, that must look horrible in the reference manual).

2011-08-18 12:43:10 +0100 answered a question Can sage tweet?

Sage can send e-mails. Is twitter so much different?

2011-08-03 17:30:54 +0100 answered a question Knot Theory and Sage?

A long time ago, I created a Wiki with the purpose to collect (algebraic) topology software that could eventually become part of Sage (as an optional package, at least).

The wiki is here. However, it seems that nothing came out of it.

2011-07-14 04:22:15 +0100 received badge  Supporter (source)
2011-06-30 14:53:37 +0100 commented answer How to give latex names to generators of polynomial rings?

Yep, if you intend to use Gröbner bases then a (multivariate) polynomial ring is the right tool - symbolic variables do not offer much (or any?) functionality in that context.

2011-06-30 13:21:47 +0100 answered a question How to give latex names to generators of polynomial rings?

First of all, when you define a_ij=var('a_ij') then you define symbolic variables. But when you later do (with inject_on()) PolynomialRing(QQ,a_ij), then a_ij becomes a generator of a polynomial ring.

It is a very common mistake to confuse these two very different objects, and I recommend that you carefully decide whether you want to work with polynomials (i.e., you have a polynomial ring, ideals, want to compute Gröbner bases and those things) or with symbolic expressions (they may happen to look like a polynomial, but provide largely different features).

In particular, since a_ij has completely changed its meaning, it is no surprise that the latex name has gone.

You could do:

sage: R.<a_12,a_23> = QQ[]  # you don't need inject_on()
sage: type(a_12)  # It is not a symbolic variable!
<type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>
sage: latex(a_12)  # This is not how you like it
a_{12}
sage: R._latex_names  # This is where the names are stored
['a_{12}', 'a_{23}']
sage: R._latex_names = ['a_{1,2}','a_{2,3}'] # Override it...
sage: latex(a_12)  # ... and enjoy
a_{1,2}

I think it is a hack, and there should be a method, say, R.set_latex_names(), but unfortunately there isn't, yet.

2011-06-10 02:59:32 +0100 answered a question Can I use @parallel for class/instance methods?

Here are some ideas for making the @parallel decorator usable on methods.

I did not check the code. But usually, a decorator takes as its argument a function f. Now, it is easy to check whether f is a plain function or a method: Use ismethod() or ismethoddescriptor() from the inspect module.

On top of that, one may even think of making @parallel usable on wrapped methods, such as

@parallel
@cached_method
def my_method(self, L,**args):

In that case, the function put into the @parallel decorator would be an instance of a CachedMethodCaller. Those things could be tested with the function isclassinstance() from sage.misc.sageinspect. Perhaps that particular example does not make sense, but it may still be a case to be taken into account.

2011-06-06 18:21:25 +0100 commented answer How to change _latex_ of log to \ln ?

For the record: Meanwhile my preliminary patch is uploaded to the ticket.