cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
lala
Level VIII

Can animation of this difficulty be achieved with JSL?

I saw this Rule30 in the video.

https://mathworld.wolfram.com/Rule30.html 

It must be complicated.

 

Thanks Experts!

7 REPLIES 7
lala
Level VIII

回复: Can animation of this difficulty be achieved with JSL?

2024-05-18_19-18-18.png

jthi
Super User

回复: Can animation of this difficulty be achieved with JSL?

I'm not sure what the animation is supposed to look like but you can do something like this for example using new image, set pixels and ad frame

-Jarmo
hogi
Level XII

回复: Can animation of this difficulty be achieved with JSL?

Or just plot it as Heatmap in GraphBuilder and record it.

 

 

 

hogi
Level XII

回复: Can animation of this difficulty be achieved with JSL?

another approach - for infinite loops.

with the data table created on the fly ...

 

dt = New Table( "cellular automaton",
	New Column( "pos", Nominal ),
	New Column( "step", Nominal ),
	New Column( "status", Nominal )
);

dt << add rows( 1 );
:pos[1] = 0;
:step[1] = 1;
:status[1] = 1;
t0 = hptime();
gb = dt << Graph Builder(
	Show Control Panel( 0 ),
	Show Title( 0 ),
	Show X Axis( 0 ),
	Show X Axis Title( 0 ),
	Variables( X( :pos ), Y( :step ), Color( :status ) ),
	Elements( Heatmap( X, Y, Legend( 1 ) ) ),
	SendToReport(
		Dispatch( {}, "pos", ScaleBox, {Label Row( Tick Mark Style( "Long Divider" ) )} ),
		Dispatch( {}, "step", ScaleBox,
			{Reversed Scale, Label Row( Tick Mark Style( "Long Divider" ) )}
		),
		Dispatch( {}, "400", ScaleBox,
			{Legend Model(
				1,
				Properties( 1, {Fill Color( 0 )}, Item ID( "1", 1 ) ),
				Properties( 2, {Fill Color( 2 )}, Item ID( "0", 1 ) )
			)}
		)
	)
);

wait(0);

