def predict_one_source(w, query_data, params):
	K = params["K"]
	candidates = query_data["candidates"]
	(A, A_data) = edge_computation.compute_A(w, query_data["feature_stack"], query_data["edge_ij"], params["edge_strength_fun"], query_data["num_nodes"])
	Q = edge_computation.compute_Q(A, A_data, query_data["edge_ij"], query_data["source"], query_data["num_nodes"], params)
	p_0 = numpy.ones((query_data["num_nodes"], 1)) / (1.0 * query_data["num_nodes"])
	p = page_rank_update.update_p(p_0, Q, params)
	indices = numpy.argsort(-1.0 * p[candidates], axis = 0)
	positives = []
	negatives = []
		
	for k in range(indices.shape[0]):
		if k < K:
			positives.append(candidates[indices[k, 0]])
		else:
			negatives.append(candidates[indices[k, 0]])
	
	#print("min(p+) - max(p-) = %f"%(numpy.amin(p[positives]) - numpy.amax(p[negatives])))
	#print("max(p+) - min(p-) = %f"%(numpy.amax(p[positives]) - numpy.amin(p[negatives])))
	return (positives, negatives)
def cost_one_source(w, training_data, p_warm_start, params):
    s = training_data["source"]
    (A, A_data) = edge_computation.compute_A(
        w,
        training_data["feature_stack"],
        training_data["edge_ij"],
        params["edge_strength_fun"],
        training_data["num_nodes"],
    )
    Q = edge_computation.compute_Q(A, A_data, training_data["edge_ij"], s, training_data["num_nodes"], params)
    p = page_rank_update.update_p(p_warm_start, Q, params)
    loss_fun = params["loss_fun"]
    margin = params["margin"]
    positives = training_data["positives"]
    negatives = training_data["negatives"]
    candidates = list(set(positives + negatives))
    p_prime = p / numpy.sum(p[candidates])

    diff_generating_mat = training_data["diff_generating_mat"]
    diffs = diff_generating_mat.dot(p_prime)

    loss = numpy.sum(loss_fun(diffs, margin))

    return (loss, p)
import numpy.random
import scipy.sparse
import partial_gradient_update
import page_rank_update
import sys
import random

num_nodes = 2
perturbation = 0
rho = float(sys.argv[1]) * random.random()

numpy.random.seed(0)
Q_dense = numpy.random.rand(num_nodes, num_nodes)
Q_dense /= numpy.tile(numpy.dot(Q_dense, numpy.ones((num_nodes, 1))), (1, num_nodes))
print(numpy.eye(num_nodes, num_nodes) - Q_dense.T)
A = numpy.eye(num_nodes, num_nodes) - Q_dense.T
z = 100.0 * numpy.random.rand(num_nodes, 1)
Q_grad_dense = numpy.tile(numpy.dot(A, z), (1, num_nodes)).T
Q_grad_dense += perturbation * numpy.random.rand(num_nodes, num_nodes)
Q = scipy.sparse.csr_matrix(Q_dense)
p = numpy.random.rand(num_nodes, 1)
p_grad = numpy.zeros((num_nodes, 1))
p_grad[0] = rho
p /= numpy.sum(p)
p = page_rank_update.update_p(p, Q, {"page_rank_epsilon": 1e-12})
print(p)
Q_grad = scipy.sparse.csr_matrix(Q_grad_dense)
print(Q_grad.T.dot(p))
p_grad = partial_gradient_update.update_p_grad(p, p_grad, Q, [Q_grad], 1, {"partial_gradient_update_epsilon": 1e-12})
print(numpy.dot(A, p_grad) - numpy.dot(A, z))