Controlling NumPy __mul__ method or forcing it to use __rmul__ of the "other"

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Controlling NumPy __mul__ method or forcing it to use __rmul__ of the "other"

Ilhan Polat
I will assume some simple linear systems knowledge but the question can be generalized to any operator that implements __mul__ and __rmul__ methods.

Motivation:

I am trying to implement a gain matrix, say 3x3 identity matrix, for time being with a single input single output (SISO) system that I have implemented as a class modeling a Transfer or a state space representation.

In the typical usecase, suppose you would like to create an n-many parallel connections with the same LTI system sitting at each branch. MATLAB implements this as an elementwise multiplication and returning a multi input multi output(MIMO) system.

G = tf(1,[1,1]);
eye(3)*G

produces (manually compactified)

ans =
 
  From input 1 to output...
   [    1                          ]
   [  ------    ,   0   ,     0    ]
   [  s + 1                        ]
   [                 1             ]
   [  0        ,   ------ ,   0    ]
   [               s + 1           ]
   [                          1    ]
   [  0        ,   0    ,  ------  ]
   [                        s + 1  ]
 
Notice that the result type is of LTI system but, in our context, not a NumPy array with "object" dtype.

In order to achieve a similar behavior, I would like to let the __rmul__ of G take care of the multiplication. In fact, when I do G.__rmul__(np.eye(3)) I can control what the behavior should be and I receive the exception/result I've put in. However the array never looks for this method and carries out the default array __mul__ behavior.

The situation is similar if we go about it as left multiplication G*eye(3) has no problems since this uses directly the __mul__ of G. Therefore we get a different result depending on the direction of multiplication.

Is there anything I can do about this without forcing users subclassing or just letting them know about this particular quirk in the documentation?

What I have in mind is to force the users to create static LTI objects and then multiply and reject this possibility. But then I still need to stop NumPy returning "object" dtyped array to be able to let the user know about this.


Relevant links just in case

the library : https://github.com/ilayn/harold/

the issue discussion (monologue actually) : https://github.com/ilayn/harold/issues/7

The question I've asked on SO (but with a rather offtopic answer): https://stackoverflow.com/q/40694380/4950339


ilhan

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Controlling NumPy __mul__ method or forcing it to use __rmul__ of the "other"

Stephan Hoyer-2
I answered your question on StackOverflow:

In brief, you need to set __array_priority__ or __array_ufunc__ on your object.

On Mon, Jun 19, 2017 at 5:27 AM, Ilhan Polat <[hidden email]> wrote:
I will assume some simple linear systems knowledge but the question can be generalized to any operator that implements __mul__ and __rmul__ methods.

Motivation:

I am trying to implement a gain matrix, say 3x3 identity matrix, for time being with a single input single output (SISO) system that I have implemented as a class modeling a Transfer or a state space representation.

In the typical usecase, suppose you would like to create an n-many parallel connections with the same LTI system sitting at each branch. MATLAB implements this as an elementwise multiplication and returning a multi input multi output(MIMO) system.

G = tf(1,[1,1]);
eye(3)*G

produces (manually compactified)

ans =
 
  From input 1 to output...
   [    1                          ]
   [  ------    ,   0   ,     0    ]
   [  s + 1                        ]
   [                 1             ]
   [  0        ,   ------ ,   0    ]
   [               s + 1           ]
   [                          1    ]
   [  0        ,   0    ,  ------  ]
   [                        s + 1  ]
 
Notice that the result type is of LTI system but, in our context, not a NumPy array with "object" dtype.

In order to achieve a similar behavior, I would like to let the __rmul__ of G take care of the multiplication. In fact, when I do G.__rmul__(np.eye(3)) I can control what the behavior should be and I receive the exception/result I've put in. However the array never looks for this method and carries out the default array __mul__ behavior.

The situation is similar if we go about it as left multiplication G*eye(3) has no problems since this uses directly the __mul__ of G. Therefore we get a different result depending on the direction of multiplication.

Is there anything I can do about this without forcing users subclassing or just letting them know about this particular quirk in the documentation?

