Let X be a mealy machine. More specifically, I'm representing it as a 3 by 3 by 2 by N array where N is the number of states. View it as a row of N 3 by 3 matrices and another such layer behind it. The layer behind gives the state transitions and the one in front the output values. So say I start from state N and input (x,y), I get output X(x,y,1,N) and then move to state X(x,y,2,N). For a sequence of inputs (x,y)...(x',y') I want to know the output sequence and am currently using the following code. Any speed up suggestions would be very welcome. A related question is does 'isequal' work faster when comparing rows of matrices than when comparing cells entries (related to another 'checking' code not the code below).
function [ T, O ] = mealy( X ,w ,k )
%Given a Mealy machine X, input word w and starting state k, T == 1 means
%this mealy machine does not have sufficient information to give an output
%for input word w. Else T == 0 and O is the output sequence for w.
L = length(w);
S = zeros(1,L); %state sequence
O = cell(1,L); %letter and output sequence
T = 0;
S(1) = k; %start from state k
% build output sequence O from input word w
for i = 2:L
e = w{i-1};
S(i) = X(e(1),e(2),2,S(i-1));
if S(i) < 0, T = 1; return, end
t = X(e(1),e(2),1,S(i-1));
if t < -1.5, T = 1; return, end
O{i-1} = [e(1),e(2),t];
end
e = w{L};
t = X(e(1),e(2),1,S(L));
if t < -1.5, T = 1;return, end
O{L}= [e(1),e(2),t];
end
Related
I am using below Matlab code to calculate power function [ without using built-in function] to calculate power = b^e.
At the moment , I am unable to get power function going that support fractional exponential values b^(1/2) = sqrt(b) or 3.4 ^ (1/4) to calculate power due inefficient approach , because it loops e times. I need help in efficient logic for fractional exponent.
Thank you
b = [-32:32]; % example input values
e = [-3:3]; % example input values but doesn't support fraction's
power_function(b,e)
p = 1;
if e < 0
e = abs(e);
multiplier = 1/b;
else
multiplier = b;
end
for k = 1:e
p(:) = p * multiplier; % n-th root for any given number
end
Background
I am trying to model a system that can change its configurations each time step. The variety of configurations is known in advance and does not depend on the time step. Transitions are allowed between certain configurations and forbidden between others. The objective is to build an adjacency connectivity matrix of allowed transitions, which spans multiple time steps.
Setting
Let A be an s*s*k logical matrix representing allowed transitions, and A1...Ak represent the pages/slices of A:
A1 = A(:,:,1); A2 = A(:,:,2); ... Ak = A(:,:,k);
The meaning of the 3rd dimension is how many time steps are required for a transition, for example: if A(1,3,2) is nonzero, it means that state #1 can transition to state #3 and this will take 2 time steps.
Let B be the adjacency matrix that we want to build, which represents nt time steps. The shape of B should be schematically (in block matrix notation):
_ _
| [0] [A1] [A2] ... [Ak] [0] ... [0] |
B = | [0] [0] [A1] [A2] ... [Ak] ... [0] |
| ⋮ ⋮ ⋱ ⋱ ⋱ ⋮ |
|_[0] [0] … … … … … … … … [0]_| "[A1] [A2] ... [Ak]"
where the main block diagonal consists of nt 0-blocks, and the slices of A get gradually "pushed" to the right until "time runs out", the slices of A end up "outside" of B ⇒ indicating no more transitions are possible. Since B consists of nt*nt s*s blocks, its size is (nt*s)×(nt*s).
Question: Given A and nt, how can we construct B in the most CPU- and memory-efficient way?
Notes
Since B is mostly filled with zeros, it probably makes sense for it to be sparse.
CPU efficiency (runtime) is more important in my application than memory efficiency.
In the real problem, s=250 and nt=6000.
External scripts/classes/tools are welcome.
An idea I had was not constructing the matrix staggered initially, but instead having a main diagonal of [A1] blocks and circshift-ing and masking when everything else is done.
Demonstration + Naïve implementation
s = 3; k = 4; nt = 8;
A = logical(cat(3, triu(ones(s)), eye(s), zeros(s), [0 0 0; 0 0 0; 0 1 0]));
% Unwrap A (reshape into 2D):
Auw = reshape(A, s, []);
% Preallocate a somewhat larger B:
B = false(nt*s, (nt+k)*s);
% Assign Auw into B in a staggered fashion:
for it = 1:nt
B( (it-1)*s+1:it*s, it*s+1:(it+k)*s ) = Auw;
end
% Truncate the extra elements of B (from the right)
B = B(1:nt*s, 1:nt*s);
spy(B);
Resulting in:
One solution could be to calculate all the indices using implicit expansion:
% Dev-iL minimal example
s = 3; k = 4; nt = 8;
A = logical(cat(3, triu(ones(s)), eye(s), zeros(s), [0 0 0; 0 0 0; 0 1 0]));
Auw = reshape(A, s, []);
% Compute the indice:
[x,y] = find(Auw);
x = reshape(x+[0:s:s*(nt-1)],[],1);
y = reshape(y+[s:s:s*nt],[],1);
% Detection of the unneeded non zero elements:
ind = x<=s*nt & y<=s*nt;
% Sparse matrix creation:
S = sparse(x(ind),y(ind),1,s*nt,s*nt);
% Plot the results:
spy(S)
Here we only compute the position of non zero values. We avoid to preallocate a big matrix that will slow down the computation.
Benchmark:
I have used matlab online to run the benchmark, the available memory is limited. If someone would run the benchmark on his local computer with bigger value, feel free to do so.
With those configurations, it seems that using implicit expansion is indeed faster.
Benchmark code:
for ii = 1:100
s = ii; k = 4; nt = ii;
Auw = rand(s,s*k)>0.75;
f_expa = #() func_expansion(s,nt,Auw);
f_loop = #() func_loop(s,k,nt,Auw);
t_expa(ii) = timeit(f_expa);
t_loop(ii) = timeit(f_loop);
end
plot(1:100,t_expa,1:100,t_loop)
legend('Implicit expansion','For loop')
ylabel('Runtime (s)')
xlabel('x and nt value')
% obchardon suggestion
function S = func_expansion(s,nt,Auw)
[x,y] = find(Auw);
x = reshape(x+[0:s:s*(nt-1)],[],1);
y = reshape(y+[s:s:s*nt],[],1);
ind = x<=s*nt & y<=s*nt;
S = sparse(x(ind),y(ind),1,s*nt,s*nt);
end
% Dev-il suggestion
function B = func_loop(s,k,nt,Auw)
B = false(nt*s, (nt+k)*s);
for it = 1:nt
B( (it-1)*s+1:it*s, it*s+1:(it+k)*s ) = Auw;
end
B = B(1:nt*s, 1:nt*s);
end
I have 2 functions:
ccexpan - which calculates coefficients of interpolating polynomial of function f with N nodes in Chebyshew polynomial of the first kind basis.
csum - calculates value for arguments t using coefficients c from ccexpan (using Clenshaw algorithm).
This is what I have written so far:
function c = ccexpan(f,N)
z = zeros (1,N+1);
s = zeros (1,N+1);
for i = 1:(N+1)
z(i) = pi*(i-1)/N;
end
t = f(cos(z));
for k = 1:(N+1)
s(k) = sum(t.*cos(z.*(k-1)));
s(k) = s(k)-(f(1)+f(-1)*cos(pi*(k-1)))/2;
end
c = s.*2/N;
and:
function y = csum(t,c)
M = length(t);
N = length(c);
y = t;
b = zeros(1,N+2);
for k = 1:M
for i = N:-1:1
b(i) = c(i)+2*t(k)*b(i+1)-b(i+2);
end
y(k)=(b(1)-b(3))/2;
end
Unfortunately these programs are very slow, and also slightly inacurrate. Please give me some tips on how to speed them up, and how to improve accuracy.
Where possible try to get away from looping structures. At first blush, I would trade out your first for loop of
for i = 1:(N+1)
z(i) = pi*(i-1)/N;
end
and replace with
i=1:(N+1)
z = pi*(i-1)/N
I did not check the rest of you code but the above example will definitely speed up you code. And a second strategy is to combine loops when possible.
Martin,
Consider the following strategy.
% create hypothetical N and f
N = 3
f = #(x) 1./(1+15*x.*x)
% calculate z and t
i=1:(N+1)
z = pi*(i-1)/N
t = f(cos(z))
% make a column vector of k's
k = (1:(N+1))'
% do this: s(k) = sum(t.*cos(z.*(k-1)))
s1 = t.*cos(z.*(k-1)) % should be a matrix with one row for each row of k
% via implicit expansion
s2 = sum(s1,2) % row sum, i.e., one value for each row of k
% do this: s(k) = s(k)-(f(1)+f(-1)*cos(pi*(k-1)))/2
s3 = s2 - (f(1)+f(-1)*cos(pi*(k-1)))/2
% calculate c
c = s3 .* 2/N
I am trying to write a function that calculates the number of iterations it takes for two chambers to have equally as many particles.The evolution of the system is considered as a series of time-steps, beginning at t = 1. At each time-step exactly
one particle will pass through the hole, and we assume that the particles do not interact. The probability that
a particle will move from the left to the right chamber is pLR = NL/N, and the probability of a particle will
move from the right to the left chamber is pRL = 1 − pLR = (N − NL)/N.
The simulation will iteratively proceed as follows:
Get a random number r from the interval 0 ≤ r ≤ 1.
If r ≤ pLR, move one particle from the left to the right chamber. Otherwise move one particle from the
right to the left chamber.
Repeat step 1 and 2 until NL = NR. Report back, how many time-steps it took to reach this equilibrium
This is my code thus far.
function t = thermoEquilibrium(N, r) %N = number of particles, r = random numbers from 0-1
h = []; %right side of the chamber
v = []; %left side of the chamber
rr = r;
k = false
NL=N-length(h) %This is especially where i suspect i make a mistake.
%How can the probability change with every iteration?
pLR = NL/N;
pRL = 1 - pLR;
count = 1
while k==false
for i = r
if i<=pLR
h(end+1)=i
rr = rr(rr~=i)
end
end
for l = h
if pRL>l
v(end+1) = l
h = h(h~=l)
end
end
if length(h)==N/2 && length(v)==N/2
k=true
end
count = count + 1
end
t = count
Can someone point me in a direction, so i can get a bit closer to something that works?
I'm trying to convert a base-10 integer k into a base-q integer, but not in the standard way. Firstly, I'd like my result to be a vectors (or a string 'a,b,c,...' so that it can be converted to a vector, but not 'abc...'). Most importantly, I'd like each 'digit' to be in base-10. As an example, suppose I have the number 23 (in base-10) and I want to convert it to base-12. This would be 1B in the standard 1,...,9,A,B notation; however, I want it to come out as [1, 11]. I'm only interested in numbers k with 0 \le k \le n^q - 1, where n is fixed in advance.
Put another way, I wish to find coefficients a(r) such that
k = \sum_{r=0}^{n-1} a(r) q^r
where each a(r) is in base-10. (Note that 0 \le a(r) \le q-1.)
I know I could do this with a for-loop -- struggling to get the exact formula at the moment! -- but I want to do it vectorised, or with a fast internal function.
However, I want to be able to take n to be large, so would prefer a faster way than this. (Of course, I could change this to a parfor-loop or do it on the GPU; these aren't practical for my current situation, so I'd prefer a more direct version.)
I've looked at stuff like dec2base, num2str, str2num, base2dec and so on, but with no luck. Any suggestion would be most appreciated.
Regarding speed and space, any preallocation for integers in the range [0, q-1] or similar would also be good.
To be clear, I am looking for an algorithm that works for any q and n, converting any number in the range [0,q^n - 1].
You can use dec2base and replace the characters by numbers:
x = 23;
b = 12;
[~, result] = ismember(dec2base(x,b), ['0':'9' 'A':'Z']);
result = result -1;
gives
>> result
result =
1 11
This works for base up to 36 only, due to dec2base limitations.
For any base (possibly above 36) you need to do the conversion manually. I once wrote a base2base function to do that (it's essentially long division). The number should be input as a vector of digits in the origin base, so you need dec2base(...,10) first. For example:
x = 125;
b = 6;
result = base2base(dec2base(x,10), '0':'9', b); % origin nunber, origin base, target base
gives
result =
3 2 5
Or if you need to specify the number of digits:
x = 125;
b = 6;
d = 5;
result = base2base(dec2base(x,10), '0':'9', b, d)
result =
0 0 3 2 5
EDIT (August 15, 2017): Corrected two bugs: handling of input consisting of all "zeros" (thanks to #Sanchises for noticing), and properly left-padding the output with "zeros" if needed.
function Z = base2base(varargin)
% Three inputs: origin array, origin base, target base
% If a base is specified by a number, say b, the digits are [0,1,...,d-1].
% The base can also be directly an array with the digits
% Fourth input, optional: how many digits the output should have as a
% minimum (padding with leading zeros, i.e with the first digit)
% Non-valid digits in origin array are discarded.
% It works with cell arrays. In this case it gives a matrix in which each
% row is padded with leading zeros if needed
% If the base is specified as a number, digits are numbers, not
% characters as in `dec2base` and `base2dec`
if ~iscell(varargin{1}), varargin{1} = varargin(1); end
if numel(varargin{2})>1, ax = varargin{2}; bx=numel(ax); else bx = varargin{2}; ax = 0:bx-1; end
if numel(varargin{3})>1, az = varargin{3}; bz=numel(az); else bz = varargin{3}; az = 0:bz-1; end
Z = cell(size(varargin{1}));
for c = 1:numel(varargin{1})
x = varargin{1}{c}; [valid, x] = ismember(x,ax); x = x(valid)-1;
if ~isempty(x) && ~any(x) % Non-empty input, all zeros
z = 0;
elseif ~isempty(x) % Non-empty input, at least a nonzero
z = NaN(1,ceil(numel(x)*log2(bx)/log2(bz))); done_outer = false;
n = 0;
while ~done_outer
n = n + 1;
x = [0 x(find(x,1):end)];
y = NaN(size(x)); done_inner = false;
m = 0;
while ~done_inner
m = m + 1;
t = x(1)*bx+x(2);
r = mod(t, bz); q = (t-r)/bz;
y(m) = q; x = [r x(3:end)];
done_inner = numel(x) < 2;
end
y = y(1:m);
z(n) = r; x = y; done_outer = ~any(x);
end
z = z(n:-1:1);
else % Empty input
z = []; % output will be empty (unless user has required left-padding) with the
% appropriate class
end
if numel(varargin)>=4 && numel(z)<varargin{4}, z = [zeros(1,varargin{4}-numel(z)) z]; end
% left-pad if required by user
Z{c} = z;
end
L = max(cellfun(#numel, Z));
Z = cellfun(#(x) [zeros(1, L-numel(x)) x], Z, 'uniformoutput', false); % left-pad so that
% result will be a matrix
Z = vertcat(Z{:});
Z = az(Z+1);
Matlab's internal dec2base command contains essentially what you are asking for.
It actually creates an array of base-10 digits before they are converted to a character array of '0'-'9' and 'A'-'Z' which is the reason for its limitation to bases <= 36.
So after removing the last step of character conversion from dec2base and modifying the error checking accordingly gives the function dec2basevect you were asking for.
The result will be a base-10 vector and you are no longer limited to bases <= 36. The most significant digit will be in index one of this vector. If you need it the other way round, i.e. least significant digit in index one, just do a fliplr to the result.
Due to copyrights by MathWorks, you have to make the necessary modifications to dec2baseon your own.