'fit the model subject to linear equality constraints
The constraints are of the form   `R params = q`
where R is the constraint_matrix and q is the vector of
constraint_values.
The estimation creates a new model with transformed design matrix,
exog, and converts the results back to the original parameterization.
Parameters
constraints : formula expression or tuple
If it is a tuple, then the constraint needs to be given by two
arrays (constraint_matrix, constraint_value), i.e. (R, q).
Otherwise, the constraints can be given as strings or list of
strings.
see t_test for details
start_params : None or array_like
starting values for the optimization. `start_params` needs to be
given in the original parameter space and are internally
transformed.
**fit_kwds : keyword arguments
fit_kwds are used in the optimization of the transformed model.
Returns
results : Results instance'

def fit_constrained(self, constraints, start_params=None, **fit_kwds):

    from patsy import DesignInfo
    from statsmodels.base._constraints import fit_constrained
    lc = DesignInfo(self.exog_names).linear_constraint(constraints)
    (R, q) = (lc.coefs, lc.constants)
    (params, cov, res_constr) = fit_constrained(self, R, q, start_params=start_params, fit_kwds=fit_kwds)
    res = self.fit(start_params=params, maxiter=0)
    res._results.params = params
    res._results.normalized_cov_params = cov
    k_constr = len(q)
    res._results.df_resid += k_constr
    res._results.df_model -= k_constr
    res._results.constraints = lc
    res._results.k_constr = k_constr
    res._results.results_constrained = res_constr
    res._results.model.history = res_constr.model.history
    return res