What I have in mind is to force the users to create static LTI objects and then multiply and reject this possibility. But then I still need to stop NumPy returning "object" dtyped array to be able to let the user know about this.


Relevant links just in case

the library : https://github.com/ilayn/harold/

the issue discussion (monologue actually) : https://github.com/ilayn/harold/issues/7

The question I've asked on SO (but with a rather offtopic answer): https://stackoverflow.com/q/40694380/4950339


ilhan

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Controlling NumPy __mul__ method or forcing it to use __rmul__ of the "other"

Ilhan Polat
Thank you. I didn't know that it existed. Is there any place where I can get a feeling for a sane priority number compared to what's being done in production? Just to make sure I'm not stepping on any toes.

On Mon, Jun 19, 2017 at 5:36 PM, Stephan Hoyer <[hidden email]> wrote:
I answered your question on StackOverflow:

In brief, you need to set __array_priority__ or __array_ufunc__ on your object.

On Mon, Jun 19, 2017 at 5:27 AM, Ilhan Polat <[hidden email]> wrote:
I will assume some simple linear systems knowledge but the question can be generalized to any operator that implements __mul__ and __rmul__ methods.

Motivation:

I am trying to implement a gain matrix, say 3x3 identity matrix, for time being with a single input single output (SISO) system that I have implemented as a class modeling a Transfer or a state space representation.

In the typical usecase, suppose you would like to create an n-many parallel connections with the same LTI system sitting at each branch. MATLAB implements this as an elementwise multiplication and returning a multi input multi output(MIMO) system.

G = tf(1,[1,1]);
eye(3)*G

produces (manually compactified)

ans =
 
  From input 1 to output...
   [    1                          ]
   [  ------    ,   0   ,     0    ]
   [  s + 1                        ]
   [                 1             ]
   [  0        ,   ------ ,   0    ]
   [               s + 1           ]
   [                          1    ]
   [  0        ,   0    ,  ------  ]
   [                        s + 1  ]
 
Notice that the result type is of LTI system but, in our context, not a NumPy array with "object" dtype.

In order to achieve a similar behavior, I would like to let the __rmul__ of G take care of the multiplication. In fact, when I do G.__rmul__(np.eye(3)) I can control what the behavior should be and I receive the exception/result I've put in. However the array never looks for this method and carries out the default array __mul__ behavior.

The situation is similar if we go about it as left multiplication G*eye(3) has no problems since this uses directly the __mul__ of G. Therefore we get a different result depending on the direction of multiplication.

Is there anything I can do about this without forcing users subclassing or just letting them know about this particular quirk in the documentation?

What I have in mind is to force the users to create static LTI objects and then multiply and reject this possibility. But then I still need to stop NumPy returning "object" dtyped array to be able to let the user know about this.


Relevant links just in case

the library : https://github.com/ilayn/harold/

the issue discussion (monologue actually) : https://github.com/ilayn/harold/issues/7

The question I've asked on SO (but with a rather offtopic answer): https://stackoverflow.com/q/40694380/4950339


ilhan

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Controlling NumPy __mul__ method or forcing it to use __rmul__ of the "other"

Nathan Goldbaum
I don't think there's any real standard here. Just doing a github search reveals many different choices people have used:


On Mon, Jun 19, 2017 at 11:07 AM, Ilhan Polat <[hidden email]> wrote:
Thank you. I didn't know that it existed. Is there any place where I can get a feeling for a sane priority number compared to what's being done in production? Just to make sure I'm not stepping on any toes.

On Mon, Jun 19, 2017 at 5:36 PM, Stephan Hoyer <[hidden email]> wrote:
I answered your question on StackOverflow:

In brief, you need to set __array_priority__ or __array_ufunc__ on your object.

On Mon, Jun 19, 2017 at 5:27 AM, Ilhan Polat <[hidden email]> wrote:
I will assume some simple linear systems knowledge but the question can be generalized to any operator that implements __mul__ and __rmul__ methods.

Motivation:

I am trying to implement a gain matrix, say 3x3 identity matrix, for time being with a single input single output (SISO) system that I have implemented as a class modeling a Transfer or a state space representation.

