Matlab Codegen build error - c++

I am trying to convert the below Matlab code into C++ using codegen. However it fails at build and I get the error:
"??? Unless 'rows' is specified, the first input must be a vector. If the vector is variable-size, the either the first dimension or the second must have a fixed length of 1. The input [] is not supported. Use a 1-by-0 or 0-by-1 input (e.g., zeros(1,0) or zeros(0,1)) to represent the empty set."
It then points to [id,m,n] = unique(id); being the culprit. Why doesn't it build and what's the best way to fix it?
function [L,num,sz] = label(I,n) %#codegen
% Check input arguments
error(nargchk(1,2,nargin));
if nargin==1, n=8; end
assert(ndims(I)==2,'The input I must be a 2-D array')
sizI = size(I);
id = reshape(1:prod(sizI),sizI);
sz = ones(sizI);
% Indexes of the adjacent pixels
vec = #(x) x(:);
if n==4 % 4-connected neighborhood
idx1 = [vec(id(:,1:end-1)); vec(id(1:end-1,:))];
idx2 = [vec(id(:,2:end)); vec(id(2:end,:))];
elseif n==8 % 8-connected neighborhood
idx1 = [vec(id(:,1:end-1)); vec(id(1:end-1,:))];
idx2 = [vec(id(:,2:end)); vec(id(2:end,:))];
idx1 = [idx1; vec(id(1:end-1,1:end-1)); vec(id(2:end,1:end-1))];
idx2 = [idx2; vec(id(2:end,2:end)); vec(id(1:end-1,2:end))];
else
error('The second input argument must be either 4 or 8.')
end
% Create the groups and merge them (Union/Find Algorithm)
for k = 1:length(idx1)
root1 = idx1(k);
root2 = idx2(k);
while root1~=id(root1)
id(root1) = id(id(root1));
root1 = id(root1);
end
while root2~=id(root2)
id(root2) = id(id(root2));
root2 = id(root2);
end
if root1==root2, continue, end
% (The two pixels belong to the same group)
N1 = sz(root1); % size of the group belonging to root1
N2 = sz(root2); % size of the group belonging to root2
if I(root1)==I(root2) % then merge the two groups
if N1 < N2
id(root1) = root2;
sz(root2) = N1+N2;
else
id(root2) = root1;
sz(root1) = N1+N2;
end
end
end
while 1
id0 = id;
id = id(id);
if isequal(id0,id), break, end
end
sz = sz(id);
% Label matrix
isNaNI = isnan(I);
id(isNaNI) = NaN;
[id,m,n] = unique(id);
I = 1:length(id);
L = reshape(I(n),sizI);
L(isNaNI) = 0;
if nargout>1, num = nnz(~isnan(id)); end

Just an FYI, if you are using MATLAB R2013b or newer, you can replace error(nargchk(1,2,nargin)) with narginchk(1,2).
As the error message says, for codegen unique requires that the input be a vector unless 'rows' is passed.
If you look at the report (click the "Open report" link that is shown) and hover over id you will likely see that its size is neither 1-by-N nor N-by-1. The requirement for unique can be seen if you search for unique here:
http://www.mathworks.com/help/coder/ug/functions-supported-for-code-generation--alphabetical-list.html
You could do one of a few things:
Make id a vector and treat it as a vector for the computation. Instead of the declaration:
id = reshape(1:prod(sizI),sizI);
you could use:
id = 1:numel(I)
Then id would be a row vector.
You could also keep the code as is and do something like:
[idtemp,m,n] = unique(id(:));
id = reshape(idtemp,size(id));
Obviously, this will cause a copy, idtemp, to be made but it may involve fewer changes to your code.

Remove the anonymous function stored in the variable vec and make vec a subfunction:
function y = vec(x)
coder.inline('always');
y = x(:);
Without the 'rows' option, the input to the unique function is always interpreted as a vector, and the output is always a vector, anyway. So, for example, something like id = unique(id) would have the effect of id = id(:) if all the elements of the matrix id were unique. There is no harm in making the input a vector going in. So change the line
[id,m,n] = unique(id);
to
[id,m,n] = unique(id(:));

