Ask Your Question
1

Can attributes of sage classes be changed?

asked 2020-10-13 19:37:51 +0100

more_weight gravatar image

I want to change the way vectors are rendered in sagetex. For example, consider v = vector([1, 2, 3]). In sagetex, the command $v=\sage{v}$ renders as $$ v=(1, 2, 3) $$ Instead, I want my vectors to take the form $$ v=\left[\begin{array}{rrr}1&2&3\end{array}\right]^\intercal $$ I thought I could do this by resetting the _latex_ method of the sage.modules.free_module_element.FreeModuleElement class as follows.

def my_vector_latex(self):
    return matrix(v)._latex_() + r'^\intercal'

setattr(sage.modules.free_module_element.FreeModuleElement, '_latex_', my_vector_latex)

However, this code throws the following error:

TypeError: can't set attributes of built-in/extension type 'sage.modules.free_module_element.FreeModuleElement'

So, it looks like I can't modify the methods of FreeModuleElement in this way. Is there anything else I could do?

edit retag flag offensive close merge delete

Comments

The problem is that FreeModuleElementis a Cython class, and attributes of those can't be modified, I believe. See https://cython.readthedocs.io/en/late....

John Palmieri gravatar imageJohn Palmieri ( 2020-10-14 05:15:03 +0100 )edit

Are there any workarounds?

more_weight gravatar imagemore_weight ( 2020-10-14 06:03:32 +0100 )edit

Cython classes can't be monkey-patched, indeed. ISTR to have tried that, unsuccessfully...

<handwaving>

You might try creating a subclass of the relevant base class (in your case sage.modules.vector_integer_dense.Vector_integer_dense), with updated latex-related methods.But that should be done for any vector class you wish to use...

</handwaving>

Or propose a patch allowing setting _latex_ attribute of vectors at run time, as it is done for var and function. But that could be (run time) costly...

Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2020-10-14 08:14:51 +0100 )edit

1 Answer

Sort by ยป oldest newest most voted
4

answered 2020-10-15 01:17:19 +0100

updated 2020-10-16 00:16:20 +0100

I haven't tried this in sagetex, but it works in a Sage session:

sage: v = vector([1,2,3])
sage: latex(v)
\left(1,\,2,\,3\right)

That's not what you want, so use latex.vector_delimiters to change the parentheses to what you want:

sage: latex.vector_delimiters("[", "]^{\\intercal}")
sage: latex(v)
\left[1,\,2,\,3\right]^{\intercal}

Edit: An alternative is to modify your sagetex.sty file: change the line

\newcommand{\sage}[1]{\ST@sage{latex(#1)}}

to

\newcommand{\sage}[1]{\ST@sage{my_print(#1)}}

Or maybe better, create an .sty file with this change, with a new name and use that instead of sagetex.sty.

Then the first thing in your LaTeX file (after "\begin{document}") should be

\begin{sagesilent}
def my_print(v):
    if isinstance(v, sage.modules.free_module_element.FreeModuleElement):
        return matrix(v)._latex_() + r'^\intercal'
    else:
        return latex(v)
\end{sagesilent}

Then you can customize the output for each class, however you want.

edit flag offensive delete link more

Comments

This isn't quite what I want. The commas are still there and the numbers are not inside an array.

more_weight gravatar imagemore_weight ( 2020-10-15 20:46:05 +0100 )edit
2

I added an alternative in the edit.

John Palmieri gravatar imageJohn Palmieri ( 2020-10-16 00:16:42 +0100 )edit

Really cool idea! Thanks!

more_weight gravatar imagemore_weight ( 2020-10-16 16:56:00 +0100 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2020-10-13 19:37:51 +0100

Seen: 396 times

Last updated: Oct 16 '20