In the typical usecase, suppose you would like to create an n-many parallel connections with the same LTI system sitting at each branch. MATLAB implements this as an elementwise multiplication and returning a multi input multi output(MIMO) system.

G = tf(1,[1,1]);
eye(3)*G

produces (manually compactified)

ans =
 
  From input 1 to output...
   [    1                          ]
   [  ------    ,   0   ,     0    ]
   [  s + 1                        ]
   [                 1             ]
   [  0        ,   ------ ,   0    ]
   [               s + 1           ]
   [                          1    ]
   [  0        ,   0    ,  ------  ]
   [                        s + 1  ]
 
Notice that the result type is of LTI system but, in our context, not a NumPy array with "object" dtype.

In order to achieve a similar behavior, I would like to let the __rmul__ of G take care of the multiplication. In fact, when I do G.__rmul__(np.eye(3)) I can control what the behavior should be and I receive the exception/result I've put in. However the array never looks for this method and carries out the default array __mul__ behavior.

The situation is similar if we go about it as left multiplication G*eye(3) has no problems since this uses directly the __mul__ of G. Therefore we get a different result depending on the direction of multiplication.

Is there anything I can do about this without forcing users subclassing or just letting them know about this particular quirk in the documentation?

What I have in mind is to force the users to create static LTI objects and then multiply and reject this possibility. But then I still need to stop NumPy returning "object" dtyped array to be able to let the user know about this.


Relevant links just in case

the library : https://github.com/ilayn/harold/

the issue discussion (monologue actually) : https://github.com/ilayn/harold/issues/7

The question I've asked on SO (but with a rather offtopic answer): https://stackoverflow.com/q/40694380/4950339


ilhan

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Controlling NumPy __mul__ method or forcing it to use __rmul__ of the "other"

Stephan Hoyer-2
Coming up with a single number for a sane "array priority" is basically an impossible task :). If you only need compatibility with the latest version of NumPy, this is one good reason to set __array_ufunc__ instead, even if only to write __array_ufunc__ = None. 

On Mon, Jun 19, 2017 at 9:14 AM, Nathan Goldbaum <[hidden email]> wrote:
I don't think there's any real standard here. Just doing a github search reveals many different choices people have used:


On Mon, Jun 19, 2017 at 11:07 AM, Ilhan Polat <[hidden email]> wrote:
Thank you. I didn't know that it existed. Is there any place where I can get a feeling for a sane priority number compared to what's being done in production? Just to make sure I'm not stepping on any toes.

On Mon, Jun 19, 2017 at 5:36 PM, Stephan Hoyer <[hidden email]> wrote:
I answered your question on StackOverflow:

In brief, you need to set __array_priority__ or __array_ufunc__ on your object.

On Mon, Jun 19, 2017 at 5:27 AM, Ilhan Polat <[hidden email]> wrote:
I will assume some simple linear systems knowledge but the question can be generalized to any operator that implements __mul__ and __rmul__ methods.

Motivation:

I am trying to implement a gain matrix, say 3x3 identity matrix, for time being with a single input single output (SISO) system that I have implemented as a class modeling a Transfer or a state space representation.

In the typical usecase, suppose you would like to create an n-many parallel connections with the same LTI system sitting at each branch. MATLAB implements this as an elementwise multiplication and returning a multi input multi output(MIMO) system.

G = tf(1,[1,1]);
eye(3)*G

produces (manually compactified)

ans =
 
  From input 1 to output...
   [    1                          ]
   [  ------    ,   0   ,     0    ]
   [  s + 1                        ]
   [                 1             ]
   [  0        ,   ------ ,   0    ]
   [               s + 1           ]
   [                          1    ]
   [  0        ,   0    ,  ------  ]
   [                        s + 1  ]
 
Notice that the result type is of LTI system but, in our context, not a NumPy array with "object" dtype.

In order to achieve a similar behavior, I would like to let the __rmul__ of G take care of the multiplication. In fact, when I do G.__rmul__(np.eye(3)) I can control what the behavior should be and I receive the exception/result I've put in. However the array never looks for this method and carries out the default array __mul__ behavior.

The situation is similar if we go about it as left multiplication G*eye(3) has no problems since this uses directly the __mul__ of G. Therefore we get a different result depending on the direction of multiplication.

