I have a custom function called dissmeasure that outputs a scalar from an input vector of frequencies. Another function called music.tone2freq converts integers numbers to frequencies.
My objective is to create a surface plot of dissmeasure for all pairs of x,y integers where X and Y equal [0:1:11].
It should look something like this (this is mesh(X,Y, ones(12,12) ) ):
Following from the mesh docs, what I have tried is doing:
[X,Y] = meshgrid(0:1:12)
Z = dissmeasure(music.tone2freq([X., Y.]))
But I get Error: Expression or statement is incorrect--possibly unbalanced (, {, or [..
Z = dissmeasure(music.tone2freq([X(:), Y(:)]))
But [X(:), Y(:)] doesn't seem to have the correct size. Also my function that accepts a vector returns one scalar for that whole input. What I need is multiple returns.
Note that both dissmeasure(music.tone2freq([X(:), Y(:)])) and dissmeasure(music.tone2freq([X, Y])) work, but the result from dissmeasure is a single scalar number, not a matrix of the result of this function for each x,y pair.
Any help? Thank you
tone2freq.m
function f = tone2freq(T)
% MUSIC.TONE2FREQ converts a musical semitone to a frequency.
% F = MUSIC.TONE2FREQ(T) converts the musical semitones in T to frequencies.
%
% Example
% f = music.tone2freq(0:2); % returns [261.63 277.19 293.67]
%
% See also music.tone2interval, music.tone2note, music.freq2tone.
% Author: E. Johnson
% Copyright 2010 The MathWorks, Inc.
fC4 = 261.625565300599; % Middle C (C4) is 261.63 Hz
f = fC4 .* 2 .^ (T / 12);
dissmeasure.m:
% calculate dissonace
% input param fvec - list of frequencies
% input param amp - list of amplitudes
% output is sum of dissonances of each pair of partials (scalar)
function d = dissmeasure(fvec, amp)
if ~exist('amp','var')
amp = ones(size(fvec));
end
Xstar = 0.24; % place with maximum dissonance
S1 = 0.0207; % to fit frequency dependend curves
S2 = 18.96; % so max. dissonance occures at 1/4 critical bandwidth
C1 = 5;
C2 = -5;
B1 = -3.51; % derived from model of Levelt & Plomp
B2 = -5.75;
N = length(fvec);
[fvec, idx_list] = sort(fvec); % sort partial frequencies ascending
amp = amp(idx_list); % rearrange amplitude values
%amp = loudness(amp);
D = 0;
for i=2:N
Fmin = fvec(1 : N-i+1); % get slice as list of Fmin
S = Xstar./(S1*Fmin+S2); % calc list of s-scalings with list of Fmin
% treat vector as tail and head ...
Fdif = fvec(i:N) - fvec(1:N-i+1); % build element wise difference
a = min(amp(i:N), amp(1:N-i+1)); % select element wise a minimum
Dnew = a .* (C1*exp(B1*S.*Fdif) + C2*exp(B2*S.*Fdif));
D = D + sum(Dnew); % sum up last D and vector elements
end
d=D;
Your function dissmeasure does not support vectorized operations, which means that for inputs of size N the function is evaluated for each element and an output of size N is returned.
Instead your function returns the summarized dissonance.
%assuming you have X and Y already converted
Z=X*0 % initialize Z of same size
for ix = 1:numel(X)
Z(ix)=dissmeasure(X(ix),Y(ix));
end
Related
I attempted to solve the problem, and would like a solution to compare to.
The question is:
Write a function that determines the (n-1)th order Newton polynomial and interpolates for a
set of values. The inputs of your function should be: a vector of x values, a corresponding
vector of y values, and a vector of values to interpolate. Your outputs should be the
coefficients of the polynomial (as a vector, [a1 a2 ···an]) and the corresponding function
values for the interpolation. Thoroughly comment your code to show that you
know what you are doing.
My attempt is:
function yint = Newtint(x,y,xx)
n = length(x);
if length(y)~=n, error('x and y must be same length'); end
b = zeros(n,n);
b(:,1) = y(:); % the (:) ensures that y is a column vector.
for j = 2:n
for i = 1:n-j+1
b(i,j) = (b(i+1,j-1)-b(i,j-1))/(x(i+j-1)-x(i));
end
end
xt = 1;
yint = b(1,1);
for j = 1:n-1
xt = xt*(xx-x(j));
yint = yint+b(1,j+1)*xt;
end
% input:
% x = independent variable
% y = dependent variable
% xx = value of independent variable at which
% interpolation is calculated
% output:
% yint = interpolated value of dependent variable
% compute the finite divided differences in the form of a
% difference table
I am having trouble with this code for a piecewise cubic Hermite polynomial. In my assignment we are not allowed to use pchip. We are supposed to write a function which takes as it's input arguments an integer n and a 3 by n matrix which contains the x values, the values of a function evaluated at each x, and the values of the derivative evaluated at each x; in the first, second and third rows of the matrix respectively.
With this information we are supposed to calculate the coefficients for each Hermite polynomial on each subinterval of the interval given by the first row of the input matrix, then piece it altogether using mkpp.
Unfortunately, my code produces a very poor interpolating polynomial and I am having trouble figuring out why. For example for the function x^2 we have for instance n = 4 and M = [0,1,2,3; 0,1,4,9; 0,1,4,6] and when plugged into my function produces the following graph
I would really appreciate help with this, it's driving me nuts.
Here is my code:
function [ HP ] = HermiteInter( n,M )
%HermiteInter
% This function constructs a peicewise cubic Hermite polynomial.
% The input areguments are an integer n and M a 3 by n matrix, whose
% first row contains the values of x which a given function will be
% evaluated at. The second row contains the values of a function
% evaluated at those
% points and the third row contains the value of the derivative of
% the function evaluated at those points.
% Divided differences using these values are found by calling the
% function HermiteDD. These divided differences are then passed into the
% function mkpp to create the peicewise polynomial.
X = M(1,:);
Y = M(2,:);
Z = M(3,:);
Q = zeros(n-1,4);
for i = 1 : n-1
Q(i,:) = HermiteDD([X(i),X(i),X(i+1),X(i+1)],[Y(i),Y(i+1)],[Z(i),Z(i+1)]);
end
HP = mkpp(X,Q);
end
function [ HDD ] = HermiteDD(X,Y,Z)
%HermiteDD
% This function creates a table of divided differences for
% Hermite polynomials. The input arguments are X, the values at
% which a function was evaluated at, Y the values of the function at
% these points and Z the values of the derivative of the function at
% these points.
DD = zeros(4, 4);
DD(1, 1) = Y(1);
DD(2, 1) = Y(1);
DD(3, 1) = Y(2);
DD(4, 1) = Y(2);
DD(1, 2) = Z(1);
DD(2, 2) = (Y(1)-Y(2))/(X(1)-X(3));
DD(3, 2) = Z(2);
for j = 3 : 4
for i = 1 : (4 - j+1)
DD(i,j) = (DD(i + 1, j - 1) - DD(i, j - 1)) / (X(i + j-1) - X(i));
end
end
HDD = DD(1,:);
end
I found matlab file (https://in.mathworks.com/matlabcentral/fileexchange/9700-random-vectors-with-fixed-sum) which generates probability matrix with uniform probability and each column has sum 1. file is as follow
function [x,v] = randfixedsum(n,m,s,a,b)
%[x,v] = randfixedsum(n,m,s,a,b)
%
% This generates an n by m array x, each of whose m columns
% contains n random values lying in the interval [a,b], but
% subject to the condition that their sum be equal to s. The
% scalar value s must accordingly satisfy n*a <= s <= n*b. The
% distribution of values is uniform in the sense that it has the
% conditional probability distribution of a uniform distribution
% over the whole n-cube, given that the sum of the x's is s.
%
% The scalar v, if requested, returns with the total
% n-1 dimensional volume (content) of the subset satisfying
% this condition. Consequently if v, considered as a function
% of s and divided by sqrt(n), is integrated with respect to s
% from s = a to s = b, the result would necessarily be the
% n-dimensional volume of the whole cube, namely (b-a)^n.
%
% This algorithm does no "rejecting" on the sets of x's it
% obtains. It is designed to generate only those that satisfy all
% the above conditions and to do so with a uniform distribution.
% It accomplishes this by decomposing the space of all possible x
% sets (columns) into n-1 dimensional simplexes. (Line segments,
% triangles, and tetrahedra, are one-, two-, and three-dimensional
% examples of simplexes, respectively.) It makes use of three
% different sets of 'rand' variables, one to locate values
% uniformly within each type of simplex, another to randomly
% select representatives of each different type of simplex in
% proportion to their volume, and a third to perform random
% permutations to provide an even distribution of simplex choices
% among like types. For example, with n equal to 3 and s set at,
% say, 40% of the way from a towards b, there will be 2 different
% types of simplex, in this case triangles, each with its own
% area, and 6 different versions of each from permutations, for
% a total of 12 triangles, and these all fit together to form a
% particular planar non-regular hexagon in 3 dimensions, with v
% returned set equal to the hexagon's area.
%
% Roger Stafford - Jan. 19, 2006
% Check the arguments.
if (m~=round(m))|(n~=round(n))|(m<0)|(n<1)
error('n must be a whole number and m a non-negative integer.')
elseif (s<n*a)|(s>n*b)|(a>=b)
error('Inequalities n*a <= s <= n*b and a < b must hold.')
end
% Rescale to a unit cube: 0 <= x(i) <= 1
s = (s-n*a)/(b-a);
% Construct the transition probability table, t.
% t(i,j) will be utilized only in the region where j <= i + 1.
k = max(min(floor(s),n-1),0); % Must have 0 <= k <= n-1
s = max(min(s,k+1),k); % Must have k <= s <= k+1
s1 = s - [k:-1:k-n+1]; % s1 & s2 will never be negative
s2 = [k+n:-1:k+1] - s;
w = zeros(n,n+1); w(1,2) = realmax; % Scale for full 'double' range
t = zeros(n-1,n);
tiny = 2^(-1074); % The smallest positive matlab 'double' no.
for i = 2:n
tmp1 = w(i-1,2:i+1).*s1(1:i)/i;
tmp2 = w(i-1,1:i).*s2(n-i+1:n)/i;
w(i,2:i+1) = tmp1 + tmp2;
tmp3 = w(i,2:i+1) + tiny; % In case tmp1 & tmp2 are both 0,
tmp4 = (s2(n-i+1:n) > s1(1:i)); % then t is 0 on left & 1 on right
t(i-1,1:i) = (tmp2./tmp3).*tmp4 + (1-tmp1./tmp3).*(~tmp4);
end
% Derive the polytope volume v from the appropriate
% element in the bottom row of w.
v = n^(3/2)*(w(n,k+2)/realmax)*(b-a)^(n-1);
% Now compute the matrix x.
x = zeros(n,m);
if m == 0, return, end % If m is zero, quit with x = []
rt = rand(n-1,m); % For random selection of simplex type
rs = rand(n-1,m); % For random location within a simplex
s = repmat(s,1,m);
j = repmat(k+1,1,m); % For indexing in the t table
sm = zeros(1,m); pr = ones(1,m); % Start with sum zero & product 1
for i = n-1:-1:1 % Work backwards in the t table
e = (rt(n-i,:)<=t(i,j)); % Use rt to choose a transition
sx = rs(n-i,:).^(1/i); % Use rs to compute next simplex coord.
sm = sm + (1-sx).*pr.*s/(i+1); % Update sum
pr = sx.*pr; % Update product
x(n-i,:) = sm + pr.*e; % Calculate x using simplex coords.
s = s - e; j = j - e; % Transition adjustment
end
x(n,:) = sm + pr.*s; % Compute the last x
% Randomly permute the order in the columns of x and rescale.
rp = rand(n,m); % Use rp to carry out a matrix 'randperm'
[ig,p] = sort(rp); % The values placed in ig are ignored
x = (b-a)*x(p+repmat([0:n:n*(m-1)],n,1))+a; % Permute & rescale x
return
but I want to generate matrix which has each row elements sum 1 and each row have uniform probability in matlab. how to do this with above programme. to run above programme I am calling it to another file and setting parameters
i.e.
m=4;n=4; a=0; b=1.5;s=1;
[x,v] = randfixedsum(n,m,s,a,b)
create a random matrix and divide each row by sum of elements of that row:
function result = randrowsum(m ,n)
rnd = rand(m,n);
rowsums = sum(rnd,2);
result = bsxfun(#rdivide, rnd, rowsums);
end
to create an m * n random matrix :
a=randrowsum(3,4)
check if sum of each row is 1:
sum(a,2)
I would say the easiest was is to generate the array with the given function.
[x,v] = randfixedsum(n,m,s,a,b);
Then just transport the results.
x = x';
This question already has answers here:
Random numbers that add to 100: Matlab
(4 answers)
Closed 7 years ago.
I am looking how to pick 10 positive non-zero elements in 1x10 array randomly whose sum is 1
Example :
A=[0.0973 0.1071 0.0983 0.0933 0.1110 0.0942 0.1062 0.0970 0.0981 0.0974]
Note: If we sum the elements in above matrix it will be 1. I need matlab to generate a matrix like this randomly
Try using Roger's fex submission: http://www.mathworks.com/matlabcentral/fileexchange/9700-random-vectors-with-fixed-sum
Here is a copy of the content of the file (in case the link dies).
All the credit obviously goes to the original poster Roger Stafford:
function [x,v] = randfixedsum(n,m,s,a,b)
% [x,v] = randfixedsum(n,m,s,a,b)
%
% This generates an n by m array x, each of whose m columns
% contains n random values lying in the interval [a,b], but
% subject to the condition that their sum be equal to s. The
% scalar value s must accordingly satisfy n*a <= s <= n*b. The
% distribution of values is uniform in the sense that it has the
% conditional probability distribution of a uniform distribution
% over the whole n-cube, given that the sum of the x's is s.
%
% The scalar v, if requested, returns with the total
% n-1 dimensional volume (content) of the subset satisfying
% this condition. Consequently if v, considered as a function
% of s and divided by sqrt(n), is integrated with respect to s
% from s = a to s = b, the result would necessarily be the
% n-dimensional volume of the whole cube, namely (b-a)^n.
%
% This algorithm does no "rejecting" on the sets of x's it
% obtains. It is designed to generate only those that satisfy all
% the above conditions and to do so with a uniform distribution.
% It accomplishes this by decomposing the space of all possible x
% sets (columns) into n-1 dimensional simplexes. (Line segments,
% triangles, and tetrahedra, are one-, two-, and three-dimensional
% examples of simplexes, respectively.) It makes use of three
% different sets of 'rand' variables, one to locate values
% uniformly within each type of simplex, another to randomly
% select representatives of each different type of simplex in
% proportion to their volume, and a third to perform random
% permutations to provide an even distribution of simplex choices
% among like types. For example, with n equal to 3 and s set at,
% say, 40% of the way from a towards b, there will be 2 different
% types of simplex, in this case triangles, each with its own
% area, and 6 different versions of each from permutations, for
% a total of 12 triangles, and these all fit together to form a
% particular planar non-regular hexagon in 3 dimensions, with v
% returned set equal to the hexagon's area.
%
% Roger Stafford - Jan. 19, 2006
% Check the arguments.
if (m~=round(m))|(n~=round(n))|(m<0)|(n<1)
error('n must be a whole number and m a non-negative integer.')
elseif (s<n*a)|(s>n*b)|(a>=b)
error('Inequalities n*a <= s <= n*b and a < b must hold.')
end
% Rescale to a unit cube: 0 <= x(i) <= 1
s = (s-n*a)/(b-a);
% Construct the transition probability table, t.
% t(i,j) will be utilized only in the region where j <= i + 1.
k = max(min(floor(s),n-1),0); % Must have 0 <= k <= n-1
s = max(min(s,k+1),k); % Must have k <= s <= k+1
s1 = s - [k:-1:k-n+1]; % s1 & s2 will never be negative
s2 = [k+n:-1:k+1] - s;
w = zeros(n,n+1); w(1,2) = realmax; % Scale for full 'double' range
t = zeros(n-1,n);
tiny = 2^(-1074); % The smallest positive matlab 'double' no.
for i = 2:n
tmp1 = w(i-1,2:i+1).*s1(1:i)/i;
tmp2 = w(i-1,1:i).*s2(n-i+1:n)/i;
w(i,2:i+1) = tmp1 + tmp2;
tmp3 = w(i,2:i+1) + tiny; % In case tmp1 & tmp2 are both 0,
tmp4 = (s2(n-i+1:n) > s1(1:i)); % then t is 0 on left & 1 on right
t(i-1,1:i) = (tmp2./tmp3).*tmp4 + (1-tmp1./tmp3).*(~tmp4);
end
% Derive the polytope volume v from the appropriate
% element in the bottom row of w.
v = n^(3/2)*(w(n,k+2)/realmax)*(b-a)^(n-1);
% Now compute the matrix x.
x = zeros(n,m);
if m == 0, return, end % If m is zero, quit with x = []
rt = rand(n-1,m); % For random selection of simplex type
rs = rand(n-1,m); % For random location within a simplex
s = repmat(s,1,m);
j = repmat(k+1,1,m); % For indexing in the t table
sm = zeros(1,m); pr = ones(1,m); % Start with sum zero & product 1
for i = n-1:-1:1 % Work backwards in the t table
e = (rt(n-i,:)<=t(i,j)); % Use rt to choose a transition
sx = rs(n-i,:).^(1/i); % Use rs to compute next simplex coord.
sm = sm + (1-sx).*pr.*s/(i+1); % Update sum
pr = sx.*pr; % Update product
x(n-i,:) = sm + pr.*e; % Calculate x using simplex coords.
s = s - e; j = j - e; % Transition adjustment
end
x(n,:) = sm + pr.*s; % Compute the last x
% Randomly permute the order in the columns of x and rescale.
rp = rand(n,m); % Use rp to carry out a matrix 'randperm'
[ig,p] = sort(rp); % The values placed in ig are ignored
x = (b-a)*x(p+repmat([0:n:n*(m-1)],n,1))+a; % Permute & rescale x
return
I'm trying to find zeros of a function. See my code below.
Because fft expects a numerical array, I didn't define the symbolic function to use fzero.
However, this approach is not accurate and depend on step. Do you have a better idea?
step=2000;
x=0:pi/step:2*pi;
y= 4+5*cos(10*x)+20*cos(40*x)+cos(100*x);
fy = fft(y');
fy(1:8) =0;
fy(12:end-10)=0;
fy(end-6:end)=0;
ffy = ifft(fy);
t=diff(ffy);
x=0:pi/step:2*pi-pi/step;
plot(x,t)
indices= find(t<5e-4 & t>-5e-4);
You could proceed along the array t and look for points where the values change sign. That would indicate the presence of a zero.
Actaully, MATLAB's fzero function uses a similar method. You said you didn't use it because you required an array, rather than an anonymous function, but you could convert the array into an anonymous function using simple linear interpolation like so:
func = #(k) interp1(x,t,k); % value of t(x) interpolated at x=k
fzero(func,initial_value);
EDIT : Just to clarify what I mean. If you have an array t and you want to find its zeros...
f = 5; % frequency of wave in Hz
x = 0:0.01:1; % time index
t = cos( 2*pi*f*x ); % cosine wave of frequency f
zeroList = []; % start with an empty list of zeros
for i = 2:length(t) % loop through the array t
current_t = t(i); % current value of t
previous_t = t(i-1); % previous value of t
if current_t == 0 % the case where the zero is exact
newZero = x(i);
zeroList = [zeroList,newZero];
elseif current_t*previous_t < 0 % a and b have opposite sign if a*b is -ve
% do a linear interpolation to find the zero (solve y=mx+b)
slope = (current_t-previous_t)/(x(i)-x(i-1));
newZero = x(i) - current_t/slope;
zeroList = [zeroList,newZero];
end
end
figure(1); hold on;
axis([ min(x) max(x) -(max(abs(t))) (max(abs(t))) ]);
plot(x,t,'b');
plot(x,zeros(length(x)),'k-.');
scatter(zeroList,zeros(size(zeroList)),'ro');
The zeros I get are correct: