Matlab Codegen: Does not support anonymous functions - c++

I am attempting to change some Matlab code into C++ however when I use %#codegen the error "Code generation does not support anonymous functions" appears next to vec = #(x) x(:); . Below is the Matlab function. What can I change to remove this error?
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

You can use following function and comment the anonymous function
function x=vec( id )
x = id(:);
end
This basically does same what your anonymous is achieving

MATLAB Coder supports anonymous functions since R2016b. The above example works with the latest version of MATLAB Coder (checked 11/30/2021).

Related

How to get all solutions for an integer program in ortools?

I am trying to get all solutions for a Mixed Integer program through ortools. I have two lists x and y of size 4. I want to get all solutions which satisfy sum(x) = 4 * sum(y). I created a function which takes list of past solutions as input and returns next solution. I am able to get only 2 solutions even though there are more. What am I doing wrong here?
I am expecting the following solutions
Solution 1:
xs1 = [0,0,0,0], ys1 = [0,0,0,0]
Solution 2:
xs2 = [4,0,0,0], ys2 = [1,0,0,0]
Solution 3:
xs3 = [0,4,0,0], ys3 = [1,0,0,0]
Solution 4:
xs4 = [0,0,4,0], ys4 = [0,0,1,0]
and soon on
from ortools.linear_solver import pywraplp
def opt(xs, ys):
solver = pywraplp.Solver.CreateSolver('SCIP')
infinity = solver.infinity()
# x and y are integer non-negative variables.
n = 4
M = 20
x = [0]* n
y = [0]* n
w = [[0]* n]*len(xs)
δ = [[0]* n]*len(xs)
for i in range(0,n):
x[i] = solver.IntVar(0, 20, 'x'+str(i))
y[i] = solver.IntVar(0, 20, 'y'+str(i))
for j in range(len(xs)):
w[j][i] = solver.IntVar(0, 20, 'zp'+str(j)+ '-' + str(i))
δ[j][i] = solver.IntVar(0, 1, 'δ'+str(j)+ '-' + str(i))
for j in (range(len(xs))):
for i in range(0,n):
solver.Add((w[j][i] - x[i] + xs[j][i]) >=0)
solver.Add((w[j][i] - x[i] + xs[j][i]) <= M*(1-δ[j][i]))
solver.Add((w[j][i] + x[i] - xs[j][i]) >=0)
solver.Add((w[j][i] + x[i] - xs[j][i]) <= M*δ[j][i])
for j in range(len(xs)):
solver.Add(solver.Sum([w[j][i] for i in range(0,n)]) >= 1)
solver.Add(solver.Sum([x[i] for i in range(0, n)]) - 4 * solver.Sum([y[i] for i in range(0, n)]) == 0)
solver.Minimize(solver.Sum([x[i] for i in range(0, n)]))
status = solver.Solve()
if status == pywraplp.Solver.OPTIMAL:
solver_x = [0]*n
solver_y = [0]*n
for i in range(0,n):
solver_x[i] = x[i].solution_value()
solver_y[i] = y[i].solution_value()
return ([solver_x, solver_y, solver.Objective().Value()])
else:
print('No Solution')
return ([[0], [0]], -1)
psx = [[0,0,0,0], [0,4,0,0]]
psy = [[0,0,0,0], [1,0,0,0]]
ns = opt(psx, psy)
print(ns)
Output:
No Solution
([[0], [0]], -1)
Reference:
Finding multiple solutions to general integer linear programs
How to write constraints for sum of absolutes
If you have a pure integer programming model, you can use the CP-SAT solver which allows you to print all the solutions [See this].

How to save several networks (graphs) as a list in matlab?