cells = [1];
j=4;
For( i = 2, i > 0, i++, 
//i=2
	cells = Insert( Insert( cells, 0, 1 ), 0 );
	cells0 = Insert( Insert( cells, 0, 1 ), 0 );
	cells = Transform Each( {dummy, idx}, cells, 
//idx=3;
		myPattern = 100 * cells0[idx] + 10 * cells0[idx + 1] + cells0[idx + 2];
		Match( mypattern,
			100, 1,
			11, 1,
			10, 1,
			1, 1,
			0 // all other variants give 0	
		);
	);
	Ncells = N Items( cells );
	nr = N Rows( dt );
	dt << add rows( 2 * i - 1 );
	rows = nr + (1 :: Ncells);
	dt[rows, "step"] = J( Ncells, 1, i );
	dt[rows, "pos"] = ((1 :: Ncells) - i)`;
	dt[rows, "status"] = cells;
	if(hptime()-t0>10000,wait(0);t0=hptime())
);
hogi
Level XII

回复: Can animation of this difficulty be achieved with JSL?

I have to admit: It took me a while to get the Zoom right.

 

The first idea: restrict the view to rows with Data=1: While the entries are calculated, more and more entries will show up, leading to a zoom-out.

But this approach did not work as expected - see below. 

 

Please notice the Data Filter - it starts with the correct setting: Data=1,

but when the column is cleared and the calculation starts, there is no such data anymore - and the Data Filter just forgets it's settings (!!!). 


This bug was first described in Outlier (👽) screening with Jmp Dashboards - how? .

- some workarounds can be found here 
- a wish to fix the bug: Local Data Filter: option: restrict or do not restrict to current data  

- a more elegant way to tackle such issues: 🙏 Column Property: Inclusive Values 

 

DataFilter_reset.gif

lala
Level VIII

回复: Can animation of this difficulty be achieved with JSL?

It's still too hard for me.

Thanks Experts!

2024-05-19_18-31-13.png

jthi
Super User

回复: Can animation of this difficulty be achieved with JSL?

What are you attempting to do? Have a demonstration that JMP is capable of some sort of animation? Have a calculation for https://en.wikipedia.org/wiki/Rule_30 ? Something totally different and this is just an example?

 

Edit:

Whatever the case is I post my code here (lots of optimization could still be done)

View more...
Names Default To Here(1);

xor = Function({first, second}, {Default Local},
	return((first | second) & !(first & second));
);

check_rule30 = function({items}, {Default Local},
	// https://en.wikipedia.org/wiki/Rule_30
	res = xor(items[1], items[2] | items[3]);
	
	return(res);
);

initial_state = function({width}, {Default Local},
	m = J(Floor(width / 2) + 1, width + !Mod(width, 2), 0);
	m[1, Floor(width / 2) + 1] = 1;

	return(m);
);


cellular_automaton_rule30 = function({width}, {Default Local},
	m = initial_state(width);
	
	For(r = 2, r <= N Rows(m), r++,
		For(c = 1, c <= N Cols(m[r, 0]), c++,
			If(c == 1, // fill [0] for edges
				three = [0] || m[r - 1, c::c + 1];
			, c == N Cols(m[r, 0]),
				three = m[r - 1, c - 1::c] || [0];
			,
				three = m[r - 1, c - 1::c + 1];
			);
			
			res = check_rule30(three);
			
			m[r, c] = res;
		);
	);
	
	return(m);
);

magnify_matrix = function({m, magnification = 1}, {Default Local},
	If(magnification == 1,
		return(m);
	);
	
	magnified = J(N Rows(m) * magnification, N Cols(m) * magnification);

	magnified = Transform Each({z, {row, col}}, magnified, 
		// and filling each value with one from the small matrix
		m[Floor((row - 1) / magnification) + 1, Floor((col - 1) / magnification) + 1]
	);
	
	return(magnified);
);


animate_matrix = Function({m_magnified}, {Default Local},
	// Substitute Into(m_magnified, 1, -16777215); // to make white white
	start = Tick Seconds();

	initial = J(N Row(m_magnified), N Col(m_magnified), 0);
	initial[1::magnification, 0] = Substitute(m_magnified[1::magnification, 0], 1, -16777215);

	img = New Image(initial);
	For(i = 1, i < N Rows(m), i++,
		indices = (i * magnification + 1)::((i + 1) * magnification);
		cur_row = m_magnified[indices, 0];
		
		If(i == N Rows(m) - 1, // could be moved outside of the loop
			Substitute Into(cur_row, 1, -16777215);
		,
			Substitute Into(cur_row, 1, -65280);
		);
		Substitute Into(cur_row, 1, -65280);
		Substitute Into(initial, -65280, -16777215);
		
		initial[indices, 0] = cur_row;
		img << Add Frame(10);
		img << Set Pixels(initial);
	);
	wait(0);
	end = Tick Seconds();
	Write(Eval Insert("animate_matrix: ^Round(end - start, 3)^s.\!N"));

	nw = New Window("Multi-Frame Image", img);
	durs = img << Get Frame Durations();
	For(i = 0, i < img << Get N Frames, i++, // might be off by one
		img << Set Current Frame(i);
		nw << reshow();
		dur = durs[i + 1] / 800.0; // use to modify the speed of animation
		Wait(dur);
	);
	
	return(img);
);


view_matrix = function({m}, {Default Local},
	nw = New Window("Matrix",
		pic = New Heat Image(m,
			gradient({Color Theme("White to Black"), Scale Values([0 1]), Reverse Gradient(1)})
		)
	);
);

width = 250;
magnification = 5;

start = Tick Seconds();
m = cellular_automaton_rule30(width);
wait(0);
end = Tick Seconds();
Write(Eval Insert("cellular_automaton_rule30: ^Round(end - start, 3)^s.\!N"));

start = Tick Seconds();
m_magnified = magnify_matrix(m, magnification);
wait(0);
end = Tick Seconds();
Write(Eval Insert("magnify_matrix: ^Round(end - start, 3)^s.\!N"));

animation = animate_matrix(m_magnified);
wait(0);

Write("Done\!N");

rule30_cellular_automaton.gif

-Jarmo