Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple critical bugs in 3-opt search #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 84 additions & 74 deletions src/ThreeOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,29 +48,32 @@ bool ThreeOpt::route_search(class VRP *V, int r, int rules)

ii=0;

// CG: ~~We begin with the edges a-b, c-d, and e-f~~
// This is incorrect, the first
// edge triplet should be:
// a-b, b-c, c-d ! (?)

b= V->route[r].start;
a=VRPH_MAX(V->pred_array[b],0);
// edge 1 is a-b
c=VRPH_MAX(V->next_array[b],0);
c=b;
if(c==VRPH_DEPOT)
return false;
d=VRPH_MAX(V->next_array[c],0);
if(d==VRPH_DEPOT)
return false;
e=VRPH_MAX(V->next_array[d],0);
e=d;
if(e==VRPH_DEPOT)
return false;
f=VRPH_MAX(V->next_array[e],0);
if(f==VRPH_DEPOT)
return false;

int a_end, c_end, e_end;
// Set the a_end to 3 hops back from the route's end since
// Set the a_end to 2 hops back from the route's end since
// we will have searched all possible moves by this point.
// This is ugly...
a_end = VRPH_MAX(VRPH_DEPOT,V->pred_array[VRPH_MAX(VRPH_DEPOT,V->pred_array[VRPH_MAX(VRPH_DEPOT, V->pred_array[V->route[r].end])])]);
c_end = VRPH_MAX(VRPH_DEPOT, V->pred_array[V->route[r].end]);
e_end = V->route[r].end;
a_end = VRPH_MAX(VRPH_DEPOT, V->pred_array[V->route[r].end]);
c_end = VRPH_MAX(VRPH_DEPOT, V->route[r].end);
e_end = VRPH_DEPOT;

int *old_sol=NULL;
if(rules & VRPH_TABU)
Expand All @@ -80,55 +83,21 @@ bool ThreeOpt::route_search(class VRP *V, int r, int rules)
V->export_solution_buff(old_sol);
}

//Do not evaluate the first move separately, do it in the loop.


// Evaluate the first move and then enter the loop
// We begin with the edges a-b, c-d, and e-f
if(evaluate(V,a,b,c,d,e,f,rules,&M)==true)
{
if(accept_type==VRPH_FIRST_ACCEPT || ((accept_type==VRPH_LI_ACCEPT)&&M.savings<-VRPH_EPSILON))
{
// Make the move
if(move(V, &M)==false)
report_error("%s: move error 1\n",__FUNCTION__);
else
{
if(!(rules & VRPH_TABU))
return true;
else
{
// Check VRPH_TABU status of move - return true if its ok
// or revert to old_sol if not and continue to search.
if(V->check_tabu_status(&M, old_sol))
{
delete [] old_sol;
return true; // The move was ok
}
// else we reverted back - continue the search for a move
}
}
}

if(accept_type==VRPH_BEST_ACCEPT || accept_type==VRPH_LI_ACCEPT)
{
if(M.is_better(V, &BestM, rules))//if(M.savings<BestM.savings)
BestM=M;
}
}

a=b;


while(a!=a_end)
b = V->route[r].start;
a = VRPH_MAX(V->pred_array[b], 0);
do
{
b=VRPH_MAX(V->next_array[a],0);
c=VRPH_MAX(V->next_array[b],0);
while(c!=c_end)
if (a!=0)
b = VRPH_MAX(V->next_array[a],0);
c = b;
do
{
d=VRPH_MAX(V->next_array[c],0);
e=VRPH_MAX(V->next_array[d],0);
while(e!=e_end)
{
e = d;
do
{
f=VRPH_MAX(V->next_array[e],0);

// Evaluate the move!
Expand All @@ -142,7 +111,9 @@ bool ThreeOpt::route_search(class VRP *V, int r, int rules)
else
{
if(!(rules & VRPH_TABU))
{
return true;
}
else
{
// Check VRPH_TABU status of move - return true if its ok
Expand All @@ -165,11 +136,11 @@ bool ThreeOpt::route_search(class VRP *V, int r, int rules)
}
}
e=f;
}
} while(e != e_end);
c=d;
}
} while (c != c_end);
a=b;
}
} while (a != a_end);


