How would you make these for loops dynamically recursive?

% Value that each row will sum up to in final matrix
qualmax=8;
% Almost unused var that I'd like to use to cut down on code
iters=8;
% Determine number of rows in the answer
syms s
a=sym2poly(symprod(s+qualmax,s,1,iters)/factorial(iters));
% Initialization Values
c=1;
n=zeros(a,9);
% a(1) is used to remove a sum of n_ values
for n1=0:qualmax
a1(1)=(qualmax-n1);
for n2=0:a1(1)
a1(2)=(a1(1)-n2);
for n3=0:a1(2)
a1(3)=(a1(2)-n3);
for n4=0:a1(3)
a1(4)=(a1(3)-n4);
for n5=0:a1(4)
a1(5)=(a1(4)-n5);
for n6=0:a1(5)
a1(6)=(a1(5)-n6);
for n7=0:a1(6)
a1(7)=(a1(6)-n7);
for n8=0:a1(7)
% Here is where we question what's left to get to qual max
a1(8)=(a1(7)-n8);
% Setting values
n(c,9)=n1;
n(c,8)=n2;
n(c,8)=n2;
n(c,7)=n3;
n(c,6)=n4;
n(c,5)=n5;
n(c,4)=n6;
n(c,3)=n7;
n(c,2)=n8;
n(c,1)=a1(8);
% Increment the index
c=c+1;
end
end
end
end
end
end
end
end

4 件のコメント