My code creates several networks in a for loop, and I wanted to have a list of all the graphs so that I can check isomorphism of the graphs in the list. However I found that it is not possible to use cell array since it does not support the graph type. Is there any other way to do that?
Here is my code
n=5;
vertices=1:n;
for k = 1:length(vertices)
subsets = nchoosek(vertices,k);
sizes = size(subsets);
for j = 1:sizes(1)
sizes(1)
length(vertices)
l = subsets(j,:);
g = circulant(n,l);
FileName = sprintf('%d.jpeg',k*j)
fig = plot(g,'Layout','circle');
saveas(fig,FileName);
end
end
function g = circulant(n,l)
%input: n denotes size of graph, l is a list of integers
%output: the generated circulant graph
g=graph;
g = addnode(g,n);
for i = 1:numnodes(g)
for j = 1:length(l)
i = int64(i);
j = l(j);
if mod(i+j,n)==0
g = addedge(g,i,n);
else
g = addedge(g,i,mod(i+j,n));
end
if mod(i-j,n)==0
g = addedge(g,i,n);
else
g = addedge(g,i,mod(i-j,n));
end
end
end
g = graph(unique(g.Edges));
g = rmedge(g, 1:numnodes(g), 1:numnodes(g));
end

Merge Sort returns the same array in Python

for merge sort i wrote this code:
I have tested merge function that works correctly. but in mergeSort function i coudn't handle the arrays. it returns the same list as the input list.
def mergeSort(a):
l, h = 0, len(a)-1
mid = (l+h)/2
if (l<h-1): #the lowest length must be 2
mergeSort(a[l:mid+1])
mergeSort(a[mid+1:h+1])
return merge(a[l:mid+1],a[mid+1:h+1])
def merge(a,b):
n_a = len(a)
n_b = len(b)
c = [[] for i in range(n_a + n_b)]
i,j,k=0,0,0
while (i<n_a and j<n_b):
if a[i]<b[j]:
c[k] = a[i]
i += 1
else:
c[k]= b[j]
j += 1
k += 1
while(i<n_a):
c[k] = a[i]
k+=1
i+=1
while(j< n_b):
c[k] = b[j]
k+=1
j+=1
return c
I would rewrite merge as so:
def mergeSort(a):
h = len(a)
mid = h / 2
if h >= 2:
return merge(mergeSort(a[:mid]), mergeSort(a[mid:]))
else:
return a
A few notes:
l is always 0, might as well remove it
h is len(a) - 1, but then you use h + 1, might as well use h = len(a)
Actually writting h >= 2 makes it clearer that you need at least 2 items in your list
mid can be len(a) / 2.
when taking the complete beginning/end of an array in a slice, the first/last bound is not required

How can I replace multiple substrings simultaneously within a cell array using MATLAB

