matlab coder: cannot transpose a matrix that is incorrectly deemed to be 3-D when it should always be 2-D - mex

I have a function (with the code given below) that I wish to convert into a MEX file. I am trying to use matlab coder to do so.
%% Inputs
dof = 3;
num_divs = 72;
ind_cr =
0 0
1 1
1 2
2 2
1 3
2 3
3 3
ind_switch =
1
1
1
0
1
0
0
len_stat_atoms =
1
72
5184
72
373248
5184
72
num_stat_atoms =
108
111
111
3
111
3
3
coordFile =
[3x1 double]
[3x1 double]
[3x72x3 double]
[3x5184x3 double]
[3x373248x4 double]
radii_cell =
[108x1x3 double]
[111x72x3 double]
[111x5184x3 double]
[ 3x72x3 double]
[111x373248x4 double]
[ 3x5184x4 double]
[ 3x72x4 double]
stat_cell =
[3x1x108 double]
[3x72x111 double]
[3x5184x111 double]
[3x72x3 double]
[3x373248x111 double]
[3x5184x3 double]
[3x72x3 double]
%% Code that calls function
for i = 1:(dof*(dof+1)/2+1)
%% Load matrices
radii_mat = radii_cell{i,1};
stat_mat = stat_cell{i,1};
if ind_switch(i)
coordFile_mat = coordFile{ind_cr(i,2)+2};
end
%% Call the function
potential_mat = func_test(i,coordFile_mat,radii_mat,stat_mat,...
ind_cr,len_stat_atoms,num_stat_atoms,num_coord_atoms,...
counter,num_divs,dof);
end
%% Function code
function potential_mat = func_test(i,coordFile_mat,radii_mat,stat_mat,...
ind_cr,len_stat_atoms,num_stat_atoms,num_coord_atoms,...
counter,num_divs,dof);
potential_mat = zeros(num_coord_atoms,num_divs^dof);
for j = 1:size(coordFile_mat,3)
%% Compute distances
a = zeros(3,len_stat_atoms(i));
a = coordFile_mat(:,1:len_stat_atoms(i),j);
b = zeros(3,len_stat_atoms(i),num_stat_atoms(i));
b = repmat(a,[1 1 num_stat_atoms(i)]);
c = zeros(1,len_stat_atoms(i),num_stat_atoms(i));
c = sqrt(sum((b - stat_mat).^2,1));
d = zeros(len_stat_atoms(i),num_stat_atoms(i));
d = shiftdim(c,1);
distances = zeros(num_stat_atoms(i),len_stat_atoms(i));
distances = d';
%% Compute clashes and potentials
clashes = distances < radii_mat(:,:,j);
potentials = zeros(size(distances));
potentials(clashes) = (1-(distances(clashes)./radii_mat(find(clashes)+numel(clashes)*(j-1))).^6).^2;
%% Iterate over nodes
col = ind_cr(i,1); row = ind_cr(i,2);
if col == 1
ind_kron = repmat(1:size(potentials,2),[num_divs^(dof-row) 1]);
potentials = potentials(:,ind_kron(:)');
elseif row == dof
vec_repmat = [1 num_divs^(col-1)];
potentials = repmat(potentials,vec_repmat);
elseif col > 0
vec_repmat = [1 num_divs^(col-1)];
ind_kron = repmat(1:size(potentials,2),[num_divs^(dof-row) 1]);
potentials = repmat(potentials(:,ind_kron(:)'),vec_repmat);
else
potentials = repmat(sum(potentials),[1 num_divs^dof]);
end
counter = counter+1;
potential_mat(counter,:) = sum(potentials,1);
end
end
The problem occurs at the second line below, where it throws an error because it cannot transpose an ND matrix.
d = shiftdim(c,1);
distances = d';
Matlab coder identifies c to be of size 1 x :? x :?, which is correct. The d = shiftdim(c,1) line should then yield a 2D matrix of size :? x :?, which I then transpose. However, it fails to correctly shift the dimensions of d, and gives it a size of :? x :? x :?. This then causes the transpose error. How can I resolve this problem? Furthermore, for my own edification, why is matlab coder unable to correctly assign the dimensions of my variables, specifically a, b, c, d, and distances?

The docs describe this as an Incompatibility with MATLAB in Determining Size of Variable-Size N-D Arrays (d is created in a loop, so seems to be variable size):
For variable-size N-D arrays, the size function can return a different result in generated code than in MATLAB. In generated code, size(A) returns a fixed-length output because it does not drop trailing singleton dimensions of variable-size N-D arrays. By contrast, size(A) in MATLAB returns a variable-length output because it drops trailing singleton dimensions.
For example, if the shape of array A is :?x:?x:? and size(A,3)==1, size(A) returns:
Three-element vector in generated code
Two-element vector in MATLAB code
The issue addressed in the above documentation pertains to the use of the size function. However, in your case, you just want to be able to transpose. The workaround is to use permute, since the transpose is a general case of permute:
% after shiftdim:
distances = permute(d,[2 1 3]) % same as d' for 2d array, but handles 3d
You could also cut out the shiftdim entirely:
distances = permute(c,[2 3 1])
Also, I don't have much experience with Coder, but does it really require all those initializations with zeros? They seem unnecessary.

Related

Polynomial interpolation in python

I am studying function approximation and while trying to understand/implement polynomial interpolation I've found an example here. I find the code below a good example to understand what is actually going on instead of using ready functions, however it doesn't run:
Defining the interpolation algorithm. Essentially, we are trying to come up with a representation of true f as a linear combination of basis functions (psi-s).
import sympy as sym
def interpolation(f, psi, points):
N = len(psi) - 1 #order of the approximant polynomial
A = sym.zeros((N+1, N+1)) # initiating the square matrix, whose regular element is psi evaluated at each nodes
b = sym.zeros((N+1, 1)) # original function f evaluated at the selected nodes
psi_sym = psi # save symbolic expression
# Turn psi and f into Python functions
x = sym.Symbol('x')
psi = [sym.lambdify([x], psi[i]) for i in range(N+1)]
f = sym.lambdify([x], f)
for i in range(N+1):
for j in range(N+1):
A[i,j] = psi[j](points[i])
b[i,0] = f(points[i])
c = A.LUsolve(b) #finding the accurate weights for each psi
# c is a sympy Matrix object, turn to list
c = [sym.simplify(c[i,0]) for i in range(c.shape[0])]
u = sym.simplify(sum(c[i,0]*psi_sym[i] for i in range(N+1)))
return u, c
True function f:= 10(x-1)^2 -1, nodes: x0:= 1 + 1/3 and x1 = 1 + 2/3. Interval: [1,2].
x = sym.Symbol('x')
f = 10*(x-1)**2 - 1
psi = [1, x] # approximant polynomial of order 1 (linear approximation)
Omega = [1, 2] #interval
points = [1 + sym.Rational(1,3), 1 + sym.Rational(2,3)]
u, c = interpolation(f, psi, points)
comparison_plot(f, u, Omega)
The code doesn't run. The error occurs in line
A = sym.zeros((N+1, N+1))
Error message: ValueError: (2, 2) is not an integer
But A isn't supposed to be an integer, it is a square matrix whose each element is psi evaluated at each node. f = A*c.
Thank you!!!

Product of a multi-dimensional array (or tensor) and vectors

I would like to ask for a fast way to perform the following operations, either in native Matlab, C++, or using toolboxes/libraries, whichever would give the fastest solutions.
Let M be a tensor of D dimensions: n1 x n2 x... x nD, and let v1, v2,..., vD be D vectors whose dimensions are respectively n1, n2,..., nD.
Compute the product M*vi (1 <= i <= D). The result is a multi-dimensional array of (D-1) dimensions.
Compute the product of M with all vectors, except vi.
For example, with D = 3:
The product of M and v1 is a tensor N of 2 dimensions (i.e. a matrix) where
N[i2][i3] = Sum_over_i1 of M[i1][i2][i3]*v1[i1]
The product of M and v2 is a matrix N where
N[i1][i3] = Sum_over_i2 of M[i1][i2][i3]*v2[i2]
The product of M and v2 and v3 is a vector v where
v[i1] = Sum_over_i2 of (Sum_over_i3 of M[i1][i2][i3]*v2[i2]*v3[i3])
A further question: the above but for sparse tensors.
An example of Matlab code is given below.
Thank you very much in advance for your help!!
n1 = 3;
n2 = 5;
n3 = 4;
M = randn(n1,n2,n3);
v1 = randn(n1,1);
v2 = randn(n2,1);
v3 = randn(n3,1);
%% N = M*v2
N = zeros(n1,n3);
for i1=1:n1
for i3=1:n3
for i2=1:n2
N(i1,i3) = N(i1,i3) + M(i1,i2,i3)*v2(i2);
end
end
end
%% v = M*v2*v3
v = zeros(n1,1);
for i1=1:n1
for i2=1:n2
for i3=1:n3
v(i1) = v(i1) + M(i1,i2,i3)*v2(i2)*v3(i3);
end
end
end
I've noticed that operation you are describing takes (D - 1) dimensional slices of M and scales them by the corresponding entry of vi subsequently summing the result over the indices of vi. This code seems to work for getting N in your example:
N2 = squeeze(sum(M.*(v2)', 2));
To get v in your code, all you need to do is multiply N by v3:
v2 = N2*v3;
EDIT
On older versions of MatLab the element-wise operator .* doesn't work the way I've used it above. One alternative is bsxfun:
N2 = squeeze(sum(bsxfun(#times, M, v2'), 2));
Just checked: In terms of performance, the bsxfun way seems as fast as the .* way for large arrays, at least on R2016b.

Range Update - Range Query using Fenwick Tree

http://ayazdzulfikar.blogspot.in/2014/12/penggunaan-fenwick-tree-bit.html?showComment=1434865697025#c5391178275473818224
For example being told that the value of the function or f (i) of the index-i is an i ^ k, for k> = 0 and always stay on this matter. Given query like the following:
Add value array [i], for all a <= i <= b as v Determine the total
array [i] f (i), for each a <= i <= b (remember the previous function
values ​​clarification)
To work on this matter, can be formed into Query (x) = m * g (x) - c,
where g (x) is f (1) + f (2) + ... + f (x).
To accomplish this, we
need to know the values ​​of m and c. For that, we need 2 separate
BIT. Observations below for each update in the form of ab v. To
calculate the value of m, virtually identical to the Range Update -
Point Query. We can get the following observations for each value of
i, which may be:
i <a, m = 0
a <= i <= b, m = v
b <i, m = 0
By using the following observation, it is clear that the Range Update - Point Query can be used on any of the BIT. To calculate the value of c, we need to observe the possibility for each value of i, which may be:
i <a, then c = 0
a <= i <= b, then c = v * g (a - 1)
b <i, c = v * (g (b) - g (a - 1))
Again, we need Range Update - Point Query, but in a different BIT.
Oiya, for a little help, I wrote the value of g (x) for k <= 3 yes: p:
k = 0 -> x
k = 1 -> x * (x + 1) / 2
k = 2 -> x * (x + 1) * (2x + 1) / 6
k = 3 -> (x * (x + 1) / 2) ^ 2
Now, example problem SPOJ - Horrible Queries . This problem is
similar issues that have described, with k = 0. Note also that
sometimes there is a matter that is quite extreme, where the function
is not for one type of k, but it could be some that polynomial shape!
Eg LA - Alien Abduction Again . To work on this problem, the solution
is, for each rank we make its BIT counter m respectively. BIT combined
to clear the counters c it was fine.
How can we used this concept if:
Given an array of integers A1,A2,…AN.
Given x,y: Add 1×2 to Ax, add 2×3 to Ax+1, add 3×4 to Ax+2, add 4×5 to
Ax+3, and so on until Ay.
Then return Sum of the range [Ax,Ay].

Do loop parameters considered as non-numeric characters

I am a Newbie to Fortran, facing a problem within a Do loop. I am programming a Fortran Code for a MEX File to be used within Matlab.
I assume it has a problem with the definition of k and z, but I don't see why. Maybe you guys have a hint for me what I am doing wrong. Thank you very much!
Error Message and Code
innerloops.F
do k = 1, 4
1
Error: Non-numeric character in statement label at (1)
innerloops.F
do k = 1, 4
1
Error: Unclassifiable statement at (1)
innerloops.F
do z = 1, 25
1
Error: Non-numeric character in statement label at (1)
innerloops.F
do z = 1, 25
Error: Unclassifiable statement at (1)
C Computational routine
subroutine innerloops(J,c1,c2,c3,c4,n1,n2,n3,n4,y,m,n)
mwSize m, n
integer k, z
real*8 J(m,n), y(4,1), c1, c2, c3, c4, n1, n2, n3, n4
real*8 QuadRuleX(25,2)
real*8 QuadRuleW(25,1)
real*8 X(5,1), r, t
real*8 P, c_h, n_h
integer h = 10
C Gaussian Points
X(1) = -.906179
X(2) = -.538469
X(3) = 0
X(4) = .538469
X(5) = .906179
C Corresponding QuadRule points
QuadRuleX(1,1) = X(1)
QuadRuleX(1,2) = X(1)
C .... (snipped it here for readability)
C Corresponding weights
QuadRuleW(1) = Y(1)*Y(1)
QuadRuleW(2) = Y(2)*Y(1)
C .... (snipped it here for readability)
do k = 1, 4
do z = 1, 25
r = QuadRuleX(z,1)
t = QuadRuleX(z,2)
P = shape(k,r,t)
c_h = c1*shape(k,r,t)
n_h = n1*shape(k,r,t)
y(k,1) = (P*((((h-1)*c_h)/(h-1)*c_h+1))*n_h*(2-n_h)-n_h)
continue
continue
return
end do
end subroutine innerloops
C defining the shape functions
Function shape(q,c,d)
implicit none
real q,c,d,P
if (q == 1) then
P = 1/4*(c-1)*(d-1)
else if (q == 2) then
P = -1/4*(c+1)*(d-1)
else if (q == 3) then
P = 1/4*(c+1)*(d+1)
else if (q == 4) then
P = -1/4*(c-1)*(d+1)
endif
return
end Function shape
By using a .F suffix the compiler by default assumes that you are using a fixed format source code. In fixed format certain columns are reserved for special purposes. Here it appears that your "do" has been mistakenly put into a column reserved for statement label (columns 1 through 5). Your statement has to fit between column 7 and 72 in a fixed-format fortran file. This is what the compiler was complaining about. As mentioned by others, your code also contain other errors that need to be fixed.
To make things simpler, you can use a free format instead by changing the suffix to .f90 and replacing the "C" comment indicator with "!".

Enumeration all possible matrices with constraints

I'm attempting to enumerate all possible matrices of size r by r with a few constraints.
Row and column sums must be in non-ascending order.
Starting from the top left element down the main diagonal, each row and column subset from that entry must be made up of combinations with replacements from 0 to the value in that upper left entry (inclusive).
The row and column sums must all be less than or equal to a predetermined n value.
The main diagonal must be in non-ascending order.
Important note is that I need every combination to be store somewhere, or if written in c++, to be ran through another few functions after finding them
r and n are values that range from 2 to say 100.
I've tried a recursive way to do this, along with an iterative, but keep getting hung up on keeping track column and row sums, along with all the data in a manageable sense.
I have attached my most recent attempt (which is far from completed), but may give you an idea of what is going on.
The function first_section(): builds row zero and column zero correctly, but other than that I don't have anything successful.
I need more than a push to get this going, the logic is a pain in the butt, and is swallowing me whole. I need to have this written in either python or C++.
import numpy as np
from itertools import combinations_with_replacement
global r
global n
r = 4
n = 8
global myarray
myarray = np.zeros((r,r))
global arraysums
arraysums = np.zeros((r,2))
def first_section():
bigData = []
myarray = np.zeros((r,r))
arraysums = np.zeros((r,2))
for i in reversed(range(1,n+1)):
myarray[0,0] = i
stuff = []
stuff = list(combinations_with_replacement(range(i),r-1))
for j in range(len(stuff)):
myarray[0,1:] = list(reversed(stuff[j]))
arraysums[0,0] = sum(myarray[0,:])
for k in range(len(stuff)):
myarray[1:,0] = list(reversed(stuff[k]))
arraysums[0,1] = sum(myarray[:,0])
if arraysums.max() > n:
break
bigData.append(np.hstack((myarray[0,:],myarray[1:,0])))
if printing: print 'myarray \n%s' %(myarray)
return bigData
def one_more_section(bigData,index):
newData = []
for item in bigData:
if printing: print 'item = %s' %(item)
upperbound = int(item[index-1]) # will need to have logic worked out
if printing: print 'upperbound = %s' % (upperbound)
for i in reversed(range(1,upperbound+1)):
myarray[index,index] = i
stuff = []
stuff = list(combinations_with_replacement(range(i),r-1))
for j in range(len(stuff)):
myarray[index,index+1:] = list(reversed(stuff[j]))
arraysums[index,0] = sum(myarray[index,:])
for k in range(len(stuff)):
myarray[index+1:,index] = list(reversed(stuff[k]))
arraysums[index,1] = sum(myarray[:,index])
if arraysums.max() > n:
break
if printing: print 'index = %s' %(index)
newData.append(np.hstack((myarray[index,index:],myarray[index+1:,index])))
if printing: print 'myarray \n%s' %(myarray)
return newData
bigData = first_section()
bigData = one_more_section(bigData,1)
A possible matrix could look like this:
r = 4, n >= 6
|3 2 0 0| = 5
|3 2 0 0| = 5
|0 0 2 1| = 3
|0 0 0 1| = 1
6 4 2 2
Here's a solution in numpy and python 2.7. Note that all the rows and columns are in non-increasing order, because you only specified that they should be combinations with replacement, and not their sortedness (and generating combinations is the simplest with sorted lists).
The code could be optimized somewhat by keeping row and column sums around as arguments instead of recomputing them.
import numpy as np
r = 2 #matrix dimension
maxs = 5 #maximum sum of row/column
def generate(r, maxs):
# We create an extra row and column for the starting "dummy" values.
# Filling in the matrix becomes much simpler when we do not have to treat cells with
# one or two zero indices in special way. Thus, we start iteration from the
# (1, 1) index.
m = np.zeros((r + 1, r + 1), dtype = np.int32)
m[0] = m[:,0] = maxs + 1
def go(n, i, j):
# If we completely filled the matrix, yield a copy of the non-dummy parts.
if (i, j) == (r, r):
yield m[1:, 1:].copy()
return
# We compute the next indices in row major order (the choice is arbitrary).
(i2, j2) = (i + 1, 1) if j == r else (i, j + 1)
# Computing the maximum possible value for the current cell.
max_val = min(
maxs - m[i, 1:].sum(),
maxs - m[1:, j].sum(),
m[i, j-1],
m[i-1, j])
for n2 in xrange(max_val, -1, -1):
m[i, j] = n2
for matrix in go(n2, i2, j2):
yield matrix
return go(maxs, 1, 1) #note that this is a generator object
# testing
for matrix in generate(r, maxs):
print
print matrix
If you'd like to have all the valid permutations in the rows and columns, this code below should work.
def generate(r, maxs):
m = np.zeros((r + 1, r + 1), dtype = np.int32)
rows = [0]*(r+1) # We avoid recomputing row/col sums on each cell.
cols = [0]*(r+1)
rows[0] = cols[0] = m[0, 0] = maxs
def go(i, j):
if (i, j) == (r, r):
yield m[1:, 1:].copy()
return
(i2, j2) = (i + 1, 1) if j == r else (i, j + 1)
max_val = min(rows[i-1] - rows[i], cols[j-1] - cols[j])
if i == j:
max_val = min(max_val, m[i-1, j-1])
if (i, j) != (1, 1):
max_val = min(max_val, m[1, 1])
for n in xrange(max_val, -1, -1):
m[i, j] = n
rows[i] += n
cols[j] += n
for matrix in go(i2, j2):
yield matrix
rows[i] -= n
cols[j] -= n
return go(1, 1)