Unable to perform assignment because the size of the left side is 1-by-7-by-7 and the size of the right side is 6-by-6 [closed] - matlab

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am looking for a way to find same eigenvectors for 2 given matrices, this way I would make a joint diagonalisation. For this, I found out and tried to use qndiag (from https://github.com/pierreablin/qndiag.git ) from the following function :
function [D, B, infos] = qndiag(C, varargin)
% Joint diagonalization of matrices using the quasi-Newton method
%
% The algorithm is detailed in:
%
% P. Ablin, J.F. Cardoso and A. Gramfort. Beyond Pham’s algorithm
% for joint diagonalization. Proc. ESANN 2019.
% https://www.elen.ucl.ac.be/Proceedings/esann/esannpdf/es2019-119.pdf
% https://hal.archives-ouvertes.fr/hal-01936887v1
% https://arxiv.org/abs/1811.11433
%
% The function takes as input a set of matrices of size `(p, p)`, stored as
% a `(n, p, p)` array, `C`. It outputs a `(p, p)` array, `B`, such that the
% matrices `B * C(i,:,:) * B'` are as diagonal as possible.
%
% There are several optional parameters which can be provided in the
% varargin variable.
%
% Optional parameters:
% --------------------
% 'B0' Initial point for the algorithm.
% If absent, a whitener is used.
% 'weights' Weights for each matrix in the loss:
% L = sum(weights * KL(C, C')).
% No weighting (weights = 1) by default.
% 'maxiter' (int) Maximum number of iterations to perform.
% Default : 1000
%
% 'tol' (float) A positive scalar giving the tolerance at
% which the algorithm is considered to have converged.
% The algorithm stops when |gradient| < tol.
% Default : 1e-6
%
% lambda_min (float) A positive regularization scalar. Each
% eigenvalue of the Hessian approximation below
% lambda_min is set to lambda_min.
%
% max_ls_tries (int), Maximum number of line-search tries to
% perform.
%
% return_B_list (bool) Chooses whether or not to return the list
% of iterates.
%
% verbose (bool) Prints informations about the state of the
% algorithm if True.
%
% Returns
% -------
% D : Set of matrices jointly diagonalized
% B : Estimated joint diagonalizer matrix.
% infos : structure containing monitoring informations, containing the times,
% gradient norms and objective values.
%
% Example:
% --------
%
% [D, B] = qndiag(C, 'maxiter', 100, 'tol', 1e-5)
%
% Authors: Pierre Ablin <pierre.ablin#inria.fr>
% Alexandre Gramfort <alexandre.gramfort#inria.fr>
%
% License: MIT
% First tests
if nargin == 0,
error('No signal provided');
end
if length(size(C)) ~= 3,
error('Input C should be 3 dimensional');
end
if ~isa (C, 'double'),
fprintf ('Converting input data to double...');
X = double(X);
end
% Default parameters
C_mean = squeeze(mean(C, 1));
[p, d] = eigs(C_mean);
p = fliplr(p);
d = flip(diag(d));
B = p' ./ repmat(sqrt(d), 1, size(p, 1));
max_iter = 1000;
tol = 1e-6;
lambda_min = 1e-4;
max_ls_tries = 10;
return_B_list = false;
verbose = false;
weights = [];
% Read varargin
if mod(length(varargin), 2) == 1,
error('There should be an even number of optional parameters');
end
for i = 1:2:length(varargin)
param = lower(varargin{i});
value = varargin{i + 1};
switch param
case 'B0'
B0 = value;
case 'max_iter'
max_iter = value;
case 'tol'
tol = value;
case 'weights'
weights = value / mean(value(:));
case 'lambda_min'
lambda_min = value;
case 'max_ls_tries'
max_ls_tries = value;
case 'return_B_list'
return_B_list = value;
case 'verbose'
verbose = value;
otherwise
error(['Parameter ''' param ''' unknown'])
end
end
[n_samples, n_features, ~] = size(C);
D = transform_set(B, C, false);
current_loss = NaN;
% Monitoring
if return_B_list
B_list = []
end
t_list = [];
gradient_list = [];
loss_list = [];
if verbose
print('Running quasi-Newton for joint diagonalization');
print('iter | obj | gradient');
end
for t=1:max_iter
if return_B_list
B_list(k) = B;
end
diagonals = zeros(n_samples, n_features);
for k=1:n_samples
diagonals(k, :) = diag(squeeze(D(k, :, :)));
end
% Gradient
if isempty(weights)
G = squeeze(mean(bsxfun(#rdivide, D, ...
reshape(diagonals, n_samples, n_features, 1)), ...
1)) - eye(n_features);
else
G = squeeze(mean(...
bsxfun(#times, ...
reshape(weights, n_samples, 1, 1), ...
bsxfun(#rdivide, D, ...
reshape(diagonals, n_samples, n_features, 1))), ...
1)) - eye(n_features);
end
g_norm = norm(G);
if g_norm < tol
break
end
% Hessian coefficients
if isempty(weights)
h = mean(bsxfun(#rdivide, ...
reshape(diagonals, n_samples, 1, n_features), ...
reshape(diagonals, n_samples, n_features, 1)), 1);
else
h = mean(bsxfun(#times, ...
reshape(weights, n_samples, 1, 1), ...
bsxfun(#rdivide, ...
reshape(diagonals, n_samples, 1, n_features), ...
reshape(diagonals, n_samples, n_features, 1))), ...
1);
end
h = squeeze(h);
% Quasi-Newton's direction
dt = h .* h' - 1.;
dt(dt < lambda_min) = lambda_min; % Regularize
direction = -(G .* h' - G') ./ dt;
% Line search
[success, new_D, new_B, new_loss, direction] = ...
linesearch(D, B, direction, current_loss, max_ls_tries, weights);
D = new_D;
B = new_B;
current_loss = new_loss;
% Monitoring
gradient_list(t) = g_norm;
loss_list(t) = current_loss;
if verbose
print(sprintf('%d - %.2e - %.2e', t, current_loss, g_norm))
end
end
infos = struct();
infos.t_list = t_list;
infos.gradient_list = gradient_list;
infos.loss_list = loss_list;
if return_B_list
infos.B_list = B_list
end
end
function [op] = transform_set(M, D, diag_only)
[n, p, ~] = size(D);
if ~diag_only
op = zeros(n, p, p);
for k=1:length(D)
op(k, :, :) = M * squeeze(D(k, :, :)) * M';
end
else
op = zeros(n, p);
for k=1:length(D)
op(k, :) = sum(M .* (squeeze(D(k, :, :)) * M'), 1);
end
end
end
function [v] = slogdet(A)
v = log(abs(det(A)));
end
function [out] = loss(B, D, is_diag, weights)
[n, p, ~] = size(D);
if ~is_diag
diagonals = zeros(n, p);
for k=1:n
diagonals(k, :) = diag(squeeze(D(k, :, :)));
end
else
diagonals = D;
end
logdet = -slogdet(B);
if ~isempty(weights)
diagonals = bsxfun(#times, diagonals, reshape(weights, n, 1));
end
out = logdet + 0.5 * sum(log(diagonals(:))) / n;
end
function [success, new_D, new_B, new_loss, delta] = linesearch(D, B, direction, current_loss, n_ls_tries, weights)
[n, p, ~] = size(D);
step = 1.;
if current_loss == NaN
current_loss = loss(B, D, false);
end
success = false;
for n=1:n_ls_tries
M = eye(p) + step * direction;
new_D = transform_set(M, D, true);
new_B = M * B;
new_loss = loss(new_B, new_D, true, weights);
if new_loss < current_loss
success = true;
break
end
step = step / 2;
end
new_D = transform_set(M, D, false);
delta = step * direction;
end
I use it with the following script that you can test with downloading the 2 input matrices at the bottom of this post :
clc; clear
m=7 % dimension
n=2 % number of matrices
% Load spectro and WL+GCph+XC
FISH_GCsp = load('Fisher_GCsp_flat.txt');
FISH_XC = load('Fisher_XC_GCph_WL_flat.txt');
% Marginalizing over uncommon parameters between the two matrices
COV_GCsp_first = inv(FISH_GCsp);
COV_XC_first = inv(FISH_XC);
COV_GCsp = COV_GCsp_first(1:m,1:m);
COV_XC = COV_XC_first(1:m,1:m);
% Invert to get Fisher matrix
FISH_sp = inv(COV_GCsp);
FISH_xc = inv(COV_XC);
% Drawing a random set of commuting matrices
C=zeros(n,m,m);
B0=zeros(n,m,m);
C(1,:,:) = FISH_sp
C(2,:,:) = FISH_xc
%[D, B] = qndiag(C, 'max_iter', 1e6, 'tol', 1e-6);
[D, B] = qndiag(C);
% Print diagonal matrices
B*C(1,:,:)*B'
B*C(2,:,:)*B'
But unfortunately, I get the following error :
Unable to perform assignment because the size of the left side is 1-by-7-by-7 and the size of the
right side is 6-by-6.
Error in qndiag>transform_set (line 224)
op(k, :, :) = M * squeeze(D(k, :, :)) * M';
Error in qndiag (line 128)
D = transform_set(B, C, false);
Error in compute_joint_diagonalization (line 32)
[D, B] = qndiag(C);
I don't understand the utility of function squeeze the most important : why the function eigs returns only 6 values and not 7 like in my data (the input matrices has 7x7 size).
What might be wrong with this issue of array dimension and how can I fix it ?
I put the 2 input files available here :
Matrix Fisher_GCsp_flat.txt
Matrix Fisher_XC_GCph_WL_flat.txt
You can test the above code that calls qndiag for these 2 matrices.
Update 1
To allow people interested to test quickly the code, I put a link of the archive:
Archive_Matlab_StackOver.tar
You just have to untar and execute under Matlab the script compute_joint_diagonalization.m and you will see normally the above error (regarding the use of eigs and squeeze functions).
It should help you understand the origin of this issue.
Update 2
If I replace [p, d] = eigs(C_mean) by [p, d] = eigs(C_mean,7) , I get another error :
Index in position 1 exceeds array bounds (must not exceed 2).
Error in qndiag>transform_set (line 224)
op(k, :, :) = M * squeeze(D(k, :, :)) * M';
Error in qndiag (line 128)
D = transform_set(B, C, false);
Error in compute_joint_diagonalization (line 27)
[D, B] = qndiag(C);
However, the dimensions of the 2 matrices used are 7x7 and should be correctly processed with eigs(C_mean,7).
Update 3
The size of op, D, M and k are equal to (including after the error message) :
size(D) =
2 7 7
length(D) =
7
size(M) =
7 7
size(op) =
2 7 7
Index in position 1 exceeds array bounds (must not exceed 2).
Error in qndiag>transform_set (line 231)
op(k, :, :) = M * squeeze(D(k, :, :)) * M';
Error in qndiag (line 128)
D = transform_set(B, C, false);
Error in compute_joint_diagonalization (line 27)
[D, B] = qndiag(C);
Notice that k varies from 1 to length(D)=7.
Is there an issue which could appear with these dimensions ?

From the documentation for eigs:
d = eigs(A) returns a vector of the six largest magnitude eigenvalues of matrix A.
If you want all seven, you need to call d = eigs(A,7) or d = eig(A). For a small matrix (e.g. < 1000 x 1000) it's usually easier to just get all the eigenvalues with eig, rather than get a subset with eigs.
Edit: Responding to your "Update 3"
for k=1:length(D) should be replaced by for k=1:n. This needs to be changed on two lines. Judging from your error message they are lines 231 and 236.
L = length(X) returns the length of the largest array dimension in X, which in your case is 7, i.e. too high for the first dimension.

Related

All my weights for gradient descent become 0 on feature expansion

I have 2 features which I expand to contain all possible combinations of the two features under order 6. When I do MATLAB's fminunc, it returns a weight vector where all elements are 0.
The dataset is here
clear all;
clc;
data = load("P2-data1.txt");
m = length(data);
para = 0; % regularization parameter
%% Augment Feature
y = data(:,3);
new_data = newfeature(data(:,1), data(:,2), 3);
[~, n] = size(new_data);
betas1 = zeros(n,1); % initial weights
options = optimset('GradObj', 'on', 'MaxIter', 400);
[beta_new, cost] = fminunc(#(t)(regucostfunction(t, new_data, y, para)), betas1, options);
fprintf('Cost at theta found by fminunc: %f\n', cost);
fprintf('theta: \n');
fprintf(' %f \n', beta_new); % get all 0 here
% Compute accuracy on our training set
p_new = predict(beta_new, new_data);
fprintf('Train Accuracy after feature augmentation: %f\n', mean(double(p_new == y)) * 100);
fprintf('\n');
%% the functions are defined below
function g = sigmoid(z) % running properly
g = zeros(size(z));
g=ones(size(z))./(ones(size(z))+exp(-z));
end
function [J,grad] = regucostfunction(theta,x,y,para) % CalculateCost(x1,betas1,y);
m = length(y); % number of training examples
J = 0;
grad = zeros(size(theta));
hyp = sigmoid(x*theta);
err = (hyp - y)';
grad = (1/m)*(err)*x;
sum = 0;
for k = 2:length(theta)
sum = sum+theta(k)^2;
end
J = (1/m)*((-y' * log(hyp) - (1 - y)' * log(1 - hyp)) + para*(sum) );
end
function p = predict(theta, X)
m = size(X, 1); % Number of training examples
p = zeros(m, 1);
index = find(sigmoid(theta'*X') >= 0.5);
p(index,1) = 1;
end
function out = newfeature(X1, X2, degree)
out = ones(size(X1(:,1)));
for i = 1:degree
for j = 0:i
out(:, end+1) = (X1.^(i-j)).*(X2.^j);
end
end
end
data contains 2 columns of rows followed by a third column of 0/1 values.
The functions used are: newfeature returns the expanded features and regucostfunction computes the cost. When I did the same approach with the default features, it worked and I think the problem here has to do with some coding issue.

Error using feval Undefined function or variable 'Sfun'

I have always used R, so I am quite new to Matlab and running into some troubleshooting issues. I am running some code for a tensor factorization method (available here: https://github.com/caobokai/tBNE). To start I tried to run the demo code, which generates simulated data to run the method with, which results in the following error(s):
Error using feval
Undefined function or variable 'Sfun'.
Error in OptStiefelGBB (line 199)
[F, G] = feval(fun, X , varargin{:}); out.nfe = 1;
Error in tbne_demo>tBNE_fun (line 124)
S, #Sfun, opts, B, P, X, L, D, W, Y, alpha, beta);
Here is the block of code I am running:
clear
clc
addpath(genpath('./tensor_toolbox'));
addpath(genpath('./FOptM'));
rng(5489, 'twister');
m = 10;
n = 10;
k = 10; % rank for tensor
[X, Z, Y] = tBNE_data(m, n, k); % generate the tensor, guidance and label
[T, W] = tBNE_fun(X, Z, Y, k);
[~, y1] = max(Y, [], 2);
[~, y2] = max(T{3} * W, [], 2);
fprintf('accuracy %3.2e\n', sum(y1 == y2) / n);
function [X, Z, Y] = tBNE_data(m, n, k)
B = randn(m, k);
S = randn(n, k);
A = {B, B, S};
X = ktensor(A);
Z = randn(n, 4);
Y = zeros(n, 2);
l = ceil(n / 2);
Y(1 : l, 1) = 1;
Y(l + 1 : end, 2) = 1;
X = tensor(X);
end
function [T, W] = tBNE_fun(X, Z, Y, k)
% t-BNE computes brain network embedding based on constrained tensor factorization
%
% INPUT
% X: brain networks stacked in a 3-way tensor
% Z: side information
% Y: label information
% k: rank of CP factorization
%
% OUTPUT
% T is the factor tensor containing
% vertex factor matrix B = T{1} and
% subject factor matrix S = T{3}
% W is the weight matrix
%
% Example: see tBNE_demo.m
%
% Reference:
% Bokai Cao, Lifang He, Xiaokai Wei, Mengqi Xing, Philip S. Yu,
% Heide Klumpp and Alex D. Leow. t-BNE: Tensor-based Brain Network Embedding.
% In SDM 2017.
%
% Dependency:
% [1] Matlab tensor toolbox v 2.6
% Brett W. Bader, Tamara G. Kolda and others
% http://www.sandia.gov/~tgkolda/TensorToolbox
% [2] A feasible method for optimization with orthogonality constraints
% Zaiwen Wen and Wotao Yin
% http://www.math.ucla.edu/~wotaoyin/papers/feasible_method_matrix_manifold.html
%% set algorithm parameters
printitn = 10;
maxiter = 200;
fitchangetol = 1e-4;
alpha = 0.1; % weight for guidance
beta = 0.1; % weight for classification loss
gamma = 0.1; % weight for regularization
u = 1e-6;
umax = 1e6;
rho = 1.15;
opts.record = 0;
opts.mxitr = 20;
opts.xtol = 1e-5;
opts.gtol = 1e-5;
opts.ftol = 1e-8;
%% compute statistics
dim = size(X);
normX = norm(X);
numClass = size(Y, 2);
m = dim(1);
n = dim(3);
l = size(Y, 1);
D = [eye(l), zeros(l, n - l)];
L = diag(sum(Z * Z')) - Z * Z';
%% initialization
B = randn(m, k);
P = B;
S = randn(n, k);
S = orth(S);
W = randn(k, numClass);
U = zeros(m, k); % Lagrange multipliers
%% main loop
fit = 0;
for iter = 1 : maxiter
fitold = fit;
% update B
ete = (S' * S) .* (P' * P); % compute E'E
b = 2 * ete + u * eye(k);
c = 2 * mttkrp(X, {B, P, S}, 1) + u * P + U;
B = c / b;
% update P
ftf = (S' * S) .* (B' * B); % compute F'F
b = 2 * ftf + u * eye(k);
c = 2 * mttkrp(X, {B, P, S}, 2) + u * B - U;
P = c / b;
% update U
U = U + u * (P - B);
% update u
u = min(rho * u, umax);
% update S
tic;
[S, out] = OptStiefelGBB(...
S, #Sfun, opts, B, P, X, L, D, W, Y, alpha, beta);
tsolve = toc;
fprintf(...
['[S]: obj val %7.6e, cpu %f, #func eval %d, ', ...
'itr %d, |ST*S-I| %3.2e\n'], ...
out.fval, tsolve, out.nfe, out.itr, norm(S' * S - eye(k), 'fro'));
% update W
H = D * S;
W = (H' * H + gamma * eye(k)) \ H' * Y;
% compute the fit
T = ktensor({B, P, S});
normresidual = sqrt(normX ^ 2 + norm(T) ^ 2 - 2 * innerprod(X, T));
fit = 1 - (normresidual / normX);
fitchange = abs(fitold - fit);
if mod(iter, printitn) == 0
fprintf(' Iter %2d: fitdelta = %7.1e\n', iter, fitchange);
end
% check for convergence
if (iter > 1) && (fitchange < fitchangetol)
break;
end
end
%% clean up final results
T = arrange(T); % columns are normalized
fprintf('factorization error %3.2e\n', fit);
end
I know that there is little context here, but my suspicion is that I need to have Simulink, as Sfun is a Simulink related function(?). The script requires two toolboxes: tensor_toolbox, and FOptM.
Available at:
https://www.sandia.gov/~tgkolda/TensorToolbox/index-2.6.html
https://github.com/andland/FOptM
Thank you so much for your help,
Paul
Although SFun is an often used abbreviation for a Simulink S-Function, in this case the error has nothing to do with Simulink, and the name is a coincidence. (There is no Simulink related function specifically called Sfun, it is just a general term.)
Your error message has #Sfun in it, which is a way in MATLAB of creating a function handle to an (m-code) function called Sfun. I'd summize from the code you've shown that this is a cost function used in the optimization.
If you look at the code that your code is based on (tBNE_fun.m) you'll see that there is a function at the end of the file called Sfun. It is this that you are missing.

Precompute weights for multidimensional linear interpolation

I have a non-uniform rectangular grid along D dimensions, a matrix of logical values V on the grid, and a matrix of query data points X. The number of grid points differs across dimensions.
I run the interpolation multiple times for the same grid G and query X, but for different values V.
The goal is to precompute the indexes and weights for the interpolation and to reuse them, because they are always the same.
Here is an example in 2 dimensions, in which I have to compute indexes and values every time within the loop, but I want to compute them only once before the loop. I keep the data types from my application (mostly single and logical gpuArrays).
% Define grid
G{1} = single([0; 1; 3; 5; 10]);
G{2} = single([15; 17; 18; 20]);
% Steps and edges are reduntant but help make interpolation a bit faster
S{1} = G{1}(2:end)-G{1}(1:end-1);
S{2} = G{2}(2:end)-G{2}(1:end-1);
gpuInf = 1e10;
% It's my workaround for a bug in GPU version of discretize in Matlab R2017a.
% It throws an error if edges contain Inf, realmin, or realmax. Seems fixed in R2017b prerelease.
E{1} = [-gpuInf; G{1}(2:end-1); gpuInf];
E{2} = [-gpuInf; G{2}(2:end-1); gpuInf];
% Generate query points
n = 50; X = gpuArray(single([rand(n,1)*14-2, 14+rand(n,1)*7]));
[G1, G2] = ndgrid(G{1},G{2});
for i = 1 : 4
% Generate values on grid
foo = #(x1,x2) (sin(x1+rand) + cos(x2*rand))>0;
V = gpuArray(foo(G1,G2));
% Interpolate
V_interp = interpV(X, V, G, E, S);
% Plot results
subplot(2,2,i);
contourf(G1, G2, V); hold on;
scatter(X(:,1), X(:,2),50,[ones(n,1), 1-V_interp, 1-V_interp],'filled', 'MarkerEdgeColor','black'); hold off;
end
function y = interpV(X, V, G, E, S)
y = min(1, max(0, interpV_helper(X, 1, 1, 0, [], V, G, E, S) ));
end
function y = interpV_helper(X, dim, weight, curr_y, index, V, G, E, S)
if dim == ndims(V)+1
M = [1,cumprod(size(V),2)];
idx = 1 + (index-1)*M(1:end-1)';
y = curr_y + weight .* single(V(idx));
else
x = X(:,dim); grid = G{dim}; edges = E{dim}; steps = S{dim};
iL = single(discretize(x, edges));
weightL = weight .* (grid(iL+1) - x) ./ steps(iL);
weightH = weight .* (x - grid(iL)) ./ steps(iL);
y = interpV_helper(X, dim+1, weightL, curr_y, [index, iL ], V, G, E, S) +...
interpV_helper(X, dim+1, weightH, curr_y, [index, iL+1], V, G, E, S);
end
end
I found a way to do this and posting it here because (as of now) two more people are interested. It takes only a slight modification to my original code (see below).
% Define grid
G{1} = single([0; 1; 3; 5; 10]);
G{2} = single([15; 17; 18; 20]);
% Steps and edges are reduntant but help make interpolation a bit faster
S{1} = G{1}(2:end)-G{1}(1:end-1);
S{2} = G{2}(2:end)-G{2}(1:end-1);
gpuInf = 1e10;
% It's my workaround for a bug in GPU version of discretize in Matlab R2017a.
% It throws an error if edges contain Inf, realmin, or realmax. Seems fixed in R2017b prerelease.
E{1} = [-gpuInf; G{1}(2:end-1); gpuInf];
E{2} = [-gpuInf; G{2}(2:end-1); gpuInf];
% Generate query points
n = 50; X = gpuArray(single([rand(n,1)*14-2, 14+rand(n,1)*7]));
[G1, G2] = ndgrid(G{1},G{2});
[W, I] = interpIW(X, G, E, S); % Precompute weights W and indexes I
for i = 1 : 4
% Generate values on grid
foo = #(x1,x2) (sin(x1+rand) + cos(x2*rand))>0;
V = gpuArray(foo(G1,G2));
% Interpolate
V_interp = sum(W .* single(V(I)), 2);
% Plot results
subplot(2,2,i);
contourf(G1, G2, V); hold on;
scatter(X(:,1), X(:,2), 50,[ones(n,1), 1-V_interp, 1-V_interp],'filled', 'MarkerEdgeColor','black'); hold off;
end
function [W, I] = interpIW(X, G, E, S)
global Weights Indexes
Weights=[]; Indexes=[];
interpIW_helper(X, 1, 1, [], G, E, S, []);
W = Weights; I = Indexes;
end
function [] = interpIW_helper(X, dim, weight, index, G, E, S, sizeV)
global Weights Indexes
if dim == size(X,2)+1
M = [1,cumprod(sizeV,2)];
Weights = [Weights, weight];
Indexes = [Indexes, 1 + (index-1)*M(1:end-1)'];
else
x = X(:,dim); grid = G{dim}; edges = E{dim}; steps = S{dim};
iL = single(discretize(x, edges));
weightL = weight .* (grid(iL+1) - x) ./ steps(iL);
weightH = weight .* (x - grid(iL)) ./ steps(iL);
interpIW_helper(X, dim+1, weightL, [index, iL ], G, E, S, [sizeV, size(grid,1)]);
interpIW_helper(X, dim+1, weightH, [index, iL+1], G, E, S, [sizeV, size(grid,1)]);
end
end
To do the task the whole process of interpolation ,except computing the interpolated values, should be done. Here is a solution translated from the Octave c++ source. Format of the input is the same as the frst signature of the interpn function except that there is no need to the v array. Also Xs should be vectors and should not be of the ndgrid format. Both the outputs W (weights) and I (positions) have the size (a ,b) that a is the number of neighbors of a points on the grid and b is the number of requested points to be interpolated.
function [W , I] = lininterpnw(varargin)
% [W I] = lininterpnw(X1,X2,...,Xn,Xq1,Xq2,...,Xqn)
n = numel(varargin)/2;
x = varargin(1:n);
y = varargin(n+1:end);
sz = cellfun(#numel,x);
scale = [1 cumprod(sz(1:end-1))];
Ni = numel(y{1});
index = zeros(n,Ni);
x_before = zeros(n,Ni);
x_after = zeros(n,Ni);
for ii = 1:n
jj = interp1(x{ii},1:sz(ii),y{ii},'previous');
index(ii,:) = jj-1;
x_before(ii,:) = x{ii}(jj);
x_after(ii,:) = x{ii}(jj+1);
end
coef(2:2:2*n,1:Ni) = (vertcat(y{:}) - x_before) ./ (x_after - x_before);
coef(1:2:end,:) = 1 - coef(2:2:2*n,:);
bit = permute(dec2bin(0:2^n-1)=='1', [2,3,1]);
%I = reshape(1+scale*bsxfun(#plus,index,bit), Ni, []).'; %Octave
I = reshape(1+sum(bsxfun(#times,scale(:),bsxfun(#plus,index,bit))), Ni, []).';
W = squeeze(prod(reshape(coef(bsxfun(#plus,(1:2:2*n).',bit),:).',Ni,n,[]),2)).';
end
Testing:
x={[1 3 8 9],[2 12 13 17 25]};
v = rand(4,5);
y={[1.5 1.6 1.3 3.5,8.1,8.3],[8.4,13.5,14.4,23,23.9,24.2]};
[W I]=lininterpnw(x{:},y{:});
sum(W.*v(I))
interpn(x{:},v,y{:})
Thanks to #SardarUsama for testing and his useful comments.

Can't recover the parameters of a model using ode45

I am trying to simulate the rotation dynamics of a system. I am testing my code to verify that it's working using simulation, but I never recovered the parameters I pass to the model. In other words, I can't re-estimate the parameters I chose for the model.
I am using MATLAB for that and specifically ode45. Here is my code:
% Load the input-output data
[torque outputs] = DataLogs2();
u = torque;
% using the simulation data
Ixx = 1.00;
Iyy = 2.00;
Izz = 3.00;
x0 = [0; 0; 0];
Ts = .02;
t = 0:Ts:Ts * ( length(u) - 1 );
[ T, x ] = ode45( #(t,x) rotationDyn( t, x, u(1+floor(t/Ts),:), Ixx, Iyy, Izz), t, x0 );
w = x';
N = length(w);
q = 1; % a counter for the A and B matrices
% The Algorithm
for k=1:1:N
w_telda = [ 0 -w(3, k) w(2,k); ...
w(3,k) 0 -w(1,k); ...
-w(2,k) w(1,k) 0 ];
if k == N % to handle the problem of the last iteration
w_dash(:,k) = (-w(:,k))/Ts;
else
w_dash(:,k) = (w(:,k+1)-w(:,k))/Ts;
end
a = kron( w_dash(:,k)', eye(3) ) + kron( w(:,k)', w_telda );
A(q:q+2,:) = a; % a 3N*9 matrix
B(q:q+2,:) = u(k,:)'; % a 3N*1 matrix % u(:,k)
q = q + 3;
end
% Forcing J to be diagonal. This is the case when we consider our quadcopter as two thin uniform
% rods crossed at the origin with a point mass (motor) at the end of each.
A_new = [A(:, 1) A(:, 5) A(:, 9)];
vec_J_diag = A_new\B;
J_diag = diag([vec_J_diag(1), vec_J_diag(2), vec_J_diag(3)])
eigenvalues_J_diag = eig(J_diag)
error = norm(A_new*vec_J_diag - B)
where my dynamic model is defined as:
function [dw, y] = rotationDyn(t, w, tau, Ixx, Iyy, Izz, varargin)
% The output equation
y = [w(1); w(2); w(3)];
% State equation
% dw = (I^-1)*( tau - cross(w, I*w) );
dw = [Ixx^-1 * tau(1) - ((Izz-Iyy)/Ixx)*w(2)*w(3);
Iyy^-1 * tau(2) - ((Ixx-Izz)/Iyy)*w(1)*w(3);
Izz^-1 * tau(3) - ((Iyy-Ixx)/Izz)*w(1)*w(2)];
end
Practically, what this code should do, is to calculate the eigenvalues of the inertia matrix, J, i.e. to recover Ixx, Iyy, and Izz that I passed to the model at the very begining (1, 2 and 3), but all what I get is wrong results.
Is the problem with using ode45?
Well the problem wasn't in the ode45 instruction, the problem is that in system identification one can create an n-1 samples-signal from an n samples-signal, thus the loop has to end at N-1 in the above code.

Matlab error: Undefined function 'dmod' for input arguments of type 'double'. How come there is no dmod function as it should come with Matlab?

I have been working on some exam and need to do an exercise involving some frequency shift keying. That is why I use dmod function from Matlab - it comes with Matlab. But as I write in my console
yfsk=dmod([1 0], 3, 0.5, 100,'fsk', 2, 1);
it gives me this
`Undefined function 'dmod' for input arguments of type 'double'.
I have also tried doc dmod and it says 'page not found' in matlab help window.
Do you know wheter this is because I didn't install all the matlab packages or this function is not suported with matlab 2012a?
Thank you
This is gonna be helpful:
function [y, t] = dmod(x, Fc, Fd, Fs, method, M, opt2, opt3)
%DMOD
%
%WARNING: This is an obsolete function and may be removed in the future.
% Please use MODEM.PAMMOD, MODEM.QAMMOD, MODEM.GENQAMMOD, FSKMOD,
% MODEM.PSKMOD, or MODEM.MSKMOD instead.
% Y = DMOD(X, Fc, Fd, Fs, METHOD...) modulates the message signal X
% with carrier frequency Fc (Hz) and symbol frequency Fd (Hz). The
% sample frequency of Y is Fs (Hz), where Fs > Fc and where Fs/Fd is
% a positive integer. For information about METHOD and subsequent
% parameters, and about using a specific modulation technique,
% type one of these commands at the MATLAB prompt:
%
% FOR DETAILS, TYPE MODULATION TECHNIQUE
% dmod ask % M-ary amplitude shift keying modulation
% dmod psk % M-ary phase shift keying modulation
% dmod qask % M-ary quadrature amplitude shift keying
% % modulation
% dmod fsk % M-ary frequency shift keying modulation
% dmod msk % Minimum shift keying modulation
%
% For baseband simulation, use DMODCE. To plot signal constellations,
% use MODMAP.
%
% See also DDEMOD, DMODCE, DDEMODCE, MODMAP, AMOD, ADEMOD.
% Copyright 1996-2007 The MathWorks, Inc.
% $Revision: 1.1.6.5 $ $Date: 2007/06/08 15:53:47 $
warnobsolete(mfilename, 'Please use MODEM.PAMMOD, MODEM.QAMMOD, MODEM.GENQAMMOD, FSKMOD, MODEM.PSKMOD, or MODEM.MSKMOD instead.');
swqaskenco = warning('off', 'comm:obsolete:qaskenco');
swapkconst = warning('off', 'comm:obsolete:apkconst');
swmodmap = warning('off', 'comm:obsolete:modmap');
swamod = warning('off', 'comm:obsolete:amod');
opt_pos = 6; % position of 1st optional parameter
if nargout > 0
y = []; t = [];
end
if nargin < 1
feval('help','dmod')
return;
elseif isstr(x)
method = lower(deblank(x));
if length(method) < 3
error('Invalid method option for DMOD.')
end
if nargin == 1
% help lines for individual modulation method.
addition = 'See also DDEMOD, DMODCE, DDEMODCE, MODMAP, AMOD, ADEMOD.';
if method(1:3) == 'qas'
callhelp('dmod.hlp', method(1:4), addition);
else
callhelp('dmod.hlp', method(1:3), addition);
end
else
% plot constellation, make a shift.
opt_pos = opt_pos - 3;
M = Fc;
if nargin >= opt_pos
opt2 = Fd;
else
modmap(method, M);
return;
end
if nargin >= opt_pos+1
opt3 = Fs;
else
modmap(method, M, opt2);
return;
end
modmap(method, M, opt2, opt3); % plot constellation
end
return;
end
if (nargin < 4)
error('Usage: Y = DMOD(X, Fc, Fd, Fs, METHOD, OPT1, OPT2, OPT3) for passband modulation');
elseif nargin < opt_pos-1
method = 'samp';
else
method = lower(method);
end
len_x = length(x);
if length(Fs) > 1
ini_phase = Fs(2);
Fs = Fs(1);
else
ini_phase = 0; % default initial phase
end
if ~isfinite(Fs) | ~isreal(Fs) | Fs<=0
error('Fs must be a positive number.');
elseif length(Fd)~=1 | ~isfinite(Fd) | ~isreal(Fd) | Fd<=0
error('Fd must be a positive number.');
else
FsDFd = Fs/Fd; % oversampling rate
if ceil(FsDFd) ~= FsDFd
error('Fs/Fd must be a positive integer.');
end
end
if length(Fc) ~= 1 | ~isfinite(Fc) | ~isreal(Fc) | Fc <= 0
error('Fc must be a positive number. For baseband modulation, use DMODCE.');
elseif Fs/Fc < 2
warning('Fs/Fc must be much larger than 2 for accurate simulation.');
end
% determine M
if isempty(findstr(method, '/arb')) & isempty(findstr(method, '/cir'))
if nargin < opt_pos
M = max(max(x)) + 1;
M = 2^(ceil(log(M)/log(2)));
M = max(2, M);
elseif length(M) ~= 1 | ~isfinite(M) | ~isreal(M) | M <= 0 | ceil(M) ~= M
error('Alphabet size M must be a positive integer.');
end
end
if isempty(x)
y = [];
return;
end
[r, c] = size(x);
if r == 1
x = x(:);
len_x = c;
else
len_x = r;
end
% expand x from Fd to Fs.
if isempty(findstr(method, '/nomap'))
if ~isreal(x) | all(ceil(x)~=x)
error('Elements of input X must be integers in [0, M-1].');
end
yy = [];
for i = 1 : size(x, 2)
tmp = x(:, ones(1, FsDFd)*i)';
yy = [yy tmp(:)];
end
x = yy;
clear yy tmp;
end
if strncmpi(method, 'ask', 3)
if isempty(findstr(method, '/nomap'))
% --- Check that the data does not exceed the limits defined by M
if (min(min(x)) < 0) | (max(max(x)) > (M-1))
error('An element in input X is outside the permitted range.');
end
y = (x - (M - 1) / 2 ) * 2 / (M - 1);
else
y = x;
end
[y, t] = amod(y, Fc, [Fs, ini_phase], 'amdsb-sc');
elseif strncmpi(method, 'fsk', 3)
if nargin < opt_pos + 1
Tone = Fd;
else
Tone = opt2;
end
if (min(min(x)) < 0) | (max(max(x)) > (M-1))
error('An element in input X is outside the permitted range.');
end
[len_y, wid_y] = size(x);
t = (0:1/Fs:((len_y-1)/Fs))'; % column vector with all the time samples
t = t(:, ones(1, wid_y)); % replicate time vector for multi-channel operation
osc_freqs = pi*[-(M-1):2:(M-1)]*Tone;
osc_output = (0:1/Fs:((len_y-1)/Fs))'*osc_freqs;
mod_phase = zeros(size(x))+ini_phase;
for index = 1:M
mod_phase = mod_phase + (osc_output(:,index)*ones(1,wid_y)).*(x==index-1);
end
y = cos(2*pi*Fc*t+mod_phase);
elseif strncmpi(method, 'psk', 3)
% PSK is a special case of QASK.
[len_y, wid_y] = size(x);
t = (0:1/Fs:((len_y-1)/Fs))';
if findstr(method, '/nomap')
y = dmod(x, Fc, Fs, [Fs, ini_phase], 'qask/cir/nomap', M);
else
y = dmod(x, Fc, Fs, [Fs, ini_phase], 'qask/cir', M);
end
elseif strncmpi(method, 'msk', 3)
M = 2;
Tone = Fd/2;
if isempty(findstr(method, '/nomap'))
% Check that the data is binary
if (min(min(x)) < 0) | (max(max(x)) > (1))
error('An element in input X is outside the permitted range.');
end
x = (x-1/2) * Tone;
end
[len_y, wid_y] = size(x);
t = (0:1/Fs:((len_y-1)/Fs))'; % column vector with all the time samples
t = t(:, ones(1, wid_y)); % replicate time vector for multi-channel operation
x = 2 * pi * x / Fs; % scale the input frequency vector by the sampling frequency to find the incremental phase
x = [0; x(1:end-1)];
y = cos(2*pi*Fc*t+cumsum(x)+ini_phase);
elseif (strncmpi(method, 'qask', 4) | strncmpi(method, 'qam', 3) |...
strncmpi(method, 'qsk', 3) )
if findstr(method,'nomap')
[y, t] = amod(x, Fc, [Fs, ini_phase], 'qam');
else
if findstr(method, '/ar') % arbitrary constellation
if nargin < opt_pos + 1
error('Incorrect format for METHOD=''qask/arbitrary''.');
end
I = M;
Q = opt2;
M = length(I);
% leave to the end for processing
CMPLEX = I + j*Q;
elseif findstr(method, '/ci') % circular constellation
if nargin < opt_pos
error('Incorrect format for METHOD=''qask/circle''.');
end
NIC = M;
M = length(NIC);
if nargin < opt_pos+1
AIC = [1 : M];
else
AIC = opt2;
end
if nargin < opt_pos + 2
PIC = NIC * 0;
else
PIC = opt3;
end
CMPLEX = apkconst(NIC, AIC, PIC);
M = sum(NIC);
else % square constellation
[I, Q] = qaskenco(M);
CMPLEX = I + j * Q;
end
y = [];
x = x + 1;
% --- Check that the data does not exceed the limits defined by M
if (min(min(x)) < 1) | (max(max(x)) > M)
error('An element in input X is outside the permitted range.');
end
for i = 1 : size(x, 2)
tmp = CMPLEX(x(:, i));
y = [y tmp(:)];
end
ind_y = [1: size(y, 2)]';
ind_y = [ind_y, ind_y+size(y, 2)]';
ind_y = ind_y(:);
y = [real(y) imag(y)];
y = y(:, ind_y);
[y, t] = amod(y, Fc, [Fs, ini_phase], 'qam');
end
elseif strncmpi(method, 'samp', 4)
% This is for converting an input signal from sampling frequency Fd
% to sampling frequency Fs.
[len_y, wid_y] = size(x);
t = (0:1/Fs:((len_y-1)/Fs))';
y = x;
else % invalid method
error(sprintf(['You have used an invalid method.\n',...
'The method should be one of the following strings:\n',...
'\t''ask'' Amplitude shift keying modulation;\n',...
'\t''psk'' Phase shift keying modulation;\n',...
'\t''qask'' Quadrature amplitude shift-keying modulation, square constellation;\n',...
'\t''qask/cir'' Quadrature amplitude shift-keying modulation, circle constellation;\n',...
'\t''qask/arb'' Quadrature amplitude shift-keying modulation, user defined constellation;\n',...
'\t''fsk'' Frequency shift keying modulation;\n',...
'\t''msk'' Minimum shift keying modulation.']));
end
if r==1 & ~isempty(y)
y = y.';
end
warning(swqaskenco);
warning(swapkconst);
warning(swmodmap);
warning(swamod);
% [EOF]
I do believe that dmod function (Communication Toolbox) has been abandoned in the latest MATLAB releases.
It looks like dmod is no more :-)
Here is the link that says it was removed:
http://www.mathworks.com/help/comm/release-notes.html?searchHighlight=dmod
It should be replaced wit with comm.FSKModulator System object
I think you may be looking for the demodulation function (demod) from the signal processing toolbox.
http://www.mathworks.com.au/help/signal/ref/demod.html