I have a matrix of the form:
m = 1, 0, 10, 20, 30, 40, 50;
2, 1, 11, 20, 30, 40, 50;
3, 0, 12, 20, 30, 40, 50;
4, 1, 12, 21, 30, 40, 50;
For a given column index (say 3) and row index (say 1), I'd like to filter out all rows that have the same values to the right of that column in that row. Using the above example of m, columnIndex = 3, and rowIndex = 1 (noted with asterisks):
**
f(m, 3) = * 1, 0, 10, 20, 30, 40, 50; % [20, 30, 40, 50] matches itself, include
2, 1, 11, 20, 30, 40, 50; % [20, 30, 40, 50] matches the subvector in row 1, include
3, 0, 12, 20, 30, 40, 50; % [20, 30, 40, 50] matches the subvector in row 1, include
4, 1, 12, 21, 30, 40, 50; % [21, 30, 40, 50] does NOT match the subvector in row 1, filter this out
How can I achieve this behavior? I've tried this, but I'm getting an dimension mismatch error.
key = data( rowIndex, columnIndex:end );
filteredData = ( data( :, columnIndex:end ) == key );
Index those that you keep with == within bsxfun():
r = 3;
c = 2;
idx = all(bsxfun(#eq, m(:,c:end),m(r,c:end)),2);
m(idx,:)
I think you're looking to use the isequal operator, documented here.
isequal(m(1,columnIndex:end),key)
and here's kind of an inefficient one liner :-)
cellfun(#(x) isequal(key,x),mat2cell(m(:,columnIndex:end),ones(1,size(m,2)-columnIndex+1)))
Here's how it goes
Change the matrix to a cell array of the subvectors we're interested in: mat2cell(m(:,columnIndex:end),ones(1,size(m,2)-columnIndex+1))
Anonymous function to run on each cell element: #(x) isequal(key,x)
Function to cause each cell element to be passed to the anonymous function, cellfun
My answer using m above as an example:
cellfun(#(x) isequal(key,x),mat2cell(m(:,columnIndex:end),ones(1,size(m,2)-columnIndex+1)))
ans =
1
1
1
0
HTH!
Related
This is my code for sobel filter:
def init_f(shape, dtype=None):
sobel_x = tf.constant([[-5, -4, 0, 4, 5], [-8, -10, 0, 10, 8], [-10, -20, 0, 20, 10], [-8, -10, 0, 10, 8], [-5, -4, 0, 4, 5]])
ker = np.zeros(shape, dtype)
ker_shape = tf.shape(ker)
kernel = tf.tile(sobel_x, ker_shape)//*Is this correct?*
return kernel
model.add(Conv2D(filters=30, kernel_size=(5,5), kernel_initializer=init_f, strides=(1,1), activation='relu'))
So far I have managed to do this.
But, this gives me error:
Shape must be rank 2 but is rank 4 for 'conv2d_17/Tile' (op: 'Tile') with input shapes: [5,5], [4].
Tensorflow Version: 2.1.0
You're close, but the args to tile don't appear to be correct. That is why you're getting the error "Shape must be rank 2 but is rank 4 for..." You're sobel_x must be a rank 4 tensor, so you need to add two more dimensions. I used reshape in this example.
from tensorflow import keras
import tensorflow as tf
import numpy
def kernelInitializer(shape, dtype=None):
print(shape)
sobel_x = tf.constant(
[
[-5, -4, 0, 4, 5],
[-8, -10, 0, 10, 8],
[-10, -20, 0, 20, 10],
[-8, -10, 0, 10, 8],
[-5, -4, 0, 4, 5]
], dtype=dtype )
#create the missing dims.
sobel_x = tf.reshape(sobel_x, (5, 5, 1, 1))
print(tf.shape(sobel_x))
#tile the last 2 axis to get the expected dims.
sobel_x = tf.tile(sobel_x, (1, 1, shape[-2],shape[-1]))
print(tf.shape(sobel_x))
return sobel_x
x1 = keras.layers.Input((128, 128, 3))
cvl = keras.layers.Conv2D(30, kernel_size=(5,5), kernel_initializer=kernelInitializer, strides=(2,2), activation='relu')
model = keras.Sequential();
model.add(x1)
model.add(cvl)
data = numpy.ones((1, 128, 128, 3))
data[:, 0:64, 0:64, :] = 0
pd = model.predict(data)
print(pd.shape)
d = pd[0, :, :, 0]
for row in d:
for col in row:
m = '0'
if col != 0:
m = 'X'
print(m, end="")
print("")
I looked at using expand_dims instead of reshape but there didn't appear any advantage. broadcast_to seems ideal, but you still have to add the dimensions, so I don't think it was better than tile.
Why 30 filters of the same filter though? Are they going to be changed afterwards?
I wrote a script (at the bottom) to solve the travelling salesman problem (TSP) with the branch and bound algorithm. My script allows two input possiblities.
1) Coordinates of the cities in an excel file with the file name 'Test'. A city can be described also by more than two dimensions. Later the script generates the distance matrix.
2) Insert direct the distance matrix in the script.
At the moment the second input variant is active for my code. (15 cities, A-O)
I have no programming experience and therefore my code looks maybe a little bit inelegant. Nevertheless I would like to measure the performance of the algorithm. What are the best ways to achieve that? Is it possible to establish a performance graph? Additionally I would like to visualize the results. Is it possible to generate a map with the city connections or even a branch and bound tree?
I hope someone could help me
Best
clear all
clc
% Choose between two input possibilities: Coordinates in Excel file
% 'Test'from different cities or insert distance matrix direct here in script
% %%%Input coordinates of the cities via Excel file
% data = xlsread('Test.xlsx',1)
% dist = dist(data(:,2:5)') % how many coordinates are necessary to describe the location from one city
% dist(dist==0) = inf
%%%Input directly distance matrix
% Input information
A = [inf, 4, 12, 7, 4, 1, 2, 8, 4, 6, 7, 12, 3, 5, 20];
B = [5, inf, 20, 18, 6, 3, 4, 8, 9, 23, 1, 12, 5, 4, 9];
C = [11, 5, inf, 6, 1, 5, 6, 8, 7, 12, 31, 5, 1, 14, 5];
D = [10, 2, 3, inf, 5, 7, 8, 8, 6, 21, 4, 7, 5, 5, 1];
E = [1, 2, 6, 9, inf, 9, 10, 8, 45, 12, 11, 5, 6, 2, 11];
F = [17, 7, 6, 5, 11, inf, 12, 8, 63, 1, 2, 3, 12, 4, 8];
G = [11, 8, 3, 9, 3, 5, inf, 4, 6, 8, 1, 3, 12, 4, 8];
H = [12, 14, 2, 5, 4, 8, 4, inf, 12, 4, 1, 23, 7, 4, 56];
I = [4, 1, 2, 8, 4, 6, 7, 12, 3, inf, 7, 5, 6, 12, 14];
J = [6, 1, 5, 6, 8, 7, 12, 31, 5, 1, inf, 12, 1, 2, 6];
K = [7, 8, 8, 6, 21, 4, 7, 5, 5, 1, 11, inf, 13, 1, 2];
L = [1, 6, 1, 5, 6, 8, 7, 12, 8, 9, 10, 12, inf, 7, 5];
M = [8, 4, 6, 7, 12, 3, 8, 4, 6, 7, 12, 3, inf, 14, 15];
N = [21, 4, 7, 5, 5, 1, 21, 4, 7, 5, 5, 1,13, inf, 1];
O = [4, 12, 7, 4, 1, 2, 8, 4, 6, 7, 12, 3, 5, 20, inf];
% Generate distance matrix
dist = [A; B; C; D; E; F; G; H; I; J; K; L; M; N; O]
% Initalization
MaxCity = length(dist);
i = 1;
n = 1;
Parentcity = 1;
Childcity = 0;
% Array
costarray = zeros(MaxCity, 2);
wayarray = zeros(MaxCity, 2);
wayarray(1,:)=[1 0]
% Reduktion und Kosten der ParentCity
row_reduction = min(dist, [], 2);
row_reduction(isinf(row_reduction)) = 0;
M_row_reduced = dist - row_reduction;
column_reduction = min(M_row_reduced);
M_working = M_row_reduced - column_reduction;
M_working(isnan(M_working)) = inf;
M_reduced = M_working;
costparent = sum(row_reduction) + sum(column_reduction);
for n = [n:1:MaxCity] % levels der baumstruktur
for i = [i:1:MaxCity]; % childcity i= childcity
if i == Parentcity ||i==1
cost = inf;
else
M_working= M_reduced;
M_working(Parentcity, :) = inf;
M_working(:, i) = inf;
M_working(i, Parentcity) = inf;
M_working(Parentcity,i) = 0; %!!!!
row_reduction = min(M_working, [], 2);
row_reduction(isinf(row_reduction)) = 0;
M_row_reduced = M_working - row_reduction;
column_reduction = min(M_row_reduced);
M_working = M_row_reduced - column_reduction;
M_working(isnan(M_working)) = inf;
cost = costparent+ sum(row_reduction) + sum(column_reduction)+ M_reduced(Parentcity, i);
end
costarray(i, :) = [i,cost];
end
i = 1;
% minimum der cost array finden
[M, I] = min(costarray);
childcity = I(1, 2);
costparent = M(1, 2);
wayarray(n +1, :) = [childcity, dist(wayarray(n,1),childcity)]; %änderung!!
% nimm childcity, reduziere matrix für diese
M_working=M_reduced;
M_working(Parentcity, childcity) = inf;
M_working(:, childcity) = inf;
M_working(childcity, Parentcity) = inf;
M_working(Parentcity,childcity) = 0; %!!!!
row_reduction = min(M_working, [], 2);
row_reduction(isinf(row_reduction)) = 0;
M_row_reduced = M_working - row_reduction;
column_reduction = min(M_row_reduced);
M_working = M_row_reduced - column_reduction;
M_working(isnan(M_working)) = inf;
M_reduced=M_working;
Parentcity = childcity;
end
wayarray(n+1,2)=dist(wayarray(n,1),1)
gesamtlaenge=sum(wayarray(:,2))
I have the following code for positioning some subplots:
fig = figure;
fig.Units = 'centimeters';
fig.Position(3:4) = [25 25];
plotPositions = [ 3, 21, 7, 7;
12, 21, 7, 7;
];
nPlots=length(plotPositions); % shorthand variable for convenience
hAx=zeros(nPlots,1); % preallocate array for axes/subplot handles
for i = 1:length(plotPositions)
plotHandle = subplot(3, 2, i);
plotHandle.Units = 'centimeters';
plotHandle.Position = plotPositions(i,:);
hAx(i)=subplot(3, 2, i);
axis(hAx(i),[ -300 300 0 150]); %
end
If I use
plotPositions = [ 3, 21, 7, 7;
12, 21, 7, 7;
3, 12, 7, 7;
12, 12, 7, 7;
3, 3, 7, 7;
12, 3, 7, 7];
it works, but if use
plotPositions = [ 3, 21, 7, 7;
12, 21, 7, 7;
];
it does not work, and I'm getting the error:
Matrix dimensions must agree.
Index exceeds matrix dimensions.
What's going on?
You shouldn't be using the function length but instead the function size(...,1) to count the rows of plotPositions. length is actually max(size(vec)), which is 6 (number of rows, correctly) in the "working" case, and 4 (number of columns) in the non-working one.
Thus, in the 2nd case you're actually trying to access "nonexistent" rows, so MATLAB complains....
So my problem is, I'd like to do this without the for loop. Geting the prod() of multiple vectors but of different lengths.
I am dealing with rays intersecting voxels. I typically have 1e6 rays and 1e5 voxels, but this can vary.
intxRays is a list of rays that have intersected voxels.
gainList is a one dimensional vector, each element has a value that corresponds to a specific ray voxel intersection calculated previously (actually with the help of you lovely lot here).
rayIntxStart and rayIntxEnd are vectors of indices for, where in the gainlist array, each ray's corresponding values start and end (they're all in order).
Here is the code and some examples and expected outputs.
gainSum = zeros(1, 5);
% only interested in the intx uniques
intxSegCtr = 1;
% loop through all of the unique segments
for rayCtr = 1:max(intxRays)
if rayCtr == intxRays(intxSegCtr)
startInd = rayIntxStart(intxSegCtr);
endInd = rayIntxEnd(intxSegCtr);
% find which rows correspoond to those segements
gainVals = gainList(startInd:endInd);
gainProd = prod(gainVals);
% get the product of the gains for those voxels
gainSumIdx = intxRays(intxSegCtr);
gainSum(gainSumIdx) = gainProd;
% increment counter
intxSegCtr = intxSegCtr + 1;
end
end
Example data for five rays and nine voxels. Assume the voxel gain array looked like this (for simplicity) for nine voxels (used in previous step).
voxelGains = 10:10:90;
Now say rays 1 and 3 don't hit anything, ray 2 hits voxels 1 and 2, ray 4 hits voxels 2:7
and ray 5 hits voxels 6:9
intxRays = [2, 4, 5];
gainList = [10, 20, 20, 30, 40, 50, 60, 70, 60 70, 80, 90];
rayIntxStart = [1, 3, 9];
rayIntxEnd = [2, 8, 12];
For these numbers the above code would give as a result:
gainSum = [0, 200, 0, 5.0400e+09, 3.024e+07];
I hope this all makes sense.
When I developed it I was using far smaller ray and voxel numbers and it worked fine. As I'm moving up though, the major bottleneck in my code is this loop. Actually just the gainVals and gainProd assignment is like 80% and 15% of my runtime on their own.
This is the only method I can find that works, padding and the like won't work due to the sizes involved.
Is there a way to get the value I want, without this loop?
Many thanks!
ok this is a very small performance boost, but it might help. for testing the matrix way without the loop a bigger data sample is needed.
These are 3 soultions, your original, an optimized and the optimized way as a oneliner. could you please try if this is already doing something for you?
clear all
% orignial loop through all Rays
intxRays = [2, 4, 5];
gainList = [10, 20, 20, 30, 40, 50, 60, 70, 60 70, 80, 90];
rayIntxStart = [1, 3, 9];
rayIntxEnd = [2, 8, 12];
gainSum = zeros(1, 5);
tic
% only interested in the intx uniques
intxSegCtr = 1;
% loop through all of the unique segments
for rayCtr = 1:max(intxRays)
if rayCtr == intxRays(intxSegCtr)
startInd = rayIntxStart(intxSegCtr);
endInd = rayIntxEnd(intxSegCtr);
% find which rows correspoond to those segements
gainVals = gainList(startInd:endInd);
gainProd = prod(gainVals);
% get the product of the gains for those voxels
gainSumIdx = intxRays(intxSegCtr);
gainSum(gainSumIdx) = gainProd;
% increment counter
intxSegCtr = intxSegCtr + 1;
end
end
toc
clear all
%loop insted of every single one to max just through the intxRays
intxRays = [2, 4, 5];
gainList = [10, 20, 20, 30, 40, 50, 60, 70, 60 70, 80, 90];
rayIntxStart = [1, 3, 9];
rayIntxEnd = [2, 8, 12];
gainSum = zeros(1, 5);
tic
for rayCtr=1:length(intxRays)
%no if as you just go through them
%intxRays(rayCtr) is the corresponding element
startInd = rayIntxStart(rayCtr);
endInd = rayIntxEnd(rayCtr);
% find which rows correspoond to those segements
gainVals = gainList(startInd:endInd);
gainProd = prod(gainVals);
% get the product of the gains for those voxels and set them to the ray
gainSum(intxRays(rayCtr)) = gainProd;
end
%disp(gainSum);
toc
clear all
%same as above, but down to 1 line so no additional values are generated
intxRays = [2, 4, 5];
gainList = [10, 20, 20, 30, 40, 50, 60, 70, 60 70, 80, 90];
rayIntxStart = [1, 3, 9];
rayIntxEnd = [2, 8, 12];
gainSum = zeros(1, 5);
tic
for rayCtr=1:length(intxRays)
gainSum(intxRays(rayCtr))=prod(gainList(rayIntxStart(rayCtr):rayIntxEnd(rayCtr)));
end
toc
I have a Matlab object of integer keys in the range 1:1:7 e.g.
[3, 1, 4, 5, 6]
I also have a size 7 vector containing an associated value for each integer key, e.g.
vals = (10, 20, 30, 4000, 50, 60, 70)
what is the most efficient way to create a matrix of the values using the keys as indices, e.g. a matrix
[30, 10, 4000, 50, 60]
(in reality the key object is 6D). Must I loop?
For the case of a 1D matrix a general approach could be:
keys=[3, 1, 4, 5, 6];
vals = [10, 20, 30, 4000, 50, 60, 70]
m=vals(keys)
With this approach you use the values stored in the keys array as indices of the vals array. You can find more information about array insdexing here.
In a more general case in which keys has n rows (3 in the following example):
keys=[3, 1, 4, 5, 6;
1 3 2 4 6 ;
7 6 5 4 3];
vals = [10, 20, 30, 4000, 50, 60, 70]
m=reshape(vals(keys(:)),size(keys))
Hope this helps.
Qapla'
I think this should work. If I got the question.
inds = [3, 1, 4, 5, 6];
vals = inds;
vals(vals==1) = 10;
vals(vals==2) = 20;
vals(vals==3) = 30;
vals(vals==4) = 4000;
vals(vals==5) = 50;
vals(vals==6) = 60;
Is it like that?