if(accept_type==VRPH_FIRST_ACCEPT || BestM.savings==VRP_INFINITY)
Expand Down Expand Up @@ -251,7 +222,6 @@ bool ThreeOpt::evaluate(class VRP *V, int a, int b, int c, int d, int e, int f,

double s1, s2, s3, s4, s5, s6, s7, old;


// savings = new-old
double minval=VRP_INFINITY;
int type=0;
Expand Down Expand Up @@ -345,19 +315,24 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int
//
double oldlen, oldobj;
double temp_maxlen;
int temp_vehcap, a_route;
int temp_vehcap;

// Remember the actual maximums as we may need to artificially inflate them.
temp_maxlen= V->max_route_length;
temp_vehcap= V->max_veh_capacity;

Flip flip;

a_route= V->route_num[b];// b is not VRPH_DEPOT

oldlen= V->route[a_route].length;
oldobj= V->total_route_length;



// #a->b# c->e d->f ( 2-opt move )
// _____
// / \
// >--a--b->-c d-<-e f-->
// \____/
if(type==1)
{

Expand All @@ -377,6 +352,11 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int

}

// a->c b->d #e->f# ( 2-opt move )
// _____
// / \
// >--a b-<-c d->-e--f-->
// \____/
if(type==2)
{

Expand All @@ -396,6 +376,11 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int
return true;
}

// a->c b->e d->f ( 3-opt move )
// ________
// / \
// >--a b-<-c d-<-e f-->
// \____/ \____/
if(type==3)
{
V->max_route_length=VRP_INFINITY;
Expand Down Expand Up @@ -431,10 +416,14 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int
}


// a->d b->e c->f (3-opt move)
// _________
// / \
// >--a b->-c d->-e f-->
// \______\_/ /
// \______/
if(type==4)
{
a_route= V->route_num[b]; // b not VRPH_DEPOT!

if(a!=VRPH_DEPOT && f!=VRPH_DEPOT)
{
V->next_array[a]=d;
Expand Down Expand Up @@ -473,6 +462,7 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int

V->next_array[a]=d;
V->pred_array[d]=a;
V->route[a_route].end=c;///!!!!
}

if(a==VRPH_DEPOT && f==VRPH_DEPOT)
Expand All @@ -491,13 +481,12 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int
V->pred_array[prev_start]=-c;

V->route[a_route].start=d;///!!!!

V->route[a_route].end=c;///!!!!

}

//Now manually adjust the route_len and obj. value


V->route[a_route].length=oldlen+M->savings;//s4;
V->total_route_length=oldobj+M->savings;//s4;

Expand All @@ -508,17 +497,25 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int

}

// a->d c->e b->f (3-opt move)
// _________
// / ____ \
// / / \ \
// >--a b-<-c d->-e f-->
// \_______/
if(type==5)
{
V->max_route_length=VRP_INFINITY;
V->max_veh_capacity=VRP_INFINITY;

int prev_end=-1;
// Before any operation, store the jumps to the next/pred route.
// These are needed in case a or f are VRPH_DEPOT.
int prev_end = VRPH_ABS(V->pred_array[b]);
int prev_start = VRPH_ABS(V->next_array[e]);

// Remember: flip changes the obj. value!!!!
if(a==VRPH_DEPOT)
{
prev_end=VRPH_ABS(V->pred_array[b]);
V->presert_dummy(b);
flip.move(V,V->dummy_index,d);
V->remove_dummy();
Expand All @@ -542,10 +539,9 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int

if(f==VRPH_DEPOT)
{
int prev_start=VRPH_ABS(V->next_array[e]);
V->next_array[b]=-prev_start;
V->pred_array[prev_start]=-b;

V->route[a_route].end = b; //!!!
}
else
{
Expand All @@ -563,9 +559,6 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int
V->max_route_length=temp_maxlen;
V->max_veh_capacity=temp_vehcap;


a_route= V->route_num[b];

V->route[a_route].length=oldlen+M->savings;//s5;
V->total_route_length=oldobj+M->savings;//s5;

Expand All @@ -574,12 +567,21 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int
return true;
}

// a->e b->d c->f (3-opt move)
// _______
// / \
// >--a b->-c d-<-e f-->
// \ \____/ /
// \_________/
if(type==6)
{
V->max_route_length=VRP_INFINITY;
V->max_veh_capacity=VRP_INFINITY;

int prev_end=VRPH_ABS(V->pred_array[b]);
// Before any operation, store the jumps to the next/pred route.
// These are needed in case a or f are VRPH_DEPOT.
int prev_end = VRPH_ABS(V->pred_array[b]);
int prev_start = VRPH_ABS(V->next_array[e]);

if(f==VRPH_DEPOT)
{
Expand Down Expand Up @@ -609,10 +611,9 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int

if(f==VRPH_DEPOT)
{
int prev_start=VRPH_ABS(V->next_array[e]);
V->next_array[c]=-prev_start;
V->pred_array[prev_start]=-c;

V->route[V->route_num[b]].end = c; //!!!
}
else
{
Expand All @@ -635,6 +636,11 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int

}

// a->e #c->d# b->f (2-opt move)
// ____________
// / \
// >--a b-<-c--d-<-e f-->
// \___________/
if(type==7)
{

Expand Down Expand Up @@ -672,6 +678,10 @@ bool ThreeOpt::move(class VRP *V, VRPMove *M)// int a, int b, int c, int d, int
}

}
else
{
report_error("%s: inter-route 3-opt operations are not supported!\n",__FUNCTION__);
}


return false;
Expand Down