1 /*===========================================================================*/
2 /*                                                                           */
3 /* This file is part of a demonstration application for use with the         */
4 /* SYMPHONY Branch, Cut, and Price Library. This application is a solver for */
5 /* the Vehicle Routing Problem and the Traveling Salesman Problem.           */
6 /*                                                                           */
7 /* (c) Copyright 2000-2007 Ted Ralphs. All Rights Reserved.                  */
8 /*                                                                           */
9 /* This application was developed by Ted Ralphs (ted@lehigh.edu)             */
10 /*                                                                           */
11 /* This software is licensed under the Eclipse Public License. Please see    */
12 /* accompanying file for terms.                                              */
13 /*                                                                           */
14 /*===========================================================================*/
15 
16 #define COMPILING_FOR_LP
17 
18 /* system include files */
19 #include <math.h>
20 #include <memory.h>
21 #include <stdio.h>
22 
23 /* SYMPHONY include files */
24 #include "sym_constants.h"
25 #include "sym_macros.h"
26 #include "sym_qsort.h"
27 #include "sym_lp_u.h"
28 /*__BEGIN_EXPERIMENTAL_SECTION__*/
29 #include "sym_lp.h"
30 /*___END_EXPERIMENTAL_SECTION___*/
31 
32 /* VRP include files */
33 #include "vrp_lp.h"
34 #include "vrp_macros.h"
35 #include "vrp_const.h"
36 #include "sym_timemeas.h"
37 
38 /*===========================================================================*/
39 
40 /*===========================================================================*\
41  * This file contains the user-written functions for the LP process related
42  * to branching.
43 \*===========================================================================*/
44 
45 /*===========================================================================*\
46  * This function determines whether to branch. You can eseentially
47  * leave this up to SYMPHONY unless there is some compelling reason not to.
48 \*===========================================================================*/
49 
user_shall_we_branch(void * user,double lpetol,int cutnum,int slacks_in_matrix_num,cut_data ** slacks_im_matrix,int slack_cut_num,cut_data ** slack_cuts,int varnum,var_desc ** vars,double * x,char * status,int * cand_num,branch_obj *** candidates,int * action)50 int user_shall_we_branch(void *user, double lpetol, int cutnum,
51 			 int slacks_in_matrix_num, cut_data **slacks_im_matrix,
52 			 int slack_cut_num, cut_data **slack_cuts, int varnum,
53 			 var_desc **vars, double *x, char *status,
54 			 int *cand_num, branch_obj ***candidates,
55 			 int *action)
56 {
57 
58    int i;
59    double fracx, lpetol1 = 1 - lpetol;
60 
61    for (i = varnum - 1; i >= 0; i--){
62       if (vars[i]->is_int){
63 	 fracx = x[i] - floor(x[i]);
64 	 if (fracx > lpetol && fracx < lpetol1){
65 	    break;
66 	 }
67       }
68    }
69 
70    if(i >= 0 ){
71       *action = USER__BRANCH_IF_TAILOFF;
72    } else{
73       *action = USER__BRANCH_IF_MUST;
74    }
75 
76 #if 0
77    vrp_lp_problem *vrp = (vrp_lp_problem *) user;
78 
79    if (!vrp->par.detect_tailoff){
80       *action = USER__BRANCH_IF_MUST;
81    }else{
82       *action = USER__BRANCH_IF_TAILOFF;
83    }
84 #endif
85 
86    return(USER_SUCCESS);
87 }
88 
89 /*===========================================================================*/
90 
91 /*===========================================================================*\
92  * Here, we select the branching candidates. This can essentially be
93  * left to SYMPHONY too using one of the built-in functions, but here, I
94  * demonstrate how to branch on cuts, which must be done by the user.
95 \*===========================================================================*/
96 
user_select_candidates(void * user,double lpetol,int cutnum,int slacks_in_matrix_num,cut_data ** slacks_in_matrix,int slack_cut_num,cut_data ** slack_cuts,int varnum,var_desc ** vars,double * x,char * status,int * cand_num,branch_obj *** candidates,int * action,int bc_level)97 int user_select_candidates(void *user, double lpetol, int cutnum,
98 			   int slacks_in_matrix_num,
99 			   cut_data **slacks_in_matrix, int slack_cut_num,
100 			   cut_data **slack_cuts, int varnum, var_desc **vars,
101 			   double *x, char *status, int *cand_num,
102 			   branch_obj ***candidates, int *action,
103 			   int bc_level)
104 
105 {
106    vrp_lp_problem *vrp = (vrp_lp_problem *)user;
107    cut_data *cut;
108    branch_obj **cand_list, *can;
109    int i, candnum, found_violated = FALSE;
110    p_w_l *pwl;
111    double left_hand_side, lpetol1 = 1 - lpetol, lpetol5=.95, slack, fracx;
112    waiting_row **new_rows;
113    int new_row_num;
114    int *userind;
115    int sim_cand_num = 0, sc_cand_num = 0;
116    /* numbers of slacks_in_matrix, slack_cuts and variables, that are used
117       as branching cands */
118 
119    if (!vrp->par.branch_on_cuts && vrp->par.branching_rule == 2)
120       /* use the built-in rule */
121       return(USER_DEFAULT);
122 
123    *cand_num = 0;
124    candnum = 0;
125    /* allocate also memory for the basic vars */
126    *candidates = cand_list = (branch_obj **)
127       malloc((varnum + (vrp->par.branch_on_cuts ?
128 		       (slacks_in_matrix_num + slack_cut_num) : 0)) *
129       sizeof(branch_obj *));
130    switch (vrp->par.branch_on_cuts){
131     case TRUE:
132       pwl = (p_w_l *) malloc((slacks_in_matrix_num + slack_cut_num)*
133 			     sizeof(p_w_l));
134       userind = (int *) malloc(varnum*ISIZE);
135 
136       for (i = varnum - 1; i >= 0; i--)
137 	 userind[i] = vars[i]->userind;
138 
139       /* First go through the slack cuts and enlist the violated ones */
140       for (i = 0; i < slack_cut_num; i++){
141 	 left_hand_side = compute_lhs(varnum, userind, x, cut = slack_cuts[i],
142 				      vrp->vertnum);
143 	 switch (cut->type){
144 	  case SUBTOUR_ELIM_SIDE:
145 	    slack = cut->rhs - left_hand_side;
146 	    if (slack < -lpetol){/*---------------- This cut became violated */
147 	       found_violated = TRUE;
148 	       can = cand_list[candnum++] =
149 		  (branch_obj *) calloc(1, sizeof(branch_obj));
150 	       can->type = VIOLATED_SLACK;
151 	       can->position = i;
152 	    }else if ((!found_violated) && (slack>lpetol) &&
153 		      !(cut->sense == 'R' || cut->sense == 'E')){
154 	       pwl[sc_cand_num].lhs = left_hand_side;
155 	       pwl[sc_cand_num++].position = i;
156 	    }
157 	    break;
158 
159 	  case SUBTOUR_ELIM_ACROSS:
160 	    slack = left_hand_side  - cut->rhs;
161 	    if (slack < -lpetol){/*---------------- This cut became violated */
162 	       found_violated = TRUE;
163 	       can = cand_list[candnum++] =
164 		  (branch_obj *) calloc(1, sizeof(branch_obj));
165 	       can->type = VIOLATED_SLACK;
166 	       can->position = i;
167 	    }else if ((!found_violated) && (slack>lpetol) &&
168 		      !(cut->sense=='R' || cut->sense=='E')){
169 	       pwl[sc_cand_num].lhs = left_hand_side;
170 	       pwl[sc_cand_num++].position = i;
171 	    }
172 	    break;
173 
174 	 default:
175 	    break;
176 	 }
177       }
178       if (found_violated){
179 	 *cand_num = candnum;
180 	 FREE(pwl);
181 	 *action = USER__DO_NOT_BRANCH;
182 	 return(USER_SUCCESS);
183       }
184 
185       /* now go through the slack rows in the matrix and add the potential
186 	 candidates to the end of the pos/weight lists */
187       for (i = 0; i < slacks_in_matrix_num; i++)
188 	 if ((cut = slacks_in_matrix[i]) &&
189 	     (cut->type==SUBTOUR_ELIM_SIDE || cut->type== SUBTOUR_ELIM_ACROSS)
190 	     && !(cut->sense=='R' || cut->sense=='E')){
191 	    left_hand_side = compute_lhs(varnum, userind, x, cut,
192 					 vrp->vertnum);
193 	    switch (cut->type){
194 	     case SUBTOUR_ELIM_SIDE:
195 	       slack = cut->rhs - left_hand_side;
196 	       /* if (slack > lpetol && slack < lpetol1){*/
197 	       if (slack > lpetol ){
198 		  pwl[sc_cand_num+sim_cand_num].lhs = left_hand_side;
199 		  pwl[sc_cand_num+sim_cand_num].position = i;
200 		  sim_cand_num++;
201 	       }
202 	       break;
203 
204 	     case SUBTOUR_ELIM_ACROSS:
205 	       slack = left_hand_side - cut->rhs;
206 	       /* if (slack > lpetol && slack < 2-lpetol){*/
207 	       if (slack > lpetol ){
208 		  pwl[sc_cand_num+sim_cand_num].lhs = left_hand_side;
209 		  pwl[sc_cand_num+sim_cand_num].position = i;
210 		  sim_cand_num++;
211 	       }
212 	       break;
213 
214 	     default:
215 	       break;
216 	    }
217 	 }
218 
219       /* set the children's rhs etc */
220       for (i = 0 ; i < sc_cand_num + sim_cand_num; i++){
221 	 can = cand_list[candnum++] =
222 	    (branch_obj *) calloc(1, sizeof(branch_obj));
223 	 if (i < sc_cand_num ){
224 	    can->type = CANDIDATE_CUT_NOT_IN_MATRIX;
225 	    cut = slack_cuts[can->position = pwl[i].position ];
226 	    user_unpack_cuts(user, CUT_NOT_IN_MATRIX_SLACK,
227 			     UNPACK_CUTS_SINGLE, varnum, vars, 1,
228 			     slack_cuts+can->position, &new_row_num,
229 			     &new_rows);
230 	    can->row = *new_rows;
231 	    cut = can->row->cut;
232 	    FREE(new_rows);
233 	 }else{
234 	    can->type = CANDIDATE_CUT_IN_MATRIX;
235 	    cut = slacks_in_matrix[can->position = pwl[i].position  ];
236 	 }
237 	 can->child_num = 2;
238 	 can->lhs = pwl[i].lhs;
239 	 /* no need to allocate these. they are of fixed length
240 	    can->sense = (char *) malloc(2 * CSIZE);
241 	    can->rhs = (double *) malloc(2 * DSIZE);
242 	    can->range = (double *) malloc(2 * DSIZE);
243 	    */
244 	 switch (cut->type){
245 	  case SUBTOUR_ELIM_SIDE:
246 	    if ((slack = cut->rhs - can->lhs) < lpetol1){
247 	       can->sense[0] = 'E';
248 	       can->rhs[0] = cut->rhs;
249 	       can->range[0] = 0;
250 	       can->branch[0] = DO_NOT_BRANCH_ON_THIS_ROW;
251 	       can->sense[1] = 'L';
252 	       can->rhs[1] = cut->rhs - 1;
253 	       can->range[1] = 0;
254 	       can->branch[1] = ALLOWED_TO_BRANCH_ON;
255 	    }else{
256 	       can->sense[0] = 'R';
257 	       can->rhs[0] = cut->rhs;
258 	       can->range[0] = -floor(slack) ;
259 	       can->branch[0] = DO_NOT_BRANCH_ON_THIS_ROW;
260 	       can->sense[1] = 'L';
261 	       can->rhs[1] = cut->rhs - ceil(slack);
262 	       can->range[1] = 0;
263 	       can->branch[1] = ALLOWED_TO_BRANCH_ON;
264 	    }
265 	    break;
266 	  case SUBTOUR_ELIM_ACROSS:
267 	    if ((slack = can->lhs - cut->rhs) < 2-lpetol){
268 	       can->sense[0] = 'E';
269 	       can->rhs[0] = cut->rhs;
270 	       can->range[0] = 0;
271 	       can->branch[0] = DO_NOT_BRANCH_ON_THIS_ROW;
272 	       can->sense[1] = 'G';
273 	       can->rhs[1] = cut->rhs + 2;
274 	       can->range[1] = 0;
275 	       can->branch[1] = ALLOWED_TO_BRANCH_ON;
276 	    }else{
277 	       can->sense[0] = 'R';
278 	       can->rhs[0] = cut->rhs;
279 	       can->range[0] = 2*floor(slack/2);
280 	       can->branch[0] = DO_NOT_BRANCH_ON_THIS_ROW;
281 	       can->sense[1] = 'G';
282 	       can->rhs[1] = cut->rhs + 2*floor(slack/2) +2;
283 	       can->range[1] = 0;
284 	       can->branch[1] = ALLOWED_TO_BRANCH_ON;
285 	    }
286 	    break;
287 	 /*__BEGIN_EXPERIMENTAL_SECTION__*/
288 	 case FARKAS:
289 	    break;
290 	 case NO_COLUMNS:
291 	    break;
292 	 /*___END_EXPERIMENTAL_SECTION___*/
293 	 }
294       }
295       FREE(pwl);
296       FREE(userind);
297       *cand_num = candnum;
298       cand_list = *candidates + *cand_num;
299 
300     case FALSE:
301 
302       switch (((vrp_lp_problem *)user)->par.branching_rule){
303        case 0:
304 	 {
305 	    int *xind = (int *) malloc(varnum*ISIZE);
306 	    double *xval = (double *) malloc(varnum*DSIZE);
307 	    int cnt = 0;
308 
309 	    for (i = varnum-1; i >= 0; i--){
310 	       fracx = x[i] - floor(x[i]);
311 	       if (fracx > lpetol && fracx < 1-lpetol){
312 		  xind[cnt] = i;
313 		  xval[cnt++] = fabs(fracx - .5);
314 	       }
315 	    }
316 	    qsort_di(xval, xind, cnt);
317 
318 	    candnum = vrp->par.strong_branching_cand_num_max -
319 	       vrp->par.strong_branching_red_ratio * bc_level;
320 	    candnum = MAX(candnum, vrp->par.strong_branching_cand_num_min);
321 	    candnum = MIN(candnum, cnt);
322 
323 	    for (i = candnum-1; i >= 0; i--){
324 	       can=cand_list[i]=(branch_obj *) calloc(1, sizeof(branch_obj));
325 	       can->type = CANDIDATE_VARIABLE;
326 	       can->child_num = 2;
327 	       can->position = xind[i];
328 	       can->sense[0] = 'L';
329 	       can->sense[1] = 'G';
330 	       can->rhs[0] = floor(x[xind[i]]);
331 	       can->rhs[1] = can->rhs[0] + 1;
332 	       can->range[0] = can->range[1] = 0;
333 	    }
334 	    FREE(xind);
335 	    FREE(xval);
336 	 }
337        break;
338 
339        case 1:
340 	 candnum = 0;
341 	 for (i = varnum-1; i >= 0; i--){
342 	    fracx = x[i] - floor(x[i]);
343 	    if (fracx > lpetol && fracx < lpetol5){
344 	       can = cand_list[candnum++] =
345 		  (branch_obj *) calloc(1, sizeof(branch_obj));
346 	       can->type = CANDIDATE_VARIABLE;
347 	       can->child_num = 2;
348 	       can->position = i;
349 	       can->sense[0] = 'L';
350 	       can->sense[1] = 'G';
351 	       can->rhs[0] = floor(x[i]);
352 	       can->rhs[1] = can->rhs[0] + 1;
353 	       can->range[0] = can->range[1] = 0;
354 	    }
355 	 }
356 	 break;
357 
358        case 2:
359 	 return(USER__CLOSE_TO_HALF);
360       }
361       *cand_num += candnum;
362       *action = USER__DO_BRANCH;
363    }
364    return(USER_SUCCESS);
365 }
366 
367 /*===========================================================================*/
368 
compute_lhs(int number,int * indices,double * values,cut_data * cut,int vertnum)369 double compute_lhs(int number, int *indices, double *values, cut_data *cut,
370 		   int vertnum)
371 {
372    char *coef;
373    int v0, v1;
374    double lhs = 0;
375    int i;
376    /*__BEGIN_EXPERIMENTAL_SECTION__*/
377    int num_arcs, edge_index ;
378    char *cpt;
379    int *arcs ;
380    char *indicators;
381    double bigM, *weights ;
382    int jj;
383    /*___END_EXPERIMENTAL_SECTION___*/
384 
385    switch (cut->type){
386 
387     case SUBTOUR_ELIM_SIDE:
388       coef = (char *)(cut->coef);
389       for (i = 0, lhs = 0; i<number; i++){
390 	 BOTH_ENDS(indices[i], &v1, &v0);
391 	 if (coef[v0 >> DELETE_POWER] & (1 << (v0 & DELETE_AND)) &&
392 	     (coef[v1 >> DELETE_POWER]) & (1 << (v1 & DELETE_AND)))
393 	    lhs += values[i];
394 
395       }
396       return(lhs);
397 
398     case SUBTOUR_ELIM_ACROSS:
399       coef = (char *)(cut->coef);
400       for (lhs = 0, i = 0; i<number; i++){
401 	 BOTH_ENDS(indices[i], &v1, &v0);
402 	 if ((coef[v0 >> DELETE_POWER] >> (v0 & DELETE_AND) & 1) ^
403 	     (coef[v1 >> DELETE_POWER] >> (v1 & DELETE_AND) & 1))
404 	    lhs += values[i];
405       }
406 
407       return(lhs);
408     /*__BEGIN_EXPERIMENTAL_SECTION__*/
409 
410     case FARKAS:
411       coef = (char *)(cut->coef);
412       arcs = (int *) calloc( ((vertnum*vertnum)/2), sizeof(int));
413       weights = (double *) calloc( ((vertnum*vertnum)/2), sizeof(double)) ;
414 
415       cpt=coef+ ((vertnum >> DELETE_POWER) + 1);
416       memcpy((char *)&num_arcs, cpt, ISIZE);
417       memcpy((char *)arcs, cpt, ISIZE*(num_arcs +1));
418       arcs++;
419       cpt+=(ISIZE*(num_arcs +1))/CSIZE;
420       memcpy((char *)weights, cpt, DSIZE*(num_arcs +1));
421       bigM=(*(double *)weights);
422       weights++;
423 
424       for (i = 0, lhs=0 ; i<number; i++){
425 	 BOTH_ENDS(indices[i], &v1, &v0);
426 	 edge_index=indices[i];
427 
428 	 if (isset(coef, v1) || isset(coef,v0)){
429 	    for (jj=0; jj<num_arcs; jj++){
430 	       if ( arcs[jj]==edge_index){
431 		       lhs+=weights[jj]*values[i];
432 		       break;
433 	       }
434 	    }
435 	    if (jj==num_arcs) lhs+=bigM*values[i];
436 
437 	 }
438       }
439       arcs--;
440       weights--;
441       FREE(arcs);
442       FREE(weights);
443       return(lhs);
444 
445 
446     case NO_COLUMNS:
447       coef = (char *)(cut->coef);
448       arcs = (int *) malloc( ((vertnum*vertnum)/2)* sizeof(int));
449       indicators = (char *) malloc( ((vertnum*vertnum)/2)* sizeof(char));
450 
451       cpt=coef+ ((vertnum >> DELETE_POWER) + 1);
452       memcpy((char *)&num_arcs, cpt, ISIZE);
453       cpt+= ISIZE /CSIZE;
454       memcpy((char *)arcs, cpt, ISIZE*(num_arcs));
455       cpt+=(ISIZE*(num_arcs ))/CSIZE;
456       memcpy((char *)indicators, cpt, CSIZE*(num_arcs));
457 
458       for (i = 0, lhs=0 ; i<number; i++){
459 	 BOTH_ENDS(indices[i], &v1, &v0);
460 	 edge_index=indices[i];
461 
462 	 if (isset(coef, v1) || isset(coef,v0)){
463 	    for (jj=0; jj<num_arcs; jj++){
464 	       if ( arcs[jj]==edge_index){
465 		  lhs+=values[i]* ( indicators[jj] ? 1.0:0.0);
466 		  break;
467 	       }
468 	    }
469 	    if (jj==num_arcs) lhs-=values[i];
470 	 }
471       }
472       FREE(arcs);
473       FREE(indicators);
474       return(lhs);
475     /*___END_EXPERIMENTAL_SECTION___*/
476 
477     default:
478       printf("Cut type's not recognized! \n\n");
479       return(0);
480    }
481 }
482 
483 /*__BEGIN_EXPERIMENTAL_SECTION__*/
484 #if 0
485 /*===========================================================================*/
486 
487 int user_select_candidates(lp_prob *p, void *user, double lpetol, int cutnum,
488 			   int slacks_in_matrix_num,
489 			   cut_data **slacks_im_matrix, int slack_cut_num,
490 			   cut_data **slack_cuts, int varnum, var_desc **vars,
491 			   double *x, char *status, int *cand_num,
492 			   branch_obj ***candidates, int *action)
493 
494 {
495    return(USER__CLOSE_TO_HALF);
496 }
497 
498 /*===========================================================================*/
499 
500 int user_select_candidates(lp_prob *p, void *user, double lpetol, int cutnum,
501 			   int slacks_in_matrix_num,
502 			   cut_data **slacks_im_matrix, int slack_cut_num,
503 			   cut_data **slack_cuts, int varnum, var_desc **vars,
504 			   double *x, char *status, int *cand_num,
505 			   branch_obj ***candidates, int *action)
506 
507 {
508    vrp_lp_problem *vrp = (vrp_lp_problem *)user;
509    int i;
510    int *sorted_cand_list, j = 0, k = 0;
511    double *sorted_diffs;
512    int cand_num = vrp->par.max_branch_cand;
513    int branch_rule = vrp->par.branching_rule;
514    branch_obj **candidates, *cand;
515 
516    candidates =
517       *candidates = (branch_obj **) malloc(cand_num * sizeof(branch_obj *));
518 
519    sorted_cand_list = (int *) calloc (varnum, sizeof(int));
520    sorted_diffs     = (double *) calloc (varnum, sizeof(double));
521    for (i = 0; i < varnum; i++){
522       sorted_cand_list[i] = i;
523       sorted_diffs[i] = fabs(x[i] - .5);
524    }
525 
526    cand_sort(sorted_cand_list, sorted_diffs, varnum);
527 
528    switch(vrp->par.branching_rule){ /* which branching rule to use */
529 
530    case DEPOTS_AT_HALF_BRANCH_RIGHT:
531    case DEPOTS_AT_HALF:
532    case VARS_AT_HALF_PREFER_DEPOT_BRANCH_RIGHT:
533    case VARS_AT_HALF_PREFER_DEPOT:
534 
535       for (i=0, j=0; sorted_diffs[i]<lpetol && i<varnum && j<cand_num; i++){
536 	 /* Here we find the depot edges that are at a half*/
537 	 if (vrp->edges[(vars[sorted_cand_list[i]]->userind) << 1] == 0){
538 	    /* This userind serves the purpose of checking whether the
539 	       variable corresponds to an edge connected to the depot */
540 	    cand = candidates[i] = (branch_obj *)calloc(1, sizeof(branch_obj));
541 	    cand->position = sorted_cand_list[i];
542 	    cand->type = CANDIDATE_VARIABLE;
543 	    cand->child_num = 2;
544 	    cand->sense[0] = 'L';
545 	    cand->sense[1] = 'G';
546 	    cand->rhs[0] = 0;
547 	    cand->rhs[1] = 1;
548 	    cand->range[0] = cand->range[1] = 0;
549 	 }
550       }
551       if (j && (branch_rule == DEPOTS_AT_HALF_BRANCH_RIGHT ||
552 		branch_rule == DEPOTS_AT_HALF)){
553 	 *cand_num = j;
554 	 break;
555       }
556       for (k = 0; k < i && j < cand_num; k++){
557 	 if (vrp->edges[(vars[sorted_cand_list[k]]->userind) << 1] != 0)
558 	    cand = candidates[j++] = (branch_obj *)
559 	                               calloc(1, sizeof(branch_obj));
560 	    cand->position = sorted_cand_list[i];
561 	    cand->type = CANDIDATE_VARIABLE;
562 	    cand->child_num = 2;
563 	    cand->sense[0] = 'L';
564 	    cand->sense[1] = 'G';
565 	    cand->rhs[0] = 0;
566 	    cand->rhs[1] = 1;
567 	    cand->range[0] = cand->range[1] = 0;
568       }
569       if (j){
570 	 *cand_num = j;
571 	 break;
572       }
573       /*otherwise, fall through*/
574 
575     case DEPOTS_CLOSEST_TO_HALF:
576     case DEPOTS_CLOSEST_TO_HALF_BRANCH_RIGHT:
577     case VARS_CLOSEST_TO_HALF_PREFER_DEPOT:
578     case VARS_CLOSEST_TO_HALF_PREFER_DEPOT_BRANCH_RIGHT:
579 
580       for (i = 0, j = 0;
581 	   i < varnum && sorted_diffs[i]<.5-lpetol && j < cand_num; i++){
582 	 if (vrp->edges[(vars[sorted_cand_list[i]]->userind) << 1] == 0){
583 	    cand = candidates[j++] = (branch_obj *)
584 	       calloc(1, sizeof(branch_obj));
585 	    cand->position = sorted_cand_list[i];
586 	    cand->type = CANDIDATE_VARIABLE;
587 	    cand->child_num = 2;
588 	    cand->sense[0] = 'L';
589 	    cand->sense[1] = 'G';
590 	    cand->rhs[0] = 0;
591 	    cand->rhs[1] = 1;
592 	    cand->range[0] = cand->range[1] = 0;
593 	 }
594       }
595       if (j && (branch_rule == DEPOTS_CLOSEST_TO_HALF ||
596 		branch_rule == DEPOTS_CLOSEST_TO_HALF_BRANCH_RIGHT)){
597 	 *cand_num = j;
598 	 break;
599       }
600       for (k = 0; k < i && j < cand_num; k++){
601 	 cand = candidates[j++] = (branch_obj *)calloc(1, sizeof(branch_obj));
602 	 cand->position = sorted_cand_list[i];
603 	 cand->type = CANDIDATE_VARIABLE;
604 	 cand->child_num = 2;
605 	 cand->sense[0] = 'L';
606 	 cand->sense[1] = 'G';
607 	 cand->rhs[0] = 0;
608 	 cand->rhs[1] = 1;
609 	 cand->range[0] = cand->range[1] = 0;
610       }
611 
612       if (j){
613 	 *cand_num = j;
614 	 break;
615       }
616       /*otherwise, fall through*/
617 
618     case VARS_CLOSEST_TO_HALF:
619 
620       for (i = 0, j = 0;
621 	   sorted_diffs[i]<.5-lpetol && i < varnum && j < cand_num; i++){
622 	 cand = candidates[j++] = (branch_obj *)calloc(1, sizeof(branch_obj));
623 	 cand->position = sorted_cand_list[i];
624 	 cand->type = CANDIDATE_VARIABLE;
625 	 cand->child_num = 2;
626 	 cand->sense[0] = 'L';
627 	 cand->sense[1] = 'G';
628 	 cand->rhs[0] = 0;
629 	 cand->rhs[1] = 1;
630 	 cand->range[0] = cand->range[1] = 0;
631       }
632       if (j){
633 	 *cand_num = j;
634 	 break;
635       }
636       /*otherwise, fall through*/
637 
638     case BEST_K:
639 #if 0
640       for (i = 0, j = 0; i < varnum && j < cand_num; i++){
641 	 if (p->lp_data->fixed[sorted_cand_list[i]] == NOT_FIXED){
642 	    cand = candidates[j++] = (branch_obj *)
643 	                                 calloc(1, sizeof(branch_obj));
644 	    cand->position = sorted_cand_list[i];
645 	    cand->type = CANDIDATE_VARIABLE;
646 	    cand->child_num = 2;
647 	    cand->sense[0] = 'L';
648 	    cand->sense[1] = 'G';
649 	    cand->rhs[0] = 0;
650 	    cand->rhs[1] = 1;
651 	    cand->range[0] = cand->range[1] = 0;
652 	 }
653       }
654 
655       *cand_num = j;
656       break;
657 #endif
658       *cand_num = 0;
659       break;
660 
661     case VARS_AT_HALF:
662 
663       for (j = 0; sorted_diffs[j] < lpetol && j < cand_num; j++){
664 	 cand = candidates[j++] = (branch_obj *)calloc(1, sizeof(branch_obj));
665 	 cand->position = sorted_cand_list[i];
666 	 cand->type = CANDIDATE_VARIABLE;
667 	 cand->child_num = 2;
668 	 cand->sense[0] = 'L';
669 	 cand->sense[1] = 'G';
670 	 cand->rhs[0] = 0;
671 	 cand->rhs[1] = 1;
672 	 cand->range[0] = cand->range[1] = 0;
673       }
674 
675       *cand_num = j;
676       break;
677 
678     default:
679       FREE(sorted_cand_list);
680       FREE(sorted_diffs);
681       return(DEFAULT);
682    }
683    FREE(sorted_cand_list);
684    FREE(sorted_diffs);
685 
686    return(USER_SUCCESS);
687 }
688 #endif
689 
690 /*___END_EXPERIMENTAL_SECTION___*/
691 /*===========================================================================*/
692 
693 /*===========================================================================*\
694  * I wrote my own function to compare candidates. Maybe this should go
695  * into SYMPHONY.
696 \*===========================================================================*/
697 
user_compare_candidates(void * user,branch_obj * can1,branch_obj * can2,double ub,double granularity,int * which_is_better)698 int user_compare_candidates(void *user, branch_obj *can1, branch_obj *can2,
699 			    double ub, double granularity,
700 			    int *which_is_better)
701 {
702    int i, j;
703    double low1, low2;
704 
705    for (i = 1; i >= 0; i--)
706       if (can1->termcode[i]==LP_OPT_FEASIBLE || can1->termcode[i]==LP_D_OBJLIM ||
707 	  can1->termcode[i]==LP_D_UNBOUNDED || can1->objval[i] > ub -
708 	  granularity)
709 	 break;
710 
711    for (j = 1; j >= 0; j--)
712       if (can2->termcode[j]==LP_OPT_FEASIBLE || can2->termcode[j]==LP_D_OBJLIM ||
713 	  can2->termcode[j] == LP_D_UNBOUNDED || can2->objval[j] > ub -
714 	  granularity)
715 	 break;
716 
717    if (i < 0 && j < 0)
718       return(USER_DEFAULT);
719 
720    if (i < 0 && j > 0){
721       *which_is_better = SECOND_CANDIDATE_BETTER;
722       return(USER_SUCCESS);
723    }
724 
725    if (i > 0 && j < 0){
726       *which_is_better = FIRST_CANDIDATE_BETTER;
727       return(USER_SUCCESS);
728    }
729 
730    low1 = i ? can1->objval[0] : can1->objval[1];
731    low2 = j ? can2->objval[0] : can2->objval[1];
732 
733    *which_is_better = low1 > low2 ? FIRST_CANDIDATE_BETTER :
734                                     SECOND_CANDIDATE_BETTER;
735 
736    return(USER_SUCCESS);
737 }
738 
739 /*===========================================================================*/
740 
741 /*===========================================================================*\
742  * You can let SYMPHONY choose which child to retain. The default is
743  * to keep the one with the lower objective function value.
744 \*===========================================================================*/
745 
user_select_child(void * user,double ub,branch_obj * can,char * action)746 int user_select_child(void *user, double ub, branch_obj *can, char *action)
747 {
748    return(USER_DEFAULT);
749 }
750 
751 /*===========================================================================*/
752 
753 /*===========================================================================*\
754  * Here, you can print out a more identifiable description of the
755  * branching object than just "variable 51". I print out the end points
756  * of the edge if an edge is branched on.
757 \*===========================================================================*/
758 
user_print_branch_stat(void * user,branch_obj * can,cut_data * cut,int n,var_desc ** vars,char * action)759 int user_print_branch_stat(void *user, branch_obj *can, cut_data *cut,
760 			   int n, var_desc **vars, char *action)
761 {
762    int v0, v1, i;
763    char *coef;
764 
765    if (cut){
766       switch(cut->type){
767        case SUBTOUR_ELIM_SIDE:
768 	 coef = (char *)(cut->coef);
769 	 for (i = 0; i < n; i++){
770 	    BOTH_ENDS(vars[i]->userind, &v1, &v0);
771 	    if (coef[v0 >> DELETE_POWER] & (1 << (v0 & DELETE_AND)) &&
772 		(coef[v1 >> DELETE_POWER]) & (1 << (v1 & DELETE_AND)))
773 	       printf("Edge (%i, %i)\n", v0, v1);
774 	 }
775 
776        case SUBTOUR_ELIM_ACROSS:
777          coef = (char *)(cut->coef);
778 	 for (i = 0; i < n; i++){
779 	    BOTH_ENDS(vars[i]->userind, &v1, &v0);
780 	    if ((coef[v0 >> DELETE_POWER] >> (v0 & DELETE_AND) & 1) ^
781 		(coef[v1 >> DELETE_POWER] >> (v1 & DELETE_AND) & 1))
782 	       printf("Edge (%i, %i)\n", v0, v1);
783 	 }
784       }
785    }else{
786       BOTH_ENDS(vars[can->position]->userind, &v1, &v0);
787       printf("Edge (%i, %i)\n", v0, v1);
788    }
789 
790    return(USER_SUCCESS);
791 }
792