def generate_separated_multinomial_weights(A,C):
	"""Generates a set of multinomial weights B, where sum(abs(B-A)) = C
		Inputs:
			A: a list of multinomial weights
			C: A float, 0 <= C <= 1
	"""

	if not isinstance(A, list):
		raise TypeError("A should be a list")

	if not math.fabs(1-sum(A)) < .0000001:
		raise ValueError("A must sum to 1.")

	if C > 1.0 or C < 0:
		raise ValueError("0 <= C <= 1")

	if C == 0.0:
		return A

	idx = [i[0] for i in sorted(enumerate(A), key=lambda x:x[1])]
	A_sum = [A[i] for i in idx]

	A = numpy.array(A)

	A_sum = numpy.cumsum(numpy.array(A_sum))
	
	B = numpy.copy(A)

	t = numpy.nonzero(A_sum >= .5)[0][0]; 

	err_up = idx[:t]
	err_dn = idx[t:]

	upper_bounds = 1.0-B;
	upper_bounds[err_dn] = 0

	lower_bounds = numpy.copy(B);
	lower_bounds[err_up] = 0

	for _ in range(int(C*10.0)):
		# increase a weight
		ups = numpy.nonzero(upper_bounds >= .05)[0]
		move_up = ups[random.randrange(len(ups))]
		B[move_up] += .05
		upper_bounds[move_up] -= .05

		# decrease a weight
		dns = numpy.nonzero(lower_bounds >= .05)[0]
		# if there is no weight to decrease
		if len(dns) == 0:
			# send the lowest weight to zero, normalize and return
			maxdex = numpy.argmin(lower_bounds)
			B[maxdex] = 0
			B /= numpy.sum(B)
			break

		move_down = dns[random.randrange(len(dns))]
		B[move_down] -= .05
		lower_bounds[move_down] -= .05
	
	assert math.fabs(1-numpy.sum(B)) < .0000001
	return B.tolist()
dataset/ETHPy150Open probcomp/crosscat/src/tests/synthetic_data_generator.py/generate_separated_multinomial_weights/original