def _obj_func_midp()

in causalml/optimize/unit_selection.py [0:0]


    def _obj_func_midp(self, data, treatment, outcome):
        '''
        Calculates bounds for the objective function. Returns the midpoint
        between bounds.

        Parameters
        ----------
        pr_y1_w1 : float
            The probability of conversion given treatment assignment.

        pr_y1_w0 : float
            The probability of conversion given control assignment.

        pr_y0_w1 : float
            The probability of no conversion fiven treatment assignment
            (1 - pr_y1_w1).

        pr_y0_w0 : float
            The probability of no conversion given control assignment
            (1 - pr_1y_w0)

        pr_y1w1_x : float
            Probability of complier or always-taker given X.

        pr_y0w0_x : float
            Probability of complier or never-taker given X.

        pr_y1w0_x : float
            Probability of defier or always-taker given X.

        pr_y0w1_x : float
            Probability of never-taker or defier given X.

        pr_y_x : float
            Organic probability of conversion.
        '''

        X = data.drop([treatment, outcome], axis=1)

        beta = self.complier_payoff
        gamma = self.alwaystaker_payoff
        theta = self.nevertaker_payoff
        delta = self.defier_payoff

        pr_y0_w1, pr_y1_w1 = np.split(self.trt_model.predict_proba(X),
                                      indices_or_sections=2, axis=1)
        pr_y0_w0, pr_y1_w0 = np.split(self.ctr_model.predict_proba(X),
                                      indices_or_sections=2, axis=1)

        segment_prob = self.segment_model.predict_proba(X)
        segment_name = self.segment_model.classes_

        pr_y1w1_x = segment_prob[:, segment_name == 'AC']
        pr_y0w0_x = segment_prob[:, segment_name == 'NC']
        pr_y1w0_x = segment_prob[:, segment_name == 'AD']
        pr_y0w1_x = segment_prob[:, segment_name == 'ND']

        if self.organic_conversion is not None:

            pr_y_x = self.organic_conversion

        else:

            pr_y_x = pr_y1_w0
            warnings.warn(
                'Probability of organic conversion estimated from control observations.')

        p1 = (beta - theta) * pr_y1_w1 + delta * pr_y1_w0 + theta * pr_y0_w0
        p2 = gamma * pr_y1_w1 + delta * pr_y0_w1 + (beta - gamma) * pr_y0_w0
        p3 = (gamma - delta) * pr_y1_w1 + delta * pr_y1_w0 + theta * \
            pr_y0_w0 + (beta - gamma - theta + delta) * (pr_y1w1_x + pr_y0w0_x)
        p4 = (beta - theta) * pr_y1_w1 - (beta - gamma - theta) * pr_y1_w0 + \
            theta * pr_y0_w0 + (beta - gamma - theta + delta) * \
            (pr_y1w0_x + pr_y0w1_x)
        p5 = (gamma - delta) * pr_y1_w1 + delta * pr_y1_w0 + theta * pr_y0_w0
        p6 = (beta - theta) * pr_y1_w1 - (beta - gamma - theta) * pr_y1_w0 + \
            theta * pr_y0_w0
        p7 = (gamma - delta) * pr_y1_w1 - (beta - gamma - theta) * pr_y1_w0 + \
            theta * pr_y0_w0 + (beta - gamma - theta + delta) * pr_y_x
        p8 = (beta - theta) * pr_y1_w1 + delta * pr_y1_w0 + theta * \
            pr_y0_w0 - (beta - gamma - theta + delta) * pr_y_x

        params_1 = np.concatenate((p1, p2, p3, p4), axis=1)
        params_2 = np.concatenate((p5, p6, p7, p8), axis=1)

        sigma = beta - gamma - theta + delta

        if sigma < 0:
            lower_bound = np.max(params_1, axis=1)
            upper_bound = np.min(params_2, axis=1)

        elif sigma > 0:
            lower_bound = np.max(params_2, axis=1)
            upper_bound = np.min(params_1, axis=1)

        return (lower_bound + upper_bound) / 2