VariableVector increment_weight_vector(const VariableVector& weights, const VariableVector& scaled_gradient) {

	VariableVector empty;
	

	if (weights.size() != scaled_gradient.size()) {
		return empty;
	}

	VariableVector incremented;
	string partial_name, weight_name;
	double scaled_partial, weight_val;

	for (VariableVector::const_iterator it = scaled_gradient.begin(); it != scaled_gradient.end(); ++it) {
		partial_name = it->first;
		scaled_partial = it->second;

		weight_name = partial_name_to_weight_name(partial_name);

		if (weights.count(weight_name) == 0) {
			return empty;
		}

		weight_val = weights.at(weight_name);

		incremented.insert(make_pair(weight_name, weight_val + scaled_partial));
	}

	return incremented;
}
VariableVector add_variable_vectors(const VariableVector& vec1, const VariableVector& vec2) {
	
	VariableVector empty;
	VariableVector sum;
	string var_name;
	double component_sum;

	// if the vectors are of different sizes, return empty
	if (vec1.size() != vec2.size()) return empty;

	for (VariableVector::const_iterator it1 = vec1.begin(); it1 != vec1.end(); ++it1) {

		var_name = it1->first;

		// if this variable is in both vectors, add the values
		if (vec2.count(var_name) != 0) {
			component_sum = it1->second + vec2.at(var_name);
			sum.insert(make_pair(var_name, component_sum));
		} 
		// if this variable is only in vec1, return empty
		else {
			return empty;
		}
	}

	// if we reach this point, every variable in vec1 is also in vec2
	// since both vectors are of the same size, it is safe to return

	return sum;
}
double distance_between_variable_vectors(const VariableVector& vec1, const VariableVector& vec2) {
	// Both vectors must have the same dimension
	if (vec1.size() != vec2.size()) {
		return -1;
	}

	double square_distance = 0;
	string var_name;
	double val1, val2;

	for (VariableVector::const_iterator it = vec1.begin(); it != vec1.end(); ++it) {

		var_name = it->first;

		// Both vectors must have exactly the same variables
		if (vec2.count(var_name) == 0) {
			return -1;
		}

		val1 = vec1.at(var_name);
		val2 = vec2.at(var_name);

		square_distance += pow((val1 - val2), 2);
	}

	return pow(square_distance, 0.5);
}
const VariableVector variable_vector_union(const VariableVector& vec1, const VariableVector& vec2) {

	VariableVector empty;
	VariableVector v;

	// add all the variables in Vec 1 first
	// if any of these variables are seen in Vec 2, this is an error. Return the empty Variable Vector.
	// if there is no overlap, then it is safe to add all the variables in Vec 2
	for (VariableVector::const_iterator it1 = vec1.begin(); it1 != vec1.end(); ++it1) {
		if (vec2.count(it1->first) != 0) {
			return empty;
		}
		v.insert(make_pair(it1->first, it1->second));
	}

	for (VariableVector::const_iterator it2 = vec2.begin(); it2 != vec2.end(); ++it2) {
		v.insert(make_pair(it2->first, it2->second));
	}

	return v;
}