22 int parentId[num_nodes];
23 unsigned short pathLength[num_nodes];
24 bool visited[num_nodes];
26 for (
unsigned short i = 0; i < num_nodes; i++) {
44 unsigned short dest = currentNode->
neighbours[i];
50 }
else if (parentId[dest] == -1) {
55 pathLength[dest] = path;
68 if (pathLength[toNode] > 2) {
70 fromNode = parentId[toNode];
92 double bestEdgesWeight[2];
95 unsigned short num_others = 0;
96 unsigned short toAdd = 0;
98 for (
unsigned short i = 0; i < candidate.
num_neighbours && toAdd<=2; i++) {
108 others[num_others] = dest;
112 if (toAdd > 2 || (toAdd + num_others) < 2) {
114 }
else if (toAdd == 2){
118 }
else if(toAdd == 1){
122 int bestFoundPos = -1;
124 for (
unsigned short j = 0; j < num_others; j++) {
125 unsigned short dest = others[j];
128 if (bestFoundWeight > candidateEdge.
weight) {
130 bestFoundWeight = candidateEdge.
weight;
139 bestEdgesPos[0] = -1;
140 bestEdgesPos[1] = -1;
144 for (
unsigned short j = 0; j < num_others; j++) {
145 unsigned short dest = others[j];
148 if (bestEdgesWeight[0] > candidateEdge.
weight) {
149 bestEdgesPos[1] = bestEdgesPos[0];
150 bestEdgesWeight[1] = bestEdgesWeight[0];
152 bestEdgesWeight[0] = candidateEdge.
weight;
153 }
else if (bestEdgesWeight[1] > candidateEdge.
weight) {
155 bestEdgesWeight[1] = candidateEdge.
weight;
171 for (
short i = 0; i < MAX_VERTEX_NUM; i++) {
172 for (
short j = i; j < MAX_VERTEX_NUM; j++) {
189 for (
short i = 0; i < MAX_VERTEX_NUM && valid; i++) {
191 short num_nothing_node = 0;
192 short num_mandatory_node = 0;
193 short num_forbidden_node = 0;
194 short nothing_nodes[MAX_VERTEX_NUM];
196 for (
short j = 0; j < MAX_VERTEX_NUM; j++) {
198 nothing_nodes[num_nothing_node] = j;
201 num_mandatory_node++;
203 num_forbidden_node++;
207 if (num_mandatory_node == 2) {
208 for (
short j = 0; j < num_nothing_node; j++) {
214 }
else if (num_mandatory_node > 2 || (MAX_VERTEX_NUM - num_forbidden_node < 2)) {
216 }
else if (MAX_VERTEX_NUM - num_forbidden_node == 2) {
218 if (num_nothing_node + num_mandatory_node == 2) {
219 for (
short j = 0; j < num_nothing_node; j++) {
237 for (
short i = 0; i < MAX_VERTEX_NUM; i++) {
239 for (
short j = i; j < MAX_VERTEX_NUM; j++) {
263 double prob_edge = to_branch.
prob;
265 for (
short i = 0; i < 2; i++) {
270 child.
prob = currentSubProblem->
prob;
325 for (
size_t j = 0; j < openSubProblems->
size && position == -1; j++) {
332 if (position == -1) {
343 unsigned short start_node,
unsigned short end_node){
348 bool visited[num_nodes];
349 int parentId[num_nodes];
351 for (
unsigned short i = 0; i < num_nodes; i++) {
362 while (stack->
size > 0 && parentId[end_node] == -1) {
367 for (
unsigned short i = 0; i < currentNode->
num_neighbours; i++) {
368 unsigned short dest = currentNode->
neighbours[i];
380 unsigned short fromNode = -1;
381 unsigned short toNode = end_node;
382 double max_edge_weight = -1;
385 while (fromNode != start_node) {
386 fromNode = parentId[toNode];
388 short position_in_1_tree = -1;
399 if (current_edge_weight > max_edge_weight) {
400 max_edge_weight = current_edge_weight;
403 if (edge_nin_1tree_weight < current_edge_weight + replacement_costs[current_in_path.
positionInGraph]) {
404 replacement_costs[current_in_path.
positionInGraph] = edge_nin_1tree_weight - current_edge_weight;
411 printf(
"ERROR: Edge not found in 1-tree\n");
417 return max_edge_weight == -1 ? -
INFINITE: max_edge_weight;
423 double replacement_costs [MAX_VERTEX_NUM - 2];
424 double best_candidate_replacement =
INFINITE;
426 for (
int i = 0; i < MAX_VERTEX_NUM - 2; i++){
436 double max_edge_path = 0;
447 if (first_candidate_edge_weight > second_candidate_edge_weight){
448 max_edge_path = first_candidate_edge_weight;
450 max_edge_path = second_candidate_edge_weight;
464 if(current_edge.
weight < best_candidate_replacement){
465 best_candidate_replacement = current_edge.
weight;
472 for (
int i = 0; i < MAX_VERTEX_NUM; i++){
509 unsigned short num_edges_inMST = 0;
513 unsigned short src = mandatory_edge.
src;
514 unsigned short dest = mandatory_edge.
dest;
516 if (src != candidateId && dest != candidateId) {
521 merge(set1_root, set2_root);
529 unsigned short num_edges_inG = 0;
531 while (num_edges_inG < graph->num_edges && num_edges_inMST < graph->num_nodes - 2) {
533 Edge current_edge = graph->
edges[num_edges_inG];
535 unsigned short src = current_edge.
src;
536 unsigned short dest = current_edge.
dest;
538 if (src != candidateId && dest != candidateId){
546 merge(set1_root, set2_root);
557 if (num_edges_inMST == graph->
num_nodes - 2) {
567 Graph graph_copy = *graph;
579 for (
unsigned short i = 0; i < graph->
num_nodes; i++){
582 values[i] = start ? FLT_MAX/2 : FLT_MAX;
588 unsigned short src = current_mandatory.
src;
589 unsigned short dest = current_mandatory.
dest;
591 if(src != candidateId && dest != candidateId) {
600 for (
unsigned short i = 0; i < graph_copy.
num_nodes; i++) {
601 if(i != candidateId){
610 fprintf(stderr,
"Error: min_pos == -1\n");
614 in_heap[min_pos] =
false;
617 if(neigh != min_pos && in_heap[neigh]) {
619 if (weight < tree_nodes[neigh].value){
621 fathers[neigh] = min_pos;
630 for(
unsigned short i = 0; i < graph->
num_nodes; i++){
631 if(fathers[i] != -1){
663 double pi[MAX_VERTEX_NUM] = {0};
664 double v[MAX_VERTEX_NUM] = {0};
665 double v_old[MAX_VERTEX_NUM] = {0};
670 double best_lower_bound = 0;
675 bool first_iter =
true;
679 for (
int iter = 1; iter <= max_iter; iter++) {
681 SubProblem analyzedSubProblem = *currentSubProb;
708 analyzedSubProblem.
type = type;
709 analyzedSubProblem.
value = 0;
715 if (iter > max_iter - k) {
718 (double) k) + 1) / ((
double) k);
736 if(analyzedSubProblem.
type !=
OPEN){
738 currentSubProb->
type = analyzedSubProblem.
type;
743 double current_lb = analyzedSubProblem.
oneTree.
cost - (2 * total_pi);
745 if (current_lb > best_lower_bound || first_iter) {
746 best_lower_bound = current_lb;
752 t_0 = best_lower_bound / (2 * MAX_VERTEX_NUM);
764 (((double) (iter - 1)) * (((
double) (2 * max_iter) - 5) / (2 * (double) (max_iter - 1))) * t_0)
765 - (((
double) iter - 2) * t_0) +
766 ((t_0 * ((double) iter - 1) * ((double) iter - 2)) /
767 (2 * ((
double) max_iter - 1) * ((
double) max_iter - 2)));
773 pi[j] += (double) ((0.6 * t * v[j]) + (0.4 * t * v_old[j]));
795 for (
size_t j = 0; j < generatedSubProblems.
size; j++) {
797 if (generatedSubProblem->
value > best_subproblem.
value &&
798 generatedSubProblem->
value <= best_lower_bound) {
799 best_subproblem = *generatedSubProblem;
802 currentSubProb->
type = best_subproblem.
type;
803 currentSubProb->
value = best_subproblem.
value;
809 double best_prob_branch = -1;
810 double best_prob = -1;
819 if ((fabs(prob_branch[i] - 0.5) < fabs(best_prob_branch - 0.5)) ||
820 (HYBRID && (fabs(prob_branch[i] - 0.5) == fabs(best_prob_branch - 0.5))
821 && (current_edge.
prob > best_prob))) {
823 best_prob_branch = prob_branch[i];
824 best_prob = current_edge.
prob;
851 unsigned short current_node = start_node;
852 bool visited[MAX_VERTEX_NUM] = {
false};
859 cycleEdge.
src = current_node;
860 cycleEdge.
dest = start_node;
865 unsigned short best_neighbour = current_node;
876 cycleEdge.
src = current_node;
877 cycleEdge.
dest = best_neighbour;
880 visited[current_node] =
true;
881 current_node = best_neighbour;
895 bool prob_visited[MAX_VERTEX_NUM] = {
false};
896 current_node = start_node;
902 cycleEdge.
src = current_node;
903 cycleEdge.
dest = start_node;
907 double best_edge_prob = -1;
908 unsigned short best_neighbour = current_node;
919 cycleEdge.
src = current_node;
920 cycleEdge.
dest = best_neighbour;
923 prob_visited[current_node] =
true;
924 current_node = best_neighbour;
932 bool better_prob = prob_nn_subProblem.
value < nn_subProblem.
value;
933 SubProblem *best = better_prob ? &prob_nn_subProblem : &nn_subProblem;
963 unsigned short best_candidate = 0;
965 best_subProblem.
value = 0;
966 best_subProblem.
prob = 0;
988 best_subProblem.
value = currentCandidate.
value;
989 best_subProblem.
prob = currentCandidate.
prob;
993 return best_candidate;
999 bool feasible =
true;
1000 for (
short i = 0; feasible && i < graph->
num_nodes; i++) {
1004 printf(
"\nThe graph is not feasible for the BB algorithm. Node %i has less than 2 neighbors.",
1037 subProblem.
prob = 0;
1051 bound(¤t_sub_problem);
1054 branch(&subProblems, ¤t_sub_problem);
1079 type =
"CLOSED_UNFEASIBLE";
1081 type =
"CLOSED_BOUND";
1083 type =
"CLOSED_NEAREST_NEIGHBOR";
1085 type =
"CLOSED_NEAREST_NEIGHBOR_HYBRID";
1087 type =
"CLOSED_SUBGRADIENT";
1089 printf(
"\nSUBPROBLEM with cost = %lf, type = %s, level of the BB tree = %i, prob_tour = %lf, BBNode number = %u and time to obtain = %lfs, edge to branch = %i\n",
1096 unsigned short last_dest = 0;
1099 unsigned short src = edge_cycle.
src;
1100 unsigned short dest = edge_cycle.
dest;
1105 printf(
" %i <-> %i,", src, dest);
1109 printf(
" %i <-> %i,", dest, src);
1113 if(src == last_dest){
1115 printf(
" %i <-> %i", src, dest);
1117 printf(
" %i <-> %i,", src, dest);
1124 printf(
" %i <-> %i", dest, src);
1126 printf(
" %i <-> %i,", dest, src);
1139 printf(
"Optimal tour found with candidate node = %i, elapsed time = %lfs and interrupted = %s\n",
1143 printf(
"\nMST solved with: %s algorithm\n",
PRIM ?
"Prim" :
"Kruskal");
1147 printf(
"\nB-&-B tree with generated BBNodes = %u, explored BBNodes = %u and max tree level = %u\n",
void add_elem_SubProblemList_index(SubProblemsList *list, SubProblem *element, size_t index)
Add a SubProblem at a specific index of a SubProblem List.
SubProblem * get_SubProblemList_elem_index(SubProblemsList *list, size_t index)
Get a SubProblem from a specific index of a SubProblem List.
void delete_SubProblemList_iterator(SubProblemsListIterator *iterator)
Delete a SubProblem List iterator.
void delete_SubProblemList_elem_index(SubProblemsList *list, size_t index)
Remove a SubProblem from a specific index of a SubProblem List.
void add_elem_SubProblemList_bottom(SubProblemsList *list, SubProblem *element)
Add a SubProblem to the bottom of a SubProblem List.
SubProblemsListIterator * create_SubProblemList_iterator(SubProblemsList *list)
Create a new SubProblem List iterator on a SubProblem List.
void new_SubProblemList(SubProblemsList *list)
Create a new SubProblem List.
void delete_SubProblemList(SubProblemsList *list)
Delete a SubProblem List.
SubProblem * SubProblemList_iterator_get_next(SubProblemsListIterator *iterator)
Get the next element of a SubProblem List iterator.
@ FORBIDDEN
The Edge is forbidden.
@ MANDATORY
The Edge is mandatory.
@ NOTHING
The Edge has no constraints.
BBNodeType
The labels used to identify the type of a SubProblem.
@ OPEN
The SubProblem is a feasible 1Tree, with a value lower than the best solution found so far.
@ CLOSED_NN
The SubProblem is a feasible 1Tree founded with the Nearest Neighbor algorithm, it is the first feasi...
@ CLOSED_1TREE
The SubProblem is closed by calculating the 1Tree.
@ CLOSED_NN_HYBRID
The SubProblem is a feasible 1Tree founded with the Hybrid version of Nearest Neighbor algorithm,...
@ CLOSED_BOUND
The SubProblem is a feasible 1Tree, with a value greater than the best solution found so far.
@ CLOSED_UNFEASIBLE
The SubProblem is not a feasible 1Tree, and so discarded.
@ CLOSED_SUBGRADIENT
The SubProblem is closed in the subgradient algorithm, the ascending dual.
void initialize_matrix(SubProblem *subProblem)
BBNodeType mst_to_one_tree(SubProblem *currentSubproblem, Graph *graph)
Transforms a MST into a 1Tree.
bool compare_subproblems(const SubProblem *a, const SubProblem *b)
Compare two OPEN SubProblems.
bool check_feasibility(Graph *graph)
Check if the Graph associated to the Problem is feasible.
void branch_and_bound(Problem *current_problem)
The Branch and Bound algorithm.
void constrained_kruskal(Graph *graph, SubProblem *subProblem, unsigned short candidateId)
void constrained_prim(Graph *graph, SubProblem *subProblem, unsigned short candidateId)
void nearest_prob_neighbour(unsigned short start_node)
This function is used to find the first feasible tour.
void dfs(SubProblem *subProblem)
A Depth First Search algorithm on a Graph.
bool compare_candidate_node(SubProblem *a, SubProblem *b)
void copy_constraints(SubProblem *subProblem, const SubProblem *otherSubProblem)
Copy the matrix of constraints of a SubProblem into another.
void print_subProblem(const SubProblem *subProblem)
Get all metrics of a certain SubProblem.
unsigned short find_candidate_node(void)
Select the candidate Node, i.e. the starting vertex of the tour.
bool check_hamiltonian(SubProblem *subProblem)
Function that checks if the 1Tree of a SubProblem is a tour.
bool infer_constraints(SubProblem *subProblem)
Infer the values of some edge variables of a SubProblem.
void set_problem(Problem *current_problem)
Define the problem to solve.
void bound(SubProblem *currentSubProb)
The Held-Karp bound function with the subgradient algorithm.
bool time_limit_reached(void)
Check if the time limit has been reached.
double max_edge_path_1Tree(SubProblem *currentSubProb, double *replacement_costs, unsigned short start_node, unsigned short end_node)
int variable_fixing(SubProblem *currentSubProb)
The function used to fix the edge variables to be mandatory or forbidden.
void branch(SubProblemsList *openSubProblems, SubProblem *currentSubProblem)
The Shutler's branching rule.
void print_problem(void)
Get all metrics of the problem.
The declaration of all the methods used by the Branch and Bound algorithm.
static Problem * problem
The pointer to the problem to solve.
void create_insert_node(FibonacciHeap *heap, OrdTreeNode *node, unsigned short key, double value)
A wrapper function to create a Node and insert it in the Fibonacci Heap.
int extract_min(FibonacciHeap *heap)
Extract the minimum Node from the Fibonacci Heap.
void create_fibonacci_heap(FibonacciHeap *heap)
Create an empty Fibonacci Heap.
void decrease_value(FibonacciHeap *heap, OrdTreeNode *node, double new_value)
Decrease the value of a Node in the Fibonacci Heap.
void wrap_quick_sort(Graph *graph)
The wrapper of the quick sort algorithm.
void delete_list_elem_index(List *list, size_t index)
Deletes the DllElem at the indicated index of the List.
void add_elem_list_bottom(List *list, void *element)
Adds an DllElem to the bottom of the List.
void add_elem_list_index(List *list, void *element, size_t index)
Adds an DllElem at the index indicated of the List.
void del_list(List *list)
Delete an instance of a List.
List * new_list(void)
Create a new instance of a List.
void * get_list_elem_index(List *list, size_t index)
Retrieves a pointer to an DllElem from the List.
void merge(Set *set1, Set *set2)
Merge two Sets in the Forest if they are not already in the same Set.
Set * find(Set *set)
Find the root of a Set.
void create_forest_constrained(Forest *forest, const Node *nodes, unsigned short num_nodes, unsigned short candidateId)
Create a new Forest with n Sets, each Set containing a Node, with constraints.
void add_edge(MST *tree, const Edge *edge)
Add an Edge to the MST.
void create_mst(MST *mst, const Node *nodes, unsigned short num_nodes)
Create a Minimum Spanning Tree from a set of Nodes.
#define EPSILON
The first constant used to compare two SubProblem in the branch and bound algorithm.
#define NUM_HK_ITERATIONS
The maximum number of dual iterations for nodes of the branch and bound tree that are not the root.
#define GHOSH_UB
The first upper bound for the problem, see: https://www.semanticscholar.org/paper/Expected-Travel-Amo...
#define PRIM
The maximum number of Node in the Graph.
#define PROB_BRANCH
The way with generate the children of a SubProblem.
#define MAX_EDGES_NUM
The maximum number of edges in the Graph.
#define INFINITE
The maximum number to set the initial value of Problem and SubProblem.
#define BETTER_PROB
The third constant used to compare two SubProblem in the branch and bound algorithm.
#define TIME_LIMIT_SECONDS
The maximum time to run the algorithm. Default: 10 minutes.
#define NUM_HK_INITIAL_ITERATIONS
The maximum number of dual iterations for the root of the branch and bound tree.
A reduced form of an Edge in the Graph, with only the source and destination Nodes.
unsigned short src
The source Node of the Edge.
unsigned short dest
The destination Node of the Edge.
unsigned short dest
ID of the destination vertex.
unsigned short src
ID of the source vertex.
double prob
Probability of the Edge to be in an optimal tour.
double weight
Weight of the Edge, 1 if the data_structures is not weighted.
unsigned short positionInGraph
Position of the Edge in the list of Edges of the Graph.
The Fibonacci Heap datastructure as collection of Heap-ordered Trees.
unsigned short num_nodes
The number of Nodes in the Heap.
A Forest is a list of Sets.
Set sets[MAX_VERTEX_NUM]
Array of Sets.
Edge edges_matrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]
Adjacency matrix of the Graph.
unsigned short num_edges
Number of Edges in the Graph.
bool orderedEdges
True if the Edges are ordered by weight, false otherwise.
Edge edges[MAX_EDGES_NUM]
Array of Edges.
Node nodes[MAX_VERTEX_NUM]
Array of Nodes.
unsigned short num_nodes
Number of Nodes in the Graph.
size_t size
The current size of the List.
unsigned short num_nodes
The number of Nodes in the MST.
short edges_matrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]
-1 if there is no Edge between the two Nodes, otherwise the index of the Edge in the MST.
double prob
The probability of the MST, i.e. the average of the probabilities of its Edges.
Edge edges[MAX_VERTEX_NUM]
The set of Edges in the MST, these are |V| because the MST can be a 1-Tree.
Node nodes[MAX_VERTEX_NUM]
The set of Nodes in the MST.
unsigned short num_edges
The number of Edges in the MST.
bool isValid
True if the MST has the correct number of Edges, false otherwise.
double cost
The total cost of the MST, i.e. the sum of the weights of the Edges.
unsigned short num_neighbours
Number of neighbours of the Node.
unsigned short positionInGraph
Position of the Node in the list of Nodes of the Graph, i.e. its unique ID.
unsigned short neighbours[MAX_VERTEX_NUM - 1]
Array of IDs of the Node's neighbors.
A Heap-ordered Tree Node where the key of the parent is <= the key of its children.
The struct used to represent the overall problem.
Graph reformulationGraph
The Graph used to perform the dual reformulation of Edge weights.
bool interrupted
True if the algorithm has been interrupted by timeout.
SubProblem bestSolution
The best solution found so far.
clock_t end
The time when the algorithm ended.
clock_t start
The time when the algorithm started.
Graph graph
The Graph of the problem.
unsigned short candidateNodeId
The id of the candidate node.
unsigned int num_fixed_edges
The number of fixed edges in the Branch and Bound tree.
unsigned int generatedBBNodes
The number of nodes generated in the Branch and Bound tree.
unsigned short totTreeLevels
The total number of levels in the Branch and Bound tree.
double bestValue
The cost of the best solution found so far.
unsigned int exploredBBNodes
The number of nodes explored in the Branch and Bound tree.
A Set is a node in the Forest.
unsigned short num_in_forest
Number of the position of the Set in the Forest.
The struct used to represent a SubProblem or node of the Branch and Bound tree.
ConstraintType constraints[MAX_VERTEX_NUM][MAX_VERTEX_NUM]
The constraints of the edges in the SubProblem.
ConstrainedEdge mandatoryEdges[MAX_VERTEX_NUM]
The mandatory edges in the SubProblem.
float timeToReach
The time needed to reach the SubProblem, in seconds.
ConstrainedEdge cycleEdges[MAX_VERTEX_NUM]
The edges in the cycle of the SubProblem.
unsigned short num_forbidden_edges
The number of forbidden edges in the SubProblem.
double prob
The probability of the SubProblem to be the best tour.
unsigned int id
The id of the SubProblem, an incremental number.
double value
The cost of the SubProblem.
unsigned int fatherId
The id of the father of the SubProblem.
int edge_to_branch
The id of the edge to branch in the SubProblem.
BBNodeType type
The label of the SubProblem.
MST oneTree
The 1Tree of the SubProblem.
unsigned short treeLevel
The level of the SubProblem in the Branch and Bound tree.
unsigned short num_mandatory_edges
The number of mandatory edges in the SubProblem.
unsigned short num_edges_in_cycle
The number of edges in the cycle of the SubProblem.
The iterator of the list of SubProblems.
The list of open SubProblems.
size_t size
The size of the list.