Related

nested list of lists of inegers - doing arithmetic operation

I have a list like below and need to firs add items in each list and then multiply all results 2+4 = 6 , 3+ (-2)=1, 2+3+2=7, -7+1=-6 then 6*1*7*(-6) = -252 I know how to do it by accessing indexes and it works (as below) but I also need to do it in a way that it will work no matter how many sublist there is
nested_lst = [[2,4], [3,-2],[2,3,2], [-7,1]]
a= nested_lst[0][0] + nested_lst[0][1]
b= nested_lst[1][0] + nested_lst[1][1]
c= nested_lst[2][0] + nested_lst[2][1] + nested_lst[2][2]
d= nested_lst[3][0] + nested_lst[3][1]
def sum_then_product(list):
multip= a*b*c*d
return multip
print sum_then_product(nested_lst)
I have tried with for loop which gives me addition but I don't know how to perform here multiplication. I am new to it. Please, help
nested_lst = [[2,4], [3,-2],[2,3,2], [-7,1]]
for i in nested_lst:
print sum(i)
Is this what you are looking for?
nested_lst = [[2,4], [3,-2],[2,3,2], [-7,1]] # your list
output = 1 # this will generate your eventual output
for sublist in nested_lst:
sublst_out = 0
for x in sublist:
sublst_out += x # your addition of the sublist elements
output *= sublst_out # multiply the sublist-addition with the other sublists
print(output)

How to perform caesar cipher logic using random key?

I want to take user input for message. Then I generate a random key using random package in python.
But how to shift each letter in message using key's ascii value to produce output as string only?
Example :
message = hi
random key generated = bi
encrypted message = "something in alphabets only like xh or mo."
use the objectype dictionary to map each character to another so that you create a new alphabet, and the loop through the dictionary and replace them using the dictionary
stringa = input()
swapa = {"A":"Q", "B":"A","C":"L"...}
for i in swapa:
stringa = stringa.replace(i,swapa[i])
print(stringa)
you could also take it a step fourther and encryot and decrypt using a keyword
ite = int(input())
for itar in range(ite):
keyw = list(input())
# removes dublicates and keep order
rem = set()
for i in keyw:
if keyw.count(i) > 1:
rem.add(i)
for i in rem:
keyw= keyw[::-1]
keyw.remove(i)
keyw= keyw[::-1]
keyw = "".join(keyw)
# sets up alfabet
linaalfa = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
linaalfa += " "*(len(keyw)-len(linaalfa)%len(keyw)) # adds spaces on the last line
linaalf = "".join([i for i in linaalfa if i not in keyw]) # removes dublicates
linaalf1 = [keyw]+[linaalf[x:x+len(keyw)] for x in range(0,len(linaalf),len(keyw))]
# alfa order find
order = dict()
for w,i in enumerate(sorted(keyw)):
order[keyw.index(i)] = w
# order in alfa ordder
orderalfa = ["".join([i[q] for i in linaalf1]) for q in range(len(keyw))] # now read by column
temp = [""]*len(orderalfa)
for w,i in enumerate(orderalfa):
temp[order[w]] = i
orderalfa = temp
orderalfa = "".join([x.strip() for x in orderalfa])
# relate to base alfabet
translate = dict()
encrypt = dict()
for w,i in enumerate(orderalfa):
translate[i] = linaalfa[w]
encrypt[linaalfa[w]] = i
# trans late message
lina = input().split()
outa = list()
for i in lina:
temp = ""
for q in i:
temp += translate[q]
outa.append(temp)
print(" ".join(outa))
here it takes the input
n # number of quaries
keyword
string that need to be operated
the last bit however is set to decrypt the message if you want it to encrupt it you need to replace the line
temp += translate[q]
to
temp += encrypt[q]
This takes a keyword and
removes dublicate letters in said keyword
Set the keyword in front of the an alfabet(a normal one)
and splits the alfabet up in peaces the same length as the keyword
places them above each other
orderes them in column order based on if the keyword's letter were written in alfabetical order
takes each coloumn and creats a new alphabet based on the each coloum put continualy after each other
this new alphabet now works as the new alphabet
for example if the beginning of the new alphabet were "HGJ" than A would be H, and B would be G and J would be C.
This is stil only a monoalphabetical encryption though.

