def solve_small_pos(
    u,
    v,
    d,
    g_norm_square,
    p,
    P,
    lam10=None,
    lam11=None,
        lam21=None):
    """[When u > v] lam20 = 0.0 and will not change throughout the optimization
    """
    # some intialization to start the alternating optimization
    LAM20 = np.float32(0.0)
    i = 0
    objective_value_list = []
    if lam21:
        ordering = [0, 1, 2]
    elif lam11:
        ordering = [1, 0, 2]
    else:
        ordering = [1, 2, 0]
    # print(ordering)
    while True:
        if i % 3 == ordering[0]:  # fix lam21
            D = np.float32(P - p * (d - np.float32(1.0)) * lam21)
            C = np.float32(D + p * v + (np.float32(1.0) - p) * u)

            E = np.float32(math.sqrt((C + (np.float32(1.0) - p) \
                                      * g_norm_square) / \
                                (C + p * g_norm_square)))
            tau = np.float32( \
                max((D / p + v - E * u) / (E + (np.float32(1.0) - p) / p), \
                    np.float32(0.0)))
            # print('tau', tau)
            if np.float32(0.0) <= tau <= (P - p * d * lam21) / \
                                    (np.float32(1.0) - p):
                lam10 = tau
                lam11 = np.float32( \
                    max(D / p - (np.float32(1.0) - p) * tau / p, \
                     np.float32(0.0)))
            else:
                # print('B')
                lam10_case1, lam11_case1 = np.float32(0), np.float32( \
                    max(P / p - (d - np.float32(1.0)) * lam21, np.float32(0.0)))
                lam10_case2, lam11_case2 = np.float32( \
                    max((P - p * d * lam21) / (np.float32(1.0) - p), \
                        np.float32(0.0))), lam21
                objective1 = symKL_objective(
                    lam10=lam10_case1,
                    lam20=LAM20,
                    lam11=lam11_case1,
                    lam21=lam21,
                    u=u,
                    v=v,
                    d=d,
                    g_norm_square=g_norm_square)
                objective2 = symKL_objective(
                    lam10=lam10_case2,
                    lam20=LAM20,
                    lam11=lam11_case2,
                    lam21=lam21,
                    u=u,
                    v=v,
                    d=d,
                    g_norm_square=g_norm_square)
                if objective1 < objective2:
                    lam10, lam11 = lam10_case1, lam11_case1
                else:
                    lam10, lam11 = lam10_case2, lam11_case2
        elif i % 3 == ordering[1]:  # fix lam11
            D = np.float32(max(P - p * lam11, np.float32(0.0)))

            def f(x): \
                return symKL_objective(lam10=(D - p * (d - 1) * x) / \
                                (np.float32(1.0) - p), \
                lam20=LAM20, lam11=lam11, lam21=x, u=u, v=v, d=d, \
                    g_norm_square=g_norm_square)

            def f_prime(x): \
                return (d - np.float32(1.0)) / u - \
                    p * (d - np.float32(1.0)) / (lam11 + v) / \
                    (np.float32(1.0) - p) - (d - 1) / (x + v) * (u / (x + v)) \
                    + (lam11 + v + g_norm_square) / \
                ((D - p * (d - 1) * x) / (np.float32(1.0) - p) + u) * p * \
                (d - np.float32(1.0)) / (np.float32(1.0) - p) / ((D - p * \
                    (d - np.float32(1.0)) * x) / (np.float32(1.0) - p) + u)

            # print('lam11', 'D/p/(d-1)', lam11, D/p/(d-1))
            lam21 = convex_min_1d(xl=np.float32(0.0), xr=min( \
                D / p / (d - np.float32(1.0)), lam11), f=f, f_prime=f_prime)
            lam10 = np.float32( \
                max((D - p * (d - 1) * lam21) / (np.float32(1.0) - p), \
                    np.float32(0.0)))

        else:  # fix lam10
            D = np.float32(max((P - (1 - p) * lam10) / p, np.float32(0.0)))

            def f(x): \
                return symKL_objective(lam10=lam10,
                                             lam20=LAM20,
                                             lam11=D-(d - np.float32(1.0)) * x,
                                             lam21=x,
                                             u=u,
                                             v=v,
                                             d=d,
                                             g_norm_square=g_norm_square)

            def f_prime(x): \
                return (d - np.float32(1.0)) / u - \
                (d - np.float32(1.0)) / (lam10 + u) - (d - np.float32(1.0)) / \
                (x + v) * (u / (x + v)) + \
                (lam10 + u + g_norm_square) / \
                (D - (d - np.float32(1.0)) * x + v) * (d - np.float32(1.0)) / \
                (D - (d - np.float32(1.0)) * x + v)

            lam21 = convex_min_1d(\
                xl=np.float32(0.0),
                xr=D / d,
                f=f,
                f_prime=f_prime)
            lam11 = np.float32(\
                max(D - (d - np.float32(1.0)) * lam21, np.float32(0.0)))

        # if lam10 <0 or LAM20 <0 or lam11 <0 or lam21 <0:
        #     assert False, i

        objective_value_list.append(
            symKL_objective(
                lam10=lam10,
                lam20=LAM20,
                lam11=lam11,
                lam21=lam21,
                u=u,
                v=v,
                d=d,
                g_norm_square=g_norm_square))
        # print(i)
        # print(objective_value_list[-1])
        # print(lam10, LAM20, lam11, lam21)
        # print('sum', p * lam11 + p*(d-1)*lam21 + \
            # (1-p) * lam10 + (1-p)*(d-1)*LAM20)

        if (i >= 3 and objective_value_list[-4] - \
                objective_value_list[-1] < OBJECTIVE_EPSILON) or i >= 100:
            # logging.info("solve_small_pos, iter: {}, terminated".format(i))
            return (lam10, LAM20, lam11, lam21, np.float32(\
                np.float32(0.5) * objective_value_list[-1] - d))

        i += 1
[When u > v] lam20 = 0.0 and will not change throughout the optimization
    
example/privacy/label_protection/solver.py