In article <fimps8$7in$1@fred.mathworks.com>,
Greg von Winckel <gregvw@gmail.com> wrote:
>What would be an efficient way to compute all vectors with
>natural number elements of length n<N such that the l^1 norm
>of the vector is N?
You mean "the knapsack problem" with a fixed number of weights
(but the size of each weight is limited only to natural numbers
1 thru N-n+1) ?
--
"All is vanity." -- Ecclesiastes
"Greg von Winckel" <gregvw@gmail.com> wrote in message
<fimps8$7in$1@fred.mathworks.com>...
> What would be an efficient way to compute all vectors with
> natural number elements of length n<N such that the l^1 norm
> of the vector is N?
My partitions code from the FEX is close to
what you are asking for. Is it efficient?
Reasonably so.
The only flaw is that its set up to limit only the
quantity of any single number, not to fix the
total number of elements.
However, it should be reasonably efficient to
write a recursive code to solve your problem
using much the same scheme found in
partitions. For example:
% =============================
function list = parts(Nsum,Nel,MaximumElement)
% parts: find all decreasing positive integer vectors of length Nel that sum to
Nsum
% list = parts(Nsum,Nel)
%
% arguments:
% Nsum - scalar integer - defines the sum
%
% Nel - scalar integer - number of elements in the vector
if (nargin<3) || isempty(MaximumElement)
MaximumElement = Nsum;
end
if (Nel == Nsum)
% the simple case, where all elements are equal and unity
list = ones(1,Nel);
return
elseif (Nsum <= 0) || (Nel == 0)
% either of these events cannot be satisfied by any list
% of positive integers
list = [];
return
elseif (Nel == 1)
% Only one element in the list - it must be Nsum
if (MaximumElement >= Nsum)
list = Nsum;
return
else
% but that possibility is disallowed
list = [];
return
end
elseif (Nel>Nsum)
% another non-viable possibility
list = [];
return
end
% if we drop down to here, there are at least two elements, and
% at least one solution to be found.
list = cell(0,1);
for maxel = min(MaximumElement,Nsum - Nel + 1):-1:1
% Assume that the first element in the list is maxel
sublist = parts(Nsum - maxel,Nel-1,maxel);
if ~isempty(sublist)
r = size(sublist,1);
list{end+1,1} = [repmat(maxel,r,1),sublist];
end
end
% aggregate all solutions into a flat array
list = cell2mat(list);
% =============================
Now I'd write a permutation code for each
row of this result. Expect this all to get nasty
exponentially fast for larger sums. parts(50,10)
found 16928 solutions, each of which can occur
in a multitude of sequences.
If you consider "natural number" starts from 0, call:
v=allVL1(n, L1);
If you consider "natural number" starts from 1, then call:
v=allVL1(n, L1-n)+1;
Bruno
function v=allVL1(n, L1)
% function v=allVL1(n, L1)
% INPUT
% n: length of the vector
% L1: desired L1 norm
% OUTPUT:
% v: m x n array such as sum(v,2)=L1
% all elements of v is naturel numbers {0,1,...}
% v contains all possible combination
if n==1
v = L1;
else
v1 = (0:L1)';
vrest = arrayfun(@(j) allVL1(n-1, L1-j), v1, ...
'UniformOutput', false);
v = arrayfun(@(i) ...
[repmat(v1(i),size(vrest{i},1),1) vrest{i}], ...
(1:length(v1))',...
'UniformOutput', false);
v = cell2mat(v);
end
Note that some of the elements of John's list appear multiple times in your
list, just with the elements permuted. For instance, [1 1 1 7] and [1 1 7
1] are each permutations of [7 1 1 1] in John's list. The OP's question
didn't specify whether the order of the elements in the vector was important
for his application.
function [v m]=allVL1(n, L1)
% function v=allVL1(n, L1)
% INPUT
% n: length of the vector
% L1: desired L1 norm
% OUTPUT:
% v: (m x n) array such as sum(v,2)=L1
% all elements of v is naturel numbers {0,1,...}
% v contains all possible combinations
% Remark:
% allVL1(n,L1-n)+1 for natural numbers defined as {1,2,...}
if n==1
v = L1;
m = 1;
else
v1 = (0:L1)';
[vrest m]= arrayfun(@(j) allVL1(n-1, L1-j), v1, ...
'UniformOutput', false);
v1 = arrayfun(@(n,m) n+zeros(m,1), v1, [m{:}]', ...
'UniformOutput', false);
v = [cell2mat(v1) cell2mat(vrest)];
m = size(v,1);
end
function v=allVL1(n, L1, head)
% function v=allVL1(n, L1);
% INPUT
% n: length of the vector
% L1: desired L1 norm
% OUTPUT:
% v: (m x n) array such as sum(v,2)=L1
% all elements of v is naturel numbers {0,1,...}
% v contains all (=m) possible combinations
% Remark:
% allVL1(n,L1-n)+1 for natural numbers defined as {1,2,...}
if n==1
v = L1;
else
v = cell2mat(arrayfun(@(j) allVL1(n-1, L1-j, j), ...
(0:L1)', 'UniformOutput', false));
end
Thanks for all the ideas. I will check out your codes. I do
indeed need every permutation of the solution vectors.
I'm working on some sparse grid codes in MATLAB and the
interpolants on a sparse grid of order N are constructed from
all possible combinations of tensor product interpolants
where the indices of the constituent dimensions add up to N.
Bruno, your code is very compact and looks good, although I
should mention that zero is not a natural number. I can make
the necessary modifications though.
"Bruno Luong" <b.luong@fogale.fr> wrote in message
<fiopha$jb7$1@fred.mathworks.com>...
> I have submitted my code in FEX. You can also select the
> criteria L1 norm by ==, or <= or < to some quantity.
>
> Bruno
"Greg von Winckel" <gregvw@gmail.com> wrote in message
<fioqaj$rrr$1@fred.mathworks.com>...
> Bruno, your code is very compact and looks good, although I
> should mention that zero is not a natural number. I can make
> the necessary modifications though.
>
Sure, feel free to modify it. Or as I write above, you could
also call the original function:
V = allVL1(n,L1-n)+1
and this will return the vectors of natural numbers starting
from 1, and satified sum(V,2)=L1.
Public Submission Policy
NOTICE: Any content you submit to MATLAB Central, including personal information, is not subject to the protections which may be afforded information collected under other sections of The MathWorks, Inc. Web site. You are entirely responsible for
all content that you upload, post, e-mail, transmit or otherwise make available via MATLAB Central. The MathWorks does not control the content posted by visitors to MATLAB Central and, does not guarantee the accuracy, integrity, or quality of such content.
Under no circumstances will The MathWorks be liable in any way for any content not authored by The MathWorks, or any loss or damage of any kind incurred as a result of the use of any content posted, e-mailed, transmitted or otherwise made available
via MATLAB Central. Read the complete Disclaimer prior to use.