{"id":1760,"date":"2016-07-20T08:32:41","date_gmt":"2016-07-20T13:32:41","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/?p=1760"},"modified":"2016-07-20T15:39:01","modified_gmt":"2016-07-20T20:39:01","slug":"matlab-is-satisfying","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2016\/07\/20\/matlab-is-satisfying\/","title":{"rendered":"MATLAB is Satisfying"},"content":{"rendered":"<div class=\"content\"><!--introduction--><p><i>Today's guest post comes from <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495\">Sean de Wolski<\/a>, one of Loren's fellow Application Engineers.  You might recognize him from <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/answers\/\">MATLAB answers<\/a> and the <a href=\"https:\/\/blogs.mathworks.com\/pick\/\">pick of the week<\/a> blog!<\/i><\/p><!--\/introduction--><h3>Contents<\/h3><div><ul><li><a href=\"#047805bc-141e-44a8-98ca-f9eef0e8346d\">Set Up<\/a><\/li><li><a href=\"#102a091b-1509-4c44-8c2c-12f8be266472\">Bounds and Integer Constraints<\/a><\/li><li><a href=\"#3db64582-367e-43a2-9181-a62c5dbd6584\">Equality Constraints<\/a><\/li><li><a href=\"#5a52c355-78b2-4168-933b-5f34494fda6b\">Row and Column<\/a><\/li><li><a href=\"#45960e20-b47f-4595-a8a0-5b4e4b26f8cd\">Diagonal and Antidiagonal<\/a><\/li><li><a href=\"#c6583354-76ea-4fe4-afe7-6c1e9aac21ac\">Solve!<\/a><\/li><li><a href=\"#a20f4cca-0553-4460-9ea5-4dbfbce1afa0\">View the Result<\/a><\/li><\/ul><\/div><p>I manned the MathWorks booth one of the days last week at the <a href=\"http:\/\/www.siam.org\/meetings\/an16\/\">annual SIAM conference<\/a> in Boston MA. The keynote speaker that day was <a href=\"https:\/\/en.wikipedia.org\/wiki\/Donald_Knuth\">Donald Knuth<\/a> who was there to discuss <a href=\"https:\/\/en.wikipedia.org\/wiki\/Boolean_satisfiability_problem\">satisfiability<\/a> and the latest chapter of his book, <a href=\"http:\/\/www-cs-faculty.stanford.edu\/~knuth\/taocp.html\"><i>\"The Art of Computer Programming\"<\/i><\/a>.<\/p><p>At the beginning of the session, he provided a satisfiability puzzle, similar to a Sudoku puzzle, for those in the audience to do.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2016\/puzzle.png\" alt=\"\"> <\/p><p>I figured, why not solve it with MATLAB?<\/p><p><b>NOTE<\/b> If you would like to solve the puzzle by hand don't scroll down!<\/p><h4>Set Up<a name=\"047805bc-141e-44a8-98ca-f9eef0e8346d\"><\/a><\/h4><p>First, let's define some useful information about the sizes.  By making these variables, and parameterizing everything else this approach will scale to similar puzzles of any size!<\/p><pre class=\"codeinput\">m = 7; <span class=\"comment\">% rows<\/span>\r\nn = 21; <span class=\"comment\">% columns<\/span>\r\nnv = m*n; <span class=\"comment\">% number of elements<\/span>\r\n<\/pre><h4>Bounds and Integer Constraints<a name=\"102a091b-1509-4c44-8c2c-12f8be266472\"><\/a><\/h4><p>We will solve this as a binary integer programming problem using <a href=\"https:\/\/www.mathworks.com\/help\/optim\/ug\/intlinprog.html\"><tt>intlinprog<\/tt><\/a>.  The variables names used will be the same from the documentation.  Each square will have a value of one or zero.  Since the solver expects to work for a column vector, we will be turning the matrix into a vector columnwise, the equivalent of <tt>m(:)<\/tt>.<\/p><p>Lower and upper bounds.<\/p><pre class=\"codeinput\">lb = zeros(1,nv);\r\nub = ones(1,nv);\r\n<\/pre><p>All variables are binary and therefore integer constrained.<\/p><pre class=\"codeinput\">intcon = 1:nv;\r\n<\/pre><p>This is a feasibility problem so <i>f<\/i> can be anything.<\/p><pre class=\"codeinput\">f = zeros(nv,1);\r\n<\/pre><h4>Equality Constraints<a name=\"3db64582-367e-43a2-9181-a62c5dbd6584\"><\/a><\/h4><p>The equality constraints are the hardest part.  We need to ensure that each column, row, diagonal, and anti-diagonal sum to the number shown.<\/p><p>The sum of each dimension, given to us by the puzzle, is the <i>beq<\/i> constraint.<\/p><p>The <i>Aeq<\/i> coefficient constraint will be a binary matrix with a specific sparsity pattern.<\/p><h4>Row and Column<a name=\"5a52c355-78b2-4168-933b-5f34494fda6b\"><\/a><\/h4><p>For the row and column coefficient matrix, <i>Aeq<\/i>, we need to replicate an identity matrix the size of the other dimension by block for rows and by element for columns.  It will be replicated <i>x<\/i> times, where <i>x<\/i> is the size of the dimension.<\/p><pre class=\"codeinput\">Aeqrows = repmat(eye(m),1,n);\r\nbeqrows = [19;7;12;6;13;0;1];\r\n\r\nAeqcols = repelem(eye(n),1,m);\r\nbeqcols = [1 1 1 5 1 5 1 5 1 1 5 3 3 3 1 6 1 4 3 3 4]';\r\n<\/pre><p>View the sparsity pattern of the constraints and what they sum to.<\/p><pre class=\"codeinput\">subplot(1,10,1:4)\r\nimagesc(Aeqcols)\r\nxlabel(<span class=\"string\">'Column Coefficients'<\/span>)\r\ntitle(<span class=\"string\">'Column equality constraints'<\/span>)\r\nsubplot(1,10,5)\r\nimagesc(beqcols)\r\nxlabel(<span class=\"string\">'Column Sum'<\/span>)\r\n\r\nsubplot(1,10,6:9)\r\nimagesc(Aeqrows)\r\nxlabel(<span class=\"string\">'Row Coefficients'<\/span>)\r\ntitle(<span class=\"string\">'Row equality constraints'<\/span>)\r\nsubplot(1,10,10)\r\nimagesc(beqrows)\r\nxlabel(<span class=\"string\">'Row sum'<\/span>)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2016\/SIAM2016_01.png\" alt=\"\"> <h4>Diagonal and Antidiagonal<a name=\"45960e20-b47f-4595-a8a0-5b4e4b26f8cd\"><\/a><\/h4><p>We will use the same algorithm for the diagonal and antidiagonal pieces.<\/p><p>The <i>beq<\/i> matrices will be the sums, starting on the left.<\/p><p>The <i>Aeq<\/i> matrices will be built using <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/diag.html\"><tt>diag<\/tt><\/a> to extract diagonals from matrix of linear indices.  This means each value in the matrix <i>idx<\/i> will be it's <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/ind2sub.html\">linear index<\/a>.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2016\/linidx.png\" alt=\"\"> <\/p><p>For the antidiagonals, we'll just flip <i>beq<\/i> and <i>idx<\/i> but use the same approach.<\/p><p>A <tt>for<\/tt>-loop will then traverse every diagonal, and turn the corresponding indices in the <i>Aeq<\/i> coefficient matrices to true.<\/p><pre class=\"codeinput\">Aeqdiag = zeros(m+n-1,nv);\r\nAeqantidiag = Aeqdiag;\r\nbeqdiag = [0 0 0 0 0 1 3 3 4 3 2 2 2 3 3 4 2 3 3 3 3 3 4 3 2 1 1].';\r\nbeqantidiag = flip([1 1 1 1 1 2 2 3 4 3 3 3 2 3 4 3 3 2 3 3 2 3 2 2 1 0 0]).';\r\n\r\nidx = reshape(1:nv,m,n);\r\nantidx = flip(idx,2);\r\n<span class=\"keyword\">for<\/span> ii = -(m-1):n-1\r\n    Aeqdiag(ii+m,diag(idx,ii)) = 1;\r\n    Aeqantidiag(ii+m,diag(antidx,ii)) = 1;\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p>View the sparsity pattern of the constraints and what they sum to.<\/p><pre class=\"codeinput\">subplot(1,10,1:4)\r\nimagesc(Aeqdiag)\r\nxlabel(<span class=\"string\">'Diag Coeff'<\/span>)\r\ntitle(<span class=\"string\">'Diagonal equality constraints'<\/span>)\r\nsubplot(1,10,5)\r\nimagesc(beqdiag)\r\nxlabel(<span class=\"string\">'Diag Sum'<\/span>)\r\n\r\nsubplot(1,10,6:9)\r\nimagesc(Aeqantidiag)\r\nxlabel(<span class=\"string\">'Antidiag Coeff'<\/span>)\r\ntitle(<span class=\"string\">'Antidiagonal equality constraints'<\/span>)\r\nsubplot(1,10,10)\r\nimagesc(beqantidiag)\r\nxlabel(<span class=\"string\">'Antidiag Sum'<\/span>)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2016\/SIAM2016_02.png\" alt=\"\"> <p>The equality constraints we've built are all independent from one another, we just need to concatenate them together in an arbitrary order to build the full equality constraints.<\/p><pre class=\"codeinput\">Aeq = [Aeqrows;Aeqcols;Aeqdiag;Aeqantidiag];\r\nbeq = [beqrows;beqcols;beqdiag;beqantidiag];\r\n<\/pre><p>View.<\/p><pre class=\"codeinput\">figure\r\nsubplot(1,5,1:4)\r\nimagesc(Aeq)\r\nxlabel(<span class=\"string\">'Aeq'<\/span>)\r\ntitle(<span class=\"string\">'Column equality constraints'<\/span>)\r\nsubplot(1,5,5)\r\nimagesc(beq)\r\nxlabel(<span class=\"string\">'beq'<\/span>)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2016\/SIAM2016_03.png\" alt=\"\"> <h4>Solve!<a name=\"c6583354-76ea-4fe4-afe7-6c1e9aac21ac\"><\/a><\/h4><p>Call the <tt>intlinprog<\/tt> solver.<\/p><pre class=\"codeinput\">x = intlinprog(f,intcon,[],[],Aeq,beq,lb,ub);\r\n<\/pre><pre class=\"codeoutput\">LP:                Optimal objective value is 0.000000.                                             \r\n\r\n\r\nOptimal solution found.\r\n\r\nIntlinprog stopped at the root node because the objective value is within a gap\r\ntolerance of the optimal value, options.AbsoluteGapTolerance = 0 (the default\r\nvalue). The intcon variables are integer within tolerance,\r\noptions.IntegerTolerance = 1e-05 (the default value).\r\n\r\n<\/pre><h4>View the Result<a name=\"a20f4cca-0553-4460-9ea5-4dbfbce1afa0\"><\/a><\/h4><p><i>x<\/i> is a vector,so we'll need to undo the <tt>m(:)<\/tt> operation from above to reshape it to be the grid size before viewing.<\/p><pre class=\"codeinput\">xi = reshape(x,m,n);\r\n\r\nfigure\r\nimagesc(xi)\r\naxis <span class=\"string\">tight<\/span> <span class=\"string\">equal<\/span> <span class=\"string\">off<\/span>\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2016\/SIAM2016_04.png\" alt=\"\"> <p>Ahh, I see what's going on.  Let's make it prettier.<\/p><pre class=\"codeinput\">s = surf([rot90(xi,2); zeros(1,n)]);\r\nview(0, -90)\r\naxis <span class=\"string\">tight<\/span> <span class=\"string\">equal<\/span> <span class=\"string\">off<\/span>\r\ns.EdgeColor = [0.8 0.8 0.8];\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2016\/SIAM2016_05.png\" alt=\"\"> <p>Any comments?  Let us know <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=1760#respond\">here<\/a>.<\/p><p>And just for completeness, <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/4781185\">Christine Tobler<\/a>, who was sitting next to me did solve it first by hand.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/loren\/2016\/puzzlechristine.png\" alt=\"\"> <\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_24c76efe6ea14766a9fb2c525ab4dfe1() {\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='24c76efe6ea14766a9fb2c525ab4dfe1 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 24c76efe6ea14766a9fb2c525ab4dfe1';\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 2016 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<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>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_24c76efe6ea14766a9fb2c525ab4dfe1()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2016a<br><\/p><\/div><!--\r\n24c76efe6ea14766a9fb2c525ab4dfe1 ##### SOURCE BEGIN #####\r\n%% MATLAB is Satisfying\r\n% _Today's guest post comes from\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495 Sean de\r\n% Wolski>, one of Loren's fellow Application Engineers.  You might\r\n% recognize him from <https:\/\/www.mathworks.com\/matlabcentral\/answers\/ MATLAB\r\n% answers> and the <https:\/\/blogs.mathworks.com\/pick\/ pick of the week>\r\n% blog!_\r\n%%\r\n% I manned the MathWorks booth one of the days last week at the\r\n% <http:\/\/www.siam.org\/meetings\/an16\/ annual SIAM conference> in Boston MA.\r\n% The keynote speaker that day was\r\n% <https:\/\/en.wikipedia.org\/wiki\/Donald_Knuth Donald Knuth> who was there\r\n% to discuss <https:\/\/en.wikipedia.org\/wiki\/Boolean_satisfiability_problem\r\n% satisfiability> and the latest chapter of his book,\r\n% <http:\/\/www-cs-faculty.stanford.edu\/~knuth\/taocp.html _\"The Art of\r\n% Computer Programming\"_>.\r\n%\r\n% At the beginning of the session, he provided a satisfiability puzzle,\r\n% similar to a Sudoku puzzle, for those in the audience to do. \r\n%\r\n% <<puzzle.png>>\r\n%\r\n% I figured, why not solve it with MATLAB?\r\n%\r\n% *NOTE* If you would like to solve the puzzle by hand don't scroll down!\r\n\r\n%% Set Up\r\n% First, let's define some useful information about the sizes.  By making\r\n% these variables, and parameterizing everything else this approach will\r\n% scale to similar puzzles of any size!\r\nm = 7; % rows\r\nn = 21; % columns\r\nnv = m*n; % number of elements\r\n\r\n%% Bounds and Integer Constraints\r\n% We will solve this as a binary integer programming problem using\r\n% <https:\/\/www.mathworks.com\/help\/optim\/ug\/intlinprog.html |intlinprog|>.  The variables names used will be the same from the\r\n% documentation.  Each square will have a value of one or zero.  Since the\r\n% solver expects to work for a column vector, we will be turning the matrix\r\n% into a vector columnwise, the equivalent of |m(:)|.\r\n%\r\n% Lower and upper bounds.\r\nlb = zeros(1,nv);\r\nub = ones(1,nv);\r\n\r\n%%\r\n% All variables are binary and therefore integer constrained.\r\nintcon = 1:nv;\r\n\r\n%%\r\n% This is a feasibility problem so _f_ can be anything.\r\nf = zeros(nv,1);\r\n\r\n%% Equality Constraints\r\n% The equality constraints are the hardest part.  We need to ensure that\r\n% each column, row, diagonal, and anti-diagonal sum to the number shown.\r\n% \r\n% The sum of each dimension, given to us by the puzzle, is the _beq_\r\n% constraint.\r\n%\r\n% The _Aeq_ coefficient constraint will be a binary matrix with a specific sparsity pattern.\r\n\r\n%% Row and Column\r\n% For the row and column coefficient matrix, _Aeq_, we need to replicate an\r\n% identity matrix the size of the other dimension by block for rows and by\r\n% element for columns.  It will be replicated _x_ times, where _x_ is the size\r\n% of the dimension.\r\nAeqrows = repmat(eye(m),1,n);\r\nbeqrows = [19;7;12;6;13;0;1];\r\n\r\nAeqcols = repelem(eye(n),1,m);\r\nbeqcols = [1 1 1 5 1 5 1 5 1 1 5 3 3 3 1 6 1 4 3 3 4]';\r\n\r\n%%\r\n% View the sparsity pattern of the constraints and what they sum to.\r\nsubplot(1,10,1:4)\r\nimagesc(Aeqcols)\r\nxlabel('Column Coefficients')\r\ntitle('Column equality constraints')\r\nsubplot(1,10,5)\r\nimagesc(beqcols)\r\nxlabel('Column Sum')\r\n\r\nsubplot(1,10,6:9)\r\nimagesc(Aeqrows)\r\nxlabel('Row Coefficients')\r\ntitle('Row equality constraints')\r\nsubplot(1,10,10)\r\nimagesc(beqrows)\r\nxlabel('Row sum')\r\n\r\n%% Diagonal and Antidiagonal\r\n% We will use the same algorithm for the diagonal and antidiagonal pieces.\r\n% \r\n% The _beq_ matrices will be the sums, starting on the left.\r\n%\r\n% The _Aeq_ matrices will be built using\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/diag.html |diag|> to extract\r\n% diagonals from matrix of linear indices.  This means each value in the\r\n% matrix _idx_ will be it's <https:\/\/www.mathworks.com\/help\/matlab\/ref\/ind2sub.html linear index>.\r\n%\r\n% <<linidx.png>>\r\n%\r\n% For the antidiagonals, we'll just flip _beq_ and\r\n% _idx_ but use the same approach.\r\n%\r\n% A |for|-loop will then traverse every diagonal, and turn the\r\n% corresponding indices in the _Aeq_ coefficient matrices to true.\r\n\r\nAeqdiag = zeros(m+n-1,nv);\r\nAeqantidiag = Aeqdiag;\r\nbeqdiag = [0 0 0 0 0 1 3 3 4 3 2 2 2 3 3 4 2 3 3 3 3 3 4 3 2 1 1].';\r\nbeqantidiag = flip([1 1 1 1 1 2 2 3 4 3 3 3 2 3 4 3 3 2 3 3 2 3 2 2 1 0 0]).';\r\n\r\nidx = reshape(1:nv,m,n);\r\nantidx = flip(idx,2);\r\nfor ii = -(m-1):n-1\r\n    Aeqdiag(ii+m,diag(idx,ii)) = 1;        \r\n    Aeqantidiag(ii+m,diag(antidx,ii)) = 1;\r\nend\r\n\r\n%%\r\n% View the sparsity pattern of the constraints and what they sum to.\r\nsubplot(1,10,1:4)\r\nimagesc(Aeqdiag)\r\nxlabel('Diag Coeff')\r\ntitle('Diagonal equality constraints')\r\nsubplot(1,10,5)\r\nimagesc(beqdiag)\r\nxlabel('Diag Sum')\r\n\r\nsubplot(1,10,6:9)\r\nimagesc(Aeqantidiag)\r\nxlabel('Antidiag Coeff')\r\ntitle('Antidiagonal equality constraints')\r\nsubplot(1,10,10)\r\nimagesc(beqantidiag)\r\nxlabel('Antidiag Sum')\r\n\r\n%% \r\n% The equality constraints we've built are all independent from one\r\n% another, we just need to concatenate them together in an arbitrary order\r\n% to build the full equality constraints.\r\n\r\nAeq = [Aeqrows;Aeqcols;Aeqdiag;Aeqantidiag];\r\nbeq = [beqrows;beqcols;beqdiag;beqantidiag];\r\n\r\n%%\r\n% View.\r\nfigure\r\nsubplot(1,5,1:4)\r\nimagesc(Aeq)\r\nxlabel('Aeq')\r\ntitle('Column equality constraints')\r\nsubplot(1,5,5)\r\nimagesc(beq)\r\nxlabel('beq')\r\n\r\n%% Solve!\r\n% Call the |intlinprog| solver.\r\nx = intlinprog(f,intcon,[],[],Aeq,beq,lb,ub);\r\n\r\n%% View the Result\r\n% _x_ is a vector, so we'll need to undo the |m(:)| operation from above to\r\n% reshape it to be the grid size before viewing.\r\nxi = reshape(x,m,n);\r\n\r\nfigure\r\nimagesc(xi)\r\naxis tight equal off\r\n\r\n%%\r\n% Ahh, I see what's going on.  Let's make it prettier.\r\ns = surf([rot90(xi,2); zeros(1,n)]);\r\nview(0, -90)\r\naxis tight equal off\r\ns.EdgeColor = [0.8 0.8 0.8];\r\n\r\n%%\r\n% Any comments?  Let us know\r\n% <https:\/\/blogs.mathworks.com\/loren\/?p=1760#respond here>.\r\n%%\r\n% And just for completeness,\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/4781185 Christine\r\n% Tobler>, who was sitting next to me did solve it first by hand.\r\n%\r\n% <<puzzlechristine.png>>\r\n%\r\n\r\n\r\n##### SOURCE END ##### 24c76efe6ea14766a9fb2c525ab4dfe1\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img src=\"https:\/\/blogs.mathworks.com\/loren\/files\/SIAM2016_02.png\" class=\"img-responsive attachment-post-thumbnail size-post-thumbnail wp-post-image\" alt=\"\" decoding=\"async\" loading=\"lazy\" \/><\/div><!--introduction--><p><i>Today's guest post comes from <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/3208495\">Sean de Wolski<\/a>, one of Loren's fellow Application Engineers.  You might recognize him from <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/answers\/\">MATLAB answers<\/a> and the <a href=\"https:\/\/blogs.mathworks.com\/pick\/\">pick of the week<\/a> blog!<\/i>... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2016\/07\/20\/matlab-is-satisfying\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":1765,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/1760"}],"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=1760"}],"version-history":[{"count":5,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/1760\/revisions"}],"predecessor-version":[{"id":1769,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/1760\/revisions\/1769"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media\/1765"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=1760"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=1760"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=1760"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}