Is there anything I can do about this without forcing users subclassing or just letting them know about this particular quirk in the documentation?

What I have in mind is to force the users to create static LTI objects and then multiply and reject this possibility. But then I still need to stop NumPy returning "object" dtyped array to be able to let the user know about this.


Relevant links just in case

the library : https://github.com/ilayn/harold/

the issue discussion (monologue actually) : https://github.com/ilayn/harold/issues/7

The question I've asked on SO (but with a rather offtopic answer): https://stackoverflow.com/q/40694380/4950339


ilhan

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: Controlling NumPy __mul__ method or forcing it to use __rmul__ of the "other"

Ilhan Polat
Ah OK. I was just wondering if there are recommended values to start with in case below some values are reserved for NumPy/SciPy internals. I'll just go with the ufunc path just in case.

This really looks like TeX overful/underful badness value adjustment. As long as the journal accepts don't mention it. :)

On Mon, Jun 19, 2017 at 6:58 PM, Stephan Hoyer <[hidden email]> wrote:
Coming up with a single number for a sane "array priority" is basically an impossible task :). If you only need compatibility with the latest version of NumPy, this is one good reason to set __array_ufunc__ instead, even if only to write __array_ufunc__ = None. 

On Mon, Jun 19, 2017 at 9:14 AM, Nathan Goldbaum <[hidden email]> wrote:
I don't think there's any real standard here. Just doing a github search reveals many different choices people have used:


On Mon, Jun 19, 2017 at 11:07 AM, Ilhan Polat <[hidden email]> wrote:
Thank you. I didn't know that it existed. Is there any place where I can get a feeling for a sane priority number compared to what's being done in production? Just to make sure I'm not stepping on any toes.

On Mon, Jun 19, 2017 at 5:36 PM, Stephan Hoyer <[hidden email]> wrote:
I answered your question on StackOverflow:

In brief, you need to set __array_priority__ or __array_ufunc__ on your object.

On Mon, Jun 19, 2017 at 5:27 AM, Ilhan Polat <[hidden email]> wrote:
I will assume some simple linear systems knowledge but the question can be generalized to any operator that implements __mul__ and __rmul__ methods.

Motivation:

I am trying to implement a gain matrix, say 3x3 identity matrix, for time being with a single input single output (SISO) system that I have implemented as a class modeling a Transfer or a state space representation.

In the typical usecase, suppose you would like to create an n-many parallel connections with the same LTI system sitting at each branch. MATLAB implements this as an elementwise multiplication and returning a multi input multi output(MIMO) system.

G = tf(1,[1,1]);
eye(3)*G

produces (manually compactified)

ans =
 
  From input 1 to output...
   [    1                          ]
   [  ------    ,   0   ,     0    ]
   [  s + 1                        ]
   [                 1             ]
   [  0        ,   ------ ,   0    ]
   [               s + 1           ]
   [                          1    ]
   [  0        ,   0    ,  ------  ]
   [                        s + 1  ]
 
Notice that the result type is of LTI system but, in our context, not a NumPy array with "object" dtype.

In order to achieve a similar behavior, I would like to let the __rmul__ of G take care of the multiplication. In fact, when I do G.__rmul__(np.eye(3)) I can control what the behavior should be and I receive the exception/result I've put in. However the array never looks for this method and carries out the default array __mul__ behavior.

The situation is similar if we go about it as left multiplication G*eye(3) has no problems since this uses directly the __mul__ of G. Therefore we get a different result depending on the direction of multiplication.

Is there anything I can do about this without forcing users subclassing or just letting them know about this particular quirk in the documentation?

What I have in mind is to force the users to create static LTI objects and then multiply and reject this possibility. But then I still need to stop NumPy returning "object" dtyped array to be able to let the user know about this.


Relevant links just in case

the library : https://github.com/ilayn/harold/

the issue discussion (monologue actually) : https://github.com/ilayn/harold/issues/7

The question I've asked on SO (but with a rather offtopic answer): https://stackoverflow.com/q/40694380/4950339


ilhan

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion



_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/numpy-discussion