{"id":32,"date":"2015-04-15T05:46:00","date_gmt":"2015-04-15T05:46:00","guid":{"rendered":"https:\/\/sandrock.co.za\/carl\/2015\/04\/15\/numpy-matrices-work-for-general-objects\/"},"modified":"2015-04-15T05:46:00","modified_gmt":"2015-04-15T05:46:00","slug":"numpy-matrices-work-for-general-objects","status":"publish","type":"post","link":"https:\/\/sandrock.co.za\/carl\/2015\/04\/numpy-matrices-work-for-general-objects\/","title":{"rendered":"Numpy matrices work for general objects"},"content":{"rendered":"<p>A student was having difficulty using a class I had created to represent transfer function objects. I discovered that they were actually placing these objects in a <span style=\"font-family: Courier New, Courier, monospace\">numpy.matrix<\/span>&nbsp;and trying to multiply things by one another. To my surprise, this actually worked! I had to investigate. The code here is all in Python.<\/p>\n<p>I created a quick tracing object which just kind of logs the operations that are done on it as an expression:<\/p>\n<pre>class operation:\n&nbsp; &nbsp; def __init__(self, name):\n&nbsp; &nbsp; &nbsp; &nbsp; self.string = name\n&nbsp; &nbsp; def __repr__(self):\n&nbsp; &nbsp; &nbsp; &nbsp; return self.string\n&nbsp; &nbsp; def __str__(self):\n&nbsp; &nbsp; &nbsp; &nbsp; return self.string\n&nbsp; &nbsp; def __add__(self, other):\n&nbsp; &nbsp; &nbsp; &nbsp; return operation(\"({} + {})\".format(str(self), str(other)))\n&nbsp; &nbsp; def __mul__(self, other):\n&nbsp; &nbsp; &nbsp; &nbsp; return operation(\"{}*{}\".format(str(self), str(other)))\n&nbsp; &nbsp; def __radd__(self, other):\n&nbsp; &nbsp; &nbsp; &nbsp; return operation(\"({} + {})\".format(str(other), str(self)))\n&nbsp; &nbsp; def __rmul__(self, other):\n&nbsp; &nbsp; &nbsp; &nbsp; return operation(\"{}*{}\".format(str(other), str(self)))\n&nbsp; &nbsp; &nbsp; &nbsp;\n<\/pre>\n<div>\nNow I can do some interesting stuff:<\/div>\n<div>\n<\/div>\n<div>\n<pre>    In []: a*b\n    Out[]: a*b\n    In []: a + b\n    Out[]: (a + b)\n<\/pre>\n<div>\n<\/div>\n<div>\nOk, but what about matrix multiplication?<\/div>\n<div>\n<\/div>\n<pre>import numpy as np\nIn []: tracer = np.matrix([[a, b, c],\n[d, e, f],\n[g, h, i]])\n\nIn []: tracer*tracer\nOut[]:\nmatrix([[((a*a + b*d) + c*g), ((a*b + b*e) + c*h), ((a*c + b*f) + c*i)],\n&nbsp; &nbsp; &nbsp; &nbsp; [((d*a + e*d) + f*g), ((d*b + e*e) + f*h), ((d*c + e*f) + f*i)],\n&nbsp; &nbsp; &nbsp; &nbsp; [((g*a + h*d) + i*g), ((g*b + h*e) + i*h), ((g*c + h*f) + i*i)]], dtype=object)\n<\/pre>\n<div>\nThat kind of blew me away! It means I can probably get away with a whole lot less code than I thought I would need to implement my own matrix-like objects.<\/div>\n<div>\n<\/div>\n<div>\nIn addition, it appears that some numpy functions will attempt to call corresponding functions in the object they act on:<\/div>\n<div>\n<\/div>\n<div>\n<pre>    In []: np.exp(a)\n---------------------------------------------------------------------------\n\nAttributeError &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Traceback (most recent call last)\n in ()\n----&gt; 1 np.exp(a)\nAttributeError: exp\n<\/pre>\n<div>\nThis error shows that np.exp is trying to access the exp attribute on this object. Let&#8217;s extend our object with an exp method like this:<\/div>\n<div>\n<\/div>\n<div>\n<pre>&nbsp; &nbsp; def exp(self):\n&nbsp; &nbsp; &nbsp; &nbsp; return operation(\"e^({})\".format(self))\n<\/pre>\n<div>\nNow (after re-instantiating a-i from above), we have<\/div>\n<div>\n<pre>In []: np.exp(a)\nOut[]: e^(a)\n<\/pre>\n<\/div>\n<div>\n<\/div>\n<div>\nThis is going to be super useful.<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>A student was having difficulty using a class I had created to represent transfer function objects. I discovered that they were actually placing these objects in a numpy.matrix&nbsp;and trying to multiply things by one another. To my surprise, this actually worked! I had to investigate. The code here is all in Python. I created a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1],"tags":[],"class_list":["post-32","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/posts\/32","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/comments?post=32"}],"version-history":[{"count":0,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/posts\/32\/revisions"}],"wp:attachment":[{"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/media?parent=32"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/categories?post=32"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/tags?post=32"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}