Least Squares

Model

import sasoptpy as so
import pandas as pd


def test(cas_conn, data=None):

    # Use default data if not passed
    if data is None:
        data = pd.DataFrame([
            [4, 8, 43.71],
            [62, 5, 351.29],
            [81, 62, 2878.91],
            [85, 75, 3591.59],
            [65, 54, 2058.71],
            [96, 84, 4487.87],
            [98, 29, 1773.52],
            [36, 33, 767.57],
            [30, 91, 1637.66],
            [3, 59, 215.28],
            [62, 57, 2067.42],
            [11, 48, 394.11],
            [66, 21, 932.84],
            [68, 24, 1069.21],
            [95, 30, 1770.78],
            [34, 14, 368.51],
            [86, 81, 3902.27],
            [37, 49, 1115.67],
            [46, 80, 2136.92],
            [87, 72, 3537.84],
        ], columns=['x1', 'x2', 'y'])

    m = so.Model(name='least_squares', session=cas_conn)

    # Regression model: L(a,b,c) = a * x1 + b * x2 + c * x1 * x2
    a = m.add_variable(name='a')
    b = m.add_variable(name='b')
    c = m.add_variable(name='c')

    x1 = data['x1']
    x2 = data['x2']
    y = data['y']

    err = m.add_implicit_variable((
        y[i] - (a * x1[i] + b * x2[i] + c * x1[i]  * x2[i]) for i in data.index
    ), name='error')
    m.set_objective(so.expr_sum(err[i]**2 for i in data.index),
                    sense=so.MIN,
                    name='total_error')
    m.solve(verbose=True, options={'with': 'nlp'})
    return m.get_objective_value()

Output

In [1]: import os

In [2]: hostname = os.getenv('CASHOST')

In [3]: port = os.getenv('CASPORT')

In [4]: from swat import CAS

In [5]: cas_conn = CAS(hostname, port)

In [6]: import sasoptpy
In [7]: from examples.client_side.least_squares import test

In [8]: test(cas_conn)
NOTE: Initialized model least_squares.
NOTE: Added action set 'optimization'.
NOTE: Converting model least_squares to OPTMODEL.
   var a;
   var b;
   var c;
   impvar error_0 = - 4 * a - 8 * b - 32 * c + 43.71;
   impvar error_1 = - 62 * a - 5 * b - 310 * c + 351.29;
   impvar error_2 = - 81 * a - 62 * b - 5022 * c + 2878.91;
   impvar error_3 = - 85 * a - 75 * b - 6375 * c + 3591.59;
   impvar error_4 = - 65 * a - 54 * b - 3510 * c + 2058.71;
   impvar error_5 = - 96 * a - 84 * b - 8064 * c + 4487.87;
   impvar error_6 = - 98 * a - 29 * b - 2842 * c + 1773.52;
   impvar error_7 = - 36 * a - 33 * b - 1188 * c + 767.57;
   impvar error_8 = - 30 * a - 91 * b - 2730 * c + 1637.66;
   impvar error_9 = - 3 * a - 59 * b - 177 * c + 215.28;
   impvar error_10 = - 62 * a - 57 * b - 3534 * c + 2067.42;
   impvar error_11 = - 11 * a - 48 * b - 528 * c + 394.11;
   impvar error_12 = - 66 * a - 21 * b - 1386 * c + 932.84;
   impvar error_13 = - 68 * a - 24 * b - 1632 * c + 1069.21;
   impvar error_14 = - 95 * a - 30 * b - 2850 * c + 1770.78;
   impvar error_15 = - 34 * a - 14 * b - 476 * c + 368.51;
   impvar error_16 = - 86 * a - 81 * b - 6966 * c + 3902.27;
   impvar error_17 = - 37 * a - 49 * b - 1813 * c + 1115.67;
   impvar error_18 = - 46 * a - 80 * b - 3680 * c + 2136.92;
   impvar error_19 = - 87 * a - 72 * b - 6264 * c + 3537.84;
   min total_error = (- 4 * a - 8 * b - 32 * c + 43.71) ^ (2) + (- 62 * a - 5 * b - 310 * c + 351.29) ^ (2) + (- 81 * a - 62 * b - 5022 * c + 2878.91) ^ (2) + (- 85 * a - 75 * b - 6375 * c + 3591.59) ^ (2) + (- 65 * a - 54 * b - 3510 * c + 2058.71) ^ (2) + (- 96 * a - 84 * b - 8064 * c + 4487.87) ^ (2) + (- 98 * a - 29 * b - 2842 * c + 1773.52) ^ (2) + (- 36 * a - 33 * b - 1188 * c + 767.57) ^ (2) + (- 30 * a - 91 * b - 2730 * c + 1637.66) ^ (2) + (- 3 * a - 59 * b - 177 * c + 215.28) ^ (2) + (- 62 * a - 57 * b - 3534 * c + 2067.42) ^ (2) + (- 11 * a - 48 * b - 528 * c + 394.11) ^ (2) + (- 66 * a - 21 * b - 1386 * c + 932.84) ^ (2) + (- 68 * a - 24 * b - 1632 * c + 1069.21) ^ (2) + (- 95 * a - 30 * b - 2850 * c + 1770.78) ^ (2) + (- 34 * a - 14 * b - 476 * c + 368.51) ^ (2) + (- 86 * a - 81 * b - 6966 * c + 3902.27) ^ (2) + (- 37 * a - 49 * b - 1813 * c + 1115.67) ^ (2) + (- 46 * a - 80 * b - 3680 * c + 2136.92) ^ (2) + (- 87 * a - 72 * b - 6264 * c + 3537.84) ^ (2);
   solve with nlp / ;
   create data solution from [i]= {1.._NVAR_} var=_VAR_.name value=_VAR_ lb=_VAR_.lb ub=_VAR_.ub rc=_VAR_.rc;
   create data dual from [j] = {1.._NCON_} con=_CON_.name value=_CON_.body dual=_CON_.dual;

NOTE: Submitting OPTMODEL code to CAS server.
NOTE: Problem generation will use 8 threads.
NOTE: The problem has 3 variables (3 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: The OPTMODEL presolver removed 0 variables, 0 linear constraints, and 0 nonlinear constraints.
NOTE: Using analytic derivatives for objective.
NOTE: The NLP solver is called.
NOTE: The Interior Point Direct algorithm is used.
                           Objective                          Optimality
              Iter             Value     Infeasibility             Error
                 0          95424613                 0        3.48646173
                 1        7.18629678                 0   0.0000000055789
NOTE: Optimal.
NOTE: Objective = 7.1862967833.
NOTE: The output table 'SOLUTION' in caslib 'CASUSER(casuser)' has 3 rows and 6 columns.
NOTE: The output table 'DUAL' in caslib 'CASUSER(casuser)' has 0 rows and 4 columns.
NOTE: The CAS table 'solutionSummary' in caslib 'CASUSER(casuser)' has 12 rows and 4 columns.
NOTE: The CAS table 'problemSummary' in caslib 'CASUSER(casuser)' has 12 rows and 4 columns.
Out[8]: 7.186296783293