Ejemplo n.º 1
0
int random_integer(float prob_distrib[])  /* Random integer generation
                                             function. */
{
    int   i;
    float u;

    /* Generate a U(0,1) random variate. */

    u = lcgrand(1);

    /* Return a random integer in accordance with the (cumulative) distribution
       function prob_distrib. */

    for (i = 1; u >= prob_distrib[i]; ++i)
        ;
    return i;
}
Ejemplo n.º 2
0
//===========================================================================
//=  Function to generate exponentially distributed random variables        =
//=    - Input:  Mean value of distribution                                 =
//=    - Output: Returns with exponentially distributed random variable     =
//===========================================================================
double expon(double x)
{
    double z;                     // Uniform random number (0 < z < 1)
    double exp_value;             // Computed exponential value to be returned

    // Pull a uniform random number (0 < z < 1)
    do
    {
        z = lcgrand(stream_id);
    }
    while ((z == 0) || (z == 1));

    // Compute exponential random variable using inversion method
    exp_value = -x * log(z);

    return(exp_value);
}
Ejemplo n.º 3
0
float uniform(float a, float b)  /* Uniform variate generation function. */
{
    /* Return a U(a,b) random variate. */

    return a + lcgrand(1) * (b - a);
}
Ejemplo n.º 4
0
float expon(float mean)  /* Exponential variate generation function. */
{
    /* Return an exponential random variate with mean "mean". */

    return -mean * log(lcgrand(1));
}
Ejemplo n.º 5
0
int main(int argc, char **argv)
{
    if(argc==1 || (argc==2 && strcmp(argv[1],"-h")==0) || (argc==2 && strcmp(argv[1],"--help")==0) 
        || (argc==2 && strcmp(argv[1],"--h")==0) )
    {
        usage(argv[0]);
        exit(-1);
    }

    time_t global_start=clock();

    int i,j,new_node, num_pushes=0, seed=0, nsplits=0, root=-1,subtree_root=-1,new_ms,max_bits=-1,
        num_spawns=0;
    // Set default p to 1/3
    double p=0.3333; 
    list<int>::iterator ii;
    char *DIMACS_file=NULL;
    bool has_graph=false,verbose=false,do_push=true,do_two_sep=true, do_init_push=false;
    Graph *G=NULL;
    time_t start,stop;
    //for printing out the graphviz representations of each move on the bd 
    bool gviz_all = false; 
    bool gviz_el = false; //edge labels on
    bool gviz_th = true;  //thicknesses off
    char gvizfile[20];
    int step = 0;

    //    time_t begin=clock();
    // Controller object has some methods which are used independently from
    // graph objects. 
    goblinController *CT;
    CT = new goblinController();
    //Turn off printing of dots.
    CT->traceLevel = 0;

    // Parse arguments
    for(i=0;i<argc;i++)
    {
        if(strcmp(argv[i],"-v")==0)
            verbose=true;

        if(strcmp(argv[i],"-f")==0)
        {
            DIMACS_file=argv[i+1];
            // Read in the file
            G=new Graph(DIMACS_file, true);
            G->write_graphviz_file("orig.gviz");
            char metis_file[100];
            sprintf(metis_file,"%s.metis",argv[i+1]);
            G->write_METIS_file(metis_file);
            sprintf(metis_file,"%s.hmetis",argv[i+1]);
            G->write_HMETIS_file(metis_file);
            has_graph=true;
            if(verbose)
            {
                print_message(0,"Read in graph from file: %s\n",DIMACS_file);
                cout << *G;
            }
        }
        if(strcmp(argv[i],"-p")==0)
            p=atof(argv[i+1]);
        if(strcmp(argv[i],"-nopush")==0)
            do_push=false;
        if(strcmp(argv[i],"-no2sep")==0)
            do_two_sep=false;
        if(strcmp(argv[i],"-seed")==0)
            seed=atoi(argv[i+1]);
        if(strcmp(argv[i],"-root")==0)
            root=atoi(argv[i+1]);
         if(strcmp(argv[i],"-subtree")==0)
            subtree_root=atoi(argv[i+1]);
         if(strcmp(argv[i],"-exhaust")==0)
             max_bits=atoi(argv[i+1]);
    }
    // Make sure we have a graph
    if(!has_graph)
        fatal_error("Did not load graph\n");

    if(!G->check_connected())
        fatal_error("Graph is not connected\n");

    if(!G->check_two_connected())
        fatal_error("Graph is not 2 connected!\n");

    // "seed" the rng
    for(i=0;i<seed;i++)
        lcgrand(0);
    // Create the tree
    BDTree btree(G);
    // Initialize to the star configuration 
    btree.create_star();

    if(gviz_all)
    {
        sprintf(gvizfile, "bd.%d.gviz", step);
        btree.write_graphviz_file(false,gvizfile,gviz_el, gviz_th);
        step++;
    }

    // Find candidate pushes
    if(do_init_push)
    {
        num_pushes=btree.push(0);
        print_message(0,"Found %d initial pushes\n",num_pushes);
    }

    if(gviz_all && num_pushes > 0)
    {
        sprintf(gvizfile, "bd.%d.gviz", step);
        btree.write_graphviz_file(false,gvizfile,gviz_el, gviz_th);
        step++;
    }

    if(do_two_sep)
    {
        // Look for 2-separations 
        list<int> X1, Y1;
        bool ts = false;
        int bv = 0;
        bool found;
        while(!ts)
        {
            //we need to try to separate a vertex with at least 4 edges adjacent to it
            found = false;
            while(found == false && bv < btree.num_nodes)
            {
                if(btree.nodes[bv].edges.size() >3)
                    found = true; 
                else
                    bv++;
            } 
            if(!found)
            {
                print_message(0, "Did not find a(nother) node of btree to split.\n");
                break;
            }

            if(verbose)
                print_message(0,"Running two separation function at vertex %d\n", bv);
            X1.clear();
            Y1.clear();
            start = clock();
	    ts= btree.two_separation(bv, &X1, &Y1, CT);
            //ts = btree.bf_two_separation(bv, &X1, &Y1);
            stop = clock(); 
            print_message(0, "Checked for two separation in %f seconds.\n",
                ((double)(stop-start))/CLOCKS_PER_SEC);    
            if(ts)
            {
                print_message(0, "Found a valid 2 separation!\n");
                print_message(0, "Splitting node %d\n", bv);
                // Split the node
                new_node = btree.split_node(bv,&X1,EDGE_SPLIT,&new_ms);
                print_message(0,"After split - new edge has middle set of size %d\n",  new_ms);

                if(gviz_all)
                {
                    sprintf(gvizfile, "bd.%d.gviz", step);
                    btree.write_graphviz_file(false,gvizfile,gviz_el, gviz_th);
                    step++;
                }

                if(do_push)
                {                    
                    //Push the vertex you split
                    num_pushes=btree.push(bv);
                    print_message(0, "Found %d pushes at %d \n",num_pushes, bv);

                    if(gviz_all && num_pushes > 0)
                    {
                        sprintf(gvizfile, "bd.%d.gviz", step);
                        btree.write_graphviz_file(false,gvizfile,gviz_el, gviz_th);
                        step++;
                    }


                    //Push the new vertex created 
                    num_pushes=btree.push(new_node);
                    print_message(0, "Found %d pushes at %d \n",num_pushes, new_node);

                    if(gviz_all && num_pushes > 0)
                    {
                        sprintf(gvizfile, "bd.%d.gviz", step);
                        btree.write_graphviz_file(false,gvizfile,gviz_el, gviz_th);
                        step++;
                    }


                }
                //Add one to our count, then reset ts and bv so we restart search for 2-seps.

                nsplits++;
                ts = false;
                bv = 0;
            }
            else
            {
                print_message(0, "No 2 separation at vertex %d!\n", bv);
                bv++;
            }
        }
        print_message(0, "Finished with two-separations. Split %d nodes.\n", nsplits);
    }

    // Now run eigenvector splitting until BD is valid    
    int split_node=0,new_node_1, new_node_2;
    nsplits=0;
    list<int> A, B, CA, CB, partition, partition2;
    vector<int> candidates(btree.num_nodes);
    while(!btree.is_valid)
    {
        // Find a BDTreeNode with at least 4 neighbors
        // fill candidates with possibilities
        // This is not smart since we really should just update
        // the candidates as we split and add nodes...
        // but it's probably in the noise anyway
        j=0;
        split_node = -1;
        for(i=0;i<btree.num_nodes;i++)
        {
            if(btree.nodes[i].edges.size()>=4)
            { 
                candidates[j]=i;
                j++;          
            }
        }
      
        print_message(1,"generating random int in 0...%d\n",j-1);
        split_node=rand_int(0,j-1);
        split_node=candidates[split_node];
        print_message(1,"split_node is %d (degree=%d)\n",split_node,btree.nodes[split_node].edges.size());
        
        A.clear(); B.clear(); CA.clear(); CB.clear();
        nsplits++;	

        // Run eigenvector heuristic - if fill_extra=true then we will 
        // we are adding "obvious" edges to A and B within this function!
        start=clock(); 
        if(btree.num_interior_nodes==1)
            btree.eigenvector_split(split_node,&A, &B, p, false);
        else
            btree.eigenvector_leaf_split(split_node,&A, &B, p, false);

        stop=clock();
        print_message(0,"Computed eigenvector with p=%f in %f seconds.\n",p,
            ((double)(stop-start))/CLOCKS_PER_SEC);
        print_message(0,"Eigenvector A:\n");
        print(0,A);
        print_message(0,"Eigenvector B:\n");
        print(0,B);

        // Should do this only if A and B require it 
        if(A.size()+B.size() < btree.nodes[split_node].edges.size())
        {
            // Run the max flow to get an actual splitting of the edges
            start=clock(); btree.split_maxflow_partition(split_node,&A,&B,&CA,&CB, CT); stop = clock(); 
            print_message(0,"Computed partition given eigenvector results in %f seconds.\n",
                ((double)(stop-start))/CLOCKS_PER_SEC);
           
            // Create  the edge set
            partition.clear();
            for(ii=A.begin();ii!=A.end();++ii)
                partition.push_back(*ii);
            for(ii=CA.begin();ii!=CA.end();++ii)
                partition.push_back(*ii);
            partition.sort();
        }
        else
        {
            // Just use A
            partition.clear();
            for(ii=A.begin();ii!=A.end();++ii)
                partition.push_back(*ii);
        }
        
        // Check the size of the exhaust BEFORE splitting the node
        int exhaust_bits=btree.nodes[split_node].edges.size() - A.size() - B.size();
        print_message(1,"Exhaust size is %d bits\n",exhaust_bits);

        int exhaust_ms_size=-1;
        time_t exh_start=0, exh_stop=0;
        list<int> C;
        // Check to see if we can/want to exhaust
        if( exhaust_bits <= max_bits)
        {
            print_message(0,"Checking exhaust\n");
            // Check this exhaustively
            exh_start=clock();
            C.clear();
            exhaust_ms_size=btree.best_partition(split_node,&A, &B, &C);
            exh_stop=clock();         
        }

        
        print_message(1,"Splitting %d with edge partition of size %d\n",split_node,partition.size());
        print(1,partition);
        if(btree.num_interior_nodes==1)
        {
            // initial star - use split node
            new_node_2=-1;
            new_node_1 = btree.split_node(split_node,&partition,EDGE_SPLIT,&new_ms);
            btree.write_graphviz_file(true,"init.gviz",true,true);
        }
        else
        {
            // Later on in the process - use spawn node
            int ms1,ms2;
            btree.spawn_nodes(split_node,&partition,EDGE_SPLIT,&ms1,&ms2, &new_node_1, &new_node_2);
            print_message(0,"After spawn - new middle sets of size %d,%d (max ms is %d)\n",ms1,ms2,btree.max_middle_set_size);
            print_message(0,"new_nodes: %d,%d\n",new_node_1, new_node_2);
            //char spawn_file[100];
            //sprintf(spawn_file,"spawn_%d.gviz",num_spawns);
            //btree.write_graphviz_file(true,spawn_file,true,true);
            num_spawns++;
        }

        // Check for validity here!!!
        if(btree.is_valid)
            break;

        // CSG - this fails because we had a spawn of a leaf that was an old node -
        // so new node1 and 2 are getting set incorrectly in spawn_node
        if(new_node_1!=-1)
        {
            // Try to push the newly created nodes
            if(btree.nodes[new_node_1].edges.size()>=4 && do_push)
            {
                num_pushes=btree.push(new_node_1);
                print_message(0,"\n\tFound %d pushes for newly introduced node %d\n",num_pushes,new_node_1);
                if(gviz_all && num_pushes > 0)
                {
                    sprintf(gvizfile, "bd.%d.gviz", step);
                    btree.write_graphviz_file(false,gvizfile,gviz_el, gviz_th);
                    step++;
                }
            }
            // Check for validity here!!!
            if(btree.is_valid)
                break;
        }

        if(new_node_2!=-1)
        {
            if(btree.nodes[new_node_2].edges.size()>=4 && do_push)
            {
                num_pushes=btree.push(new_node_2);
                print_message(0,"\n\tFound %d pushes for newly introduced node %d\n",num_pushes,new_node_2);
                if(gviz_all && num_pushes > 0)
                {
                    sprintf(gvizfile, "bd.%d.gviz", step);
                    btree.write_graphviz_file(false,gvizfile,gviz_el, gviz_th);
                    step++;
                }
            }
        }
        // Check for validity here!!!
        if(btree.is_valid)
            break;
    }

    if(root!=-1)
    {
        // This seems to be working when all graphviz flags are off, but something doesn't seem right
        // if last param is set to 2, probably because middle set is empty and we get 0 pen width??!
        // BDS - fixed this by making minimum penwidth 1 (i.e. pw = |mid set| unless |mid set| = 0, in which 
        // case, pw = 1. 
        btree.write_graphviz_file(false,"before_root.gviz",false,true);
        //cout<<btree;
        btree.root(root);
        btree.write_graphviz_file(false,"after_root.gviz",false,true);
        //cout<<btree;
    }

    if(verbose)
        cout<<btree;

#if 0
    // This section was just for generating a specific plot when running
    // c:\Users\tcg\PROJECTS\SGD\gaudi\code\trunk\branch_decomposition\Release>BranchDecomposition.exe -p .
    // 33 -no2sep -root 10 -subtree 330 -f ..\data\ch130.tsp.del.100.dimacs
    // Check to see if a subtree is desired
    if(subtree_root!=-1)
    {
        int roots[24]={400,328,267,292,263,
                       403,438,257,251,302,
                       276,452,294,405,364,
                       379,349,369,330,443,
                       338,420,291,425};
        char *colors[6]={"red","blue","green","orange","purple","yellow"};
        list<int> subtree;
        for(i=0;i<24;i++)
        {
            subtree.clear();
            btree.find_subtree(roots[i], &subtree);
            print_message(1,"Subtree rooted at %d:\n",roots[i]);
            for(ii=subtree.begin();ii!=subtree.end();++ii)
            {
                printf("%d [label=\"\",style=filled,fillcolor=%s,color=%s];\n",*ii,colors[i%6],colors[i%6]);
            }
            printf("\n\n");
        }
    }
#endif


    print_message(0,"%d splits performed\n",nsplits);
    int max_ms=0;
    for(i=0;i<btree.num_edges;i++)
        if((int)btree.edges[i].middle_set.size()>max_ms)
            max_ms=btree.edges[i].middle_set.size();
    print_message(0,"max middle set is %d\n",max_ms);

    vector<int> hist(max_ms+1,0);
    for(i=0;i<btree.num_edges;i++)
        hist[btree.edges[i].middle_set.size()]++;
    print(0,hist);

    if(gviz_all && num_pushes > 0)
    {
        sprintf(gvizfile, "bd.%d.gviz", step);
        btree.write_graphviz_file(false,gvizfile,gviz_el, gviz_th);
        step++;
    }

    time_t global_stop=clock();
    printf("%s %3.3f %3.3f %d %d\n",DIMACS_file,p,(double)(global_stop-global_start)/CLOCKS_PER_SEC,nsplits,max_ms);
    fflush(stdout);
    //write a file with thick/thin lines.
    //btree.write_graphviz_file(false,"final.gviz",false, true);


    //write a file with thick/thin lines and edge labels
    //btree.write_graphviz_file(false,"final.gviz",true, true);



    delete G;

    delete CT;

    return 1;
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
double VRP::RTR_solve(int heuristics, int intensity, int max_stuck, int max_perturbs,
                      double dev, int nlist_size, int perturb_type, int accept_type, bool verbose)
{
    ///
    /// Uses the given parameters to generate a 
    /// VRP solution via record-to-record travel.
    /// Assumes that data has already been imported into V and that we have
    /// some existing solution.
    /// Returns the objective function value of the best solution found
    ///

    // Make sure accept_type is either VRPH_BEST_ACCEPT or VRPH_FIRST_ACCEPT - matters only
    // for the downhill phase as we use VRPH_LI_ACCEPT in the diversification phase

    if(accept_type!=VRPH_BEST_ACCEPT && accept_type!=VRPH_FIRST_ACCEPT)
        report_error("%s: accept_type must be VRPH_BEST_ACCEPT or VRPH_FIRST_ACCEPT\n");

    int ctr, n, j,  i,  R, random, fixed, neighbor_list, objective, tabu;

    random=fixed=neighbor_list=0;

    if(heuristics & VRPH_RANDOMIZED)
        random=VRPH_RANDOMIZED;

    if(heuristics & VRPH_FIXED_EDGES)
        fixed=VRPH_FIXED_EDGES;

    if(heuristics & VRPH_USE_NEIGHBOR_LIST)
        neighbor_list=VRPH_USE_NEIGHBOR_LIST;

    objective=VRPH_SAVINGS_ONLY;
    // default strategy

    if(heuristics & VRPH_MINIMIZE_NUM_ROUTES)
        objective=VRPH_MINIMIZE_NUM_ROUTES;


    if(heuristics & VRPH_TABU)
    {
        tabu=VRPH_TABU; // We will use a primitive Tabu Search in the uphill phase
        // Clear the tabu list
        this->tabu_list->empty();
    }
    else
        tabu=0;

    n=num_nodes;

    // Define the heuristics we will use

    OnePointMove OPM;
    TwoPointMove TPM;
    TwoOpt         TO;
    OrOpt         OR;
    ThreeOpt     ThreeO;
    CrossExchange    CE;
    ThreePointMove ThreePM;

    double start_val;
    int *perm;
    perm=new int[this->num_nodes];


    j=VRPH_ABS(this->next_array[VRPH_DEPOT]);
    for(i=0;i<this->num_nodes;i++)
    {
        perm[i]=j;
        if(!routed[j])
            report_error("%s: Unrouted node in solution!!\n");

        j=VRPH_ABS(this->next_array[j]);
    }
    if(j!=VRPH_DEPOT)
        report_error("%s: VRPH_DEPOT is not last node in solution!!\n");


    int rules;

    // Set the neighbor list size used in the improvement search
    neighbor_list_size=VRPH_MIN(nlist_size, this->num_nodes);

    // Set the deviation
    deviation=dev;

    int num_perturbs=0;

    record=this->total_route_length;
    this->best_total_route_length=this->total_route_length;
    this->export_solution_buff(this->current_sol_buff);
    this->export_solution_buff(this->best_sol_buff);

    normalize_route_numbers();

    ctr=0;


uphill:
    // Start an uphill phase using the following "rules":
    double beginning_best=this->best_total_route_length;
    rules=VRPH_LI_ACCEPT+VRPH_RECORD_TO_RECORD+objective+random+fixed+neighbor_list+tabu;

    if(verbose)
        printf("Uphill starting at %5.2f\n",this->total_route_length);
    
    for(int k=1;k<intensity;k++)
    {
        start_val=total_route_length;

        if(heuristics & ONE_POINT_MOVE)
        {
            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)
            {
#if FIXED_DEBUG
                if(fixed && !check_fixed_edges("Before 1PM\n"))
                    fprintf(stderr,"Error before OPM search(%d)\n",perm[i-1]);
#endif
                OPM.search(this,perm[i-1],rules);

#if FIXED_DEBUG
                if(fixed && !check_fixed_edges("After 1PM\n"))
                {
                    fprintf(stderr,"Error after OPM search(%d)\n",perm[i-1]);
                    this->show_route(this->route_num[perm[i-1]]);
                }
#endif
            }
        }


        if(heuristics & TWO_POINT_MOVE)
        {
            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)    
                TPM.search(this,perm[i-1],rules + VRPH_INTER_ROUTE_ONLY);

            //check_fixed_edges("After 2PM\n");

        }


        if(heuristics & THREE_POINT_MOVE)
        {
            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)    
                ThreePM.search(this,perm[i-1],rules + VRPH_INTER_ROUTE_ONLY);

            //check_fixed_edges("After 3PM\n");

        }



        if(heuristics & TWO_OPT)
        {
            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)    
                TO.search(this,perm[i-1],rules);

            //check_fixed_edges("After TO\n");


        }        


        if(heuristics & OR_OPT)
        {
            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)    
                OR.search(this,perm[i-1],4,rules);

            for(i=1;i<=n;i++)    
                OR.search(this,perm[i-1],3,rules);

            for(i=1;i<=n;i++)    
                OR.search(this,perm[i-1],2,rules);

            //check_fixed_edges("After OR\n");

        }

        if(heuristics & THREE_OPT)
        {
            normalize_route_numbers();
            R=total_number_of_routes;

            for(i=1; i<=R; i++)    
                ThreeO.route_search(this,i,rules-neighbor_list);

            //check_fixed_edges("After 3O\n");

        }

        if(heuristics & CROSS_EXCHANGE)
        {
            normalize_route_numbers();
            this->find_neighboring_routes();
            R=total_number_of_routes;

            for(i=1; i<=R-1; i++)    
            {
                for(j=0;j<1;j++)
                    CE.route_search(this,i, route[i].neighboring_routes[j],rules-neighbor_list); 
            }

            //check_fixed_edges("After CE\n");
        }
    }

    if(total_route_length<record)
        record = total_route_length;

    if(verbose)
    {
        printf("Uphill complete\t(%d,%5.2f,%5.2f)\n",count_num_routes(),total_route_length, record);
        printf("# of recorded routes: %d[%d]\n",total_number_of_routes,count_num_routes());

    }

    if(this->best_total_route_length<beginning_best-VRPH_EPSILON)
    {
        if(verbose)
            printf("New best found in uphill!\n");
        // We found a new best solution during the uphill phase that might
        // now be "forgotten"!! I have seen this happen where it is never recovered
        // again, so we just import it and start the downhill phase with this solution...
        //this->import_solution_buff(this->best_sol_buff);

    }

