I've been doing an assignment which requires me to recreate reversi in matlab.
I have hit a break point where I can't manage to figure out how to do a section of code without turning it into linear indexing.
Essentially what I need to do is figure out a way to add a direction vector (i.e. [-1;0] to go vertically), to my already existing game_state vector in order to find the piece of data above it.
function legal = legalMove()
d_l = [0, -1];
d_r = [0, 1];
d_u = [-1, 0];
d_d = [1, 0];
d_ul = [-1, -1];
d_ur = [-1, 1];
d_dl = [1, -1];
d_dr = [1, 1];
directions = [d_l d_ul d_u d_ur d_r d_dr d_d d_dl];
valid_moves = zeros(8,8);
for ci = 1:8
for cj = 1:8
if game_state(ci,cj) == 0 %check element = 0 before continuing
for count = 1:8
d = directions(count);
selected =
while selected == player_number * -1 %while the selected piece is of enemy type
%move as long as you find your opponents stones
if you found at least 1 opponent stone and you end up on your own stone
else
end
end
end
else
end
end
end
end
My second issue after that, is the actual loop itself.
While I thought that a while loop could be used in order to find out whether to stay on the current direction, I cannot seem to figure out a way to do it myself.
Any assistance would be appreciated.
Thanks for your time!
Change directions to cell-array that contains strings:
...
directions = { 'd_l' 'd_ul' 'd_u' 'd_ur' 'd_r' 'd_dr' 'd_d' 'd_dl' };
...
Then next part of the code would go something like this (fill in the blanks!):
for count = 1:8
d = eval( directions{count} );
ti = ci+d(1);
tj = cj+d(2);
% Check if out of the board
...
% Number of enemy pieces you went over
cnt = 0;
selected = gamestate(ti, tj)
% Move while going over enemy pieces
while selected == player_number * -1
ti = ti + d(1);
tj = tj + d(2);
selected = gamestate(ti, tj);
% Check if out of the board
...
% Count pieces you went over
cnt = cnt + 1;
end
% Check if you moved over enemy pieces & whether you landed on your piece
...
end
Related
So I'm trying to write a program that simulates the movement of gas particles in a sealed environment for an undergrad project (this is my first project so I'm pretty new to coding as a whole). My issue comes down to particle-particle collisions specifically. I have an if statement within an overarching while statement that reverses either the x components or y components of the colliding particles. When I run the script however, particles that should simply collide and have their velocities reversed end up stuttering back and forth. I think what's happening is the separation distance between collided particles after their velocities have been reversed is still below the initial value for collision so the velocities are reversed again. Kinda don't want this to happen and I've been stuck on it for a while. I just want the velocities to be reversed once until a new collision occurs. Collision handling can be found at the bottom of my script. Any advice on this would be greatly appreciated.
clc; clear; close all;
f = figure;
ax = axes('XLim', [0 10], 'YLim', [0 10]);
numberOfParticles = 30;
[particles, particlePositions, particleVelocities] = initializeNewParticle(numberOfParticles);
particleMotion(particles, particleVelocities, particlePositions);
%instantiates N particles
function [particles, particlePositions, particleVelocities] = initializeNewParticle(numberOfParticles)
speedMultiplier = 0.05;
for i = 1:numberOfParticles
particlePositionX(i) = 10*rand;
particlePositionY(i) = 10*rand;
particleVelocityX(i) = speedMultiplier * (-1 + 2*rand);
particleVelocityY(i) = speedMultiplier * (-1 + 2*rand);
particles(i) = line(particlePositionX(i), particlePositionY(i), 'marker', 'o', 'color', 'k', 'markersize', 15);
end
particlePositions = [particlePositionX; particlePositionY];
particleVelocities = [particleVelocityX; particleVelocityY];
end
%initial velocities & collision handling
function [] = particleMotion(particles, particleVelocities, particlePositions)
tic;
while toc < 10
%checks if particles are within bounds of figure
if any(particlePositions(:) < 0) || any(particlePositions(:) > 10)
%creates array that converts elements to 1 if particles out of bounds
outOfBounds = particlePositions < 0 | particlePositions > 10;
%finds index position of non-zero elements
indexPos = outOfBounds(:) > 0;
%uses index to invert velocities of particles out of bounds
particleVelocities(indexPos) = -particleVelocities(indexPos);
end
particlePositions = particlePositions + particleVelocities;
set(particles, 'XData', particlePositions(1,:),'YData', particlePositions(2,:), "LineStyle", "none");
%determines all separations from i particle to all N particles
for i = 1 : length(particles)
currentParticleXPos = get(particles(i), 'XData');
targetParticlesXPos(i, :) = particlePositions(1,:) - particlePositions(1,i);
currentParticleYPos = get(particles(i), 'YData');
targetParticlesYPos(i,:) = particlePositions(2,:) - particlePositions(2,i);
distanceBetweenParticles(i,:) = sqrt(targetParticlesXPos(i,:).^2 + targetParticlesYPos(i,:).^2);
end
%collision check and handling
if find(distanceBetweenParticles >= 0 & distanceBetweenParticles <= 0.5)
collisionCoordinates = triu((distanceBetweenParticles < 0.5 & distanceBetweenParticles > 0));
linearCollisionIndexValue = find(collisionCoordinates == 1);
[particle1,particle2] = ind2sub(size(collisionCoordinates), linearCollisionIndexValue);
particleVelocityX1 = particleVelocities(1,particle1);
particleVelocityX2 = particleVelocities(1,particle2);
particleVelocityY1 = particleVelocities(2,particle1);
particleVelocityY2 = particleVelocities(2,particle2);
if ~isequal(sign(particleVelocityX1), sign(particleVelocityX2))
particleVelocities(1,particle1) = -particleVelocityX1;
particleVelocities(1,particle2) = -particleVelocityX2;
elseif ~isequal(sign(particleVelocityY1), sign(particleVelocityY2))
particleVelocities(2,particle1) = -particleVelocityY1;
particleVelocities(2,particle2) = -particleVelocityY2;
end
end
pause(0.01);
end
end
I am modelling flow through a tube in tube heat exchanger using MATLAB using the nodal port method. I need to populate a matrix with differential equations in order to solve for the enthalpies at each point. I have divided my pipe into multiple sections, each with 3 nodes. 1 node for the inner fluid, 1 node for the outer fluid, and 1 node for the pipe. However, due to the fact that there is counter flow I need to populate the matrix in a way that the outer fluid counts in reverse to the inner fluid. For example, if I have 9 nodes, my column vector will be [Eq 1 Eq 2 Eq 9 Eq 4 Eq 5 Eq6 Eq 7 Eq 8 Eq 3]. My code seems to work, but it doesn't enter anything for the 3rd position of the vector. Thank you in advance for the help.
NXP = 5; %Number of Divisions
HX = zeros(NXP,1);
cntr=2; %To see which number equation is being input
for j=1:NXP
if j==1
HX(1+(j-1)*3,1) = 125; %Boundary Condition
else
HX(1+(j-1)*3,1) = cntr;
cntr = cntr+1;
end
HX(2+(j-1)*3,1) = cntr;
cntr = cntr+1;
if j==NXP
HX(3+(j-1)*3,1) = 40; %Boundary Condition
else
HX(3*NXP-3*(j-1),1) = cntr;
cntr = cntr+1;
end
end
'''
I changed a bit your attempt, most notably moving the boundary conditions outside of the loop, but it now returns what I guess you were looking for:
NXP = 5;
HX = zeros(3*NXP, 1);
for j = 1:NXP
idx = (j - 1)*3;
HX(idx + 1, 1) = idx + 1;
HX(idx + 2, 1) = idx + 2;
HX(length(HX) - idx, 1) = idx + 3;
end
% Boundary conditions
HX(1) = 125;
HX(end) = 40;
EDIT:
Even better, just initialize the array as
HX = (1:3*NXP)';
and then just change the order for your 3rd nodes
HX(3:3:length(HX)) = flipud(HX(3:3:length(HX)));
and finally set your boundary conditions
HX(1) = 125;
HX(end) = 40;
I'm currently working on a code that makes use of a 2D cellular automata as an epidemic simulator in MATLAB. The main basic rule I'm trying to implement is that if any neighbour within a Moore Neighbourhood with a 1-cell radius is infected, the cell will become infected. But I can't seem to get a good code working for it.
Basically what I'm trying to do is say with for a cell with a one cell radius Moore neighbourhood, if any values in this neighbourhood = 2, then the initial cell will become 2.
I've tried using the forest fire code on the rosetta code as a basis for my code behaviour but it doesnt work very well. The rules don't really work that well when applying it to mine. I've tried using the mod function and a series of if loops to attach. I'll put in some code of each to give context.
This example doesn't really function well as an epidemic simulator to be honest.
matlab
clear; clc;
n = 200;
N = n/2;
E = 0.001; % Creating an arbitrary number for population exposed to
the disease but not infected
p = 1 + (rand(n,n)<E);
%p = ceil(rand(n,n)*2.12) - 1;
% ratio0 = sum(p(:)==0)/n^2;
% ratio1 = sum(p(:)==1)/n^2;
% ratio2 = sum(p(:)==2)/n^2;
% ratio3 = sum(p(:)==3)/n^2;
S = ones(3); S(2,2) = 0;
ff = 0.00000000002;
p(N,N) = 3;
%% Running the simulation for a set number of loops
colormap([1,1,1;1,0,1;1,0,0]); %Setting colourmap to Green, red and
grey
count = 0;
while(count<365) % Running the simulation with limited number of runs
count = count + 1;
image(p); pause(0.1); % Creating an image of the model
P = (p==1); % Adding empty cells to new array
P = P + (p==2).*((filter2(S,p==3)>0) + (rand(n,n)<ff) + 2); % Setting
2 as a tree, ignites based on proximity of trees and random
chance ff
P = P + (p==3); % Setting 3 as a burning tree, that becomes 1,
p = P;
end
second idea. this basically returns nothing
matlab
clear;clf;clc;
n = 200;
pos = mod((1:n),n) + 1; neg = mod((1:n)-2,n) + 1;
p = (ceil(rand(n,n)*1.0005));
for t = 1:365
if p(neg,neg) ==2
p(:,:) = 2;
end
if p(:,neg)==2
p(:,:) = 2;
end
if p(pos,neg)==2
p(:,:) = 2;
end
if p(neg,:)==2
p(:,:) = 2;
end
if p(pos,:)==2
p(:,:) = 2;
end
if p(neg,pos)==2
p(:,:) = 2;
end
if p(:,pos)==2
p(:,:) = 2;
end
if p(pos,pos)== 2
p(:,:) = 2;
end
image(p)
colormap([1,1,1;1,0,1])
end
third I tried using logic gates to see if that would work. I don't know if commas would work instead.
matlab
clear;clf;clc;
n = 200;
pos = mod((1:n),n) + 1; neg = mod((1:n)-2,n) + 1;
p = (ceil(rand(n,n)*1.0005));
%P = p(neg,neg) + p(:,neg) + p(pos,neg) + p(neg,:) + p(:,:) + p(pos,:)
+ p(neg,pos) + p(:,pos) + p(pos,pos)
for t=1:365
if p(neg,neg)|| p(:,neg) || p(pos,neg) || p(neg,:) || p(pos,:) ||
p(neg,pos) || p(:,pos) || p(pos,pos) == 2
p(:,:) = 2;
end
image(p)
colormap([1,1,1;1,0,1])
end
I expected the matrix to just gradually become more magenta but nothing happens in the second one. I get this error for the third.
"Operands to the || and && operators must be convertible to logical scalar values."
I just have no idea what to do!
Cells do not heal
I assume that
Infected is 2, non-infected is 1;
An infected cell remains infected;
A non-infected cell becomes infected if any neighbour is.
A simple way to achieve this is using 2-D convolution:
n = 200;
p = (ceil(rand(n,n)*1.0005));
neighbourhood = [1 1 1; 1 1 1; 1 1 1]; % Moore plus own cell
for t = 1:356
p = (conv2(p-1, neighbourhood, 'same')>0) + 1; % update
image(p), axis equal, axis tight, colormap([.4 .4 .5; .8 0 0]), pause(.1) % plot
end
Cells heal after a specified time
To model this, it is better to use 0 for a non-infected cell and a positive integer for an infected cell, which indicated how long it has been infected.
A cell heals after it has been infected for a specified number of iterations (but can immediately become infeced again...)
The code uses convolution, as the previous one, but now already infected cells need to be dealt with separately from newly infected cells, and so a true Moore neighbourhood is used.
n = 200;
p = (ceil(rand(n,n)*1.0005))-1; % 0: non-infected. 1: just infected
T = 20; % time to heal
neighbourhood = [1 1 1; 1 0 1; 1 1 1]; % Moore
for t = 1:356
already_infected = p>0; % logical index
p(already_infected) = p(already_infected)+1; % increase time count for infected
newly_infected = conv2(p>0, neighbourhood, 'same')>0; % logical index
p(newly_infected & ~already_infected) = 1; % these just became infected
newly_healed = p==T; % logical index
p(newly_healed) = 0; % these are just healed
image(p>0), axis equal, axis tight, colormap([.4 .4 .5; .8 0 0]), pause(.1) % plot
% infected / non-infected state
end
I'd like to return the indexes and values of the 8 cells surrounding a cell in a 3d matrix.
mat = rand(5,5,5);
% Cell of interest
pos = [3 3 3]
pos_val = mat(pos(1), pos(2), pos(3))
% Surrounding cells
surrounding_pos = [pos(1)-1:pos(1)+1; pos(2)-1:pos(2)+1; pos(2)-1:pos(2)+1]
surrounding_val = mat(surrounding_pos(1,:), surrounding_pos(2,:), surrounding_pos(3,:))
This works fine for values in the centre of a matrix, but it breaks if pos is on the edge. (E.g. if pos was [3,4,5], surrounding_pos would include [3,4,6], which is out of bounds)
I could obviously remove surrounding_pos values <0 or >size(mat), but this doesn't seem like a terribly MATLABian method. Any ideas?
Same solution as discussed here, but extended to multiple (any) dimensions:
mat = randi(10,5,5,5);
siz = size(mat );
N = numel(siz); % number of dimensions
M = 1; % surrounding region size
pos = [3 3 3];
pos_val = mat(pos(1), pos(2), pos(3));
surrounding_pos = cell(N,1);
for ii=1:N
surrounding_pos{ii} = max(1,pos(ii)-M):min(siz(ii),pos(ii)+M);
end
surrounding_val2 = mat(surrounding_pos{:});
The important part is the last four lines, it avoids having to c/p the max, min thing for every dimension..
Or if you like short code, the loop changed to an arrayfun:
surrounding_pos = arrayfun(#(ii) max(1,pos(ii)-M):min(siz(ii),pos(ii)+M), 1:N,'uni',false);
surrounding_val2 = mat(surrounding_pos{:});
Here is a tidied up version. Cheers.
mat = rand(5,5,5);
N = size(mat)
if length(N) < 3 || length(N) > 3; error('Input must be 3 dimensional'); end;
pos = [1 3 5]
surrounding_val = mat(max(pos(1)-1, 1):min(pos(1)+1, N(1)), max(pos(2)-1, 1):min(pos(2)+1, N(2)), max(pos(3)-1, 1):min(pos(3)+1, N(3)))
EDIT: Added an error trap.
I found this post because I needed to grab the surrounding indices of a chosen point in a Matrix. It seems like the answers here are returning a matrix of the surrounding values, but the question is also interested in the surrounding indices. I was able to do this with "try/catch" statements, which I previously did not know existed in MATLAB. For a 2D Matrix, Z:
%Select a node in the matrix
Current = Start_Node;
%Grab its x, y, values (these feel reversed for me...)
C_x = rem(Start_Node, length(Z));
if C_x ==0
C_x =length(Z);
end
C_y = ceil(Start_Node/length(Z));
C_C = [C_x, C_y];
%Grab the node's surrounding nodes.
try
TRY = Z(C_x - 1, C_y);
Top = Current -1;
catch
Top = Inf;
end
try
TRY = Z(C_x + 1, C_y);
Bottom = Current +1;
catch
Bottom = Inf;
end
try
TRY = Z(C_x, C_y + 1);
Right = Current + length(Z);
catch
Right = Inf;
end
try
TRY = Z(C_x, C_y - 1);
Left = Current - length(Z);
catch
Left = Inf;
end
surround = [Top, Bottom, Left, Right];
m = numel(surround == inf);
k = 1;
%Eliminate infinites.
surround(surround==inf) =[];
I hope someone finds this information relevant.
I would like to create an animation to demonstrate LDPC coding which is based on Sum-Product Algorithm
So far I have created a graph which shows the connections between symbol nodes (left) and parity nodes (right)alt text http://img29.imageshack.us/img29/9780/ldpc.jpg and would like to animate points travelling from symbol to parity nodes and back.
The figure is drawn by executing the following method:
function drawVertices(H)
hold on;
nodesCount = size(H);
parityNodesCount = nodesCount(1);
symbolNodesCount = nodesCount(2);
symbolPoints = zeros(symbolNodesCount, 2);
symbolPoints(:, 1) = 0;
for i = 0 : symbolNodesCount - 1
ji = symbolNodesCount - i;
scatter(0, ji)
symbolPoints(i + 1, 2) = ji;
end;
parityPoints = zeros(parityNodesCount, 2);
parityPoints(:, 1) = 10;
for i = 0 : parityNodesCount - 1
ji = parityNodesCount - i;
y0 = symbolNodesCount/2 - parityNodesCount/2;
scatter(10, y0 + ji)
parityPoints(i + 1, 2) = y0 + ji;
end;
axis([-1 11 -1 symbolNodesCount + 2]);
axis off
%connect vertices
d = size(H);
for i = 1 : d(1)
for j = 1 : d(2)
if(H(i, j) == 1)
plot([parityPoints(i, 1) symbolPoints(j, 1)], [parityPoints(i, 2) symbolPoints(j, 2)]);
end;
end;
end;
So what I would like to do here is to add another method which takes start point (x and y) and end point as arguments and animates a travelling circle (dot) from start to end and back along the displayed lines.
I would appreciate if anyone of you could show the solution or suggest any useful tutorial about matlab simulations.
Thank you!
I believe the best way to learn is by example. So I suggest you look at the demo lorenz which comes with MATLAB:
edit lorenz
For other cool animations, look for orbits.m and swinger.m demos part of Cleve Moler's book: Experiments with MATLAB
I show here a simple animation of a point moving along a circular path. The hold idea boils down to using EraseMode set to xor, and updating XData and YData of the point for each iteration:
%# coordinates
t = (0:.01:2*pi)'; %# 'fix SO syntax highlight
D = [cos(t) -sin(t)];
%# setup a figure and axis
hFig = figure('Backingstore','off', 'DoubleBuffer','on');
hAx = axes('Parent',hFig, 'XLim',[-1 1], 'YLim',[-1 1], ...
'Drawmode','fast', 'NextPlot','add');
axis(hAx, 'off','square')
%# draw circular path
line(D(:,1), D(:,2), 'Color',[.3 .3 .3], 'LineWidth',1);
%# initialize point
h = line('XData',D(1,1), 'YData',D(1,2), 'EraseMode','xor', ...
'Color','r', 'marker','.', 'MarkerSize',50);
%# init text
hTxt = text(0, 0, num2str(t(1)), 'FontSize',12, 'EraseMode','xor');
i=0;
while true
i = rem(i+1,numel(t)) + 1; %# circular increment
set(h,'XData',D(i,1), 'YData',D(i,2)) %# update X/Y data
set(hTxt,'String',num2str(t(i))) %# update angle text
drawnow %# force refresh
if ~ishandle(h), return; end %# in case you close the figure
end
For a detailed explanation of the parameters used (EraseMode, Backingstore, DoubleBuffer, ..), refer to this animation guide
From the documentation for comet.m
t = 0:.01:2*pi;
x = cos(2*t).*(cos(t).^2);
y = sin(2*t).*(sin(t).^2);
comet(x,y);