'Returns the result of the call to the solver.
Parameters
objective : LinOp
The canonicalized objective.
constraints : list
The list of canonicalized cosntraints.
cached_data : dict
A map of solver name to cached problem data.
warm_start : bool
Not used.
verbose : bool
Should the solver print output?
solver_opts : dict
Additional arguments for the solver.
Returns
tuple
(status, optimal value, primal, equality dual, inequality dual)'

def solve(self, objective, constraints, cached_data, warm_start, verbose, solver_opts):

    import gurobipy
    data = self.get_problem_data(objective, constraints, cached_data)
    c = data[s.C]
    b = data[s.B]
    A = dok_matrix(data[s.A])
    data[s.A] = A
    n = c.shape[0]
    solver_cache = cached_data[self.name()]
    if (warm_start and (solver_cache.prev_result is not None) and (len(data[s.DIMS][s.SOC_DIM]) == 0)):
        model = solver_cache.prev_result['model']
        variables = solver_cache.prev_result['variables']
        gur_constrs = solver_cache.prev_result['gur_constrs']
        c_prev = solver_cache.prev_result['c']
        A_prev = solver_cache.prev_result['A']
        b_prev = solver_cache.prev_result['b']
        if (len(lu.get_expr_params(objective)) > 0):
            c_diff = (c - c_prev)
            I_unique = list(set(np.where(c_diff)[0]))
            for i in I_unique:
                variables[i].Obj = c[i]
        else:
            c = c_prev
        sym_data = self.get_sym_data(objective, constraints, cached_data)
        (all_constrs, _, _) = self.split_constr(sym_data.constr_map)
        if self._param_in_constr(all_constrs):
            A_diff = dok_matrix((A - A_prev))
            b_diff = (b - b_prev)
            try:
                (I, _) = zip(*[x for x in A_diff.keys()])
            except ValueError:
                I = []
            I_unique = list((set(I) | set(np.where(b_diff)[0])))
            nonzero_locs = gurobipy.tuplelist([x for x in A.keys()])
            for i in I_unique:
                if (gur_constrs[i] is not None):
                    model.remove(gur_constrs[i])
                    gur_constrs[i] = None
                if (len(nonzero_locs.select(i, '*')) > 0):
                    expr_list = []
                    for loc in nonzero_locs.select(i, '*'):
                        expr_list.append((A[loc], variables[loc[1]]))
                    expr = gurobipy.LinExpr(expr_list)
                    if (i < data[s.DIMS][s.EQ_DIM]):
                        ctype = gurobipy.GRB.EQUAL
                    elif (data[s.DIMS][s.EQ_DIM] <= i < (data[s.DIMS][s.EQ_DIM] + data[s.DIMS][s.LEQ_DIM])):
                        ctype = gurobipy.GRB.LESS_EQUAL
                    gur_constrs[i] = model.addConstr(expr, ctype, b[i])
            model.update()
        else:
            A = A_prev
            b = b_prev
    else:
        model = gurobipy.Model()
        variables = []
        for i in range(n):
            if (i in data[s.BOOL_IDX]):
                vtype = gurobipy.GRB.BINARY
            elif (i in data[s.INT_IDX]):
                vtype = gurobipy.GRB.INTEGER
            else:
                vtype = gurobipy.GRB.CONTINUOUS
            variables.append(model.addVar(obj=c[i], name=('x_%d' % i), vtype=vtype, lb=(- gurobipy.GRB.INFINITY), ub=gurobipy.GRB.INFINITY))
        model.update()
        nonzero_locs = gurobipy.tuplelist([x for x in A.keys()])
        eq_constrs = self.add_model_lin_constr(model, variables, range(data[s.DIMS][s.EQ_DIM]), gurobipy.GRB.EQUAL, nonzero_locs, A, b)
        leq_start = data[s.DIMS][s.EQ_DIM]
        leq_end = (data[s.DIMS][s.EQ_DIM] + data[s.DIMS][s.LEQ_DIM])
        ineq_constrs = self.add_model_lin_constr(model, variables, range(leq_start, leq_end), gurobipy.GRB.LESS_EQUAL, nonzero_locs, A, b)
        soc_start = leq_end
        soc_constrs = []
        new_leq_constrs = []
        for constr_len in data[s.DIMS][s.SOC_DIM]:
            soc_end = (soc_start + constr_len)
            (soc_constr, new_leq, new_vars) = self.add_model_soc_constr(model, variables, range(soc_start, soc_end), nonzero_locs, A, b)
            soc_constrs.append(soc_constr)
            new_leq_constrs += new_leq
            variables += new_vars
            soc_start += constr_len
        gur_constrs = (((eq_constrs + ineq_constrs) + soc_constrs) + new_leq_constrs)
        model.update()
    model.setParam('OutputFlag', verbose)
    model.setParam('QCPDual', True)
    for (key, value) in solver_opts.items():
        model.setParam(key, value)
    results_dict = {}
    try:
        model.optimize()
        results_dict['primal    objective'] = model.ObjVal
        results_dict['x'] = np.array([v.X for v in variables])
        if (not self.is_mip(data)):
            vals = []
            for lc in gur_constrs:
                if (lc is not None):
                    if isinstance(lc, gurobipy.QConstr):
                        vals.append(lc.QCPi)
                    else:
                        vals.append(lc.Pi)
                else:
                    vals.append(0)
            results_dict['y'] = (- np.array(vals))
        results_dict['status'] = self.STATUS_MAP.get(model.Status, s.SOLVER_ERROR)
    except:
        results_dict['status'] = s.SOLVER_ERROR
    results_dict['model'] = model
    results_dict['variables'] = variables
    results_dict['gur_constrs'] = gur_constrs
    results_dict[s.SOLVE_TIME] = model.Runtime
    return self.format_results(results_dict, data, cached_data)