downhill:

    // Now enter a downhill phase
    double orig_val=total_route_length;
    if(verbose)
        printf("Downhill starting at %f (best=%f)\n",orig_val,this->best_total_route_length);


    if((heuristics & ONE_POINT_MOVE)|| (heuristics & KITCHEN_SINK) )
    {
        rules=VRPH_DOWNHILL+objective+random+fixed+neighbor_list+accept_type;
        for(;;)
        {
            // One Point Move
            start_val=total_route_length;

            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)
                OPM.search(this,perm[i-1],rules );


            if(VRPH_ABS(total_route_length-start_val)<VRPH_EPSILON)
                break; 

        }

    }



    if((heuristics & TWO_POINT_MOVE) || (heuristics & KITCHEN_SINK) )
    {
        rules=VRPH_DOWNHILL+VRPH_INTER_ROUTE_ONLY+objective+random+fixed+neighbor_list+accept_type;
        for(;;)
        {
            // Two Point Move
            start_val=total_route_length;

            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)    
                TPM.search(this,perm[i-1],rules);

            if(VRPH_ABS(total_route_length-start_val)<VRPH_EPSILON)
                break; 

        }

    }



    if((heuristics & TWO_OPT)|| (heuristics & KITCHEN_SINK) )
    {
        // Do inter-route first a la Li
        rules=VRPH_DOWNHILL+VRPH_INTER_ROUTE_ONLY+objective+random+fixed+neighbor_list+accept_type;
        for(;;)
        {

            start_val=total_route_length;

            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)    
                TO.search(this,perm[i-1],rules);

            if(VRPH_ABS(total_route_length-start_val)<VRPH_EPSILON)
                break; 
        }

        // Now do both intra and inter
        rules=VRPH_DOWNHILL+objective+random+fixed+neighbor_list+accept_type;

        for(;;)
        {

            start_val=total_route_length;

            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)    
                TO.search(this,perm[i-1],rules);

            if(VRPH_ABS(total_route_length-start_val)<VRPH_EPSILON)
                break; 
        }
    }

    if((heuristics & THREE_POINT_MOVE) || (heuristics & KITCHEN_SINK) )
    {
        rules=VRPH_DOWNHILL+VRPH_INTER_ROUTE_ONLY+objective+random+fixed+accept_type+neighbor_list;
        for(;;)
        {
            // Three Point Move
            start_val=total_route_length;

            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)    
                ThreePM.search(this,perm[i-1],rules);

            if(VRPH_ABS(total_route_length-start_val)<VRPH_EPSILON)
                break; 

        }
    }


    if((heuristics & OR_OPT) || (heuristics & KITCHEN_SINK))
    {

        rules=VRPH_DOWNHILL+ objective +random +fixed + accept_type + neighbor_list;

        for(;;)
        {
            // OrOpt
            start_val=total_route_length;
            if(random)
                random_permutation(perm, this->num_nodes);

            for(i=1;i<=n;i++)    
                OR.search(this,perm[i-1],4,rules);
            for(i=1;i<=n;i++)
                OR.search(this,perm[i-1],3,rules);
            for(i=1;i<=n;i++)
                OR.search(this,perm[i-1],2,rules);


            if(VRPH_ABS(total_route_length-start_val)<VRPH_EPSILON)
                break; 
        }
    }

    if((heuristics & THREE_OPT) || (heuristics & KITCHEN_SINK) )
    {
        normalize_route_numbers();
        R= total_number_of_routes;
        rules=VRPH_DOWNHILL+objective+VRPH_INTRA_ROUTE_ONLY+ random +fixed + accept_type;
        for(;;)
        {
            // 3OPT
            start_val=total_route_length;

            for(i=1;i<=R;i++)    
                ThreeO.route_search(this,i,rules);

            if(VRPH_ABS(total_route_length-start_val)<VRPH_EPSILON)
                break; 
        }
    }


    if( (heuristics & CROSS_EXCHANGE) )
    {
        normalize_route_numbers();
        this->find_neighboring_routes();
        R=total_number_of_routes;

        rules=VRPH_DOWNHILL+objective+VRPH_INTRA_ROUTE_ONLY+ random +fixed + accept_type;

        for(i=1; i<=R-1; i++)    
        {
            for(j=0;j<=1;j++)
                CE.route_search(this,i, route[i].neighboring_routes[j], rules); 
        }
    }


    // Repeat the downhill phase until we find no more improvements
    if(total_route_length<orig_val-VRPH_EPSILON)
        goto downhill;
    if(verbose)
        printf("Downhill complete: %5.2f[downhill started at %f] (%5.2f)\n",total_route_length,orig_val,
        this->best_total_route_length);


    if(total_route_length < record-VRPH_EPSILON)    
    {
        // New record - reset ctr
        ctr=1;
        record=total_route_length;
    }
    else
        ctr++;

    if(ctr<max_stuck)
        goto uphill;

    if(ctr==max_stuck)
    {
        if(num_perturbs<max_perturbs)
        {
            if(verbose)
                printf("perturbing\n");
            if(perturb_type==VRPH_LI_PERTURB)
                perturb();
            else
                osman_perturb(VRPH_MAX(20,num_nodes/10),.5+lcgrand(20));

            // Reset record
            this->record=this->total_route_length;
            if(tabu)
                this->tabu_list->empty();

            ctr=1;
            num_perturbs++;
            goto uphill;
        }
    }


    if(verbose)
    {
        if(has_service_times==false)
            printf("BEST OBJ:  %f\n",best_total_route_length);
        else
            printf("BEST OBJ:  %f\n",best_total_route_length-total_service_time);
    }

    delete [] perm; 

    // Import the best solution found
    this->import_solution_buff(best_sol_buff);

    if(has_service_times==false)
        return best_total_route_length;
    else
        return best_total_route_length-total_service_time;


}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
void OSI_add_route(OsiSolverInterface *si, VRP *V, VRPRoute *r, int id, int **orderings)
{
    ///
    /// Adds a column/route to the current set partitioning problem.  The column is assigned
    /// the name of id, which is converted to a string.
    ///

    if(id>MAX_ROUTES)
    {   
        fprintf(stderr,"Too many routes added! Increase value of MAX_ROUTES=%d\n",MAX_ROUTES);
        exit(-1);
    }   

    int i, j, k, nvars, ncols;
    int *cols_to_delete;
    int *col_indices;
    std::string col_name;
    const double *U;
    time_t start, stop;

    // Create a new route object of the right size
    VRPRoute removed_route(V->get_num_nodes());

    // Create a CoinPackedVector for the new column
    CoinPackedVector col;

    for(i=0;i<r->num_customers;i++)
        col.insert(r->ordering[i]-1, 1);// 0-based

    // Check to see if we have exceeded max_columns
    // Since we have to fix variable values instead of deleting them in GLPK,
    // we have to calculate this
    U=si->getColUpper();
    ncols=si->getNumCols();
    nvars=0;
    for(i=0 ; i < ncols ; i++)
    {
        if(U[i]==1)
            nvars++;
    }

    if(nvars>=max_columns)
    {
        // Solve the problem and then delete num_cols_to_delete variables not in the current
        // optimal solution
        start=clock();
        si->branchAndBound();
        stop=clock();
        mip_time += (stop-start); 
        const double *y=si->getColSolution();
        // Select a set of num_cols_to_delete columns to delete   
        int nn=si->getNumCols();
        cols_to_delete = new int[nn];
        col_indices= new int[num_cols_to_delete];
        memset(cols_to_delete,0,nn*sizeof(int));
        memset(col_indices,0,num_cols_to_delete*sizeof(int));
        U=si->getColUpper();
        
        if(verbose)
            printf("Finding %d columns to delete \n",num_cols_to_delete);
        k=0;
        while(k<num_cols_to_delete)
        {
            while(true)
            {
                j=(int)floor(lcgrand(10)*nn);
                // Make sure the variable/column is not in the optimal solution 
                // Since OSI/GLPK implementation of deleteCols doesn't seem right,
                // Need to make sure that this column isn't already fixed!
                if(y[j]<0.01 && cols_to_delete[j]==0 && U[j]==1)
                {
                    cols_to_delete[j]=1;
                    col_indices[k]=j;
                    k++;
                    break;
                }
            }    
        }
        
        // Delete the columns - this does not seem to work in GLPK - just fix the variable to 0
        // si->deleteCols(num_cols_to_delete,col_indices);
        
        for(k=0;k<num_cols_to_delete;k++)
        {
            col_name=si->getColName(col_indices[k],VRP_INFINITY);
            // Remove the route from VRPH's "Route Warehouse"
            int route_id=atoi(col_name.c_str());
            OSI_recover_route(route_id,orderings, &removed_route);
            
            V->route_wh->remove_route(removed_route.hash_val, removed_route.hash_val2);
            // Fix this variable/column to 0
            si->setColBounds(col_indices[k],0,0);
        }
        if(verbose)
            printf("Deleted/Fixed %d columns/variables\n",num_cols_to_delete);
    
        delete [] cols_to_delete;
        delete [] col_indices;
    }

    // Add the named column to the IP 
    sprintf(r->name,"%d",id);
    std::string new_name(r->name);
    si->addCol(col,0,1,r->length-r->total_service_time,new_name);
    ncols=si->getNumCols();
    // Set as integer (binary)
    si->setInteger(ncols-1); // 0-based

    // Copy the ordering of the route to the orderings[] array
    // Add a -1 to denote the end
    orderings[id]=new int[r->num_customers+1];
    memcpy(orderings[id],r->ordering,r->num_customers*sizeof(int));
    orderings[id][r->num_customers]=-1;
    return;
}