Using For loop on nested list

I'm using a nested list to hold data in a Cartesian coordinate type system.
The data is a list of categories which could be 0,1,2,3,4,5,255 (just 7 categories).
The data is held in a list formatted thus:
stack = [[0,1,0,0],
[2,1,0,0],
[1,1,1,3]]
Each list represents a row and each element of a row represents a data point.
I'm keen to hang on to this format because I am using it to generate images and thus far it has been extremely easy to use.
However, I have run into problems running the following code:
for j in range(len(stack)):
stack[j].append(255)
stack[j].insert(0, 255)
This is intended to iterate through each row adding a single element 255 to the start and end of each row. Unfortunately it adds 12 instances of 255 to both the start and end!
This makes no sense to me. Presumably I am missing something very trivial but I can't see what it might be. As far as I can tell it is related to the loop: if I write stack[0].append(255) outside of the loop it behaves normally.
The code is obviously part of a much larger script. The script runs multiple For loops, a couple of which are range(12) but which should have closed by the time this loop is called.
So - am I missing something trivial or is it more nefarious than that?
Edit: full code
step_size = 12, the code above is the part that inserts "right and left borders"
def classify(target_file, output_file):
import numpy
import cifar10_eval # want to hijack functions from the evaluation script
target_folder = "Binaries/" # finds target file in "Binaries"
destination_folder = "Binaries/Maps/" # destination for output file
# open the meta file to retrieve x,y dimensions
file = open(target_folder + target_file + "_meta" + ".txt", "r")
new_x = int(file.readline())
new_y = int(file.readline())
orig_x = int(file.readline())
orig_y = int(file.readline())
segment_dimension = int(file.readline())
step_size = int(file.readline())
file.close()
# run cifar10_eval and create predictions vector (formatted as a list)
predictions = cifar10_eval.map_interface(new_x * new_y)
del predictions[(new_x * new_y):] # get rid of excess predictions (that are an artefact of the fixed batch size)
print("# of predictions: " + str(len(predictions)))
# check that we are mapping the whole picture! (evaluation functions don't necessarily use the full data set)
if len(predictions) != new_x * new_y:
print("Error: number of predictions from cifar10_eval does not match metadata for this file")
return
# copy predictions to a nested list to make extraction of x/y data easy
# also eliminates need to keep metadata - x/y dimensions are stored via the shape of the output vector
stack = []
for j in range(new_y):
stack.append([])
for i in range(new_x):
stack[j].append(predictions[j*new_x + i])
predictions = None # clear the variable to free up memory
# iterate through map list and explode each category to cover more pixels
# assigns a step_size x step_size area to each classification input to achieve correspondance with original image
new_stack = []
for j in range(len(stack)):
row = stack[j]
new_row = []
for i in range(len(row)):
for a in range(step_size):
new_row.append(row[i])
for b in range(step_size):
new_stack.append(new_row)
stack = new_stack
new_stack = None
new_row = None # clear the variables to free up memory
# add a border to the image to indicate that some information has been lost
# border also ensures that map has 1-1 correspondance with original image which makes processing easier
# calculate border dimensions
top_and_left_thickness = int((segment_dimension - step_size) / 2)
right_thickness = int(top_and_left_thickness + (orig_x - (top_and_left_thickness * 2 + step_size * new_x)))
bottom_thickness = int(top_and_left_thickness + (orig_y - (top_and_left_thickness * 2 + step_size * new_y)))
print(top_and_left_thickness)
print(right_thickness)
print(bottom_thickness)
print(len(stack[0]))
# add the right then left borders
for j in range(len(stack)):
for b in range(right_thickness):
stack[j].append(255)
for b in range(top_and_left_thickness):
stack[j].insert(0, 255)
print(stack[0])
print(len(stack[0]))
# add the top and bottom borders
row = []
for i in range(len(stack[0])):
row.append(255) # create a blank row
for b in range(top_and_left_thickness):
stack.insert(0, row) # append the blank row to the top x many times
for b in range(bottom_thickness):
stack.append(row) # append the blank row to the bottom of the map
# we have our final output
# repackage this as a numpy array and save for later use
output = numpy.asarray(stack,numpy.uint8)
numpy.save(destination_folder + output_file + ".npy", output)
print("Category mapping complete, map saved as numpy pickle: " + output_file + ".npy")

