def pga_oracle(D, DtY, xOracle, xhat, alphathat=None):
    # todo
    cur_diver = DBL_MAX
    cur_patch_error = DBL_MAX
    Dr, Dc = D.shape
    DtYr, DtYc = DtY.shape
    T = np.zeros((1, Dc))
    for i in range(Dc):
        T[i] = i
    k = min(max(math.sqrt(Dc) + 1, Dr / 10 + 1), Dc)
    D_T = np.zeros((Dr, k))
    alpha = np.zeros((k, DtYc))
    D_TtY = np.zeros((k, DtYc))
    # cur_xhat = np.zeros_like(xhat)
    actual_alpha = np.zeros((k, DtYc))
    cur_spar = 0
    for cur_spar in range(k):
        atom_index = 0
        tmp_D_T = D_T[:Dr, :cur_spar + 1]
        init_alpha = alpha[:cur_spar + 1, :np.size(alpha, 1)]
        cur_D_TtY = D_TtY[:cur_spar + 1, :DtYc]
        # tmp_alpha = np.zeros_like(init_alpha)
        for cur_atom in range(Dc - cur_spar):
            tmp_D_T[:Dr, cur_spar] = D[:Dr, cur_atom]
            tmp_alpha = init_alpha
            D_TtY[cur_spar, :DtYc] = DtY[T[cur_atom], :DtYc]
            diver_error = newton(cur_D_TtY, tmp_D_T, tmp_alpha, NB_ITERATIONS_ITER)
            if diver_error < cur_diver:
                cur_diver = diver_error
                alpha[:cur_spar + 1, :np.size(alpha, 1)] = tmp_alpha
                atom_index = T[cur_atom]
        D_T[:Dr, cur_spar] = D[:Dr, atom_index]
        D_TtY[cur_spar, :DtYc] = DtY[atom_index, :DtYc]
        T[atom_index], T[Dc - 1 - cur_spar] = D[Dc - 1 - cur_spar], T[atom_index]
        cur_xhat = D_T[:Dr, :cur_spar + 1] * alpha[:cur_spar + 1, :np.size(alpha, 1)]
        cur_xhat = np.exp(cur_xhat)
        patch_error = np.linalg.norm((cur_xhat - xOracle), 'fro')
        if patch_error >= cur_patch_error:
            break
        cur_patch_error = patch_error
        actual_alpha[:cur_spar + 1, :np.size(actual_alpha, 1)] = alpha[:cur_spar + 1, :np.size(alpha, 1)]
        xhat = cur_xhat
    tmp_D_T = D_T[:Dr, :cur_spar]
    final_alpha = actual_alpha[:cur_spar, :np.size(actual_alpha, 1)]
    cur_D_TtY = D_TtY[:cur_spar, :DtYc]
    newton(cur_D_TtY, tmp_D_T, final_alpha, NB_ITERATIONS_FINAL)
    xhat = tmp_D_T * final_alpha
    xhat = np.exp(xhat)
    alphahat = np.zeros((Dc, DtYc))
    for i in range(cur_spar):
        alphahat[T[Dc - i - 1], :DtYc] = final_alpha[i, :DtYc]
    return cur_diver
def pga(D, DTY, k, xhat, alphahat=None):
    # todo
    cur_diver = DBL_MAX
    Dr, Dc = D.shape
    DtYr, DtYc = DTY.shape
    T = np.zeros((1, Dc))
    for i in range(Dc):
        T[i] = i
    D_T = np.zeros((Dr, k))
    alpha = np.zeros((k, DtYc))
    D_TtY = np.zeros((k, DtYc))
    for cur_spar in range(k):
        atom_index = 0
        tmp_D_T = D[:Dr, :cur_spar + 1]
        init_alpha = alpha[:cur_spar + 1, :DtYc]
        cur_D_TtY = D_TtY[:cur_spar + 1, :DtYc]
        # tmp_alpha = np.zeros_like(init_alpha)
        for cur_atom in range(Dc - cur_spar):
            tmp_D_T[:Dr, cur_spar] = D[:Dr, T[cur_atom]]
            tmp_alpha = init_alpha
            cur_D_TtY[cur_spar, :DtYc] = DTY[T[cur_atom], :DtYc]
            diver_error = newton(cur_D_TtY, tmp_D_T, tmp_alpha, NB_ITERATIONS_ITER)
            if diver_error < cur_diver:
                cur_diver = diver_error
                alpha[:cur_spar + 1, :DtYc] = tmp_alpha
                atom_index = T[cur_atom]
        D_T[:Dr, cur_spar] = D[:Dr, atom_index]
        D_TtY[cur_spar, :DtYc] = DTY[atom_index, :DtYc]
        T[atom_index], T[Dc - 1 - cur_spar] = T[Dc - 1 - cur_spar], T[atom_index]

    alpha = newton(D_TtY, D_T, alpha, NB_ITERATIONS_FINAL)
    xhat = D_T * alpha
    xhat = np.exp(xhat)
    alphahat = np.zeros((Dc, DtYc))
    for i in range(k):
        alphahat[T[Dc - i - 1], :DtYc] = alpha[i, :DtYc]
    return cur_diver