Walter Roberson
Walter Roberson 2022 年 10 月 20 日
Describe in words what you are trying to do.
Cameron Bruscino
Cameron Bruscino 2022 年 10 月 20 日
I am making a list of all iters+1 dimensional vectors that sum up to qualmax. The question being asked here is how can this be turned into a function with iters and qualmax as inputs, or at least make the for loops nest exactly iters number of times.
Bjorn Gustavsson
Bjorn Gustavsson 2022 年 10 月 20 日
It might help further if you explain your problem for smaller dimensions, (1) 2 or 3, just for illustration.
Cameron Bruscino
Cameron Bruscino 2022 年 10 月 20 日
Here is what it would look like going from 8 down to 1 dimensions of this problem.
clc
clear
close all
syms s
% qualmax represents the number of objects that can be 'constructed' within
% respect to 'area' constraints where each object in this case only takes
% up an 'area' of 1.
qualmax=8;
% iters represents the number 'levels' for the object in question
iters=8;
% b is a representation of the 'area' taken up by each object
b=ones(iters+1,1);
% This index is a catch case for where there are less objects in a set than
% specified for by qualmax, allowing for cascading answers for any case
% less than qualmax.
b(1)=0;
% This matrix represents values attached to each 'level' of an object.
% Initialization with zeros allows for later matrix multiplication where
% index 1 of the vector made in the for loops can represent how much
% 'area' is remaining without losing data from the vector.
Factory=zeros(iters+1,4);
% All values for a 'factory' of the 'level' specified in the first value of
% each vector.
Factory(2,:)=[1,2,0,10];
Factory(3,:)=[2,3,1,20];
Factory(4,:)=[3,4,2,35];
Factory(5,:)=[4,4,3,40];
Factory(6,:)=[5,5,4,50];
Factory(7,:)=[6,6,5,80];
Factory(8,:)=[7,7,5,100];
Factory(9,:)=[8,8,6,110];
% Concatination of the'area' values into these intrinsic values.
Factory=[b,Factory];
% Repeat of above with 'mines' as an object/'structure'.
Mine=zeros(iters+1,5);
Mine(2,:)=[1,1,0,0,5];
Mine(3,:)=[2,2,0,0,10];
Mine(4,:)=[3,3,1,0,15];
Mine(5,:)=[4,4,1,1,25];
Mine(6,:)=[5,5,2,1,40];
Mine(7,:)=[6,6,2,1,50];
Mine(8,:)=[7,7,3,1,70];
Mine(9,:)=[8,8,3,2,80];
Mine=[b,Mine];
% a=# of unique vectors where all indices are an integer and overall sum up
% to qualmax.
a=sym2poly(symprod(s+qualmax,s,1,iters)/factorial(iters));
% Index initialization for the for loops.
c=1;
% n(a,b)=Matrix of unique vectors representing all (a) combinations of
% (b-1) elements with n(:,1) representing the 'area' not taken up by each
% combination of objects. n is initialized below.
n=zeros(a,iters+1);
% n_ is an index for the number to be inserted into the vector from right
% to left. a1 is a shortening varable to reduce notation.
if iters==8
for n1=0:qualmax
a1(1)=(qualmax-n1);
for n2=0:a1(1)
a1(2)=(a1(1)-n2);
for n3=0:a1(2)
a1(3)=(a1(2)-n3);
for n4=0:a1(3)
a1(4)=(a1(3)-n4);
for n5=0:a1(4)
a1(5)=(a1(4)-n5);
for n6=0:a1(5)
a1(6)=(a1(5)-n6);
for n7=0:a1(6)
a1(7)=(a1(6)-n7);
for n8=0:a1(7)
a1(8)=(a1(7)-n8);
n(c,9)=n1;
n(c,8)=n2;
n(c,8)=n2;
n(c,7)=n3;
n(c,6)=n4;
n(c,5)=n5;
n(c,4)=n6;
n(c,3)=n7;
n(c,2)=n8;
n(c,1)=a1(8);
c=c+1;
end
end
end
end
end
end
end
end
elseif iters==7
for n1=0:qualmax
a1(1)=(qualmax-n1);
for n2=0:a1(1)
a1(2)=(a1(1)-n2);
for n3=0:a1(2)
a1(3)=(a1(2)-n3);
for n4=0:a1(3)
a1(4)=(a1(3)-n4);
for n5=0:a1(4)
a1(5)=(a1(4)-n5);
for n6=0:a1(5)
a1(6)=(a1(5)-n6);
for n7=0:a1(6)
a1(7)=(a1(6)-n7);
n(c,8)=n1;
n(c,7)=n2;
n(c,6)=n3;
n(c,5)=n4;
n(c,4)=n5;
n(c,3)=n6;
n(c,2)=n7;
n(c,1)=a1(7);
c=c+1;
end
end
end
end
end
end
end
elseif iters==6
for n1=0:qualmax
a1(1)=(qualmax-n1);
for n2=0:a1(1)
a1(2)=(a1(1)-n2);
for n3=0:a1(2)
a1(3)=(a1(2)-n3);
for n4=0:a1(3)
a1(4)=(a1(3)-n4);
for n5=0:a1(4)
a1(5)=(a1(4)-n5);
for n6=0:a1(5)
a1(6)=(a1(5)-n6);
n(c,7)=n1;
n(c,6)=n2;
n(c,5)=n3;
n(c,4)=n4;
n(c,3)=n5;
n(c,2)=n6;
n(c,1)=a1(6);
c=c+1;
end
end
end
end
end
end
elseif iters==5
for n1=0:qualmax
a1(1)=(qualmax-n1);
for n2=0:a1(1)
a1(2)=(a1(1)-n2);
for n3=0:a1(2)
a1(3)=(a1(2)-n3);
for n4=0:a1(3)
a1(4)=(a1(3)-n4);
for n5=0:a1(4)
a1(5)=(a1(4)-n5);
n(c,6)=n1;
n(c,5)=n2;
n(c,4)=n3;
n(c,3)=n4;
n(c,2)=n5;
n(c,1)=a1(5);
c=c+1;
end
end
end
end
end
elseif iters==4
for n1=0:qualmax
a1(1)=(qualmax-n1);
for n2=0:a1(1)
a1(2)=(a1(1)-n2);
for n3=0:a1(2)
a1(3)=(a1(2)-n3);
for n4=0:a1(3)
a1(4)=(a1(3)-n4);
n(c,5)=n1;
n(c,4)=n2;
n(c,3)=n3;
n(c,2)=n4;
n(c,1)=a1(4);
c=c+1;
end
end
end
end
elseif iters==3
for n1=0:qualmax
a1(1)=(qualmax-n1);
for n2=0:a1(1)
a1(2)=(a1(1)-n2);
for n3=0:a1(2)
a1(3)=(a1(2)-n3);
n(c,4)=n1;
n(c,3)=n2;
n(c,2)=n3;
n(c,1)=a1(3);
c=c+1;
end
end
end
elseif iters==2
for n1=0:qualmax
a1(1)=(qualmax-n1);
for n2=0:a1(1)
a1(2)=(a1(1)-n2);
n(c,3)=n1;
n(c,2)=n2;
n(c,1)=a1(2);
c=c+1;
end
end
elseif iters==1
for n1=0:qualmax
a1(1)=(qualmax-n1);
n(c,2)=n1;
n(c,1)=a1(1);
c=c+1;
end
end
clearvars n1 n2 n3 n4 n5 n6 n7 n8 a1 c
% This will continue to assign weights to each value in the initial data,
% corresponding to an 'income' for each 'level' so that the matrix can be
% manipulated to get the greatest 'income' for the lowest 'area' usage
% under case to case constraints.
% The question asked by the post is how to reduce the mostrosity of a mess
% within the above if/ifelse nesting to make the matrix (n) have iters+1
% columns based on values given above the point where a is declared.

