Curve Fitting: Fitting a Curve to a Set of Data Points

PROC OPTMODEL Statements and Output

The following PROC OPTMODEL statements declare an index set and parameters and then read the input data:

proc optmodel;
   set POINTS;
   num x {POINTS};
   num y {POINTS};
   read data xy_data into POINTS=[_N_] x y;

The following NUM statement declares the order parameter, which is later set to 1 for Problems (1) and (2) and set to 2 for Problem (3):

   num order;
   var Beta {0..order};
   impvar Estimate {i in POINTS}
      = Beta[0] + sum {k in 1..order} Beta[k] * x[i]^k;

The following statements encode the linearization of the norm:

   var Surplus {POINTS} >= 0;
   var Slack {POINTS} >= 0;
   min Objective1 = sum {i in POINTS} (Surplus[i] + Slack[i]);
   con Abs_dev_con {i in POINTS}:
      Estimate[i] - Surplus[i] + Slack[i] = y[i];

The following statements (which are not used but are shown here for comparison) encode an alternative linearization of the norm that requires half as many variables but twice as many constraints:

   var AbsDeviation {POINTS} >= 0;
   min Objective1 = sum {i in POINTS} AbsDeviation[i];
   con Abs_dev_con1 {i in POINTS}:
      AbsDeviation[i] >= Estimate[i] - y[i];
   con Abs_dev_con2 {i in POINTS}:
      AbsDeviation[i] >= y[i] - Estimate[i];

The following additional declarations encode the linearization of the norm:

   var MinMax;
   min Objective2 = MinMax;
   con MinMax_con {i in POINTS}:
      MinMax >= Surplus[i] + Slack[i];

The following statements (which are not used but match the formulation in Williams (1999)) encode an alternative linearization of the norm that requires the same number of variables but twice as many constraints:

   var MinMax;
   min Objective2 = MinMax;
   con MinMax_con1 {i in POINTS}:
      MinMax >= Surplus[i];
   con MinMax_con2 {i in POINTS}:
      MinMax >= Slack[i];

The following NUM statements use the ABS function, the .sol variable suffix, and the MAX aggregation operator to compute the two norms from the optimal solution:

   num sum_abs_dev = sum {i in POINTS} abs(Estimate[i].sol - y[i]);
   num max_abs_dev = max {i in POINTS} abs(Estimate[i].sol - y[i]);

The following PROBLEM statement specifies the variables, objective, and constraints for minimization:

   problem L1 include
      Beta Surplus Slack
      Objective1
      Abs_dev_con;

The following PROBLEM statement specifies the additional variables, objective, and constraints for minimization:

   problem Linf from L1 include
      MinMax
      Objective2
      MinMax_con;

The following statements specify a straight line fit, switch the focus to problem L1, solve Problem (1), print the results, and store the y-values that are predicted by the optimal solution:

   order = 1;
   use problem L1;
   solve;
   print sum_abs_dev max_abs_dev;
   print Beta;
   print x y Estimate Surplus Slack;
   create data sol_data1 from [POINTS] x y Estimate;

Figure 11.1 shows the output from the linear programming solver for Problem (1).

Figure 11.1: Output from Linear Programming Solver for Problem (1)

The OPTMODEL Procedure

Problem Summary
Objective SenseMinimization
Objective FunctionObjective1
Objective TypeLinear
  
Number of Variables40
Bounded Above0
Bounded Below38
Bounded Below and Above0
Free2
Fixed0
  
Number of Constraints19
Linear LE (<=)0
Linear EQ (=)19
Linear GE (>=)0
Linear Range0
  
Constraint Coefficients75

Performance Information
Execution ModeSingle-Machine
Number of Threads1

Solution Summary
SolverLP
AlgorithmDual Simplex
Objective FunctionObjective1
Solution StatusOptimal
Objective Value11.46625
  
Primal Infeasibility1.776357E-15
Dual Infeasibility0
Bound Infeasibility0
  
Iterations23
Presolve Time0.00
Solution Time0.00

sum_abs_devmax_abs_dev
11.4662.7688

[1]Beta
00.58125
10.63750

