<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: VConcat many matrices together in Discussions</title>
    <link>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871014#M103463</link>
    <description>&lt;P&gt;This might contain some tips regarding matrices, &lt;A href="https://www.jmp.com/support/help/en/18.2/#page/jmp/use-matrices.shtml#" target="_blank" rel="noopener"&gt; Scripting Guide &amp;gt; Efficient Scripts &amp;gt; Use Matrices&lt;/A&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Tue, 29 Apr 2025 20:17:09 GMT</pubDate>
    <dc:creator>jthi</dc:creator>
    <dc:date>2025-04-29T20:17:09Z</dc:date>
    <item>
      <title>VConcat many matrices together</title>
      <link>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/870994#M103460</link>
      <description>&lt;P&gt;Concatenating matrices in a loop slows down with loop iterations.&lt;/P&gt;
&lt;P&gt;For example this pseudocode:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;OutputM = [];
for( i=1, i&amp;lt;=N, i++,
&amp;nbsp; // do some calculations, generate a matrix of results, call it,&amp;nbsp; ThisM
&amp;nbsp; OutputM&amp;nbsp; |/ = ThisM
);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;If I do the above, then as N increases, the VConcat line gets slower and slower with every iteration.&lt;/P&gt;
&lt;P&gt;Note that each iteration produces a matrix with same number of columns, but variable number of rows.&lt;/P&gt;
&lt;P&gt;It's much faster to do this :&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;OutputList = {}; // will be a list of matrices
for( i=1, i&amp;lt;=N, i++,
&amp;nbsp; // do some calculations, generate a matrix of results, call it,&amp;nbsp; ThisM
  insertinto(OutputList, ThisM)
);
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Now we want to concat together the list of matrices we've generated.&lt;/P&gt;
&lt;P&gt;The question is how ?&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;//This doesn't work:
VConcat(OutputMList);
// Neither does this :
VConat(Eval List(OutputMList);
// Nor this:
VConcat(Eval list(Eval(OutputMList);
// I know I can concat multiple matrices, for example this works:
VConat(OutputMList[1],OutputMList[2], OutputMList[3]);
// But the desire is to generalize this&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 29 Apr 2025 18:44:27 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/870994#M103460</guid>
      <dc:creator>tsl</dc:creator>
      <dc:date>2025-04-29T18:44:27Z</dc:date>
    </item>
    <item>
      <title>Re: VConcat many matrices together</title>
      <link>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871010#M103461</link>
      <description>&lt;P&gt;I don't have time to check this idea, but it might be faster to concatenate lists and then convert the final list to matrix.&lt;/P&gt;</description>
      <pubDate>Tue, 29 Apr 2025 18:49:03 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871010#M103461</guid>
      <dc:creator>Mark_Bailey</dc:creator>
      <dc:date>2025-04-29T18:49:03Z</dc:date>
    </item>
    <item>
      <title>Re: VConcat many matrices together</title>
      <link>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871014#M103463</link>
      <description>&lt;P&gt;This might contain some tips regarding matrices, &lt;A href="https://www.jmp.com/support/help/en/18.2/#page/jmp/use-matrices.shtml#" target="_blank" rel="noopener"&gt; Scripting Guide &amp;gt; Efficient Scripts &amp;gt; Use Matrices&lt;/A&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 29 Apr 2025 20:17:09 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871014#M103463</guid>
      <dc:creator>jthi</dc:creator>
      <dc:date>2025-04-29T20:17:09Z</dc:date>
    </item>
    <item>
      <title>Re: VConcat many matrices together</title>
      <link>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871027#M103465</link>
      <description>&lt;P&gt;This seems to work fast for me&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;OutputList = {}; // will be a list of matrices
n=50;
for( i=1, i&amp;lt;=N, i++,
  // do some calculations, generate a matrix of results, call it,  ThisM
  ThisM = [1,2,3];
  insertinto(OutputList, ThisM)
);
OutputM = [];
for each({l},OutputList,
OutputM  = OutputM |/  matrix(l);
);&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Tue, 29 Apr 2025 20:58:39 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871027#M103465</guid>
      <dc:creator>txnelson</dc:creator>
      <dc:date>2025-04-29T20:58:39Z</dc:date>
    </item>
    <item>
      <title>Re: VConcat many matrices together</title>
      <link>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871147#M103478</link>
      <description>&lt;P&gt;If you are concatenating 50 or more, you might not want to use a loop to concatenate them one at a time. If you already have a list of mats to concat, you can turn the list into a vconcat function like this:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;	Substitute Into( OutputList, {}, Expr( vconcat ) ); // convert {a,b,c} -&amp;gt; vconcat(a,b,c)
	result2 = Eval( OutputList ); // evaluate the expression
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The eval can be 10X faster than the loop:&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Craige_Hales_0-1746026430357.png" style="width: 999px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/75362i088913048035DDFE/image-size/large?v=v2&amp;amp;px=999" role="button" title="Craige_Hales_0-1746026430357.png" alt="Craige_Hales_0-1746026430357.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;JSL to make the graph:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;dt = New Table( "timecat", New Column( "nmats" ), New Column( "timeloop" ), New Column( "timeeval" ) );
dt &amp;lt;&amp;lt; Graph Builder( Size( 534, 456 ), Show Control Panel( 0 ),
	Variables( X( :nmats ), Y( :timeloop ), Y( :timeeval, Position( 1 ) ) ),
	Elements( Points( X, Y( 1 ), Y( 2 ), Legend( 3 ) ) ),
	SendToReport( Dispatch( {}, "timeloop", ScaleBox,
		{Scale( "Log" ), Format( "Engineering SI", 9, 0 ), Min( 10 ), Max( 1e7 ), Inc( 1 ), Minor Ticks( 1 ),
		Add Ref Line( 1e5, "Solid", "Black", "1/10 second", 1 ), Add Ref Line( 1e6, "Solid", "Black", "one second", 1 ),
		Label Row( Show Minor Labels( 0 ) )} ),
		Dispatch( {}, "graph title", TextEditBox, {Set Text( "smaller is better" )} ),
		Dispatch( {}, "X title", TextEditBox, {Set Text( "number of vconcats" )} ),
		Dispatch( {}, "Y title", TextEditBox, {Set Text( "microseconds" )} )
	)
);

For( N = 1, N &amp;lt; 550, N = Ceiling( n * 1.2 ), // build a bunch of test sets of bigger and bigger sizes
	OutputList = {}; // will be a list of matrices
	For( i = 1, i &amp;lt;= N + 1, i++, 
  // do some calculations, generate a matrix of results, call it,  ThisM
		ThisM = J( i, 30, i ); // rows, cols, initial value. 
		Insert Into( OutputList, ThisM );
	);
// loop is slower ... blue in graph
	start = HP Time();
	result1 = OutputList[1];
	For( i = 2, i &amp;lt;= N Items( OutputList ), i += 1,
		result1 |/= OutputList[i]; // this is the vconcat into operator
	);
	t1 = HP Time() - start;
// eval is faster ... red in graph
	start = HP Time();
	Substitute Into( OutputList, {}, Expr( vconcat ) ); // convert {a,b,c} -&amp;gt; vconcat(a,b,c)
	result2 = Eval( OutputList ); // evaluate the expression
	t2 = HP Time() - start;
// capture the timings
	dt &amp;lt;&amp;lt; addrows( 1 );
	dt:nmats[N Rows( dt )] = N;
	dt:timeloop[N Rows( dt )] = t1;
	dt:timeeval[N Rows( dt )] = t2;
	If( !All( result1 == result2 ),
		Throw( "bug?" ) // they should be identical
	);
	Wait( .1 ); // watch the graph grow
);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 30 Apr 2025 15:27:28 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871147#M103478</guid>
      <dc:creator>Craige_Hales</dc:creator>
      <dc:date>2025-04-30T15:27:28Z</dc:date>
    </item>
    <item>
      <title>Re: VConcat many matrices together</title>
      <link>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871418#M103512</link>
      <description>&lt;P&gt;Thanks ! That is the "magic sauce" I needed.&lt;/P&gt;
&lt;P&gt;Agree that loop iteration will slow down for larger numbers, that's a nice demonstration of it.&lt;/P&gt;
&lt;P&gt;The 'Substitute Into()' syntax is what I'd been missing&lt;/P&gt;</description>
      <pubDate>Thu, 01 May 2025 23:29:56 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871418#M103512</guid>
      <dc:creator>tsl</dc:creator>
      <dc:date>2025-05-01T23:29:56Z</dc:date>
    </item>
    <item>
      <title>Re: VConcat many matrices together</title>
      <link>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871557#M103539</link>
      <description>&lt;P&gt;I reworked the graph to see the O(N) behavior and add a jsl loop that also achieves the O(N) behavior. The red, green, and blue curves now measure time per concatenated row. The red and green curves stabilize around .3µs / row but the blue curve is getting slower and slower per row copied for bigger and bigger problems because the blue loop recopies all of the previously copied data (and reallocates the matrix) for each mat added to the result. The last blue dot is 180µs * 3.8M rows, or 11 minutes. The red and green dots are ~200X faster.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Craige_Hales_0-1746216387055.png" style="width: 999px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/75438i5E49A8D39F0B7F49/image-size/large?v=v2&amp;amp;px=999" role="button" title="Craige_Hales_0-1746216387055.png" alt="Craige_Hales_0-1746216387055.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;dt = New Table( "timecat", New Column( "nmats" ), New Column( "loop" ), New Column( "eval" ), New Column( "copy" ) );
dt &amp;lt;&amp;lt; Graph Builder( Size( 1000, 500 ), Show Control Panel( 0 ), Legend Position( "Inside Left" ),
	Variables( X( :nmats ), Y( :loop ), Y( :eval, Position( 1 ) ), Y( :copy, Position( 1 ) ) ),
	Elements( Points( X, Y( 1 ), Y( 2 ), Y( 3 ), Legend( 3 ) ) ),
	SendToReport( Dispatch( {}, "loop", ScaleBox,
			{Scale( "Log" ), Format( "Best", 6 ), Min( 0.1 ), Max( 100 ), Inc( 1 ), Minor Ticks( 1 ), Add Ref Line( 0.2, "Solid", "Black", ".2", 1 ),
			Add Ref Line( 0.4, "Solid", "Black", ".4", 1 ), Label Row( Show Minor Labels( 0 ) )} ),
		Dispatch( {}, "graph title", TextEditBox, {Set Text( "smaller is better" )} ),
		Dispatch( {}, "X title", TextEditBox, {Set Text( "number of concats" )} ),
		Dispatch( {}, "Y title", TextEditBox, {Set Text( "microseconds / row" )} ) ) );
		
For( N = 1, N &amp;lt; 3000, N = Ceiling( n * 1.2 ), // build a bunch of test sets of bigger and bigger sizes
	result1 = result2 = result3 = .; // clear previous run memory, if any
	OutputList = {}; // will be a list of matrices
	For( i = 1, i &amp;lt;= N + 1, i++, 
  // do some calculations, generate a matrix of results, call it,  ThisM
		ThisM = J( i, 30, i ); // rows, cols, initial value. 30 makes this demo run in a reasonable time.
		Insert Into( OutputList, ThisM );
	);
// copy... fastest, green in graph, O(N) behavior. Use the red eval below because it is simpler?
	start = HP Time();
	// find total rows and pre-allocate
	nr = 0;
	nc = N Cols( OutputList[1] );
	For( i = 1, i &amp;lt;= N Items( OutputList ), i += 1,
		nr += N Rows( OutputList[i] );
		If( nc != N Cols( OutputList[i] ),
			Throw( "bad cols" )
		);
	);
	result3 = J( nr, nc, . ); // allocate the result, exactly one time
	nr = 0;
	For( i = 1, i &amp;lt;= N Items( OutputList ), i += 1,
		result3[nr + 1 :: nr + N Rows( OutputList[i] ), 0] = OutputList[i]; // copy pieces into the pre-allocated result
		nr += N Rows( OutputList[i] ); // position the next piece after this one
	);
	t3 = HP Time() - start;
// loop is slower ... blue in graph. This exhibits terrible O(N^2) behavior--reallocates the result bigger and bigger
	start = HP Time();
	result1 = OutputList[1];
	For( i = 2, i &amp;lt;= N Items( OutputList ), i += 1,
		result1 |/= OutputList[i]; // this is the vconcat into operator. copies all the previous data into a bigger mat, each time.
	);
	t1 = HP Time() - start;
// eval is faster ... red in graph ... last, because OutputList is modified. Easier than the green copy and same O(N) result.
	start = HP Time();
	Substitute Into( OutputList, {}, Expr( vconcat ) ); // convert {a,b,c} -&amp;gt; vconcat(a,b,c)
	result2 = Eval( OutputList ); // evaluate the expression
	t2 = HP Time() - start;

// capture the timings
	dt &amp;lt;&amp;lt; addrows( 1 );
	dt:nmats[N Rows( dt )] = N;
	dt:loop[N Rows( dt )] = t1 / N Rows( result1 );
	dt:eval[N Rows( dt )] = t2 / N Rows( result2 );
	dt:copy[N Rows( dt )] = t3 / N Rows( result3 );
	If( !All( result1 == result2 ) | !All( result1 == result3 ) | !(N Rows( result1 ) == N Rows( result2 ) == N Rows( result3 )),
		Throw( "bug?" ) // they should be identical
	);
	Wait( .1 ); // watch the graph grow
);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 02 May 2025 20:19:22 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/VConcat-many-matrices-together/m-p/871557#M103539</guid>
      <dc:creator>Craige_Hales</dc:creator>
      <dc:date>2025-05-02T20:19:22Z</dc:date>
    </item>
  </channel>
</rss>