サインインしてコメントする。

 採用された回答

Walter Roberson
Walter Roberson 2022 年 10 月 20 日

0 投票

For the case of integers, then what you are asking for looks to be what is known as Integer Partitions. You can use https://www.mathworks.com/matlabcentral/fileexchange/12009-partitions-of-an-integer from the File Exchange; @John D'Errico

2 件のコメント

Torsten
Torsten 2022 年 10 月 21 日
Doesn't it exclude the "0" as possible value for the partition ?
Walter Roberson
Walter Roberson 2022 年 10 月 21 日
Wouldn't take much to change that.

サインインしてコメントする。

その他の回答 (2 件)

Bruno Luong
Bruno Luong 2022 年 10 月 21 日

1 投票

5 件のコメント

Torsten
Torsten 2022 年 10 月 21 日
The problem is slightly different, I guess.
Distribute integers {0,1,...,8} at 9 positions with sum 8.
Bruno Luong
Bruno Luong 2022 年 10 月 21 日
編集済み: Bruno Luong 2022 年 10 月 21 日
AllVL1(n, s) returns all (row) vectors V of length n such that
  1. V >= 0
  2. sum(V,2) = s
If I enter
allVL1(9,8)
it returns 12870 x 9 array of solutions compatible with OP's original for-loop code.
Torsten
Torsten 2022 年 10 月 21 日
編集済み: Torsten 2022 年 10 月 21 日
Yes, works in this case since 9 > the sum (8). So the number 9 cannot appear in the 9-tuples.
In the usual case, there are three degrees of freedom: List of numbers, size of the vector V and sum(V,2).
Bruno Luong
Bruno Luong 2022 年 10 月 21 日
OP does not have list of number as input and I'm not counting the number of diophantin (linear) equation as John's code.
Also the order of elements in V by AllVL1 matters, whereas it is NOT in partition problem in general and John's code in particular.
I consider my solution is closer to wha OP's ask, not partition solver such as as John's code.
Torsten
Torsten 2022 年 10 月 21 日
編集済み: Torsten 2022 年 10 月 21 日
I consider my solution is closer to wha OP's ask, not partition solver such as as John's code.
Yes, I agree, since it solves the OP's problem while John's code doesn't (at least as far as I can see).

サインインしてコメントする。

Torsten
Torsten 2022 年 10 月 20 日
編集済み: Torsten 2022 年 10 月 20 日

0 投票