Concatenate all possible strings using one entry per variable number of lists

It's the variable number of lists that is confusing me. It's easy to (pseudo code)...
for i=1 to list1_size
for ii=1 to list2_size
for iii=1 to list3_size
results_list.add(list1[i]+list2[ii]+list3[iii])
... but I could do with a nudge in the right direction regarding how to do this with a varying number of lists.
I've started with getting a table of the number of entries in each list to work through and it does seem like a bit of recursion is required but from there I'm drawing a blank.
edit: To clarify, what I am looking for is...
Input: A varying number of lists/tables with a varying numbers of entries.
{"A","B","C"} {"1","2","3","4"} {"*","%"}
Output:
{"A1*", "A1%", "A2*", "A2%", "A3*", "A3%", "A4*", "A4%",
"B1*", "B1%", "B2*", "B2%", "B3*", "B3%", "B4*", "B4%",
"C1*", "C1%", "C2*", "C2%", "C3*", "C3%", "C4*", "C4%"}
local list_of_lists = {{"A","B","C"}, {"1","2","3","4"}, {"*","%"}}
local positions = {}
for i = 1, #list_of_lists do
positions[i] = 1
end
local function increase_positions()
for i = #list_of_lists, 1, -1 do
positions[i] = positions[i] % #list_of_lists[i] + 1
if positions[i] > 1 then return true end
end
end
local function get_concatenated_selection()
local selection = {}
for i = 1, #list_of_lists do
selection[i] = list_of_lists[i][positions[i]]
end
return table.concat(selection)
end
local result = {}
repeat
table.insert(result, get_concatenated_selection())
until not increase_positions()

Search for sequences in multiple vectors

What is the easiest way to find the sequence I need in multiple vectors in R without using loops?
For example, I need to find vectors their "yahoo" comes after "google"(only order matters).
seq = c("google","yahoo")
Matches:
vec1 = c("smth","google","smth","yahoo","smth")
Not matches:
vec2 = c("smth","yahoo","smth","google","smth")
Check this assuming you have unique values for yahoo and google:
library(dplyr)
dt = data.frame(vec1 = c("smth","google","smth","yahoo","smth"))
dt = dt %>% mutate(row = row_number()) # get the row number for each value of vec1
dt$row[dt$vec1=="google"] < dt$row[dt$vec1=="yahoo"] # returns T/F
Modify this if you don't have unique vec1 values. This one uses the max row number:
dt = data.frame(vec1 = c("smth","google","smth","yahoo","smth"))
dt = dt %>% mutate(row = row_number()) %>%
group_by(vec1) %>% summarise(row = max(row)) # get the max row number for each unique value of vec1
dt$row[dt$vec1=="google"] < dt$row[dt$vec1=="yahoo"]
You can use which function to find the positions of your search terms within a given vector
which(vec1=="google")[1] < which(vec1=="yahoo")[1]
use [1] if you're interested only in the first occurrence of each search term.