Пример #1
0
def run_instance(instance,
                 sparsity,
                 trade_off,
                 learning_rate,
                 max_iter=30000,
                 epsilon=1e-3):

    opt_x = optimize(instance, sparsity, trade_off, learning_rate, max_iter,
                     epsilon)

    pred_subgraph = np.nonzero(opt_x)[0]

    prec, rec, fm, iou = evaluate_block(instance['subgraph'], pred_subgraph)

    logger.debug('-' * 5 + ' raw performance ' + '-' * 5)
    logger.debug('precision: {:.5f}'.format(prec))
    logger.debug('recall   : {:.5f}'.format(rec))
    logger.debug('f-measure: {:.5f}'.format(fm))
    logger.debug('iou      : {:.5f}'.format(iou))

    refined_pred_subgraph = post_process_block(instance['graph'],
                                               pred_subgraph)
    prec, rec, fm, iou = evaluate_block(instance['subgraph'],
                                        refined_pred_subgraph)
    logger.debug('-' * 5 + ' refined performance ' + '-' * 5)
    logger.debug('precision: {:.5f}'.format(prec))
    logger.debug('recall   : {:.5f}'.format(rec))
    logger.debug('f-measure: {:.5f}'.format(fm))
    logger.debug('iou      : {:.5f}'.format(iou))
Пример #2
0
def density_projection(graph,
                       weight,
                       A,
                       threshold,
                       lmbd_sparsity_list,
                       normalize=False,
                       true_subgraph=None):

    if normalize:
        weight = (weight - np.min(weight)) / (np.max(weight) - np.min(weight))
    else:
        pass
    print('start density projection')

    density_subgraph_list = []
    print('density projection')
    # for lmbd in range(min_lmbd, max_lmbd, step_lmbd):
    for lmbd, sparsity in lmbd_sparsity_list:
        # for lmbd in lmbd_list:
        # for sparsity in range(min_sparsity, max_sparsity, step_sparsity):
        # for sparsity in sparsity_list:
        print('lambda, sparsity', lmbd, sparsity)
        x = proj_mp(graph,
                    weight,
                    A,
                    sparsity,
                    lmbd,
                    max_iter=10,
                    epsilon=1e-3)  # max iteration

        print('performance', evaluate_block(true_subgraph, list(x)))
        density = nx.density(nx.subgraph(graph, x))

        print('density', density)
        if density > threshold:
            print(density, len(x), sorted(list(x)))
            density_subgraph_list.append((density, x))

    # find the best result
    print('candidate', len(density_subgraph_list))
    max_weight = 0.
    best_density_subgraph = None
    for density_subgraph in density_subgraph_list:
        tmp_weight = np.linalg.norm(weight[list(density_subgraph[1])])
        if tmp_weight > max_weight:
            best_density_subgraph = density_subgraph
            max_weight = tmp_weight

    print(
        'end density projection: density {}, norm {}, size {}, set {}'.format(
            best_density_subgraph[0], max_weight,
            len(best_density_subgraph[1]),
            sorted(list(best_density_subgraph[1]))))

    return best_density_subgraph[1]
