MATLAB: All combinations of sum of vectors - matlab

So I have this piece of code (in MATLAB)
% Define vectorfield
g1=[5,0,0];
g2=[0,3,0];
g3=[0,0,4];
% Define on-off
u=[0;1];
% Define set to make field symmetric
symm=[1;-1];
k=1;
%% Generate possible combinations of vector fields
for a=1:length(u)
for b=1:length(symm)
for c=1:length(u)
for d=1:length(symm)
for e=1:length(u)
for f=1:length(symm)
allvecfields(k,:)=u(a).*symm(b).*g1+u(c).*symm(d).*g2+u(e).*symm(f).*g3;
k=k+1;
end
end
end
end
end
end
realfields=transpose(unique(allvecfields,'rows'));
Each column of realfields is a unique positive, negative or zero combination of the g's. I need some help generalizing this. That is the size of each g can be n, and the number of g's can be m. The code should still return all the unique possible combinations of the g's. I have a feeling that recursion will have to be used but all my attempts have failed so far.
Also allvecfields(k,:) just means kth row, all columns. Even if your answer contains C/C++ or Java code (without any special functions from them) that is fine for me. I will translate it into MATLAB.
I have looked at combvec and the allcomb file but they don't do what I need. For example transpose(unique(combvec(g1,g2,g3,-g1,-g2,-g3)','rows')) returns a 6x63 matrix not the 3x27 that I want. Doing
vals=transpose(unique(combvec(g1,g2,g3)','rows'));
vals=[vals transpose(unique(combvec(-g1,g2,g3)','rows'))];
vals=[vals transpose(unique(combvec(g1,-g2,g3)','rows'))];
vals=[vals transpose(unique(combvec(g1,g2,-g3)','rows'))];
vals=[vals transpose(unique(combvec(g1,-g2,-g3)','rows'))];
vals=[vals transpose(unique(combvec(-g1,g2,-g3)','rows'))];
vals=[vals transpose(unique(combvec(-g1,-g2,g3)','rows'))];
vals=[vals transpose(unique(combvec(-g1,-g2,-g3)','rows'))];
vals=unique(vals','rows');
Does give what I want, but that does not help in generalizing.
EDIT: Fixed error in last line of first code block. The required output for this case is quite large (27 columns) but if we just had g1 and g2 then the output would be:
realfields =
-5 -5 -5 0 0 0 5 5 5
-3 0 3 -3 0 3 -3 0 3
0 0 0 0 0 0 0 0 0
EDIT: Based on a suggestion in the comments, I have been able to rewrite the above code as,
u=[-1,0,1];
k=1;
for a=1:length(u)
for b=1:length(u)
for c=1:length(u)
uMat(k,:)=[u(a) u(b) u(c)];
k=k+1;
end
end
end
g1=[5,0,0];
g2=[0,3,0];
g3=[0,0,4];
gMat=[g1' g2' g3'];
for a=1:size(uMat,1)
allvecfields(k,:)=sum(bsxfun(#times,gMat,uMat(a,:)),2);
end
realfields=transpose(unique(allvecfields,'rows'))
I think this is slightly more elegant but I am still stuck at how to dynamically generate uMat given the number of columns in gMat. I can't believe a function doesn't exist for this. Any help would be appreciated.

Here is the solution
g1=[5,0,0];
g2=[0,3,0];
g3=[0,0,4];
gMat=[g1' g2' g3'];
m=size(gMat',1);
allvecfields = zeros(3^m,m);
for k = 1:3^m
allvecfields(k,:) = double(dec2base(k-1,3,m)-'1');
end
realfields = (allvecfields*gMat')'
Credits to: Roger Stafford for this ingenious solution.

Related

Splitting a series in two with zeros and the series value

I have the following in table in matlab
k ak
0 1
1 -0.166666667
2 0.008333333
... ...
where ak = (-1)^k/(2k+1)! but that's not really important, all that is important is that ak is a function of k and the (-1)^k.
I am trying to generate a new set of columns as below
i ai
0 1
1 0
2 -0.166666667
3 0
4 0.008333333
... ...
So far I've figured out that by stretching my indices (incrementing by 2 instead of 1) and applying the ak function it gets pretty close to what I want but it returns the absolute value.
if mod(i,2)=0
ai=(-1)^i/factorial(2*(i/2)+1);
else
ai=0;
end
How can I change this to be what I want?
You should be using this:
ai = (-1)^(ii/2)/factorial(2*(ii/2)+1);
% Notice ----^
Your if-else statements can be given a vector input and written in one-line as:
ai = ~mod(ii,2) .* (-1).^(ii/2)./factorial(2*(ii/2)+1);
%I used ii instead of i since i is for imaginary numbers in MATLAB

Why code is not giving proper results Matlab?

I know this type of questions may have been answered before but i am a beginner in matlab so please bear my kiddy questions.
I wan to generate a 11*12 matrix from a set of values. i have five different vectors named X,Y Z,u,v.
my code is:
A=zeros(12,11);
for i=1:6
A=[X(i) Y(i) Z(i) 1 0 0 0 0 (-u(i)*X(i)) (-u(i)*Y(i)) (-u(i)*Z(i)),0 0 0 0 X(i) Y(i) Z(i) 1 (-v(i)*X(i)) (-v(i)*Y(i)) (-v(i)*Z(i))];
end
Here for each iteration i want to fill two rows. So it becomes 12 rows in total. But the problem is that
1. it is giving me 22*1 matrix
2. It is giving wrong values
That means it is appending columns in each iteration that i do not want.
Kindly help me to find a 11*12 matrix. Thanks
You are assigning a completely new matrix to A on every iteration, so this will result in what you get.
What you want is to replace the rows each iteration. You can index the matrix to do this:
A(1,:) = [1 2 3 4];
This, for example, will replace the first row with the given values. So you can use
A(i*2-1,:)=[X(i) Y(i) Z(i) 1 0 0 0 0 (-u(i)*X(i)) (-u(i)*Y(i)) (-u(i)*Z(i))];
A(i*2,:)=[0 0 0 0 X(i) Y(i) Z(i) 1 (-v(i)*X(i)) (-v(i)*Y(i)) (-v(i)*Z(i))];
Unfortunately I don't have Matlab here now to see if you could combine those into one line by indexing A(i*2-1:i*2,:) or not.

Problems in defining limits fmincon using MATLAB

this is my question:
I have six parametres that I'll vary in fmincon toolbox of MATLAB, and these are the restrictions:
variables=[x1,x2,x3,x4,x5,x6]
x1<=x2
x3<=x4
x5<=x6
So, I defined the A matrix for fmincon like this:
A=[1 -1 0 0 0 0; 0 0 1 -1 0 0; 0 0 0 0 1 -1];
and vector b:
b=[0;0;0];
And the problem is that fmincon doesn't respect the conditions (if they are well defined), I mean por the first iteration, the parameters were:
ddx=[1 1 1 1 1 1];
And for the second iteration the variation was:
ddx=[2 1 1 1 1 1];
As you can see, there's a mistake with respect the definition in the boundaries, because x1=2 and x2=1; which is not right.
I hope you can give me some ideas.
This is an example:
function Example
clc
global xo
lbr=[2,2,300,300,3,3];
upr=[8,8,2000,2000,6,6];
xo =[3,4,400,500,4,5];
Aeq=[];
beq=[];
% Matríz de condiciones
Ain=[1 -1 0 0 0 0;0 0 1 -1 0 0;0 0 0 0 1 -1];
bin=[0;0;0];
lb=lbr./xo;
ub=upr./xo;
xo_n=ones(1,size(upr,2));
options1 = optimset('Display','iter',...
'Algorithm','sqp','PlotFcns',#optimplotfval,...
'MaxIter',400,'MaxFunEvals',1000,'DiffMinChange',1);
[ddx, FOval] = fmincon(#MyfunSSI,xo_n,Ain,bin,Aeq,beq,lb,ub,[],options1);
end
function [FO]=MyfunSSI(ddx)
global xo
ddx
x1=xo(1)*ddx(1);
x2=xo(2)*ddx(2);
x3=xo(3)*ddx(3);
x4=xo(4)*ddx(4);
x5=xo(5)*ddx(5);
x6=xo(6)*ddx(6);
% These are the conditions:
x1<=x2
x3<=x4
x5<=x6
FO=1;
end
As you can see, the restrictions are not respected.
After the function fmincon terminates, it should either satisfy the constraints, or indicated that it cannot find a feasible solution.
That during the optimization iterations constraints are violated, can be advantageous for certain problems, and hence this is supported by some of the algorithms (at least the Active Set algorithm) in fmincon. If you dont like this behavior, use Interior Point. For more details, see fmincon algorithms and violating constraints.
edit The thing that is going wrong is your objective function MyfunSSI. It just returns 1, and hence there is nothing to minimize. In addition, you are just putting the constraint statements, without processing them in any way. The constraints are dealt with by the A and b matrix, so forget about these. But the main thing is: change the function a proper objective function that uses the input ddx to come up with an output value FO.
And by the way, using sqp in this way means that the optimizer will use finite differences and hence evaluate the objective function near feasible and hence possibly infeasible points.

check if a column is composed of ones

does it exist a function built-in in matlab that checks if a column is all composed of ones? If it doesn't exist, there are some ways to build a function that work to achieve that porpouse?
all(A==1) should return true if it's composed of only 1s. Note that if you have any floating point precision errors, you should use all( abs(A-1) < eps ).
You can compare all entries of a column to 1 and sum the result
if sum(A(:,1)~=1)==0
% all ones
else
% not all ones
end
If A is a column vector:
A=[1 1 1 1]';
You could check like this:
sum(A==1)==length(A)
ans =
1

How do I get the indexes of specific elements based on value and then replace them in MATLAB?

From the exercises in a book I am using to learn MATLAB:
Given x = [3 15 9 12 -1 0 -12 9 6 1],
provide the command(s) that will
A) set the values of x that are
positive to zero
B) set values that are multiples of 3
to 3 (rem will help here)
C) multiply the values of x that are
even by 5
D) extract the values of x that are
greater than 10 into a vector called
y
E) set the values in x that are less
than the mean to zero
F) set the values in x that are above the mean to their difference from the mean
Question a) will teach you the following elements:
find a function that returns indexes given a condition, in your case x>0
use indexing in order to set selected values in x to 0
to be continued ...
x = [3 15 9 12 -1 0 -12 9 6 1]
vi = (x < 0) % statement that returns a boolean, gives a vector like
% [0 0 0 0 1 0 1 0 0 0]
x(vi) = -x(vi) % does the operation (negating in this case) on the relevant
% values of x (those with a 1 from above)
Without actually doing your homework, they all follow the above pattern.
I agree with the comments to your question, that is not necessarily the right way to go if you really want to learn something.
As to answer your question, MATLAB has a fantastic function browser I strongly suggest you take a look at it. With well chosen keywords you can go a long way. :)