Opened 8 years ago

# Create callable matrices in function notation

Reported by: Owned by: kcrisman burcin major sage-6.4 symbolics sd35.5 jason Geoffrey Ehrman N/A

In this sage-support post, the poster wants the following notation to work.

```R_theta(theta)=matrix(SR,[[cos(theta),sin(theta),0],[-sin(theta),cos(theta),0],[0,0,1]])
```

This is sort of #1722 on steroids.

In the thread above, there are a number of good ideas. The final one is

```I think this would be a good project for a person wanting to learn more
about how to do Sage development.  The modifications to
symbolic_expression should be easy (check for a nested list/tuple
structure).  Then you would need to make a new function() method, in
\$SAGE_ROOT/devel/sage/sage/matrix/matrix2.pyx probably, that would
create a corresponding matrix over the CallableSymbolicRing.  You can
see an example for vectors in
\$SAGE_ROOT/devel/sage/sage/modules/free_module.pyx (look for "def
function" in that file).
Then if you are ambitious, create a new matrix subclass for callable
symbolic expressions that mirrors what
\$SAGE_ROOT/devel/sage/sage/modules/vector_callable_symbolic_dense.py
does for vectors (i.e., changes the printing).
}}}[[Image()]]
```

### comment:1 Changed 8 years ago by jason

I think I would like this syntax instead:

```R_theta(theta)=[[cos(theta),sin(theta),0],[-sin(theta),cos(theta),0],[0,0,1]]
```

That's what the above development hint is geared towards.

### comment:2 Changed 8 years ago by kcrisman

Really? Without the word `matrix`? I guess that the preparser would in theory catch this as an error, but it seems a little bit of an overreach to me.

Could one then make a matrix `M` by doing one of

```M() = [[1,2],[2,3]]
M(1) = [[1,2],[2,3]]
M(x) = [[1,2],[2,3]]
```

and are any of those suspicious?

### comment:3 Changed 8 years ago by jason

Right now, these work to create vectors:

```M(x)=[1,2,x]
```

so I see the nested list as a natural extension of the syntax to matrices.

### comment:4 Changed 8 years ago by kcrisman

Nice, and then you are right that this is natural.

You mean

```V(x) = [1,2,x]
```

of course.

### comment:5 Changed 8 years ago by gbe

Little note: the definition of function() for vectors is located in modules/free_module_element.pyx rather than modules/free_module.pyx.

### comment:7 Changed 8 years ago by gbe

• Authors set to Geoffrey Ehrman
• Description modified (diff)

Progress thus far:

1. calculus/all.py is modified so that sage recognizes the creation of callable symbolic matrices via function notation. In particular:
```sage: m(X) = [[cos(X), -sin(X)],[sin(X), cos(X)]]
```

and is now valid syntax.

sage.matrix.matrix2.Matrix now has a method function() so the function notation syntax correctly returns a callable matrix. However, the method function() currently is creating a matrix of type Matrix_generic_dense; in analogy to the vector this this should probably be Matrix_callable_symbolic_dense. I'm unsure how significant an issue this is as most of the important things work. This certain does affect how these matrices are displayed - in all the following examples, the entries are of the form "X> f(X)" where what should probably be output is something like "X> [f(X), g(X)]\n[h(X), j(X)]".
1. Things that work correctly:
```sage: m(pi/2)
[ 0 -1]
[ 1  0]
sage: m.trace()
X |--> 2*cos(X)
sage: m(3).eigenvalues()
[-I*sin(3) + cos(3), I*sin(3) + cos(3)]
sage: m.derivative()
[X |--> -sin(X) X |--> -cos(X)]
[ X |--> cos(X) X |--> -sin(X)]
sage: m.kernel()
Vector space of degree 2 and dimension 0 over Callable function ring with arguments (X,)
Basis matrix:
[]
sage: m.image()
Vector space of degree 2 and dimension 2 over Callable function ring with arguments (X,)
Basis matrix:
[X |--> 1 X |--> 0]
[X |--> 0 X |--> 1]
```

Things that don't work (and should?):

```sage: m.eigenvalues()
NotImplementedError ...
```

Things that I'm not sure about/work incorrectly(?):

```sage: m.charpoly()
(X |--> 1)*x^2 + (X |--> -2*cos(X))*x + X |--> sin(X)^2 + cos(X)^2
sage: m.echelon_form()
[X |--> 1 X |--> 0]
[X |--> 0 X |--> 1]
```

What remains to do:

