Download
//Copyright 2018 Maria Andreina Francisco Rodriguez (andreina@comp.nus.edu.sg)
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http ://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.

#include "ortools/constraint_solver/constraint_solveri.h"

namespace operations_research {

	void printSolutionArray(std::vector<IntVar*> arrayOfVars);

	void gracefulGraph() {
		// Instantiate the solver.
		Solver solver("k4p2");
		const int64 numEdges = 16;

		// Create nodes
		std::vector<IntVar*> front;
		solver.MakeIntVarArray(4, 0, numEdges, "nodes", &front);

		// Create "back" nodes
		std::vector<IntVar*> back;
		solver.MakeIntVarArray(4, 0, numEdges, "Back nodes", &back);

		std::vector<IntVar*> allnodes;
		allnodes.insert(allnodes.end(), front.begin(), front.end());
		allnodes.insert(allnodes.end(), back.begin(), back.end());

		// The label of each node must be different
		solver.AddConstraint(solver.MakeAllDifferent(allnodes));

		// Edges
		std::vector<IntVar*> edges;
		solver.MakeIntVarArray(numEdges, 1, numEdges, "Edges", &edges);

		// Front
		solver.AddConstraint(solver.MakeEquality(edges[0], solver.MakeAbs(solver.MakeDifference(front[0], front[1]))));
		solver.AddConstraint(solver.MakeEquality(edges[1], solver.MakeAbs(solver.MakeDifference(front[0], front[2]))));
		solver.AddConstraint(solver.MakeEquality(edges[2], solver.MakeAbs(solver.MakeDifference(front[1], front[3]))));
		solver.AddConstraint(solver.MakeEquality(edges[3], solver.MakeAbs(solver.MakeDifference(front[2], front[3]))));

		// Front diagonals
		solver.AddConstraint(solver.MakeEquality(edges[4], solver.MakeAbs(solver.MakeDifference(front[0], front[3]))));
		solver.AddConstraint(solver.MakeEquality(edges[5], solver.MakeAbs(solver.MakeDifference(front[1], front[2]))));

		// Back
		solver.AddConstraint(solver.MakeEquality(edges[6], solver.MakeAbs(solver.MakeDifference(back[0], back[1]))));
		solver.AddConstraint(solver.MakeEquality(edges[7], solver.MakeAbs(solver.MakeDifference(back[0], back[2]))));
		solver.AddConstraint(solver.MakeEquality(edges[8], solver.MakeAbs(solver.MakeDifference(back[1], back[3]))));
		solver.AddConstraint(solver.MakeEquality(edges[9], solver.MakeAbs(solver.MakeDifference(back[2], back[3]))));

		// Back diagonals
		solver.AddConstraint(solver.MakeEquality(edges[10], solver.MakeAbs(solver.MakeDifference(back[0], back[3]))));
		solver.AddConstraint(solver.MakeEquality(edges[11], solver.MakeAbs(solver.MakeDifference(back[1], back[2]))));

		// Connecting edges
		solver.AddConstraint(solver.MakeEquality(edges[12], solver.MakeAbs(solver.MakeDifference(front[0], back[0]))));
		solver.AddConstraint(solver.MakeEquality(edges[13], solver.MakeAbs(solver.MakeDifference(front[1], back[1]))));
		solver.AddConstraint(solver.MakeEquality(edges[14], solver.MakeAbs(solver.MakeDifference(front[2], back[2]))));
		solver.AddConstraint(solver.MakeEquality(edges[15], solver.MakeAbs(solver.MakeDifference(front[3], back[3]))));

		//MakeAbsEquality

		// The labels of all the edges must be different
		solver.AddConstraint(solver.MakeAllDifferent(edges));

		std::vector<IntVar*> allvars;

		allvars.insert(allvars.end(), edges.begin(), edges.end());
		allvars.insert(allvars.end(), allnodes.begin(), allnodes.end());


		// Branching heuristics
		DecisionBuilder* const db1 = solver.MakePhase(allnodes,
			Solver::CHOOSE_MAX_REGRET_ON_MIN,//CHOOSE_MIN_SIZE,
			Solver::ASSIGN_MIN_VALUE);

		// Search!
		solver.Solve(db1);

		int numSolutions = 0;

		// Print
		while (solver.NextSolution()) {
			numSolutions++;
			std::cout << "Solution " << numSolutions << " :";
			printSolutionArray(allnodes);
		}

		const int64 elapsedTime = solver.wall_time();

		std::cout << "Total number of solutions: " << numSolutions << "\n";
		std::cout << "Total elapsed time: " << elapsedTime << " milliseconds.\n";


	} // gracefulGraph

	  // Prints the values of a vector of IntVar between square brakets.
	  // Elements of the vector are separated by white spaces.
	void printSolutionArray(std::vector<IntVar*> arrayOfVars) {
		int i = 0;
		int size = arrayOfVars.size();
		std::cout << "[ ";
		while (i < size) {
			std::cout << arrayOfVars[i]->Value() << " ";
			i++;
		}
		std::cout << "]\n";
	}

} // namespace operations_research

int main(int argc, char** argv) {
	operations_research::gracefulGraph();
	return 0;
} // main