SAS最大化变量函数

时间:2017-01-13 11:35:58

标签: sas

给定一组变量v(1) - v(k),函数f定义为f(v1,v2,...vk)

目标是拥有一组v(i),最大化f给定v(1)+v(2)+....+v(k)=n。所有元素都限制为非负整数。

注意:我没有SAS/IMLSAS/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;

但是,这个解决方案有几个问题。

  1. 使用循环似乎非常低效。

  2. 当k未知时,它不知道嵌套循环怎么可能。

  3. 这正是“将n个球分配到k个分区”问题,其中k由具有特定前缀的数据in中的列数确定,n由宏变量确定。 / p>

    功能f已知,例如f(i,j) = 2*i+3*j;

    这可以在数据步骤中完成吗?

1 个答案:

答案 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会认为它正在根据Ax1来解决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.1x2=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;