proc optmodel语法用于多个约束

时间:2016-01-08 07:50:49

标签: sas proc

自昨天以来,我一直在努力解决这个问题,并且已经在stackoverflow上完成了大量的材料和一些答案。 我还创建了一个我在下面粘贴的基本代码。

背景

我们有药物的单位数据,可以组合成一个组合,称为方案。例如,药物1 +药物2将是方案1,药物1 +药物2 +药物3将是方案2并且药物1 +药物2 +药物4将是方案3。 我们的最终目标是找出治疗方案中的患者数量。这只能通过找到每种方案对市场的%贡献(称为患者份额)来实现(由于跨方案的多种用途,我们无法直接从单位计算)。

基本上

units = patientshare * dosing * compliance * duration of therapy * total patients

我们知道治疗的单位,剂量和持续时间 总患者,依从性和患者份额将是有限变量。

我的问题是变量和约束处于不同的水平。

  • 单位处于药物水平(和月份);

  • 给药处于药物水平;

  • 合规是药物水平;

  • 治疗持续时间处于治疗水平;

  • 患者分享处于治疗水平

这是我的代码,如果有人能告诉我哪里出错了(我怀疑在阵列中),我将不胜感激。

   PROC OPTMODEL;


   SET <STRING> DRUG;
   SET <STRING> REGIMEN;
   SET <STRING> MONTH;

   NUMBER DOSING{DRUG};
   READ DATA DRUG_DATA INTO DRUG=[DRUG] DOSING;
   /*PRINT DOSING;*/

   NUMBER COMPLIANCE{DRUG};
   READ DATA DRUG_DATA INTO DRUG=[DRUG] COMPLIANCE;
   /*PRINT COMPLIANCE;*/

   NUMBER DOT{drug, regimen};
   READ DATA REGIMEN INTO drug=[drug] 
   {R in regimen}< DOT [drug, R]=col(R)>;
   PRINT DOT;

   NUMBER UNITS{MONTH, DRUG};
   READ DATA DATASET INTO MONTH=[MONTH]
   {D IN DRUG}< UNITS[MONTH, D]=COL(D)>;
   /*PRINT UNITS;*/

     NUMBER RATIO{MONTH};
    READ DATA RATIO_1 INTO MONTH=[MONTH] RATIO;
   /*PRINT RATIO;*/

   /*DEFINE THE PARAMETERS*/

   var ps {MONTH,DRUG} init 0.1 >=0 <=1,
   annualpatients init 7000 <=7700 >=6300, 
  compliance init 0.1 >=0.3 <=0.8,
    DOSING[RIB] INIT 5 >=6 <=4;

   /*SET THE OBJECTIVE*/
    min sse = sum{M IN MONTH}( (units[M,D in drug]-(ps[M,R IN     REGIMEN]*annualpatients*ratio[M]*dosing[D]*compliance[D]*dot[R]*7 ))**2 );


   /*SET THE CONSTRAINTS*/
   constraint  MONTHLY_patient_share {M IN MONTH}:  sum{r is regimen}(ps[R IN REGIMEN])=1;
   constraint  total_patients sum{M in months, r in regimen} : ps[m,r in regimen]*annualpatients*ratio[m]=annual_patients;

 expand;
 solve with nlpc;
 quit;

这是日志:

       2824  PROC OPTMODEL;
       2825
2826  /*DEFINE THE DATA LEVELS (SETS) OF DRUGS, MONTH AND REGIMEN*/
2827
2828  SET <STRING> DRUG;
2829  SET <STRING> REGIMEN;
2830  SET <STRING> MONTH;
2831
2832  NUMBER DOSING{DRUG};
2833  READ DATA DRUG_DATA INTO DRUG=[DRUG] DOSING;
NOTE: There were 4 observations read from the data set WORK.DRUG_DATA.
2834  /*PRINT DOSING;*/
2835
2836  /*NUMBER COMPLIANCE{DRUG};*/
2837  /*READ DATA DRUG_DATA INTO DRUG=[DRUG] COMPLIANCE;*/
2838  /*PRINT COMPLIANCE;*/
2839
2840  NUMBER DOT{drug, regimen};
2841  READ DATA REGIMEN INTO drug=[drug]
2842  {R in regimen}< DOT [drug, R]=col(R)>;
ERROR: The symbol 'REGIMEN' has no value at line 2842 column 7.
2843  PRINT DOT;
ERROR: The symbol 'REGIMEN' has no value at line 2840 column 18.
2844
2845  NUMBER UNITS{MONTH, DRUG};
2846  READ DATA DATASET INTO MONTH=[MONTH]
2847  {D IN DRUG}< UNITS[MONTH, D]=COL(D)>;
NOTE: There were 12 observations read from the data set WORK.DATASET.
2848  /*PRINT UNITS;*/
2849
2850  NUMBER RATIO{MONTH};
2851  READ DATA RATIO_1 INTO MONTH=[MONTH] RATIO;
NOTE: There were 12 observations read from the data set WORK.RATIO_1.
2852  /*PRINT RATIO;*/
2853
2854  /*DEFINE THE PARAMETERS*/
2855
2856  var ps {MONTH,DRUG} init 0.1 >=0 <=1,
2857      annualpatients init 7000 <=7700 >=6300,
2858      compliance init 0.1 >=0.3 <=0.8,
2859      DOSING[RIB] INIT 5 >=6 <=4;
                -
                22
                200
          ------
          528
