let us consider following code for impulse function
function y=impulse_function(n);
y=0;
if n==0
y=1;
end
end
this code
>> n=-2:2;
>> i=1:length(n);
>> f(i)=impulse_function(n(i));
>>
returns result
f
f =
0 0 0 0 0
while this code
>> n=-2:2;
>> for i=1:length(n);
f(i)=impulse_function(n(i));
end
>> f
f =
0 0 1 0 0
in both case i is 1 2 3 4 5,what is different?
Your function is not defined to handle vector input.
Modify your impluse function as follows:
function y=impulse_function(n)
[a b]=size(n);
y=zeros(a,b);
y(n==0)=1;
end
In your definition of impulse_function, whole array is compared to zero and return value is only a single number instead of a vector.
In the first case you are comparing an array to the value 0. This will give the result [0 0 1 0 0], which is not a simple true or false. So the statement y = 0; will not get executed and f will be [0 0 0 0 0] as shown.
In the second you are iterating through the array value by value and passing it to the function. Since the array contains the value 0, then you will get 1 back from the function in the print out of f (or [0 0 1 0 0], which is an impulse).
You'll need to modify your function to take array inputs.
Perhaps this example will clarify the issue further:
cond = 0;
if cond == 0
disp(cond) % This will print 0 since 0 == 0
end
cond = 1;
if cond == 0
disp(cond) % This won't print since since 1 ~= 0 (not equal)
end
cond = [-2 -1 0 1 2];
if cond == 0
disp(cond) % This won't print since since [-2 -1 0 1 2] ~= 0 (not equal)
end
You could define your impulse function simply as this one -
impulse_function = #(n) (1:numel(n)).*n==0
Sample run -
>> n = -6:4
n =
-6 -5 -4 -3 -2 -1 0 1 2 3 4
>> out = impulse_function(n)
out =
0 0 0 0 0 0 1 0 0 0 0
Plot code -
plot(n,out,'o') %// data points
hold on
line([0 0],[1 0]) %// impulse point
Plot result -
You can write an even simpler function:
function y=impulse_function(n);
y = n==0;
Note that this will return y as a type logical array but that should not affect later numerical computations.
Related
I have a series of values that are each being stored as UInt16. Each of these numbers represents a bitmask - these numbers are commands that have been sent to a microprocessor telling it which pins to set high or low. I would like to parse this arrow of commands to find out which pins were being set high each time in such a way that is easier to analyse later.
Consider the example value 0x3c00, which in decimal is 15360 and in binary is 0011110000000000. Currently I have the following function
function read_message(hex_rep)
return findall.(x -> x .== '1',bitstring(hex_rep))
end
Which gets called on every element of the array of UInt16. Is there a better/more efficient way of doing this?
The best approach probably depends on how you want to handle vectors of hex-values. But here's an approach for processing a single hex which is much faster than the one in the OP:
function readmsg(x::UInt16)
N = count_ones(x)
inds = Vector{Int}(undef, N)
if N == 0
return inds
end
k = trailing_zeros(x)
x >>= k + 1
i = N - 1
inds[N] = n = 16 - k
while i >= 1
(x, r) = divrem(x, 0x2)
n -= 1
if r == 1
inds[i] = n
i -= 1
end
end
return inds
end
I can suggest padding your vector into a Vector{UInt64} and use that to manually construct a BitVector. The following should mostly work (even for input element types other than UInt16), but I haven't taken into account specific endianness you might want to respect:
julia> function read_messages(msgs)
bytes = reinterpret(UInt8, msgs)
N = length(bytes)
nchunks, remaining = divrem(N, sizeof(UInt64))
padded_bytes = zeros(UInt8, sizeof(UInt64) * cld(N, sizeof(UInt64)))
copyto!(padded_bytes, bytes)
b = BitVector(undef, N * 8)
b.chunks = reinterpret(UInt64, padded_bytes)
return b
end
read_messages (generic function with 1 method)
julia> msgs
2-element Vector{UInt16}:
0x3c00
0x8000
julia> read_messages(msgs)
32-element BitVector:
0
0
0
0
0
0
0
0
0
⋮
0
0
0
0
0
0
0
1
julia> read_messages(msgs) |> findall
5-element Vector{Int64}:
11
12
13
14
32
julia> bitstring.(msgs)
2-element Vector{String}:
"0011110000000000"
"1000000000000000"
(Getting rid of the unnecessary allocation of the undef bit vector would require some black magic, I belive.)
I know how to find the number of triangles in an adjacency matrix.
tri = trace(A^3) / 6
But i require to find the nodes so that i can finally find the value of the edges from adjacency matrix since it's a sign graph. Is there already existing function which does that?
Taking the power of the adjacency matrix loses information about the intermediate nodes. Instead of a 2-dimensional matrix, we need 3 dimensions.
Given a graph:
and its adjacency matrix:
A =
0 0 0 0 1 1 0 1 0 0
0 0 0 1 0 1 0 0 0 0
0 0 0 1 0 0 0 1 0 1
0 1 1 0 1 0 1 0 0 0
1 0 0 1 0 0 1 0 0 0
1 1 0 0 0 0 0 1 1 0
0 0 0 1 1 0 0 0 1 0
1 0 1 0 0 1 0 0 0 0
0 0 0 0 0 1 1 0 0 0
0 0 1 0 0 0 0 0 0 0
Compute the 3d matrix T such that T(i,j,k) == 1 iff there is a path in the graph i=>j=>k=>i.
T = and(A, permute(A, [3 1 2]))
This is the equivalent of squaring the adjacency matrix, but keeping the path information. and is used here instead of multiplication in case A is a weighted adjacency matrix. If you sum along the 2nd dimension, you'll get A^2:
>> isequal(squeeze(sum(T,2)), A^2)
ans = 1
Now that we've got the paths of length 2, we just need to filter so we keep only the paths that return to their starting points.
T = and(T, permute(A.', [1 3 2])); % Transpose A in case graph is directed
Now, if T(i,j,k) == 1, then there is a triangle starting at node i, through nodes j and k and returning to node i. If you want to find all such paths:
[M,N,P] = ind2sub(size(T), find(T));
P = [M,N,P];
P will be a list of all triangular paths:
P =
8 6 1
6 8 1
7 5 4
5 7 4
7 4 5
4 7 5
8 1 6
1 8 6
5 4 7
4 5 7
6 1 8
1 6 8
In this case we get 12 paths. All paths in an undirected graph have 6 duplicates: one starting at each triangle point, times 2 directions. This gives the same results as trace:
>> trace(A^3)
ans = 12
If you want to remove the duplicates, the simplest way for triangles is to simply sort the vertex ordering and then take the unique rows of the list. This works for triangles only because all permutations of the nodes in the cycle are present. For longer cycles, this will not work.
P = unique(sort(P, 2), 'rows');
P =
1 6 8
4 5 7
Here is a solution using matrix multiplication:
C = (A * A.') & A;
[x, y] = find(tril(C));
n = numel(x);
D = sparse([x; y], [1:n 1:n].', 1, size(A,1), n);
[X, ~, V] = find(C * D);
tri = [x y X(V == 2)]
tri = unique(sort(tri, 2), 'rows');
First we need to know what are triangle nodes. Two nodes are triangle nodes if they have a common neighbor and both of them are neighbor of each other.
We take the definition to compute an adjacency matrix C that only contains triangle nodes and all other node are removed.
The expression A * A.' selects nodes that have common neighbors and the & A operator says that those nodes that have common neighbors should by neighbor of each other.
Now we can use [x, y] = find(tril(C)); to extract the first and the second points of each triangle as x and y respectively.
For the third node we need to find a node that has x and y as its neighbors. As before we can use the multiplication of boolean matrix trick to speed up the computation.
Finally the result tri has duplicates that should be remove using unique and sort.
I am trying to recode all values in a dataframe using an if statement.
I have:
a b c
0 .05 0
-.02 0 -.06
-.01 0 -.08
0 0 .09
I want:
a b c
0 1 0
0 0 -1
0 0 -1
0 0 1
I have tried several things like:
def unit_weighted (x):
if x >= 0.05:
return 1
elif x <= -0.05:
return -1
else:
return 0
new = df.apply(unit_weighted, axis=0)
I get this error:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
I don't want to have to list all the columns like this:
new = df['a'].apply(unit_weighted, axis=0)
new = df['b'].apply(unit_weighted, axis=0)
Any help please?
Just remove the axis=0, and it will apply element-wise.
This code :
R = ql.matrix([ [0,0,0,0,1,0],
[0,0,0,1,0,1],
[0,0,100,1,0,0],
[0,1,1,0,1,0],
[1,0,0,1,0,0],
[0,1,0,0,0,0] ])
is from :
https://github.com/PacktPublishing/Artificial-Intelligence-By-Example/blob/47bed1a88db2c9577c492f950069f58353375cfe/Chapter01/MDP.py
R is defined as the "Reward matrix for each state" . What are the states and rewards in this matrix ?
# Reward for state 0
print('R[0,]:' , R[0,])
# Reward for state 0
print('R[1,]:' , R[1,])
prints :
R[0,]: [[0 0 0 0 1 0]]
R[1,]: [[0 0 0 1 0 1]]
Is [0 0 0 0 1 0] state0 & [0 0 0 1 0 1] state1 ?
According to the book that uses that example, R represents the reward of the transitions from one current state s to another next state s'.
Specifically, R is associated with the following graph:
Each line in the matrix R represents a letter from A to F, and each column represents a letter from A to F. The 1 values represent the nodes of the graphs. I.e., R[0,]: [[0 0 0 0 1 0]] means that you can go from state s=A to next state s'=E and receive a reward of 1. Similarly, R[1,]: [[0 0 0 1 0 1]] means that you receive a reward of 1 if you go from B to F or D. The goal seems to be achieving and remaining in C, which obtains the largest reward.
I am trying to turn each element in a matrix from a value from 1 to 10 into a 10x1 zeros matrix where the element of the zeros matrix corresponding to the value of the original element is equal to 1.
Here is the code:
function q = convert
% Convert y matrix values to 10x1 vector
load('y.mat');
ZERO = zeros(10,1);
% Set 10x1 Matrix of zeros
for i = 1:length(y)
ZERO(y(i)) = 1; % Set yth element of ZERO to 1
y(i) = ZERO; % Set ith element of y equal to new zero
ZERO = zeros(10,1); % Re-establish zero
endfor
When I run it I get the error A(I) = X: X must have the same size as I. Where the matrix I am trying to input does not agree with the size of element of matrix y. Can I get around this?
Sample input:
y = [1; 2; 3; 4; 5]
Sample output:
y = [[1;0;0;0;0;0;0;0;0;0],
[0;1;0;0;0;0;0;0;0;0],
[0;0;1;0;0;0;0;0;0;0],
[0;0;0;0;1;0;0;0;0;0],
[0;0;0;0;0;1;0;0;0;0]]
I'm going to make a couple of assumptions:
You want the return value to be q as in the function signature, and
You want the output in your sample case to be a 10x5 matrix like so:
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
Fixing the loop
The problem that gives the error is that you're assigning a 10x1 vector ZERO to a single (scalar) element of the 5x1 vector y:
y(i) = ZERO;
A vector doesn't fit in a scalar. But even if you change this to assign ZERO to a column of y, it doesn't fit because the lengths of the columns are different. That's not what you want to do anyway, because if it had worked, you would have just wiped out the values in y. So let's set the values in the columns of the output array q. (Changes are marked with <== in the comments.)
function q = convert
% Convert y matrix values to 10xn matrix
%load('y.mat');
y = [1; 2; 3; 4; 5]; % <== replace load temporarily
% Set 10x1 Matrix of zeros
ZERO = zeros(10,1);
% Preallocate output array
q = zeros(10, length(y)); % <== preallocate for speed
for i = 1:length(y)
ZERO(y(i)) = 1; % Set yth element of ZERO to 1
q(:,i) = ZERO; % <== Set ith *column* of *q* equal to new zero
ZERO = zeros(10,1); % Re-establish zero
endfor
Improving the loop
This will work, but if you preallocate q, you've already got the correct number of ZERO vectors, so why not just set the values directly?
function q = convert
% Convert y matrix values to 10xn matrix
%load('y.mat');
y = [1; 2; 3; 4; 5]; % <== replace load temporarily
% Preallocate output array
q = zeros(10, length(y)); % <== preallocate for speed
for i = 1:length(y)
q(y(i),i) = 1; % <== Set element at y(ith) row and ith column of q to 1
endfor
Killing the loop
Either of these loops will give you the desired results, but you can do this whole operation without a loop. This answer summarizes different ways to do this, but I'll just show you the first one using sub2ind:
function q = convert
% Convert y matrix values to 10xn matrix
%load('y.mat');
y = [1; 2; 3; 4; 5]; % <== replace load temporarily
% Preallocate output array
q = zeros(10, length(y)); % <== preallocate for speed
idx = sub2ind(size(q), y, [1:length(y)].');
q(idx) = 1;
Final note
It's best not to use i as a variable name in Octave/MATLAB. It's natural in other languages, but in MATLAB i (or j) is the imaginary unit. If you use i as a variable, it shadows that constant. That doesn't make a difference if you use 1i (or 1j) when assigning complex values, but you're going to have to remember to do that and at some point you're going to forget.