给定一组变量v(1) - v(k)
,函数f
定义为f(v1,v2,...vk)
。
目标是拥有一组v(i),最大化f
给定v(1)+v(2)+....+v(k)=n
。所有元素都限制为非负整数。
注意:我没有SAS/IML
或SAS/OR
。
如果知道k
,请说2
,那么我可以这样做。
data out;
set in;
maxf = 0;
n1 = 0;
n2 = 0;
do i = 0 to n;
do j = 0 to n;
if i + j ne n then continue;
_max = f(i,j);
if _max > maxf then do;
maxf = max(maxf,_max);
n1 = i;
n2 = j;
end;
end;
end;
drop i j;
run;
但是,这个解决方案有几个问题。
使用循环似乎非常低效。
当k未知时,它不知道嵌套循环怎么可能。
这正是“将n个球分配到k个分区”问题,其中k
由具有特定前缀的数据in
中的列数确定,n
由宏变量确定。 / p>
功能f
已知,例如f(i,j) = 2*i+3*j
;
这可以在数据步骤中完成吗?
答案 0 :(得分:1)
如评论中所述,一般的非线性整数程序很难解决。以下方法将解决连续参数。您必须获取输出并找到最接近函数的整数值。但是,循环现在可以更小,更快地运行。
首先让我们来做一个功能。此函数具有额外参数,并且在该参数中是线性的。将你的功能包含在这样的内容中。
proc fcmp outlib=work.fns.fns;
function f(x1,x2,a);
out = -10*(x1-5)*(x1-5) + -2*(x2-2)*(x2-2) + 2*(x1-5) + 3*(x2-2);
return(out+a);
endsub;
run;quit;
options cmplib=work.fns;
我们需要添加a
参数,以便我们可以获得除了实际参数之外SAS可以传递的值。 SAS会认为它正在根据A
和x1
来解决x2
的可能性。
生成A
值的数据集。
data temp;
a = 1;
run;
现在使用PROC NLMIXED
来最大化A
的可能性。
ods output ParameterEstimates=Parameters;
ods select ParameterEstimates;
proc nlmixed data=temp;
parms x1=1 x2=1;
bounds x1>0, x2>0;
y = f(x1,x2,a);
model a ~ general(y);
run;
ods select default;
我获得x1=5.1
和x2=2.75
的输出。然后,您可以搜索“周围”,以查看最大值出现的位置。
这是我尝试在数据步骤中搜索值:
%macro call_fn(fn,n,parr);
%local i;
&fn(&parr[1]
%do i=2 %to &n;
, &parr[&i]
%end;
,0)
%mend;
%let n=2;
%let c=%sysevalf(2**&n);
data max;
set Parameters end=last;
array parms[&n] _temporary_;
array start[&n] _temporary_;
array pmax[&n];
max = -9.99e256;
parms[_n_] = estimate;
if last then do;
do i=1 to &n;
start[i] = floor(parms[i]);
end;
do i=1 to &c;
x = put(i,$binary2.);
do j=1 to &n;
parms[j] = input(substr(x,j,1),best.) + start[j];
end;
/*You need a macro to write this dynamically*/
val = %call_fn(f,&n,parms);
*put i= max= val=;
if val > max then do;
do j=1 to &n;
pmax[j] = parms[j];
end;
max = val;
end;
end;
output;
end;