int main(int argc, char *argv[]) { /// /// This is the main() routine that demonstrates how to import solutions and /// plot them. /// VRPH_version(); char in[VRPH_STRING_SIZE], plotfile[VRPH_STRING_SIZE],pdffile[VRPH_STRING_SIZE], solfile[VRPH_STRING_SIZE]; int i,n; int orientation=1; bool do_pdf=false; // Usage: vrp_plotter -f <vrp_file> -s <sol_file> -p <plot_file> if(argc<7 ) { fprintf(stderr,"Usage: %s -f <vrp_file> -s <sol_file> -p <plot_file> [-e -w -r]\n",argv[0]); fprintf(stderr,"\t <plot_file> must be .ps format\n"); fprintf(stderr,"\t .pdf format requires the epstopdf executable\n"); fprintf(stderr,"\t -pdf <pdf_file> will also create a .pdf image of the solution\n"); fprintf(stderr,"\t -e will not show the depot edges\n"); fprintf(stderr,"\t -w will weight the size of the non-depot nodes by their demand\n"); fprintf(stderr,"\t -o will rotate 90 degrees\n"); exit(-1); } int options=VRPH_DEFAULT_PLOT; bool has_filename=false; for(i=1;i<argc;i++) { if(strcmp(argv[i],"-f")==0) { // Get the input file name has_filename=true; strcpy(in,argv[i+1]); } if(strcmp(argv[i],"-s")==0) { // Get the solution file name strcpy(solfile,argv[i+1]); } if(strcmp(argv[i],"-p")==0) { // Get the plot file name strcpy(plotfile,argv[i+1]); } if(strcmp(argv[i],"-pdf")==0) { do_pdf=true; strncpy(pdffile,argv[i+1],strlen(argv[i+1])); pdffile[strlen(argv[i+1])]='\0'; } if(strcmp(argv[i],"-e")==0) options+=VRPH_NO_DEPOT_EDGES; if(strcmp(argv[i],"-w")==0) options+=VRPH_WEIGHTED; if(strcmp(argv[i],"-r")==0) { // Get the plot file name orientation=0; } } if(!has_filename) report_error("No file name given!\n"); n=VRPGetDimension(in); VRP V(n); // Load the problem data V.read_TSPLIB_file(in); printf("Imported instance\n"); V.read_solution_file(solfile); int *sol; sol=new int[V.get_num_nodes()+2]; V.export_canonical_solution_buff(sol); V.import_solution_buff(sol); printf("Imported solution\n"); // Show the solution to stdout V.summary(); printf("Plotfile is %s\n",plotfile); V.plot(plotfile,options,orientation); if(do_pdf) { // Create a .pdf file char command[VRPH_STRING_SIZE]; sprintf(command,"%s %s --outfile=%s\n",VRPH_EPS_EXE,plotfile,pdffile); system(command); } delete [] sol; return 0; }
int main(int argc, char **argv) { #if USE_VRPH // A few things required by VRPH int i; double best_sol=VRP_INFINITY; int best_sol_buff[500]; #endif vrp_problem *vrp; sym_environment *env = sym_open_environment(); version(); sym_parse_command_line(env, argc, argv); sym_get_user_data(env, (void**)&vrp); #if USE_VRPH // Get the size of the problem in the input file int n=VRPGetDimension(vrp->par.infile); // Declare a VRP object of size n VRP V(n); // Declare a ClarkeWright object of size n ClarkeWright CW(n); // Populate the VRP object with the input file V.read_TSPLIB_file(vrp->par.infile); // Now create NUM_VRPH_SOLUTIONS solutions using VRPH and set the // upper bound to the best solution discovered for(i=0;i<NUM_VRPH_SOLUTIONS;i++) { // Create default routes - each customer on its own route V.create_default_routes(); // Create a new random feasible solution with Clarke Wright CW.Construct(&V, .5+ lcgrand(1),false); // Improve it with the RTR heuristic V.RTR_solve(ONE_POINT_MOVE+TWO_POINT_MOVE+TWO_OPT+THREE_OPT, 30,5,1,.01,25,VRPH_LI_PERTURB,VRPH_BEST_ACCEPT,false); if(V.get_total_route_length()-V.get_total_service_time()<best_sol) { best_sol=V.get_total_route_length()-V.get_total_service_time(); V.export_canonical_solution_buff(best_sol_buff); } // Reset VRPH's internal data structures V.reset(); } // Import the best solution and display it - if SYMPHONY claims an infeasibility // because the VRPH solution is optimal, we wouldn't see it otherwise! printf("VRPH set SYMPHONY upper bound to %f based on solution:\n",best_sol); V.import_solution_buff(best_sol_buff); V.summary(); // Set the upper bound using VRPH solution by accessing SYMPHONY's // internal data structures env->has_ub=1; env->ub=best_sol ; #if 0 // Note that this might be incorrect if the VRPH solution is not optimal // So the # of trucks still needs to be passed in on the command line! vrp->numroutes=V.get_total_number_of_routes(); #endif #endif // Now just let SYMPHONY do its thing. If an infeasibility is encountered, // then this certifies that the solution found by VRPH is indeed optimal // Note that the par.test will not work as we have processed only a single // file. Thus, we changed the following line // if (vrp->par.test){ if (0 && vrp->par.test){ vrp_test(env, argc, argv); } else { sym_load_problem(env); sym_find_initial_bounds(env); sym_set_str_param(env, "lp_executable_name", "vrp_lp_cg"); sym_set_str_param(env, "cp_executable_name", "vrp_cp"); sym_set_int_param(env, "generate_cgl_cuts", FALSE); sym_solve(env); } sym_close_environment(env); return(0); }
int main(int argc, char **argv) { VRPH_version(); int i, j, k, n, status, num_attempts, *sol_buff, *IP_sol_buff; char in_file[200]; double lambda, best_heur_sol=VRP_INFINITY; bool first_sol=false, bootstrap=false;; VRPSolution *fresh_solution; OsiSolverInterface *si; const double *x; int last_num_cols=0, route_id=0; time_t start, stop; int *orderings[MAX_ROUTES]; for(i=0;i<MAX_ROUTES;i++) orderings[i]=NULL; // Set timing counters to 0 heur_time=mip_time=0; // Check arguments if(argc<5) { fprintf(stderr,"Usage: %s -f input_file -n num_runs [-v,-b,-c max_columns -d cols_to_delete]\n", argv[0]); fprintf(stderr,"\t Will solve the problem num_solutions times and add the routes\n"); fprintf(stderr,"\t to a set partitioning problem.\n"); fprintf(stderr,"\t Other options:\n"); fprintf(stderr,"\t -v runs in verbose mode\n"); fprintf(stderr,"\t -b will use bootstrapping where we send the set partitioning\n" "\t solution back to the metaheuristic solver\n"); fprintf(stderr,"\t -c max_columns will allow this many active columns/variables in the IP.\n"); fprintf(stderr,"\t Default value is max_columns=500\n"); fprintf(stderr,"\t -d num_cols_to_delete will delete this many columns once we have too many\n"); fprintf(stderr,"\t in the IP. Default value is num_cols_to_delete=100\n"); exit(-1); } // Set defaults verbose=false; max_columns=500; num_cols_to_delete=100; // Parse command line for(i=0;i<argc;i++) { if(strcmp(argv[i],"-f")==0) strcpy(in_file,argv[i+1]); if(strcmp(argv[i],"-n")==0) num_attempts=atoi(argv[i+1]); if(strcmp(argv[i],"-v")==0) verbose=true; if(strcmp(argv[i],"-b")==0) bootstrap=true; if(strcmp(argv[i],"-c")==0) max_columns=atoi(argv[i+1]); if(strcmp(argv[i],"-d")==0) num_cols_to_delete=atoi(argv[i+1]); } // This is the # of non-VRPH_DEPOT nodes n=VRPGetDimension(in_file); // This will be used to import/export solutions fresh_solution = new VRPSolution(n); // Create buffers for importing solutions sol_buff= new int[n+2]; IP_sol_buff = new int[n+2]; // Declare an OSI interface si=new OsiGlpkSolverInterface; si->setIntParam(OsiNameDiscipline,2); for(i=0;i<n;i++) { si->addRow(0,NULL,NULL,1,1); } // Declare a VRP of the right size and import the file VRP V(n); ClarkeWright CW(n); VRPRoute route(n); V.read_TSPLIB_file(in_file); // Set up a "route warehouse" to store the routes to be added to the IP V.route_wh=new VRPRouteWarehouse(HASH_TABLE_SIZE); // Set up a minimization problem si->setObjSense(1); // Set to error only output si->setHintParam(OsiDoReducePrint,true, OsiHintDo); // Unfortunately GLPK still prints out something regarding the conflict graph for(i=0;i<num_attempts;i++) { if(i==0 || !bootstrap) { lambda=.5+1.5*lcgrand(0); // Start with a clean VRP object V.reset(); CW.Construct(&V, lambda, false); if(verbose) printf("CW solution %d[%5.3f]: %f\n",i,lambda,V.get_total_route_length()-V.get_total_service_time()); } else // Use the solution from the IP V.import_solution_buff(IP_sol_buff); // Run VRPH's RTR algorithm to improve the solution start=clock(); V.RTR_solve(ONE_POINT_MOVE | TWO_POINT_MOVE | TWO_OPT | VRPH_USE_NEIGHBOR_LIST, 30, 5, 2, .01, 30, VRPH_LI_PERTURB, VRPH_FIRST_ACCEPT,false); stop=clock(); heur_time += (stop-start); if(verbose) printf("RTR Metaheuristic found solution %5.3f\n",V.get_total_route_length()-V.get_total_service_time()); // The RTR algorithm keeps a "warehouse" of the best solutions discovered during // the algorithm's search // Now go through the solutions in the solution warehouse and add the new routes // discovered to the IP for(j=0;j<V.solution_wh->num_sols;j++) { // Import solution j from the warehouse V.import_solution_buff(V.solution_wh->sols[j].sol); if(V.get_total_route_length()-V.get_total_service_time() < best_heur_sol) best_heur_sol = V.get_total_route_length()-V.get_total_service_time() ; // Now add the routes from this solution to the IP for(k=1;k<=V.get_total_number_of_routes();k++) { // Clean up the route by running INTRA_ROUTE optimizations only // using the route_search method of the different local search // heuristics, accepting improving moves only (VRPH_DOWNHILL) OnePointMove OPM; TwoOpt TO; ThreeOpt ThO; while(OPM.route_search(&V,k,k,VRPH_DOWNHILL|VRPH_INTRA_ROUTE_ONLY )){} while(TO.route_search(&V,k,k,VRPH_DOWNHILL|VRPH_INTRA_ROUTE_ONLY )){}; while(ThO.route_search(&V,k,VRPH_DOWNHILL|VRPH_INTRA_ROUTE_ONLY )){}; // Copy route k from the solution to the VRPRoute R V.update_route(k,&route); route.create_name(); // Add it to the "route warehouse" - this uses a hash table to keep track // of duplicate columns status=V.route_wh->add_route(&route); if(status!=DUPLICATE_ROUTE) { // This route is not currently in the WH and so it cannot be in the // set partitioning problem //OSI_add_route(si,&V,&route); OSI_add_route(si,&V,&route,route_id,orderings); route_id++; } } // Set the row RHS's if we need to if(first_sol) { first_sol=false; for(int rownum=0;rownum<n;rownum++) si->setRowBounds(rownum,1,1); // Note that changing this to >= would be a set covering problem // where each customer can be visited by more than one route } } // Now erase all the solutions from the WH V.solution_wh->liquidate(); if(verbose) { printf("Attempt %02d: Solving IP with %d columns\n",i,si->getNumCols()); printf("%d routes in the WH\n",V.route_wh->num_unique_routes); } // Solve the current set partitioning problem using the MIP solver start=clock(); si->branchAndBound(); stop=clock(); mip_time += (stop-start); double opt=si->getObjValue(); x=si->getColSolution(); last_num_cols=si->getNumCols(); if(verbose) printf("Optimal solution (%d columns) is %f\n",last_num_cols,opt); // Now recover the solution from the IP solution OSI_recover_solution(si, orderings, IP_sol_buff); if(verbose) printf("IP solution has obj. function value: %5.2f\n" "Best heuristic obj. function value: %5.2f\n", si->getObjValue(),best_heur_sol); } if(verbose) printf( "\nResults\n" "--------\n" "After %d runs\n" "IP solution has obj. function value: %5.2f\n" "Best heuristic obj. function value: %5.2f\n", num_attempts,si->getObjValue(),best_heur_sol); // print to stderr since GLPK prints "conflict graph" to stdout (a known bug...) // best_heur_sol best_mip_sol heur_time mip_time fprintf(stderr,"%5.3f %5.3f %5.3f %5.3f\n", best_heur_sol, si->getObjValue(), (double)(heur_time)/CLOCKS_PER_SEC, (double)(mip_time)/CLOCKS_PER_SEC); delete V.route_wh; delete fresh_solution; delete [] sol_buff; delete [] IP_sol_buff; delete si; for(i=0;i<MAX_ROUTES;i++) if(orderings[i]) delete [] orderings[i]; return 0; }