def run_dataset(paras):
    dataset, sparsity, trade_off, learning_rate, max_iter, epsilon, write_to_dir, tao = paras

    if not write_to_dir:
        logger = logging.getLogger('fei')
    else:
        log_fn = '{}_sparsity_{:d}_trade_{}_lr_{}_parallel.txt'.format(
            DATASET, sparsity, trade_off, learning_rate)

        if os.path.isfile(os.path.join(write_to_dir, log_fn)):
            print('file exist !!!')
            return

        logger = logging.getLogger(log_fn)
        formatter = logging.Formatter('')
        file_handler = logging.FileHandler(filename=os.path.join(
            write_to_dir, log_fn),
                                           mode='w')
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)

    all_performance = []
    logger.debug('-' * 5 + ' setting ' + '-' * 5)
    logger.debug('sparsity: {:d}'.format(sparsity))
    logger.debug('learning rate: {:.5f}'.format(learning_rate))
    logger.debug('trade off: {:.5f}'.format(trade_off))
    logger.debug('tao: {:d}'.format(tao))

    for i, instance in enumerate(dataset):

        logger.debug('instance: {:d}'.format(i))

        normalize = True
        if normalize:
            print('normalize')
            instance['features'] = instance['features'] / np.max(
                instance['features'])

        # opt_x, run_time = optimize(instance, sparsity, trade_off, learning_rate, max_iter, epsilon, logger=None, tao=tao)
        opt_x, run_time = optimize(instance,
                                   sparsity,
                                   trade_off,
                                   learning_rate,
                                   max_iter,
                                   epsilon,
                                   logger=logger,
                                   tao=tao)

        logger.debug('run time: {:.5f}'.format(run_time))

        raw_pred_subgraph = np.nonzero(opt_x)[0]

        prec, rec, fm, iou = evaluate_block(instance['true_subgraph'],
                                            raw_pred_subgraph)

        logger.debug('-' * 5 + ' performance of raw prediction ' + '-' * 5)
        logger.debug('precision: {:.5f}'.format(prec))
        logger.debug('recall   : {:.5f}'.format(rec))
        logger.debug('f-measure: {:.5f}'.format(fm))
        logger.debug('iou      : {:.5f}'.format(iou))

        refined_pred_subgraph = post_process_block(instance['graph'],
                                                   raw_pred_subgraph,
                                                   dataset=DATASET)
        refined_prec, refined_rec, refined_fm, refined_iou = evaluate_block(
            instance['true_subgraph'], refined_pred_subgraph)

        logger.debug('-' * 5 + ' performance of refined prediction ' + '-' * 5)
        logger.debug('refined precision: {:.5f}'.format(refined_prec))
        logger.debug('refined recall   : {:.5f}'.format(refined_rec))
        logger.debug('refined f-measure: {:.5f}'.format(refined_fm))
        logger.debug('refined iou      : {:.5f}'.format(refined_iou))

        all_performance.append((prec, rec, fm, iou, refined_prec, refined_rec,
                                refined_fm, refined_iou, run_time))

    all_performance = np.array(all_performance)
    avg_performance = np.mean(all_performance, axis=0)
    logger.debug('-' * 5 + ' average performance ' + '-' * 5)
    logger.debug('average presision: {:.5f}'.format(avg_performance[0]))
    logger.debug('average recall   : {:.5f}'.format(avg_performance[1]))
    logger.debug('average f-measure: {:.5f}'.format(avg_performance[2]))
    logger.debug('average iou      : {:.5f}'.format(avg_performance[3]))
    logger.debug('avg refined prec : {:.5f}'.format(avg_performance[4]))
    logger.debug('avg refined rec  : {:.5f}'.format(avg_performance[5]))
    logger.debug('avg refined fm   : {:.5f}'.format(avg_performance[6]))
    logger.debug('avg refined iou  : {:.5f}'.format(avg_performance[7]))
    logger.debug('average run time : {:.5f}'.format(avg_performance[8]))