I have been asked to take a barcode symbol sequence, and replace each number substring with the actual number representation. In other words, a number '1' in the barcode sequence is represented by '...::'. Each number [0-9] is represented by a 5 character symbol. Each barcode is made up of 10 digits, so I want to create a number string that is equivalent to the symbolic barcode string.
ex.-
'...:::.:.....::::....:..::.:..:.:..:.:..:..:.::...' would be equivalent to 1910499980
What I am trying to accomplish is to capture each 5 character sequence, replace it with its numeric equivalent, then move on to the next 5 character sequence. The code I have so far is below, but it does not function correctly, it replaces some of the symbols, but not all. It also substitutes some of the numbers incorrectly. I forgot to mention that the first character of each line is to be omitted, so a portion of my code has already taken care of that.
Any help you can provide would be great,
Thanks,
Dan
barcodes = {':...:::.:.....::::....:..::.:..:.:..:.:..:..:.::...';
':::...:..:...::...::.::.....:.:.:..:..::...:.:..:.:';
'::.:...:..:.::..::...:...:::.....::...::.::...:..:.';
'::...:.:..:::...:...::..:...:.:..::.:..:..:..::...:';
':::....::...:.:...:.:::...:.:..:.:..::...::...:.:..';
':.:..:..::...:.:...::::......:::...:.:..:.::..:...:';
'::.:..:..:....::..:.:..:.:.:..:..::..:.:.:..:.:..:.';
':.::.....:::...:.::.....::..::..:..:.:..:.:..:.:..:';
'::...::..:..::...::...::..:...:.:.:.:...:.:.:...::.';
'::..:...::...:.:::......:::..:...::..:..:..:.::.:..';
'::..:...:.:::...:...:...::.:..:.:..:.:..:.:..:.::..';
':.:..::..:.:..:...:.:.:..::.:..:.:..:.:..:..:.:.:..';
':..::...:.:..::.::....::....::..:..:..:.:.:.:...:.:';
':..::..::.....::::....:..:.:.:.:.:..:..:...::....::';
':.::...::...:.:.::....::....:.:::.....:.:..::.:...:';
'::..:..:..:..::...:.:..:.:.:..:..::.:.:...:..:...::';
':.:.:.:...:::...::...:...:..::..:..:..:.:.:..::..:.';
':...::..:.:..:.:.:..:.::....::.:..:.:..:.:..:.:..:.';
':..:.:..::.:..:.::....::..:...:.:..:..::...:.::...:';
':.:..::...::..:.::...:.:....::.:..:...:.:...:::..:.';
'::..:..:.:.::...::....:..:.:..:..::..:.:..:..::...:';
'::..:.::....:.:...:.:..::.:..:..:..:..::...:.:.:.:.';
':.:.:..::..::...::......:::..:..:..:.:.:..:.:..::..';
':..::.:...:..:.:::...:.:.....::..:.:...::..::...:.:';
':.:..:::....::..::......::.::...::...:.:..:..::..:.';
':..:.::...:.::..:.:...:.:..:..:..::...:.::.:....::.';
':.::...:.:.:..:.:.:..:...:.:..::.:....::...:.::...:';
':..::.::.....::.::.....::.:..:..:..::...:.:..::..:.';
':::.....:.:...::..::.:.:..::...::...::...::....:.:.';
':::...:..:..:.:..:..:::....:..:.:.:..:.:...::.:...:';
':::.....:.::.:..::.....::..:..:..::...:.::.:..:..:.';
'::..:.:.:..::...::.....:.:.::..::....::..::...:.:..';
':.:.:.::...::......::...::..::..:..:.:..:..:.:::...';
':.:.:...::.:...:::....::..:.:....::...:.:...::.:..:'};
pat1 = '...::';
pat2 = '..:.:';
pat3 = '..::.';
pat4 = '.:..:';
pat5 = '.:.:.';
pat6 = '.::..';
pat7 = ':...:';
pat8 = ':..:.';
pat9 = ':.:..';
pat0 = '::...';
num1 = '1';
num2 = '2';
num3 = '3';
num4 = '4';
num5 = '5';
num6 = '6';
num7 = '7';
num8 = '8';
num9 = '9';
num0 = '0';
patterns = [pat1;pat2;pat3;pat4;pat5;pat6;pat7;pat8;pat9;pat0];
numbers = [num1;num2;num3;num4;num5;num6;num7;num8;num9;num0];
eachString = [];
barcodeMinusFirst = [];
for i = 1:length(barcodes);
eachString = [eachString; cellstr(barcodes(i))];
end
barcodeStrings = char(eachString);
barcodeStrings = barcodeStrings(:,2:end);
barcodeStrings = cellstr(barcodeStrings);
patternCell = cellstr(patterns);
numberCell = cellstr(numbers);
for i = 1:length(barcodes)
newBarcodes = regexprep(barcodeStrings, patternCell, numberCell);
end
The containters.Map class would serve this purpose:
>> nums = [1:9 0];
>> patterns = {'...::';'..:.:';'..::.';'.:..:';'.:.:.';...
'.::..';':...:';':..:.';':.:..';'::...'};
>> map = containers.Map(patterns,vals)
map =
Map with properties:
Count: 10
KeyType: char
ValueType: double
Use the values method to look up a value based on an input pattern or patterns:
>> codeTest = patterns([5 4 7 1]);
>> map.values(codeTest)'
ans =
[5] [4] [7] [1]
Segment your strings into cells and now you can translate all your barcode values:
bc = cell2mat(barcodes); bc = bc(:,2:end);
codes5 = mat2cell(bc,ones(size(bc,1),1),5*ones(1,size(bc,2)/5));
codesNumeric = cell2mat(map.values(codes5))
Try this -
Function
function output_string = barcode_seq(input_string)
%%// Params
pat1 = '...::';
pat2 = '..:.:';
pat3 = '..::.';
pat4 = '.:..:';
pat5 = '.:.:.';
pat6 = '.::..';
pat7 = ':...:';
pat8 = ':..:.';
pat9 = ':.:..';
pat0 = '::...';
patterns = [pat1;pat2;pat3;pat4;pat5;pat6;pat7;pat8;pat9;pat0];
barcode_len = size(patterns,2);
s1 = reshape(input_string,barcode_len,[])';
comp_exp_mat = bsxfun(#eq,patterns,permute(s1,[3 2 1]));
[x,y] = find(squeeze(sum(comp_exp_mat,2))==barcode_len);
x(x==10)=0;
output_string = num2str(x)';
Run
>> barcode_seq('...:::.:.....::::....:..::.:..:.:..:.:..:..:.::...')
ans =
1910499980
Using the initial barcodes variable, patterns variable, and numbers variable, this code will read through each line in barcodes. It will then convert the cell array to a character array, remove the first character, create a new cell array, split the cell array into 5 symbol segments, and replace each segment with its numeric counterpart. The final step is to combine the new numeric strings into a matrix similar to the original barcodes array.
barcodes = {':...:::.:.....::::....:..::.:..:.:..:.:..:..:.::...';
':::...:..:...::...::.::.....:.:.:..:..::...:.:..:.:';
'::.:...:..:.::..::...:...:::.....::...::.::...:..:.';
'::...:.:..:::...:...::..:...:.:..::.:..:..:..::...:';
':::....::...:.:...:.:::...:.:..:.:..::...::...:.:..';
':.:..:..::...:.:...::::......:::...:.:..:.::..:...:';
'::.:..:..:....::..:.:..:.:.:..:..::..:.:.:..:.:..:.';
':.::.....:::...:.::.....::..::..:..:.:..:.:..:.:..:';
'::...::..:..::...::...::..:...:.:.:.:...:.:.:...::.';
'::..:...::...:.:::......:::..:...::..:..:..:.::.:..';
'::..:...:.:::...:...:...::.:..:.:..:.:..:.:..:.::..';
':.:..::..:.:..:...:.:.:..::.:..:.:..:.:..:..:.:.:..';
':..::...:.:..::.::....::....::..:..:..:.:.:.:...:.:';
':..::..::.....::::....:..:.:.:.:.:..:..:...::....::';
':.::...::...:.:.::....::....:.:::.....:.:..::.:...:';
'::..:..:..:..::...:.:..:.:.:..:..::.:.:...:..:...::';
':.:.:.:...:::...::...:...:..::..:..:..:.:.:..::..:.';
':...::..:.:..:.:.:..:.::....::.:..:.:..:.:..:.:..:.';
':..:.:..::.:..:.::....::..:...:.:..:..::...:.::...:';
':.:..::...::..:.::...:.:....::.:..:...:.:...:::..:.';
'::..:..:.:.::...::....:..:.:..:..::..:.:..:..::...:';
'::..:.::....:.:...:.:..::.:..:..:..:..::...:.:.:.:.';
':.:.:..::..::...::......:::..:..:..:.:.:..:.:..::..';
':..::.:...:..:.:::...:.:.....::..:.:...::..::...:.:';
':.:..:::....::..::......::.::...::...:.:..:..::..:.';
':..:.::...:.::..:.:...:.:..:..:..::...:.::.:....::.';
':.::...:.:.:..:.:.:..:...:.:..::.:....::...:.::...:';
':..::.::.....::.::.....::.:..:..:..::...:.:..::..:.';
':::.....:.:...::..::.:.:..::...::...::...::....:.:.';
':::...:..:..:.:..:..:::....:..:.:.:..:.:...::.:...:';
':::.....:.::.:..::.....::..:..:..::...:.::.:..:..:.';
'::..:.:.:..::...::.....:.:.::..::....::..::...:.:..';
':.:.:.::...::......::...::..::..:..:.:..:..:.:::...';
':.:.:...::.:...:::....::..:.:....::...:.:...::.:..:'};
pat1 = '...::';%patterns corresponding to each barcode sequence
pat2 = '..:.:';
pat3 = '..::.';
pat4 = '.:..:';
pat5 = '.:.:.';
pat6 = '.::..';
pat7 = ':...:';
pat8 = ':..:.';
pat9 = ':.:..';
pat0 = '::...';
num1 = '1'; % variables for each number
num2 = '2';
num3 = '3';
num4 = '4';
num5 = '5';
num6 = '6';
num7 = '7';
num8 = '8';
num9 = '9';
num0 = '0';
split = [];
patterns = [pat1;pat2;pat3;pat4;pat5;pat6;pat7;pat8;pat9;pat0]; %character matrix for comparison
numbers = [num1;num2;num3;num4;num5;num6;num7;num8;num9;num0]; %character matrix for replacement
patternCell = cellstr(patterns); %convert patterns to cell array
numberCell = cellstr(numbers); %convert numbers to cell array
barcodeStrings = char(barcodes); %convert to character array
barcodeStrings = barcodeStrings(:,2:end);
barcodeStrings = cellstr(barcodeStrings);
for i = 1:length(barcodes)
newBarcodes = regexp(barcodeStrings, '\W{1,5}', 'match');
end
for j = 1:length(newBarcodes)
split = [split; regexprep(newBarcodes{j}, patternCell, numberCell)];
end
numbMat = cell2mat(split);
output:
disp(numbMat)
1910499980
0833024322
9460703308
7407823847
0652099009
4321017467
9812243588
6176134444
7866675753
8320183429
8207144446
4882499989
3230634252
3610459831
6650620237
8432243941
5700734248
1224638888
2380674327
4780938218
8500443547
8052384325
5600184556
3720912132
4060166548
2769543293
6589749327
3030384748
0213900005
0854045537
0290343298
8900260609
5001134420
5370693214
Reshape your string so that each group of five symbols is on a different row, and use ismember (with the 'rows' option) to find which pattern is matched by each row:
str = '...:::.:.....::::....:..::.:..:.:..:.:..:..:.::...'; %// example string
%// Variables "patterns" and "numbers" are defined in your code
[~, ind] = ismember(reshape(str,5,[]).', patterns, 'rows');
result = numbers(ind).';
which gives
result =
1910499980

Summing the indexes from a generated list of arrays

Hello I have list of arrays generated from a defined function below. I am wondering if there is way to sum up the same index in each array in the list giving me only 1 array?
import numpy as np
Tsp = np.linspace(3500, 40000, 3)
wcm = np.linspace(100, 10000, 5)
def blackbody(T, wcm):
k = 1.38*10**-16.0 #ergs/k
h = 6.625*10**-27.0 #erg/s
c = 3*10.0**10.0 #cm/s
bbtop = (2.0*h*c**2.0)
bbbot = (wcm**5.0)*(np.exp((h*c)/(wcm*k*T)) - 1)
bbs = bbtop/bbbot
return bbs
outflux = [blackbody(T_i, wcm) for T_i in Tsp]
Change the definition to:
def blackbody(T, wcm):
k = 1.38*10**-16.0 #ergs/k
h = 6.625*10**-27.0 #erg/s
c = 3*10.0**10.0 #cm/s
bbtop = (2.0*h*c**2.0)
T = np.atleast_1d(T) #So you can pass a single number if desired.
bbbot = (wcm**5.0)*(np.exp((h*c)/(wcm*k*T[:,None])) - 1) #Changed T to T[:,None]
bbs = bbtop/bbbot
return bbs
Now you can call it as:
blackbody(Tsp, wcm)
Double check that they are equal:
looped = np.array([blackbody(T_i, wcm) for T_i in Tsp])
broadcast = blackbody(Tsp, wcm)
print np.allclose(looped,broadcast)
True
Now that you have a single array you can sum on the axis you need using np.sum:
data = blackbody(Tsp, wcm)
data
[[ 2.89799404e-10 6.59157826e-16 4.45587348e-17 9.03800033e-18
2.89799993e-18]
[ 1.80089940e-09 4.09619532e-15 2.76900716e-16 5.61647169e-17
1.80089999e-17]
[ 3.31199940e-09 7.53323285e-15 5.09242710e-16 1.03291433e-16
3.31200005e-17]]
np.sum(data,axis=1)
[ 2.89800119e-10 1.80090385e-09 3.31200758e-09]
np.sum(data,axis=0)
[ 5.40269821e-09 1.22885860e-14 8.30702161e-16 1.68494151e-16
5.40270004e-17]
The data is aligned in both axes, but im not sure which you want from your question.