ERROR 22-322: Syntax error, expecting one of the following: ;, ',', <=, >=, BINARY, INIT,
              INTEGER, {.

ERROR 200-322: The symbol is not recognized and will be ignored.

ERROR 528-782: The name 'DOSING' is already declared.

2860
2861  /*SET THE OBJECTIVE*/
2862  min sse = sum{M IN MONTH}( (units[M,D in drug]-(ps[M,R IN
                                          -        -         --        -
-
-
-
                                          537      651       631       651
537
537
648
ERROR 537-782: The symbol 'D' is unknown.

ERROR 651-782: Subscript 2 must be a string, found a number.

ERROR 648-782: The subscript count does not match array 'DOT', 1 NE 2.

                                            --
-
                                            631
647
ERROR 631-782: The operand types for 'IN' are mismatched, found a number and a set<string>.

ERROR 647-782: The name 'compliance' must be an array.

2862! min sse = sum{M IN MONTH}( (units[M,D in drug]-(ps[M,R IN
                                                           -
-
-
                                                           537
651
537
2862! REGIMEN]*annualpatients*ratio[M]*dosing[D]*compliance[D]*dot[R]*7 ))**2 );
ERROR 537-782: The symbol 'R' is unknown.

ERROR 651-782: Subscript 1 must be a string, found a number.

2863
2864
2865  /*SET THE CONSTRAINTS*/
2866  constraint  MONTHLY_patient_share {M IN MONTH}:  sum{r in regimen}(ps[R IN REGIMEN])=1;
                                                                                        -
                                                                                        648
ERROR 648-782: The subscript count does not match array 'ps', 1 NE 2.

2867  constraint  total_patients sum{M in months, r in regimen} : ps[m,r in
                                 ---
                                 22
                                 76
2867! regimen]*annualpatients*ratio[m]=annual_patients;
ERROR 22-322: Syntax error, expecting one of the following: !!, (, *, **, +, -, .., /, :, <=, <>,
              =, ><, >=, BY, CROSS, DIFF, ELSE, INTER, SYMDIFF, TO, UNION, [, ^, {, ||.

ERROR 76-322: Syntax error, statement will be ignored.

2868
2869       expand;
NOTE: Previous errors might cause the problem to be resolved incorrectly.
ERROR: The constraint 'MONTHLY_patient_share' has an incomplete declaration.
NOTE: The problem has 50 variables (0 free, 0 fixed).
NOTE: The problem has 0 linear constraints (0 LE, 0 EQ, 0 GE, 0 range).
NOTE: The problem has 0 nonlinear constraints (0 LE, 0 EQ, 0 GE, 0 range).
NOTE: Unable to create problem instance due to previous errors.
2870       solve with nlpc;
ERROR: No objective has been specified at line 2870 column 6.
2871       quit;
NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROCEDURE OPTMODEL used (Total process time):
      real time           0.07 seconds
      cpu time            0.07 seconds

1 个答案:

答案 0 :(得分:0)

发生第一个错误(在日志行2842上),因为OPTMODEL在您引用它时没有设置REGIMEN的数据。

我无法看到您的数据集,但似乎您有DRUG - by - REGIMEN矩阵。 因此,在使用它来读取列之前,您需要告诉OPTMODEL REGIMEN的列表。以下是将列名称读入OPTMODEL的两种有效方法:

/* a simple example matrix with numbers and their squares */
data m_by_n (drop=i);
    do i = 1 to 3;
        n = i;
        n_square = i * i;
        output;
    end;
run;

/* get the variable names in the `name` column, plus other information */
proc contents data=m_by_n out=contents_of_m_by_n; quit;

proc optmodel;
    set      ROWS;
    set<str> COLS;
    num val{ROWS,COLS};

    /* use the output from PROC CONTENTS */
    read data contents_of_m_by_n  into COLS=[name];
    read data m_by_n              into ROWS=[_N_] 
        { j in COLS }< val[_N_,j] = col( j ) >; 
    put val[*]=;

    /* Or, all within OPTMODEL */
    num dsid init open('m_by_n');
    set COLS2 = setof{i in 1 .. attrn(dsid,'nvars')} varname(dsid,i);
    read data m_by_n              into ROWS=[_N_] 
        { j in COLS2 }< val[_N_,j] = col( j ) >; 
    put val[*]=;
quit;