Code available under
It's brute-force - thus caution: quite memory-intensive.
I don't know if it's faster than the nested loop. At least it's more general.
iters = 8;
qualmax = 8;
v = 0:qualmax;
C = permn(v,iters+1);
size(C)
I = sum(C,2)==qualmax;
C = C(I,:);
size(C)
function [M, I] = permn(V, N, K)
% PERMN - permutations with repetition
% Using two input variables V and N, M = PERMN(V,N) returns all
% permutations of N elements taken from the vector V, with repetitions.
% V can be any type of array (numbers, cells etc.) and M will be of the
% same type as V. If V is empty or N is 0, M will be empty. M has the
% size numel(V).^N-by-N.
%
% When only a subset of these permutations is needed, you can call PERMN
% with 3 input variables: M = PERMN(V,N,K) returns only the K-ths
% permutations. The output is the same as M = PERMN(V,N) ; M = M(K,:),
% but it avoids memory issues that may occur when there are too many
% combinations. This is particulary useful when you only need a few
% permutations at a given time. If V or K is empty, or N is zero, M will
% be empty. M has the size numel(K)-by-N.
%
% [M, I] = PERMN(...) also returns an index matrix I so that M = V(I).
%
% Examples:
% M = permn([1 2 3],2) % returns the 9-by-2 matrix:
% 1 1
% 1 2
% 1 3
% 2 1
% 2 2
% 2 3
% 3 1
% 3 2
% 3 3
%
% M = permn([99 7],4) % returns the 16-by-4 matrix:
% 99 99 99 99
% 99 99 99 7
% 99 99 7 99
% 99 99 7 7
% ...
% 7 7 7 99
% 7 7 7 7
%
% M = permn({'hello!' 1:3},2) % returns the 4-by-2 cell array
% 'hello!' 'hello!'
% 'hello!' [1x3 double]
% [1x3 double] 'hello!'
% [1x3 double] [1x3 double]
%
% V = 11:15, N = 3, K = [2 124 21 99]
% M = permn(V, N, K) % returns the 4-by-3 matrix:
% % 11 11 12
% % 15 15 14
% % 11 15 11
% % 14 15 14
% % which are the 2nd, 124th, 21st and 99th permutations
% % Check with PERMN using two inputs
% M2 = permn(V,N) ; isequal(M2(K,:),M)
% % Note that M2 is a 125-by-3 matrix
%
% % PERMN can be used generate a binary table, as in
% B = permn([0 1],5)
%
% NB Matrix sizes increases exponentially at rate (n^N)*N.
%
% See also PERMS, NCHOOSEK
% ALLCOMB, PERMPOS, NEXTPERM, NCHOOSE2 on the File Exchange
% tested in Matlab 2018a
% version 6.2 (jan 2019)
% (c) Jos van der Geest
% Matlab File Exchange Author ID: 10584
% email: samelinoa@gmail.com
% History
% 1.1 updated help text
% 2.0 new faster algorithm
% 3.0 (aug 2006) implemented very fast algorithm
% 3.1 (may 2007) Improved algorithm Roger Stafford pointed out that for some values, the floor
% operation on floating points, according to the IEEE 754 standard, could return
% erroneous values. His excellent solution was to add (1/2) to the values
% of A.
% 3.2 (may 2007) changed help and error messages slightly
% 4.0 (may 2008) again a faster implementation, based on ALLCOMB, suggested on the
% newsgroup comp.soft-sys.matlab on May 7th 2008 by "Helper". It was
% pointed out that COMBN(V,N) equals ALLCOMB(V,V,V...) (V repeated N
% times), ALLCMOB being faster. Actually version 4 is an improvement
% over version 1 ...
% 4.1 (jan 2010) removed call to FLIPLR, using refered indexing N:-1:1
% (is faster, suggestion of Jan Simon, jan 2010), removed REPMAT, and
% let NDGRID handle this
% 4.2 (apr 2011) corrrectly return a column vector for N = 1 (error pointed
% out by Wilson).
% 4.3 (apr 2013) make a reference to COMBNSUB
% 5.0 (may 2015) NAME CHANGED (COMBN -> PERMN) and updated description,
% following comment by Stephen Obeldick that this function is misnamed
% as it produces permutations with repetitions rather then combinations.
% 5.1 (may 2015) always calculate M via indices
% 6.0 (may 2015) merged the functionaly of permnsub (aka combnsub) and this
% function
% 6.1 (may 2016) fixed spelling errors
% 6.2 (jan 2019) fixed some coding style warnings
narginchk(2, 3) ;
if fix(N) ~= N || N < 0 || numel(N) ~= 1
error('permn:negativeN','Second argument should be a positive integer') ;
end
nV = numel(V) ;
if nargin==2
%% PERMN(V,N) - return all permutations
if nV == 0 || N == 0
M = zeros(nV, N) ;
I = zeros(nV, N) ;
elseif N == 1
% return column vectors
M = V(:) ;
I = (1:nV).' ;
else
% this is faster than the math trick used with 3 inputs below
[Y{N:-1:1}] = ndgrid(1:nV) ;
I = reshape(cat(N+1, Y{:}), [], N) ;
M = V(I) ;
end
else
%% PERMN(V,N,K) - return a subset of all permutations
nK = numel(K) ;
if nV == 0 || N == 0 || nK == 0
M = zeros(numel(K), N) ;
I = zeros(numel(K), N) ;
elseif nK < 1 || any(K<1) || any(K ~= fix(K))
error('permn:InvalidIndex','Third argument should contain positive integers.') ;
else
V = reshape(V, 1, []) ; % v1.1 make input a row vector
nV = numel(V) ;
Npos = nV^N ;
if any(K > Npos)
warning('permn:IndexOverflow', ...
'Values of K exceeding the total number of combinations are saturated.')
K = min(K, Npos) ;
end
% The engine is based on version 3.2 with the correction
% suggested by Roger Stafford. This approach uses a single matrix
% multiplication.
B = nV.^(1-N:0) ;
I = ((K(:)-.5) * B) ; % matrix multiplication
I = rem(floor(I), nV) + 1 ;
M = V(I) ;
end
end
% Algorithm using for-loops
% which can be implemented in C or VB
%
% nv = length(V) ;
% C = zeros(nv^N,N) ; % declaration
% for ii=1:N,
% cc = 1 ;
% for jj=1:(nv^(ii-1)),
% for kk=1:nv,
% for mm=1:(nv^(N-ii)),
% C(cc,ii) = V(kk) ;
% cc = cc + 1 ;
% end
% end
% end
% end
end

カテゴリ

ヘルプ センター および File ExchangeMathematics and Optimization についてさらに検索

製品

リリース

R2021b

質問済み:

2022 年 10 月 20 日

編集済み:

2022 年 10 月 21 日

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by