Пример #4
0
def run_dataset(paras):
    dataset, sparsity, threshold, trade_off, learning_rate, max_iter, epsilon, write_to_dir = paras

    if not write_to_dir:
        logger = logging.getLogger('fei')
    else:
        log_fn = '{}_sparsity_{:d}_threshold_{}_trade_{}_lr_{}.txt'.format(
            DATASET, sparsity, threshold, trade_off, learning_rate)

        if os.path.isfile(os.path.join(write_to_dir, log_fn)):
            print('file exists !!!')
            return

        logger = logging.getLogger(log_fn)
        formatter = logging.Formatter('')
        file_handler = logging.FileHandler(filename=os.path.join(
            write_to_dir, log_fn),
                                           mode='w')
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)

    all_performance = []
    logger.debug('-' * 5 + ' setting ' + '-' * 5)
    logger.debug('sparsity: {:d}'.format(sparsity))
    logger.debug('learning rate: {:.5f}'.format(learning_rate))
    logger.debug('trade off: {:.5f}'.format(trade_off))

    for i, instance in enumerate(dataset):
        logger.debug('instance: {:d}'.format(i))

        # if normalize:
        #     logger.debug('feature normalized')
        #     instance['features'] = instance['features'] / np.max(instance['features'])

        opt_x, opt_y, run_time = optimize(instance,
                                          sparsity,
                                          threshold,
                                          trade_off,
                                          learning_rate,
                                          max_iter,
                                          epsilon,
                                          logger=logger)

        logger.debug('run time: {:.5f}'.format(run_time))

        second_graph = instance['second_graph']

        raw_pred_subgraph_x = np.nonzero(opt_x)[0]  # ndarray

        prec, rec, fm, iou = evaluate_block(instance['true_subgraph'],
                                            raw_pred_subgraph_x)

        logger.debug('-' * 5 + ' performance of x prediction ' + '-' * 5)
        logger.debug('precision: {:.5f}'.format(prec))
        logger.debug('recall   : {:.5f}'.format(rec))
        logger.debug('f-measure: {:.5f}'.format(fm))
        logger.debug('iou      : {:.5f}'.format(iou))
        logger.debug('raw density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, list(raw_pred_subgraph_x)))))

        raw_pred_subgraph_y = np.nonzero(opt_y)[0]

        prec, rec, fm, iou = evaluate_block(instance['true_subgraph'],
                                            raw_pred_subgraph_y)

        logger.debug('-' * 5 + ' performance of y prediction ' + '-' * 5)
        logger.debug('precision: {:.5f}'.format(prec))
        logger.debug('recall   : {:.5f}'.format(rec))
        logger.debug('f-measure: {:.5f}'.format(fm))
        logger.debug('iou      : {:.5f}'.format(iou))
        logger.debug('raw density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, list(raw_pred_subgraph_y)))))

        # connected in first graph
        refined_pred_subgraph_x = post_process_block(instance['first_graph'],
                                                     raw_pred_subgraph_x,
                                                     dataset=DATASET)
        refined_prec, refined_rec, refined_fm, refined_iou = evaluate_block(
            instance['true_subgraph'], refined_pred_subgraph_x)

        logger.debug('-' * 5 + ' performance of refined x prediction ' +
                     '-' * 5)
        logger.debug('refined precision: {:.5f}'.format(refined_prec))
        logger.debug('refined recall   : {:.5f}'.format(refined_rec))
        logger.debug('refined f-measure: {:.5f}'.format(refined_fm))
        logger.debug('refined iou      : {:.5f}'.format(refined_iou))
        logger.debug('refined x density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, refined_pred_subgraph_x))))

        refined_pred_subgraph_y = post_process_block(instance['first_graph'],
                                                     raw_pred_subgraph_y,
                                                     dataset=DATASET)
        refined_prec, refined_rec, refined_fm, refined_iou = evaluate_block(
            instance['true_subgraph'], refined_pred_subgraph_y)

        logger.debug('-' * 5 + ' performance of refined y prediction ' +
                     '-' * 5)
        logger.debug('refined precision: {:.5f}'.format(refined_prec))
        logger.debug('refined recall   : {:.5f}'.format(refined_rec))
        logger.debug('refined f-measure: {:.5f}'.format(refined_fm))
        logger.debug('refined iou      : {:.5f}'.format(refined_iou))
        logger.debug('refined y density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, refined_pred_subgraph_y))))

        # print(type(raw_pred_subgraph_x))
        # print(type(raw_pred_subgraph_y))

        combine_pred_subgraph = set(list(raw_pred_subgraph_x)) & set(
            list(raw_pred_subgraph_y))

        combine_prec, combine_rec, combine_fm, combine_iou = evaluate_block(
            instance['true_subgraph'], combine_pred_subgraph)

        logger.debug('-' * 5 + ' combine performance of prediction ' + '-' * 5)
        logger.debug('precision: {:.5f}'.format(combine_prec))
        logger.debug('recall   : {:.5f}'.format(combine_rec))
        logger.debug('f-measure: {:.5f}'.format(combine_fm))
        logger.debug('iou      : {:.5f}'.format(combine_iou))
        logger.debug('combined density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, combine_pred_subgraph))))

        refined_combine_pred_subgraph = post_process_block(
            instance['first_graph'], combine_pred_subgraph, dataset=DATASET)
        refined_combine_prec, refined_combine_rec, refined_combine_fm, refined_combine_iou = evaluate_block(
            instance['true_subgraph'], refined_combine_pred_subgraph)

        logger.debug('-' * 5 + ' refined combine performance of prediction ' +
                     '-' * 5)
        logger.debug('precision: {:.5f}'.format(refined_combine_prec))
        logger.debug('recall   : {:.5f}'.format(refined_combine_rec))
        logger.debug('f-measure: {:.5f}'.format(refined_combine_fm))
        logger.debug('iou      : {:.5f}'.format(refined_combine_iou))
        logger.debug('refined combined density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph,
                                   refined_combine_pred_subgraph))))
Пример #5
0
def run_dataset(paras):
    dataset, sparsity, threshold, trade_off, learning_rate, max_iter, epsilon, write_to_dir = paras

    # print log setting
    if not write_to_dir:
        logger = logging.getLogger('fei')
    else:
        log_fn = '{}_sparsity_{:d}_threshold_{}_trade_off_{}_lr_{}.txt'.format(
            DATASET, sparsity, threshold, trade_off, learning_rate)

        if os.path.isfile(os.path.join(write_to_dir, log_fn)):
            print('file exists !!!')
            return

        logger = logging.getLogger(log_fn)
        formatter = logging.Formatter('')
        file_handler = logging.FileHandler(filename=os.path.join(
            write_to_dir, log_fn),
                                           mode='w')
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)

    all_performance = []
    logger.debug('-' * 5 + ' setting ' + '-' * 5)
    logger.debug('sparsity: {:d}'.format(sparsity))
    logger.debug('learning rate: {:.5f}'.format(learning_rate))
    logger.debug('trade off: {:.5f}'.format(trade_off))

    for i, instance in enumerate(dataset):

        logger.debug('instance: {:d}'.format(i))

        opt_x, opt_y, run_time = optimize(instance,
                                          sparsity,
                                          threshold,
                                          trade_off,
                                          learning_rate,
                                          max_iter,
                                          epsilon,
                                          logger=logger)

        logger.debug('run time: {:.5f}'.format(run_time))

        second_graph = instance['second_graph']

        raw_pred_subgraph_x = np.nonzero(opt_x)[0]

        x_prec, x_rec, x_fm, x_iou = evaluate_block(instance['true_subgraph'],
                                                    raw_pred_subgraph_x)

        logger.debug('-' * 5 + ' performance of x prediction ' + '-' * 5)
        logger.debug('precision: {:.5f}'.format(x_prec))
        logger.debug('recall   : {:.5f}'.format(x_rec))
        logger.debug('f-measure: {:.5f}'.format(x_fm))
        logger.debug('iou      : {:.5f}'.format(x_iou))
        logger.debug('raw density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, list(raw_pred_subgraph_x)))))

        raw_pred_subgraph_y = np.nonzero(opt_y)[0]

        print('length y', len(raw_pred_subgraph_y))

        y_prec, y_rec, y_fm, y_iou = evaluate_block(instance['true_subgraph'],
                                                    raw_pred_subgraph_y)

        logger.debug('-' * 5 + ' performance of y prediction ' + '-' * 5)
        logger.debug('precision: {:.5f}'.format(y_prec))
        logger.debug('recall   : {:.5f}'.format(y_rec))
        logger.debug('f-measure: {:.5f}'.format(y_fm))
        logger.debug('iou      : {:.5f}'.format(y_iou))
        logger.debug('raw density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, list(raw_pred_subgraph_y)))))

        # connected in first graph
        connected_pred_subgraph_x = post_process_block(instance['first_graph'],
                                                       raw_pred_subgraph_x,
                                                       dataset=DATASET)
        connected_x_prec, connected_x_rec, connected_x_fm, connected_x_iou = evaluate_block(
            instance['true_subgraph'], connected_pred_subgraph_x)

        logger.debug('-' * 5 + ' performance of connected x prediction ' +
                     '-' * 5)
        logger.debug('refined precision: {:.5f}'.format(connected_x_prec))
        logger.debug('refined recall   : {:.5f}'.format(connected_x_rec))
        logger.debug('refined f-measure: {:.5f}'.format(connected_x_fm))
        logger.debug('refined iou      : {:.5f}'.format(connected_x_iou))
        logger.debug('connected x density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, connected_pred_subgraph_x))))

        connected_pred_subgraph_y = post_process_block(instance['first_graph'],
                                                       raw_pred_subgraph_y,
                                                       dataset=DATASET)
        connected_y_prec, connected_y_rec, connected_y_fm, connected_y_iou = evaluate_block(
            instance['true_subgraph'], connected_pred_subgraph_y)

        logger.debug('-' * 5 + ' performance of connected y prediction ' +
                     '-' * 5)
        logger.debug('refined precision: {:.5f}'.format(connected_y_prec))
        logger.debug('refined recall   : {:.5f}'.format(connected_y_rec))
        logger.debug('refined f-measure: {:.5f}'.format(connected_y_fm))
        logger.debug('refined iou      : {:.5f}'.format(connected_y_iou))
        logger.debug('refined y density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, connected_pred_subgraph_y))))

        # print(type(raw_pred_subgraph_x))
        # print(type(raw_pred_subgraph_y))

        intersect_pred_subgraph = set(list(raw_pred_subgraph_x)) & set(
            list(raw_pred_subgraph_y))

        intersect_prec, intersect_rec, intersect_fm, intersect_iou = evaluate_block(
            instance['true_subgraph'], intersect_pred_subgraph)

        logger.debug('-' * 5 + ' intersect performance of prediction ' +
                     '-' * 5)
        logger.debug('precision: {:.5f}'.format(intersect_prec))
        logger.debug('recall   : {:.5f}'.format(intersect_rec))
        logger.debug('f-measure: {:.5f}'.format(intersect_fm))
        logger.debug('iou      : {:.5f}'.format(intersect_iou))
        logger.debug('intersect density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, intersect_pred_subgraph))))

        connected_intersect_pred_subgraph = post_process_block(
            instance['first_graph'], intersect_pred_subgraph, dataset=DATASET)
        connected_intersect_prec, connected_intersect_rec, connected_intersect_fm, connected_intersect_iou = evaluate_block(
            instance['true_subgraph'], connected_intersect_pred_subgraph)

        logger.debug('-' * 5 +
                     ' connected intersect performance of prediction ' +
                     '-' * 5)
        logger.debug('precision: {:.5f}'.format(connected_intersect_prec))
        logger.debug('recall   : {:.5f}'.format(connected_intersect_rec))
        logger.debug('f-measure: {:.5f}'.format(connected_intersect_fm))
        logger.debug('iou      : {:.5f}'.format(connected_intersect_iou))
        logger.debug('connected intersect density second graph: {:.5f}'.format(
            nx.density(
                nx.subgraph(second_graph, connected_intersect_pred_subgraph))))

        union_pred_subgraph = set(list(raw_pred_subgraph_x)) | set(
            list(raw_pred_subgraph_y))
        union_prec, union_rec, union_fm, union_iou = evaluate_block(
            instance['true_subgraph'], union_pred_subgraph)

        logger.debug('-' * 5 + ' union performance of prediction ' + '-' * 5)
        logger.debug('precision: {:.5f}'.format(union_prec))
        logger.debug('recall   : {:.5f}'.format(union_rec))
        logger.debug('f-measure: {:.5f}'.format(union_fm))
        logger.debug('iou      : {:.5f}'.format(union_iou))
        logger.debug('union density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph, union_pred_subgraph))))

        connected_union_pred_subgraph = post_process_block(
            instance['first_graph'], union_pred_subgraph, dataset=DATASET)
        connected_union_prec, connected_union_rec, connected_union_fm, connected_union_iou = evaluate_block(
            instance['true_subgraph'], connected_union_pred_subgraph)

        logger.debug('-' * 5 + ' connected union performance of prediction ' +
                     '-' * 5)
        logger.debug('precision: {:.5f}'.format(connected_union_prec))
        logger.debug('recall   : {:.5f}'.format(connected_union_rec))
        logger.debug('f-measure: {:.5f}'.format(connected_union_fm))
        logger.debug('iou      : {:.5f}'.format(connected_union_iou))
        logger.debug('connected union density second graph: {:.5f}'.format(
            nx.density(nx.subgraph(second_graph,
                                   connected_union_pred_subgraph))))
Пример #6
0
def optimize(instance, sparsity, trade_off, learning_rate, max_iter, epsilon):

    graph = instance['graph']
    true_subgraph = instance['subgraph']
    features = instance['features']
    block_node_sets = instance['block_node_sets']
    block_boundary_edges_dict = instance['block_boundary_edges_dict']

    num_nodes = graph.number_of_nodes()
    num_edges = graph.number_of_edges()
    num_blocks = len(block_boundary_edges_dict)

    logger.debug('-' * 5 + ' related info ' + '-' * 5)
    logger.debug('algorithm: graph block-structured IHT')
    logger.debug('sparsity: {:d}'.format(sparsity))
    logger.debug('max iteration: {:d}'.format(max_iter))
    logger.debug('number of nodes: {:d}'.format(num_nodes))
    logger.debug('number of edges: {:d}'.format(num_edges))
    logger.debug('number of blocks: {:d}'.format(num_blocks))

    node_id_dict = relabel_nodes(block_node_sets)
    relabeled_edge_sets = relabel_edges(graph, block_node_sets, node_id_dict)

    logger.debug('-' * 5 + ' start iterating ' + '-' * 5)
    start_time = time.time()
    acc_proj_time = 0.
    func = BlockSumEMS(features=features,
                       nodes_set=block_node_sets,
                       boundary_edges_dict=block_boundary_edges_dict,
                       nodes_id_dict=node_id_dict,
                       trade_off=trade_off)

    true_x = np.zeros(num_nodes)
    true_x[true_subgraph] = 1.
    true_x = np.array(true_x)
    true_obj_val, true_sum_ems_val, true_penalty = func.get_obj_val(true_x)
    logger.debug(
        'ground truth, obj value: {:.5f}, sum ems value: {:.5f}, penalty: {:.5f}'
        .format(true_obj_val, true_sum_ems_val, true_penalty))

    current_x = func.get_init_x_zeros() + 1e-6
    for iter in range(max_iter):  # cyclic block coordinate version
        for b in range(num_blocks):
            logger.debug('iteration: {:d}'.format(iter))
            prev_x = np.copy(current_x)
            iter_time = time.time()
            iter_proj_time = 0.

            sorted_node_set = sorted(block_node_sets[b])
            block_x = current_x[sorted_node_set]
            block_boundary_edge_x_dict = get_boundary_xs(
                current_x, block_boundary_edges_dict[b], node_id_dict)
            block_features = features[sorted_node_set]
            block_grad = func.get_gradient(block_x, block_features,
                                           block_boundary_edge_x_dict)
            block_x = block_x if iter > 0 else np.zeros_like(block_x,
                                                             dtype=np.float64)

            normalized_block_grad = normalize_gradient(block_x, block_grad)
            edges = np.array(relabeled_edge_sets[b])
            edge_weights = np.ones(len(edges))

            start_proj_time = time.time()
            re_head = head_proj(edges=edges,
                                weights=edge_weights,
                                x=normalized_block_grad,
                                g=1,
                                s=sparsity,
                                budget=sparsity - 1.,
                                delta=1. / 169.,
                                max_iter=100,
                                err_tol=1e-8,
                                root=-1,
                                pruning='strong',
                                epsilon=1e-10,
                                verbose=0)
            re_nodes, _, _ = re_head
            iter_proj_time += time.time() - start_proj_time
            block_omega_x = set(
                re_nodes
            )  # note, elements in block_omega_x are all local (block) node id

            # update one block
            block_x = current_x[sorted_node_set]
            block_features = features[sorted_node_set]
            block_indicator_x = np.zeros_like(current_x[sorted_node_set])
            block_indicator_x[list(block_omega_x)] = 1.
            block_boundary_edge_x_dict = get_boundary_xs(
                current_x, block_boundary_edges_dict[b], node_id_dict)

            current_x[sorted_node_set] = current_x[
                sorted_node_set] + learning_rate * func.get_gradient(
                    block_x, block_features,
                    block_boundary_edge_x_dict) * block_indicator_x

            block_bx = current_x[sorted_node_set]
            start_proj_time = time.time()
            re_tail = tail_proj(edges=edges,
                                weights=edge_weights,
                                x=block_bx,
                                g=1,
                                s=sparsity,
                                budget=sparsity - 1.,
                                nu=2.5,
                                max_iter=100,
                                err_tol=1e-8,
                                root=-1,
                                pruning='strong',
                                verbose=0)
            re_nodes, _, _ = re_tail
            iter_proj_time += time.time() - start_proj_time
            psi_x = set(re_nodes)
            block_x = np.zeros_like(current_x[sorted_node_set])
            block_x[list(psi_x)] = block_bx[list(psi_x)]
            normalized_block_x = normalize(block_x)
            current_x[
                sorted_node_set] = normalized_block_x  # constrain current block x in [0, 1]

            acc_proj_time += iter_proj_time

            obj_val, sum_ems_val, penalty = func.get_obj_val(current_x)
            logger.debug(
                'objective value: {:.5f}, sum ems value: {:.5f}, penalty: {:.5f}'
                .format(obj_val, sum_ems_val, penalty))
            logger.debug('iteration time: {:.5f}'.format(time.time() -
                                                         iter_time))
            logger.debug('iter projection time: {:.5f}'.format(iter_proj_time))
            logger.debug('acc projection time: {:.5f}'.format(
                acc_proj_time))  # accumulative projection time
            pred_subgraph = np.nonzero(current_x)[0]
            prec, rec, fm, iou = evaluate_block(instance['subgraph'],
                                                pred_subgraph)
            logger.debug(
                'precision: {:.5f}, recall: {:.5f}, f-measure: {:.5f}'.format(
                    prec, rec, fm))
            logger.debug('-' * 10)

            diff_norm_x = np.linalg.norm(current_x - prev_x)
            if diff_norm_x < epsilon:
                print('difference {:.5f}'.format(diff_norm_x))
                break

    run_time = time.time() - start_time
    obj_val, sum_ems_val, penalty = func.get_obj_val(current_x)
    logger.debug(
        'objective value: {:.5f}, sum ems value: {:.5f}, penalty: {:.5f}'.
        format(obj_val, sum_ems_val, penalty))
    logger.debug('run time of whole algorithm: {:.5f}'.format(run_time))
    logger.debug('accumulative projection time: {:.5f}'.format(acc_proj_time))

    return current_x