[1]xyEstimateSurplusSlack
10.01.00.581250.000000.41875
20.50.90.900000.000000.00000
31.00.71.218750.518750.00000
41.51.51.537500.037500.00000
51.92.01.792500.000000.20750
62.52.42.175000.000000.22500
73.03.22.493750.000000.70625
83.52.02.812500.812500.00000
94.02.73.131250.431250.00000
104.53.53.450000.000000.05000
115.01.03.768752.768750.00000
125.54.04.087500.087500.00000
136.03.64.406250.806250.00000
146.62.74.788752.088750.00000
157.05.75.043750.000000.65625
167.64.65.426250.826250.00000
178.56.06.000000.000000.00000
189.06.86.318750.000000.48125
1910.07.36.956250.000000.34375


The following statements switch the focus to problem Linf, solve Problem (2), print the results, and store the y-values that are predicted by the optimal solution:

   use problem Linf;
   solve;
   print sum_abs_dev max_abs_dev;
   print Beta;
   print x y Estimate Surplus Slack;
   create data sol_data2 from [POINTS] x y Estimate;

Figure 11.2 shows the output from the linear programming solver for Problem (2).

Figure 11.2: Output from Linear Programming Solver for Problem (2)

Problem Summary
Objective SenseMinimization
Objective FunctionObjective2
Objective TypeLinear
  
Number of Variables41
Bounded Above0
Bounded Below38
Bounded Below and Above0
Free3
Fixed0
  
Number of Constraints38
Linear LE (<=)0
Linear EQ (=)19
Linear GE (>=)19
Linear Range0
  
Constraint Coefficients132

Performance Information
Execution ModeSingle-Machine
Number of Threads1

Solution Summary
SolverLP
AlgorithmDual Simplex
Objective FunctionObjective2
Solution StatusOptimal
Objective Value1.725
  
Primal Infeasibility2.220446E-15
Dual Infeasibility0
Bound Infeasibility0
  
Iterations26
Presolve Time0.00
Solution Time0.00

sum_abs_devmax_abs_dev
19.951.725

[1]Beta
0-0.400
10.625

[1]xyEstimateSurplusSlack
10.01.0-0.40000.0001.4000
20.50.9-0.08750.0000.9875
31.00.70.22500.0000.4750
41.51.50.53750.0000.9625
51.92.00.78750.0001.2125
62.52.41.16250.0001.2375
73.03.21.47500.0001.7250
83.52.01.78750.0000.2125
94.02.72.10000.0000.6000
104.53.52.41250.0001.0875
115.01.02.72501.7250.0000
125.54.03.03750.0000.9625
136.03.63.35000.0000.2500
146.62.73.72501.0250.0000
157.05.73.97500.0001.7250
167.64.64.35000.0000.2500
178.56.04.91250.0001.0875
189.06.85.22500.0001.5750
1910.07.35.85000.0001.4500


The following statements specify a quadratic curve fit, solve both parts of Problem (3), print the results, and store the y-values that are predicted by the optimal solutions:

   order = 2;
   use problem L1;
   solve;
   print sum_abs_dev max_abs_dev;
   print Beta;
   print x y Estimate Surplus Slack;
   create data sol_data3 from [POINTS] x y Estimate;

   use problem Linf;
   solve;
   print sum_abs_dev max_abs_dev;
   print Beta;
   print x y Estimate Surplus Slack;
   create data sol_data4 from [POINTS] x y Estimate;
quit;

Figure 11.3 shows the output from the linear programming solver for the first part of Problem (3).

Figure 11.3: Output from Linear Programming Solver for First Part of Problem (3)

Problem Summary
Objective SenseMinimization
Objective FunctionObjective1
Objective TypeLinear
  
Number of Variables41
Bounded Above0
Bounded Below38
Bounded Below and Above0
Free3
Fixed0
  
Number of Constraints19
Linear LE (<=)0
Linear EQ (=)19
Linear GE (>=)0
Linear Range0
  
Constraint Coefficients93

Performance Information
Execution ModeSingle-Machine
Number of Threads1

Solution Summary
SolverLP
AlgorithmDual Simplex
Objective FunctionObjective1
Solution StatusOptimal
Objective Value10.458964706
  
Primal Infeasibility7.993606E-15
Dual Infeasibility0
Bound Infeasibility0
  
