I have this matrix:
a1 a2 a3 a4 a5
b1 b2 b3 b4 b5
c1 c2 c3 c4 c5
d1 d2 d3 d4 d5
e1 e2 e3 e4 e5
and i need to transform it to this matrix:
a1 a2 a3 b1 b2 b3 c1 c2 c3
a2 a3 a4 b2 b3 b4 c2 c3 c4
a3 a4 a5 b3 b4 b5 c3 c4 c5
b1 b2 b3 c1 c2 c3 d1 d2 d3
b2 b3 b4 c2 c3 c4 d2 d3 d4
b3 b4 b5 c3 c4 c5 d3 d4 d5
c1 c2 c3 d1 d2 d3 e1 e2 e3
c2 c3 c4 d2 d3 d4 e2 e3 e4
c3 c4 c5 d3 d4 d5 e3 e4 e5
i.e. by taking a 3x3 matrix and iterating over the old matrix putting it as a new row in the new matrix.
How can i do this in matlab? I heard loops are very bad and if I can I should use matrix operations.
If you have access to image processing toolbox you can use im2col which even works for symbolic variables too.
A = sym('A%d%d', [5 5]);
A = sym(A, 'real');
Subs = mat2cell(im2col(A, [3 1])', 3*ones(1,5));
Res = im2col(Subs, [3 1]);
Res is a cell matrix containing the sub matrices.
To concatenate it into a matrix:
reshape([Res{:}]', [9 9])
or if it's not symbolic this also works: cell2mat(Res).
Take a look at this code :
clear
clc
a1 = 1; a2 = 2; a3 = 3; a4 = 4; a5 = 5;
b1 = 11; b2 = 12; b3 = 13; b4 = 14; b5 = 15;
c1 = 21; c2 = 22; c3 = 23; c4 = 24; c5 = 25;
d1 = 31; d2 = 32; d3 = 33; d4 = 34; d5 = 35;
e1 = 41; e2 = 42; e3 = 43; e4 = 44; e5 = 45;
A = [a1 a2 a3 a4 a5; b1 b2 b3 b4 b5; c1 c2 c3 c4 c5; d1 d2 d3 d4 d5; e1 e2 e3 e4 e5];
B = zeros(9,9);
sizeA = size(A);
sizeB = size(B);
jj = 1;
kk = 1;
for ii = 1 : sizeB(1)
B(ii,1:sizeB(1)) = [A(kk, jj:jj+2) A(kk + 1, jj:jj+2) A(kk + 2, jj:jj+2)]
jj = jj + 1;
if mod(ii,3) == 0
kk = kk + 1;
jj = 1;
end
end
I tested it for your case where A is 5x5 and B is 9x9. Might need to be modified to work with different size of A and B.
You can do this in a somewhat general sense, but it is not pretty:
a = [a1, a2, a3, a4, a5];
b = [b1, b2, b3, b4, b5];
% etc.
% Rearrange your vector into a matrix configured how you want it
A = flipdim(toeplitz(a),1); % 5 x 5 matrix in our case
A = A(ceil(size(A,1)/2):size(A,1), ceil(size(A,2)/2):size(A,2)); % now 3 x 3
%%%
% Repeat similar process for b --> B, c --> C, etc.
%%%
% Build the resulting matrix up block-by-block
M = [A, B, C;
B, C, D;
C, D, E];
I was unable to find a good way to generalize the construction of M, and unfortunately forming a toeplitz matrix using toeplitz([a,b,c,d,e]) fails; you do not get the right format for your sub-matrices. Still, you may be able to use this to start on something.
Related
I am trying to create a matrix in MATLAB by a vector in the following condition:
The vector is:
v=[a1; a2; a3; a4; a5; a1; a2; a3; a4; a5; a1; a2; a3; a4; a5; a1; a2; a3; a4; a5; a1; a2; a3; a4; a5; a1; a2; a3; a4; a5]
v is a vector of a1, a2, a3, a4, a5 elements that repeats 6 times in this example.
Now I need to make a matrix based on this vector such that:
matrix=
a1 a2 a3
a2 a1 a2
a3 a2 a1
a4 a3 a2
a5 a4 a3
a1 a2 a3
a2 a1 a2
a3 a2 a1
a4 a3 a2
a5 a4 a3
I make a gap between the two blocks of the matrix to show the concept.
The first column of the matrix is a1, a2, a3, a4, a5 (repeating two times).
The second column starts with a2 and decreases to a1, then increase again up to a4. so a2, a1, a2, a3, a4, repeat two times too.
The third column starts with a3...a1...a3 and repeats two times again.
So I need a for loop to make this matrix by the vector elements v.
I appreciate your help.
It is a rather particular sorting, so better define it directly. For example:
blockElements=[[1 2 3];[2 1 2];[3 2 1];[4 3 2];[5 4 3]];
matrixElements=[blockElements; blockElements];
Then the matrix you want is just:
matrix=v(matrixElements);
Note that for this to work you don't need v to repeat 6 times a1...a5. It would work also if v is defined like
v=[a1; a2; a3; a4; a5];
or
v=[a1, a2, a3, a4, a5];
Actually, I don't see a straightforward approach for producing that result using a one-liner function; reshaping is a good solution only as long as elements are already placed properly inside the vector... which is not the case, hence the repetition of the values in the vector is kinda useless. On the top of that, I don't see the point of using a for loop to achieve this result when you can use straighe indexing.
v = 40:45; % if it's really mandatory you can use repmat(40:45,1,6)
m = [v(repmat(1:5,1,2)).' v(repmat([2 1 2 3 4],1,2)).' v(repmat([3 2 1 2 3],1,2)).'];
m =
40 41 42
41 40 41
42 41 40
43 42 41
44 43 42
40 41 42
41 40 41
42 41 40
43 42 41
44 43 42
I am trying to replicate a linear optimisation that I found in a research paper in Matlab. I need to solve the following linear optimisation problem:
where C1, C2, C3, C4, C5, w1 and w2 are priority weightings.
j is taken from 1 to 12 (12 months of the year).
The following constraints apply:
I(j) and L(j) are monthly recordings.
I used MatLab to program a solution. Here is my code (I am quite new to this, so please forgive any bad coding!):
%set up the data for the year:
I = [72.6 26.0 23.2 20.4 15.2 22.0 40.9 45.2 38.7 41.4 142.2 116.8]
L = [1.6 1.3 0.8 0.6 0.6 0.6 1 1.5 1.8 1.8 1.8 2.0];
%set up the initial level:
S0 = 683
%set up the priority weightings
w2= 1;
w1 = 1.5;
C1 = 3;
C2 = 2;
C3 = 5;
C4 = 4;
C5 = -5;
%set up the constraint equation, lower bond and upper bound
A = [(C1*w1) C2 (C3*w2) (C4*w2) C5];
Aeq = [1 1 1 1 1];
lb = [70 0 0 0 0];
ub = [815 54.14 13.4 41.8 17345];
%set up a blank matrix to store the results
x=zeros(12,5);
%for each month calculate the optimum and store in the matrix
for j = 1:12
Beq = [(I(j)+S0-L(j))];
x(j,:) = linprog(-A,[],[],Aeq,Beq,lb,ub);
S0 = x(j,1);
end
%output the result
opt = x
The problem is when I compare my results to the research paper I find that I am getting different results. Eventually I realised that I am finding the optimum for each month, rather than a global optimum for the year. I have been searching online for how to find an optimum for the whole year (i.e. to optimize the summation function) but I can't find anything. Can anyone point me in the right direction?
Thanks to #ErwinKalvelagen I was able to solve my problem. Here is my solution for others in future:
%set up the data for the year:
I = [72.6; 26.0; 23.2; 20.4; 15.2; 22.0; 40.9; 45.2; 38.7; 41.4; 142.2; 116.8;];
I = I*1; %allows the inflow to be scaled to test the model for a dry or wet year
L = [1.6; 1.3; 0.8; 0.6; 0.6; 0.6; 1; 1.5; 1.8; 1.8; 1.8; 2.0;];
%set up the priority weightings
w1 = 2;
w2= 50;
C1 = 3;
C2 = 2;
C3 = 5;
C4 = 4;
C5 = -5;
%set up the constraint equation, lower bond and upper bound
A = [(C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5 (C1*w1) C2 (C3*w2) (C4*w2) C5];
%set up spare matrix for Aeq
Aeq = zeros(12,60);
% Populate Aeq
% first the positive portions of the monthly data
row = 1;
coloumn = 1;
for counter = 1:12
for counter = 1:5
Aeq(coloumn,row)=1;
row = row + 1;
end
coloumn = coloumn+1;
end
% then the -S0 for each month
Aeq(1, 56)=-1;
coloumn = 1;
for row = 2:12
Aeq(row,coloumn)=-1;
coloumn = coloumn+5;
end
%populate Beq
Beq = I-L;
%populate the lower and upper bounds
Smin = 70;
Smax_1_9 = 731.2;
Smax_10_12 = 673.2
QDmin = 0
QDmax = 54.14
Rmin = 0;
Rmax = 13.4;
RRmin = 0;
RRmax = 41.8;
SPILLmin = 0;
SPILLmax = 17345;
%first the lower bound
lbmonthly = [Smin; QDmin; Rmin; RRmin; SPILLmin;];
lb = vertcat(lbmonthly,lbmonthly,lbmonthly,lbmonthly,lbmonthly,lbmonthly,lbmonthly,lbmonthly,lbmonthly,lbmonthly,lbmonthly,lbmonthly);
%second the upper bound
ubmonthly_1_9 = [Smax_1_9; QDmax; Rmax; RRmax; SPILLmax;];
ubmonthly_10_12 = [Smax_10_12; QDmax; Rmax; RRmax; SPILLmax;];
ub = vertcat(ubmonthly_1_9, ubmonthly_1_9, ubmonthly_1_9, ubmonthly_1_9, ubmonthly_1_9, ubmonthly_1_9, ubmonthly_1_9, ubmonthly_1_9, ubmonthly_1_9, ubmonthly_10_12, ubmonthly_10_12, ubmonthly_10_12);
%find the optimal
opt = linprog(-A,[],[],Aeq,Beq,lb,ub);
%output the result as a matrix
opt = reshape(opt,5,12)'
I have a spark dataset like this one:
key id val1 val2 val3
1 a a1 a2 a3
2 a a4 a5 a6
3 b b1 b2 b3
4 b b4 b5 b6
5 b b7 b8 b9
6 c c1 c2 c3
I would like to group all rows by id in a list or array like this:
(a, ([1 a a1 a2 a3], [2 a a4 a5 a6]) ),
(b, ([3 b b1 b2 b3], [4 b b4 b5 b6], [5 b b7 b8 b9]) ),
(c, ([6 c c1 c2 c3]) )
I have used map to output key/value pairs with the right key but I have troubles in building the final key/array.
Can anybody help with that?
how about this:
import org.apache.spark.sql.functions._
df.withColumn("combined",array("key","id","val1","val2","val3")).groupby("id").agg(collect_list($"combined"))
The Array function converts the columns into an array of column and then its a simple groupby with collect_list
import org.apache.spark.ml.feature.VectorAssembler
import org.apache.spark.sql.functions._
val assembler = new VectorAssembler()
.setInputCols(Array("key", "id", "val1", "val2", "val3","score"))
.setOutputCol("combined")
val dfRes = assembler.transform(df).groupby("id").agg(collect_list($"combined"))
File Content of my xzy.txt file
key id val1 val2 val3
1 a a1 a2 a3
2 a a4 a5 a6
3 b b1 b2 b3
4 b b4 b5 b6
5 b b7 b8 b9
6 c c1 c2 c3
Code with Required Output
Input file Content
Let there be five matrices given as:
A= [A1 A1 A1 A1 A1; A2 A2 A2 A2 A2; A3 A3 A3 A3 A3]
B= [B1 B1 B1 B1 B1; B2 B2 B2 B2 B2;B3 B3 B3 B3 B3]
C=[ C1 C1 C1 C1 C1; C2 C2 C2 C2 C2; C3 C3 C3 C3 C3]
D= [D1 D1 D1 D1 D1 ; D2 D2 D2 D2 D2; D3 D3 D3 D3 D3]
E=[ E1 E1 E1 E1 E1; E2 E2 E2 E2 E2; E3 E3 E3 E3 E3]
I want to make a program such that ouput consists of taking each row of each given matrix and forming a new matrix. how to use looping in such cases when length of matrices increases and number of given matrices also increases. This problem seemed to me a complex one. Because I want to generalize by using loop and output for any number of matrices say 20 and having number of columns also increased to say 25, then how to get these P1 to P20 outputs. Can anyone help me regarding this complex trouble using Matlab
P1=[ A1 A1 A1 A1 A1; B1 B1 B1 B1 B1; C1 C1 C1 C1 C1 C1; D1 D1 D1 D1 D1; E1 E1 E1 E1 E1]
P2=[ A2 A2 A2 A2 A2; B2 B2 B2 B2 B2; C2 C2 C2 C2 C2 C2; D2 D2 D2 D2 D2; E2 E2 E2 E2 E2]
and similarly other matrices is obtained .
Note: That the given 5 matrices are generated with help of loop. So first I would be getting values as :
A= A1
B= B1
C=C1
D=D1
E=E1
A= A1 A1
B= B1 B1
C=C1 C1
D=D1 D1
E=E1 E1 .... AND SO ON
Get a loop and put all the matrix together to form a 3D tensor. Or just put the matrices in the 3D tensor when they are created.
M(:,:,1) = A; M(:,:,2) = B; etc
then
squeeze(M(1,:,:))' is the P1, squeeze(M(2,:,:))' is the P2
Example:
M(:,:,1) =
1 2
3 4
M(:,:,2) =
5 6
7 8
>> squeeze(M(1,:,:))'
ans =
1 2
5 6
tell me how to get every possible combination of hash
Here is an example
my %data = (
'a' => [qw(a1 a2 a3)],
'b' => [qw(b1 b2 b3)],
'c' => [qw(c1 c2 c3)]);
to get
a1
a2
a3
b1
b2
b3
c1
c2
c3
a1 b1
a1 b2
a1 b3
a1 c1
a1 c2
a1 c3
b1 c1
b1 c2
b1 c3
b2 c1
b2 c2
b2 c3
b3 c1
b3 c2
b3 c3
a1 b1 c1
a1 b1 c2
a1 b1 c3
a1 b2 c1
a1 b2 c2
a1 b2 c3
a1 b3 c1
a1 b3 c2
a1 b3 c3
a2 b1 c1
a2 b1 c2
a2 b1 c3
a2 b2 c1
a2 b2 c2
a2 b2 c3
a2 b3 c1
a2 b3 c2
a2 b3 c3
a3 b1 c1
a3 b1 c2
a3 b1 c3
a3 b2 c1
a3 b2 c2
a3 b2 c3
a3 b3 c1
a3 b3 c2
a3 b3 c3
thanks
Use brian d foy's Set::CrossProduct module. You'll need to massage your hash into array of arrays in an obvious way.
use Set::CrossProduct;
my $iterator = Set::CrossProduct->new( ARRAY_OF_ARRAYS );
my $tuples = $iterator->combinations;
My module List::Gen contains a cartesian function that can produce the results you want. This code seems to do the trick, but your example does not contain all of the permutations that this will produce, which I am assuming is just an omission in the example.
use List::Gen 'cartesian';
my %data = (
'a' => [qw(a1 a2 a3)],
'b' => [qw(b1 b2 b3)],
'c' => [qw(c1 c2 c3)],
);
my $product = cartesian {join ' ' => sort grep defined, #_}
map {[#$_, undef]}
values %data;
say for sort {length $a <=> length $b or $a cmp $b} #$product;
That is a bit dense, so to explain:
values %data returns the arrays in %data
map {[#$_, undef]} then attaches an empty value to the end of each, since you want the partial combinations
cartesian {join ' ' => sort grep defined, #_} then does the meat of the work, computing the Cartesian product of the arrays while subtracting out the undefined elements, and sorting the values as your example shows.
sort {length $a <=> length $b or $a cmp $b} #$product then prints out the product in the order specified.