def run_PMF(X,M_training,M_test,K):
    pmf = VariationalPMF(X,M_training,K)
    pmf.initialize()
    pmf.run(iterations,updates)
    X_pred = pmf.predicted_X
    
    # Calculate MSE of predictions.
    MSE = statistics.MSE(X,X_pred,M_test)
    
    print "Performance on test set: MSE=%s." % MSE  
    return MSE
def recover(M,source,target,iterations,calc_predictions=False,M_inv=[]):
	(I,J,K,X,U,V) = load_X_U_V(source)

	PMF = VariationalPMF(X,M,K)
	PMF.run(iterations=iterations,updates=10,calc_predictions=calc_predictions,M_inv=M_inv)

	predicted_U = PMF.U
	predicted_V = PMF.V
	predicted_X = PMF.predicted_X

	# Write predicted_X, U, V to output file
	store_X_U_V(target,predicted_X,predicted_U,predicted_V)

	return
def test_compute_omega():
	X = numpy.array([[1,2],[3,4],[5,6]])
	M = numpy.array([[0,1],[1,0],[1,1]])
	K = 2

	PMF = VariationalPMF(X,M,K)
	PMF.compute_omega()

	expected_omega = [(0,1),(1,0),(2,0),(2,1)]
	expected_omega_I = [[1],[0],[0,1]]
	expected_omega_J = [[1,2],[0,2]]

	assert numpy.array_equal(PMF.omega,expected_omega)
	assert numpy.array_equal(PMF.omega_I,expected_omega_I)
	assert PMF.omega_J[0] == expected_omega_J[0] and PMF.omega_J[1] == expected_omega_J[1]
	return RMSE


if __name__ == "__main__":
	X = read_data("./../../data/gi50_no_missing.txt")
	(I,J) = X.shape
	fraction_unknown = 0.1

	M = generate_M(I,J,fraction_unknown)
	M_inv = calc_inverse_M(M)
	K = 3

	outputfile = "recovered_matrices.txt"
	iterations = 10

	PMF = VariationalPMF(X,M,K)
	PMF.run(iterations=iterations,updates=1,calc_predictions=True,M_inv=M_inv)

	predicted_U = PMF.U
	predicted_V = PMF.V
	predicted_X = PMF.predicted_X

	# Store the predicted matrix X with U and V
	store_X_U_V(outputfile,predicted_X,predicted_U,predicted_V)

	# Now we plot the predictions vs the true values
	actual_vs_predicted = recover_predictions(M,X,predicted_X)
	(actual,predicted) = zip(*actual_vs_predicted)

	RMSE_predictions = compute_RMSE(actual_vs_predicted)
	RMSE_training = PMF.RMSE
def test_updates():
	# We create a simple test case by overwriting the random initialization,
	# and then test each of the updates.
	X = numpy.array([[-1,2],[3,4]])
	M = numpy.array([[0,1],[1,1]])
	K = 2

	# Reset values
	r_alpha = numpy.array([0.1,0.2])
	r_beta = numpy.array([0.3,0.4])
	r_tau = 0.5
	r_U = numpy.array([[0.6,0.7],[0.8,0.9]])
	r_S_U = numpy.array([[1.0,1.1],[1.2,1.3]])
	r_V = numpy.array([[1.4,1.5],[1.6,1.7]])
	r_S_V = numpy.array([[1.8,1.9],[2.0,2.1]])
	r_R = numpy.array([[0,						(2-(0.6*1.5)-(0.8*1.7))],
					   [(3-(0.7*1.4)-(0.9*1.6)),(4-(0.7*1.5)-(0.9*1.7))]])


	PMF = VariationalPMF(X,M,K)
	PMF.run(0)


	def reset():
		# Overwrite everything for the test case
		PMF.alpha[:] = r_alpha
		PMF.beta[:] = r_beta
		PMF.tau = r_tau
		PMF.U[:] = r_U
		PMF.S_U[:] = r_S_U
		PMF.V[:] = r_V
		PMF.S_V[:] = r_S_V
		PMF.R[:] = r_R


	# Test updating the hyperparameters
	reset()
	PMF.update_hyperparameters()

	expected_alpha = numpy.array([
		2.0 / ((0.6**2+1.0)+(0.7**2+1.1)),
		2.0 / ((0.8**2+1.2)+(0.9**2+1.3))
	])
	expected_beta = numpy.array([
		2.0 / ((1.4**2+1.8)+(1.5**2+1.9)),
		2.0 / ((1.6**2+2.0)+(1.7**2+2.1))
	])
	# tau = E_21 + E_12 + E_22 (because M_11=0)
	E_12 = (2-(0.6*1.5+0.8*1.7))**2 + (0.6**2*1.9+1.5**2*1.0+1.0*1.9) + (0.8**2*2.1+1.7**2*1.2+2.1*1.2)
	E_21 = (3-(0.7*1.4+0.9*1.6))**2 + (0.7**2*1.8+1.4**2*1.1+1.1*1.8) + (0.9**2*2.0+1.6**2*1.3+2.0*1.3)
	E_22 = (4-(0.7*1.5+0.9*1.7))**2 + (0.7**2*1.9+1.5**2*1.1+1.1*1.9) + (0.9**2*2.1+1.7**2*1.3+2.1*1.3)
	expected_tau = 3.0 / (E_21 + E_12 + E_22)

	assert numpy.array_equal(PMF.alpha,expected_alpha)
	assert numpy.array_equal(PMF.beta,expected_beta)
	assert PMF.tau == expected_tau


	# Test updating U. Testing U itself is hard because the values of R_ij change,
	# so to verify you would have to run the program itself anyways.
	reset()
	PMF.update_U()
	expected_S_U = numpy.array([
		[
			1.0/(0.1 + 0.5 * (1.5**2+1.9)),
			1.0/(0.1 + 0.5 * (1.4**2+1.8 + 1.5**2+1.9))
		],
		[
			1.0/(0.2 + 0.5 * (1.7**2+2.1)),
			1.0/(0.2 + 0.5 * (1.6**2+2.0 + 1.7**2+2.1))
		]
	])
	assert numpy.array_equal(PMF.S_U,expected_S_U)

	assert True