{"id":2660,"date":"2018-01-30T10:18:15","date_gmt":"2018-01-30T15:18:15","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/?p=2660"},"modified":"2018-02-20T14:37:38","modified_gmt":"2018-02-20T19:37:38","slug":"get-smart-be-logical","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2018\/01\/30\/get-smart-be-logical\/","title":{"rendered":"Get Smart, Be Logical!"},"content":{"rendered":"<div class=\"content\"><!--introduction-->Recently a customer asked me an interesting question about a good way to compute something. Before I sat down to tackle it, I happened to mention the problem to my pal, <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495-sean-de-wolski\">Sean<\/a>. And he quickly answered, \"max logical\". It took me just a moment to realize what he was saying, and it is the answer to the problem. But when I heard it, I heard a person's name \"Max Logical\", and though I didn't know who that was, I immediately thought of Maxwell Smart, from the 60s tv comedy in the US, called \"Get Smart\".<!--\/introduction-->\r\n\r\n<img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2018\/DonAdams.jpg\" alt=\"\" hspace=\"5\" vspace=\"5\" \/>\r\n\r\nBy General Artists Corporation-GAC-management. [Public domain], via Wikimedia Commons\r\n\r\nAnd you can see the precursor to today's mobile phones!\r\n<h3>Contents<\/h3>\r\n<div>\r\n<ul>\r\n \t<li><a href=\"#2b232966-2f4b-4430-b86a-a602580f7fc6\">The Problem<\/a><\/li>\r\n \t<li><a href=\"#e9bd96ea-8047-4e0a-b458-b8c935148ef1\">The Solution<\/a><\/li>\r\n \t<li><a href=\"#8317f983-08bd-45a7-be6f-17809801f87c\">Higher Dimensions<\/a><\/li>\r\n \t<li><a href=\"#5d922a40-8ceb-42a7-953a-66ea634f669f\">Have You Embraced Logical Indexing?<\/a><\/li>\r\n<\/ul>\r\n<\/div>\r\n<h4>The Problem<a name=\"2b232966-2f4b-4430-b86a-a602580f7fc6\"><\/a><\/h4>\r\nSo what's the problem? The customer posed it by way of an example. Given a 3-D array A, generated for this example from a matrix, find the first plane in which some condition is true.\r\n<pre class=\"codeinput\">A=[1 2; 3 4]\r\nM = cat(3, A, A+1, A+2, A+3);\r\n<\/pre>\r\n<pre class=\"codeoutput\">A =\r\n     1     2\r\n     3     4\r\n<\/pre>\r\nSo the function should work like this:\r\n\r\n<tt>IDX = someFunction(M &gt;=5);<\/tt>\r\n<pre class=\"codeinput\">IDX = [NaN 4; 3 2]\r\n<\/pre>\r\n<pre class=\"codeoutput\">IDX =\r\n   NaN     4\r\n     3     2\r\n<\/pre>\r\n<i>And<\/i>, the customer wanted this to work for arrays of higher dimensions as well.\r\n<h4>The Solution<a name=\"e9bd96ea-8047-4e0a-b458-b8c935148ef1\"><\/a><\/h4>\r\nAs I said, I mentioned this to Sean. But I had thought for about 2 seconds about it before and I realized I could do a <tt><a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/find.html\">find<\/a><\/tt> on the entire array, as if it were a vector, get the locations and sort them into their proper locations and find the first one in the correct last dimension. And then Sean said \"Max Logical\". Here's what a great solution looks like.\r\n<pre class=\"codeinput\">catdim = 3;\r\nszA = size(A);\r\n[mv,midx] = max(M &gt;= 5,[],catdim);\r\nIDX = NaN(szA);\r\nIDX(mv) = midx(mv)\r\n<\/pre>\r\n<pre class=\"codeoutput\">IDX =\r\n   NaN     4\r\n     3     2\r\n<\/pre>\r\nWhy\/how did this work? Well, I use the condition I want met into function <tt>max<\/tt>, and it is logical input, meaning only 0s and 1s. And <tt>max<\/tt> returns the index where the first condition is met, and I do this along the final dimension. Then create an array of <tt><a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/nan.html\">NaN<\/a><\/tt> values, and use logical indexing to update this index matrix. Voila!\r\n<h4>Higher Dimensions<a name=\"8317f983-08bd-45a7-be6f-17809801f87c\"><\/a><\/h4>\r\nNow let's see if it makes sense in higher dimensions. For simplicity, I again will provide a base array in 1 dimension less than I am ultimately looking, so I can construct something for which I can reasonably easily check the result.\r\n<pre class=\"codeinput\">A = randi(17, [3 2 1 3]);\r\ncatdim = ndims(A)+1\r\nM = cat(catdim, A, A+1, A+2, A+3, A+4);\r\n<\/pre>\r\n<pre class=\"codeoutput\">catdim =\r\n     5\r\n<\/pre>\r\nSee a slice of M\r\n<pre class=\"codeinput\">sliceOfM = M(:,:,:,1)\r\n<\/pre>\r\n<pre class=\"codeoutput\">sliceOfM =\r\n    12     2\r\n    13     4\r\n     8    16\r\n<\/pre>\r\nApply the <tt>max<\/tt>, logical indexing to <tt>M<\/tt> next.\r\n<pre class=\"codeinput\">szA = size(A)\r\n[mv,midx] = max(M &gt;= 13,[],catdim);\r\nIDX = NaN(szA);\r\nIDX(mv) = midx(mv)\r\n<\/pre>\r\n<pre class=\"codeoutput\">szA =\r\n     3     2     1     3\r\nIDX(:,:,1,1) =\r\n     2   NaN\r\n     1   NaN\r\n   NaN     1\r\nIDX(:,:,1,2) =\r\n   NaN     1\r\n     1   NaN\r\n     4   NaN\r\nIDX(:,:,1,3) =\r\n   NaN     1\r\n     1     1\r\n   NaN     1\r\n<\/pre>\r\n<h4>Have You Embraced Logical Indexing?<a name=\"5d922a40-8ceb-42a7-953a-66ea634f669f\"><\/a><\/h4>\r\nI have made several posts over the years on <a href=\"https:\/\/blogs.mathworks.com\/loren\/category\/indexing\/?s_tid=Blog_loren_Category\">indexing<\/a> that readers have found helpful. Do you have any interesting logical stories to share? Post them <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=2660#respond\">here<\/a>.\r\n\r\n<script language=\"JavaScript\"> <!-- \r\n    function grabCode_16207e00f0d04b3ca52c82beca38dc5c() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='16207e00f0d04b3ca52c82beca38dc5c ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 16207e00f0d04b3ca52c82beca38dc5c';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2018 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<\/p>\r\n<p>\r\n<\/p>\r\n<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\r\n<p>\r\n<\/p>\r\n<p>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script>\r\n<p style=\"text-align: right; font-size: xx-small; font-weight: lighter; font-style: italic; color: gray;\"><a><span style=\"font-size: x-small; font-style: italic;\">Get\r\nthe MATLAB code<noscript>(requires JavaScript)<\/noscript><\/span><\/a><\/p>\r\nPublished with MATLAB\u00ae R2017b\r\n\r\n<\/div>\r\n<!--\r\n16207e00f0d04b3ca52c82beca38dc5c ##### SOURCE BEGIN #####\r\n%% Get Smart, Be Logical!\r\n% Recently a customer asked me an interesting question about a good way to\r\n% compute something.  Before I sat down to tackle it, I happened to mention\r\n% the problem to my pal,\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495-sean-de-wolski % Sean>.  And he quickly answered, \"max logical\".  It took me just a moment\r\n% to realize what he was saying, and it is the answer to the problem.  But\r\n% when I heard it, I heard a person's name \"Max Logical\", and though I\r\n% didn't know who that was, I immediately thought of Maxwell Smart, from\r\n% the 60s tv comedy in the US, called \"Get Smart\".\r\n%\r\n% <<DonAdams.jpg>>\r\n%\r\n% By General Artists Corporation-GAC-management. [Public domain], via\r\n% Wikimedia Commons\r\n%\r\n%\r\n%\r\n% And you can see the precursor to today's mobile phones!\r\n%% The Problem\r\n% So what's the problem?  The customer posed it by way of an example. Given\r\n% a 3-D array A, generated for this example from a matrix, find the first\r\n% plane in which some condition is true.\r\n%%\r\nA=[1 2; 3 4]\r\nM = cat(3, A, A+1, A+2, A+3);\r\n%%\r\n% So the function should work like this:\r\n%\r\n% |IDX = someFunction(M >=5);|\r\n%\r\nIDX = [NaN 4; 3 2]\r\n\r\n%%\r\n% _And_, the customer wanted this to work for arrays of higher dimensions\r\n% as well.\r\n%% The Solution\r\n% As I said, I mentioned this to Sean.  But I had thought for about 2\r\n% seconds about it before and I realized I could do a\r\n% |<https:\/\/www.mathworks.com\/help\/matlab\/ref\/find.html find>| on the entire\r\n% array, as if it were a vector, get the locations and sort them into their\r\n% proper locations and find the first one in the correct last dimension.\r\n% And then Sean said \"Max Logical\".  Here's what a great solution looks\r\n% like.\r\n%%\r\ncatdim = 3;\r\nszA = size(A);\r\n[mv,midx] = max(M >= 5,[],catdim);\r\nIDX = NaN(szA);\r\nIDX(mv) = midx(mv)\r\n%%\r\n% Why\/how did this work?  Well, I use the condition I want met into\r\n% function |max|, and it is logical input, meaning only 0s and 1s.  And\r\n% |max| returns the index where the first condition is met, and I do this\r\n% along the final dimension. Then create an array of\r\n% |<https:\/\/www.mathworks.com\/help\/matlab\/ref\/nan.html NaN>| values, and\r\n% use logical indexing to update this index matrix.  Voila!\r\n%% Higher Dimensions\r\n% Now let's see if it makes sense in higher dimensions.  For simplicity, I\r\n% again will provide a base array in 1 dimension less than I am ultimately\r\n% looking, so I can construct something for which I can reasonably easily\r\n% check the result.\r\n%%\r\nA = randi(17, [3 2 1 3]);\r\ncatdim = ndims(A)+1\r\nM = cat(catdim, A, A+1, A+2, A+3, A+4);\r\n%%\r\n% See a slice of M\r\nsliceOfM = M(:,:,:,1)\r\n%%\r\n% Apply the |max|, logical indexing to |M| next.\r\nszA = size(A)\r\n[mv,midx] = max(M >= 13,[],catdim);\r\nIDX = NaN(szA);\r\nIDX(mv) = midx(mv)\r\n%% Have You Embraced Logical Indexing?\r\n% I have made several posts over the years on\r\n% <https:\/\/blogs.mathworks.com\/loren\/category\/indexing\/?s_tid=Blog_loren_Category % indexing> that readers have found helpful.  Do you have any interesting\r\n% logical stories to share?  Post them\r\n% <https:\/\/blogs.mathworks.com\/loren\/?p=2660#respond here>.\r\n##### SOURCE END ##### 16207e00f0d04b3ca52c82beca38dc5c\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2018\/DonAdams.jpg\" onError=\"this.style.display ='none';\" \/><\/div><!--introduction-->Recently a customer asked me an interesting question about a good way to compute something. Before I sat down to tackle it, I happened to mention the problem to my pal, <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495-sean-de-wolski\">Sean<\/a>. And he quickly answered, \"max logical\". It took me just a moment to realize what he was saying, and it is the answer to the problem. But when I heard it, I heard a person's name \"Max Logical\", and though I didn't know who that was, I immediately thought of Maxwell Smart, from the 60s tv comedy in the US, called \"Get Smart\".<!--\/introduction-->... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2018\/01\/30\/get-smart-be-logical\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/2660"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/comments?post=2660"}],"version-history":[{"count":11,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/2660\/revisions"}],"predecessor-version":[{"id":2714,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/2660\/revisions\/2714"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=2660"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=2660"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=2660"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}