1. Matrix.function() is defined in sage/matrix/matrix2.pyx. It might be better placed in sage/matrix/matrix_generic_dense.pyx as the method for function() is defined only for FreeModuleElement_generic_dense. (Minor)
1. Matrix.function() is written as an exact analog to FreeModuleElement_generic_dense.function(). This is the cause of the problem I mentioned in (2). I think the root of the problem is that the vector case is being coerced to the correct class via the category framework and the matrix class is currently lacks the code needed to coerce correctly. It's also quite possible there's a better way to write this method. I've looked through some of the matrix and module code however, and I don't yet have any sensible ideas.
1. Generalizing from (2) I've tried to make function notation for matrices as similar to function notation for vectors as similar as possible. Is this sensible, or are there enough salient differences that this is unreasonable?
1. The file sage/matrix/matrix_callable_symbolic_dense.py purposely produces several doctest failures due again to the type issue in (2). Any other failures should be considered bugs.

### comment:8 Changed 8 years ago by gbe

• Status changed from new to needs_info

### comment:9 Changed 8 years ago by gbe

• Status changed from needs_info to needs_review

### comment:10 Changed 8 years ago by gbe

• Status changed from needs_review to needs_work

### comment:11 Changed 8 years ago by gbe

The typing issue was minor - it's handled by _get_matrix_class() in matrix_space.py. However, matrix_callable_symbolic_dense.py is may currently be unusable as written.

### Changed 8 years ago by gbe

Same content as trac_12298-v2.patch, just named correctly. Apply instead of trac_12075.patch

### comment:12 Changed 8 years ago by gbe

The current version is working correctly and is probably usable in most applications. That said, I'm leaving the status as needs works as there are a few more (mostly minor, I think) remaining things to do:

Remaining issues:

• Fix the doctests in matrix2.pyx and matrix_callable_symbolic_dense.pyx. I know v2 is has these two files failing doctests; it may be that other files are also failing as I have not yet run sage --testall.
• Partial evaluation does not return a callable matrix. See #12302 for more details, as this is the exact same issue and the fix should be (basically) the same - a modification to _ _call_ _() so the function recognizes partial evaluation.

• I'm leaving the definition of function() in matrix2.pyx unless someone with more experience withh the matrix module chimes in and says differently.
• While working with this bug I unearthed bug #12302. In addition to the fixes probably being nearly identical, 12302 may have implications for this patch since
```sage: m(x) = [[x,x],[0,x]]
sage: type(m)
<type 'sage.matrix.matrix_callable_symbolic_dense.Matrix_callable_symbolic_dense'>
sage: type(m)
<class 'sage.modules.vector_callable_symbolic_dense.Vector_callable_symbolic_dense'>
```

### comment:13 Changed 7 years ago by jason

Just pinging myself and others. This came up in http://ask.sagemath.org/question/2744/symbolic-function-from-rm-to-rn

### comment:14 Changed 6 years ago by jdemeyer

• Milestone changed from sage-5.11 to sage-5.12

### comment:15 Changed 6 years ago by vbraun_spam

• Milestone changed from sage-6.1 to sage-6.2

### comment:16 Changed 6 years ago by vbraun_spam

• Milestone changed from sage-6.2 to sage-6.3

### comment:17 Changed 5 years ago by vbraun_spam

• Milestone changed from sage-6.3 to sage-6.4

### comment:18 Changed 3 years ago by mforets

As of v7.6, the requirement in Description works:

```sage: R_theta(theta) = matrix(SR,[[cos(theta),sin(theta),0],[-sin(theta),cos(theta),0],[0,0,1]])
sage: R_theta

theta |--> [ cos(theta)  sin(theta)           0]
[-sin(theta)  cos(theta)           0]
[          0           0           1]
```

is this ticket obsolete or not?

However, there is a closely related use case which does fail:

```sage: theta = var('theta')
sage: R_theta(theta) = vector([cos(theta),sin(theta),0])
...
TypeError: unable to convert (cos(theta), sin(theta), 0) to a symbolic expression
```

This was asked in when i must use lambda.

I guess this is #11507.

### comment:19 Changed 3 years ago by mforets

if you happen to read this, note that as of v7.6 evaluation of a callable matrix in function notation does not work as expected:

```sage: var('x y')
(x, y)
sage: f(x) = sin(x)
sage: f(x+y)    # ok
sin(x + y)
sage: f(x) = matrix([[sin(x)],[cos(x)]])
sage: f(x+y)    # not ok

[sin(x)]
[cos(x)]
```

This was asked in functions of variables with matrices.