Iterations20
Presolve Time0.00
Solution Time0.00

sum_abs_devmax_abs_dev
10.4592.298

[1]Beta
00.982353
10.294510
20.033725

[1]xyEstimateSurplusSlack
10.01.00.982350.000000.017647
20.50.91.138040.238040.000000
31.00.71.310590.610590.000000
41.51.51.500000.000000.000000
51.92.01.663670.000000.336329
62.52.41.929410.000000.470588
73.03.22.169410.000001.030588
83.52.02.426270.426270.000000
94.02.72.700000.000000.000000
104.53.52.990590.000000.509412
115.01.03.298042.298040.000000
125.54.03.622350.000000.377647
136.03.63.963530.363530.000000
146.62.74.395201.695200.000000
157.05.74.696470.000001.003529
167.64.65.168610.568610.000000
178.56.05.922350.000000.077647
189.06.86.364710.000000.435294
1910.07.37.300000.000000.000000


Figure 11.4 shows the output from the linear programming solver for the second part of Problem (3).

Figure 11.4: Output from Linear Programming Solver for Second Part of Problem (3)

Problem Summary
Objective SenseMinimization
Objective FunctionObjective2
Objective TypeLinear
  
Number of Variables42
Bounded Above0
Bounded Below38
Bounded Below and Above0
Free4
Fixed0
  
Number of Constraints38
Linear LE (<=)0
Linear EQ (=)19
Linear GE (>=)19
Linear Range0
  
Constraint Coefficients150

Performance Information
Execution ModeSingle-Machine
Number of Threads1

Solution Summary
SolverLP
AlgorithmDual Simplex
Objective FunctionObjective2
Solution StatusOptimal
Objective Value1.475
  
Primal Infeasibility7.105427E-15
Dual Infeasibility0
Bound Infeasibility0
  
Iterations27
Presolve Time0.00
Solution Time0.00

sum_abs_devmax_abs_dev
16.7581.475

[1]Beta
02.475
1-0.625
20.125

[1]xyEstimateSurplusSlack
10.01.02.47501.475000.00000
20.50.92.19381.293750.00000
31.00.71.97501.275000.00000
41.51.51.81880.318750.00000
51.92.01.73880.000000.26125
62.52.41.69380.000000.70625
73.03.21.72500.000001.47500
83.52.01.81880.000000.18125
94.02.71.97500.000000.72500
104.53.52.19380.000001.30625
115.01.02.47501.475000.00000
125.54.02.81880.000001.18125
136.03.63.22500.000000.37500
146.62.73.79501.095000.00000
157.05.74.22500.000001.47500
167.64.64.94500.345000.00000
178.56.06.19380.193750.00000
189.06.86.97500.175000.00000
1910.07.38.72501.425000.00000


You can find a higher-order polynomial fit simply by increasing the value of the order parameter. The dimensions of the Beta and Estimate variables are automatically updated when order changes.

The following PROC SGPLOT statements use the output data sets that are created by PROC OPTMODEL to display the results from Problems (1) and (2) in one plot:

data plot1;
   merge sol_data1(rename=(Estimate=Line1)) sol_data2(rename=(Estimate=Line2));
run;

proc sgplot data=plot1;
   scatter x=x y=y;
   series x=x y=Line1 / curvelabel;
   series x=x y=Line2 / curvelabel;
run;

Figure 11.5 shows the regression lines for Problems (1) and (2), as on page 319 of Williams (1999).

Figure 11.5: Regression Lines for Problems (1) and (2)

Regression Lines for Problems (1) and (2)


The following PROC SGPLOT statements use the output data sets that are created by PROC OPTMODEL to display the results from both parts of Problem (3) in one plot:

data plot2;
   merge sol_data3(rename=(Estimate=Curve1))
      sol_data4(rename=(Estimate=Curve2));
run;

proc sgplot data=plot2;
   scatter x=x y=y;
   series x=x y=Curve1 / curvelabel;
   series x=x y=Curve2 / curvelabel;
run;

Figure 11.6 shows the regression curves for Problem (3), as on page 319 of Williams (1999).

Figure 11.6: Regression Curves for Problem (3)

Regression Curves for Problem (3)