我正在研究一种算法,除了一件事之外它似乎工作得很好。
让我先向您展示代码,然后我将解释代码的作用以及问题所在。
public Triple<List<ROUTE>, Integer, List<Customer>> LocalSearch()
{
int noImprLS = 0;
boolean initialization = false;
List<ROUTE> bestRoutes = startRoutes;
int bestProfit = profit;
List<Customer> bestU = u;
List<ROUTE> tempBestRoutes = startRoutes;
int tempBestProfit = profit;
List<Customer> tempBestU = u;
int tempBestDistance = totalDistance(tempBestRoutes);
ELIMINATOR e = new ELIMINATOR(bestU, bestRoutes, bestProfit, initialization, name, rnd);
while (noImprLS <= noImprUB)
{
System.out.print(noImprLS);
boolean improvement = false;
long starttime = System.nanoTime();
double timeE = 0;
for (int i = 1; i <= N; i++)
{
long starttimeE = System.nanoTime();
e = new ELIMINATOR(bestU, bestRoutes, bestProfit, initialization, name, rnd);
timeE = timeE + (System.nanoTime()-starttimeE)/1000000000.0;
POSTPROCEDURE pp = new POSTPROCEDURE(e.getRoutes(), profitRoutes(e.getRoutes()), e.getU(), name);
for (int p = 0; p < pp.getBestSolution().size(); p++)
{
ROUTE r = pp.getBestSolution().get(p);
addToPOOL(r);
}
int tempprofit = pp.getTP();
int tempdistance = pp.getTD();
if (tempprofit > tempBestProfit)
{
tempBestRoutes = pp.getBestSolution();
tempBestProfit = tempprofit;
tempBestU = pp.getU();
tempBestDistance = tempdistance;
}
else if (tempprofit == tempBestProfit)
{
if (tempdistance < tempBestDistance)
{
tempBestRoutes = pp.getBestSolution();
tempBestProfit = tempprofit;
tempBestU = pp.getU();
tempBestDistance = tempdistance;
}
}
}
if (tempBestProfit > bestProfit)
{
// Move to better neighbor
bestRoutes = tempBestRoutes;
bestProfit = tempBestProfit;
bestU = tempBestU;
noImprLS = 0;
improvement = true;
System.out.print(" total profit: " + bestProfit);
}
else if (tempBestProfit == bestProfit)
{
if (totalDistance(tempBestRoutes) < totalDistance(bestRoutes))
{
// Move to better neighbor
bestRoutes = tempBestRoutes;
bestProfit = tempBestProfit;
bestU = tempBestU;
noImprLS = 0;
improvement = true;
System.out.print(" total profit: " + bestProfit + " total distance: " + totalDistance(bestRoutes));
}
}
if (improvement == false)
{
noImprLS++;
}
long endtime = System.nanoTime();
double duration = (endtime - starttime)/1000000000.0;
System.out.print(" duration: " + duration + " timeE: " + timeE + "\n");
}
解释 我知道代码很冗长,但这一切都非常重要。在这段代码中,我正在编写一个针对Time Orienteering Problem with Time Windows的算法(广泛的车辆路径问题)。我的目标是找到一套利润最大的好路线。在下面的示例中,bestRoutes和tempBestRoutes由4条不同的路由组成,profit(bestProfit / tempBestProfit)分别等于这些路由的总利润,而(temp)bestU是尚未包含在我的路由中的客户列表。
现在问题在于ELIMINATOR。此方法删除并添加一些客户。此类的输出用于PostProcedure,它也会更改路径中的某些事实。
我希望现在我的代码正在做什么。我正在考虑N个社区,我会选择最好的一个。如果最好的一个并不比我的起始解决方案好,那么我将noImprLS增加一个。我继续考虑新的nieghbours,直到我的上限连续迭代次数没有改善。
问题 现在的问题是,如果我没有找到更好的解决方案,因此我继续在ELIMINATOR中插入相同的路线和利润,我的计算时间也会增加。
一些示例,其中duration表示while循环中迭代的时间,timeE表示for循环中ELIMINATOR的总时间是多少。很明显,ELIMINATOR会导致持续时间增加。
0总利润:800持续时间:0.486570471 timeE:0.16644330999999998
0总利润:900持续时间:0.431213528时间:0.11342619799999998
0总利润:950持续时间:0.444671005 timeE:0.12090608200000001
0总利润:960期限:0.519406695时间:0.16836757300000005
0持续时间:0.460473438 timeE:0.137813155
1持续时间:0.572109775 timeE:0.30774360900000003
2持续时间:0.698965292 timeE:0.471859029
3持续时间:0.918376211 timeE:0.686916669
4持续时间:1.165481175 timeE:0.92621492
5持续时间:1.326080436 timeE:1.0874366910000002
6持续时间:2.006102605 timeE:1.674879135
7持续时间:2.787172112 timeE:2.4276636639999993
8持续时间:2.042213493 timeE:1.7967797849999998
9持续时间:2.652985618 timeE:2.3503671230000003
10持续时间:2.422183993 timeE:2.1859969810000006
消除器代码:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class ELIMINATOR extends BASIS
{
private List<Customer> u;
private List<ROUTE> routes;
private int totalprofit;
private Random prob;
public ELIMINATOR(List<Customer> u, List<ROUTE> routes, int profit, boolean initialization, String name, Random rnd)
{
super(name);
this.u = u;
this.routes = routes;
this.totalprofit = profit;
this.prob = rnd;
if (initialization == true)
{
addCustomers();
for (ROUTE route : routes)
{
checkCorrectNess(route, "after adding procedure in eliminator");
}
}
else
{
removeCustomers();
for (ROUTE route : routes)
{
checkCorrectNess(route, "after removing procedure in eliminator");
}
addCustomers();
for (ROUTE route : routes)
{
checkCorrectNess(route, "after removing and adding procedure in eliminator");
}
}
}
public void removeCustomers()
{
double Ph = 0.1;
double Pl = 0.3;
double total_profit = totalprofit;
int num_customers = 0;
// Calculate the total profit and total number of customers in the routes
for(ROUTE route : routes)
{
num_customers = num_customers + (route.getLocations().size()-2);
}
// Calculate average profit
double average_profit = total_profit/num_customers;
// For each customer on each route, determine whether he/she will be removed
for(ROUTE r : routes)
{
List<RouteNode> route = r.getLocations();
int routesize = route.size();
int j = 1;
while (j < routesize-1)
{
boolean removed = false;
RouteNode node = route.get(j);
if (node.customer.getProfit() >= average_profit)
{
if (prob.nextDouble() < Ph)
{
removed = true;
RouteNode node_toberemoved = node;
int index_node = route.indexOf(node);
route.remove(index_node);
u.add(node.customer);
route = removal(route, node_toberemoved, index_node);
r.setLocations(route);
r.setDistance(distanceOneRoute(route));
r.setProfit(profitOneRoute(route));
checkCorrectNess(r, "remove customers eliminator");
}
}
else
{
if (prob.nextDouble() < Pl)
{
removed = true;
RouteNode node_toberemoved = node;
int index_node = route.indexOf(node);
route.remove(index_node);
u.add(node.customer);
route = removal(route, node_toberemoved, index_node);
r.setLocations(route);
r.setDistance(distanceOneRoute(route));
r.setProfit(profitOneRoute(route));
checkCorrectNess(r, "remove customers eliminator");
}
}
if (removed == false)
{
j++;
}
else
{
routesize = route.size();
total_profit = total_profit-node.customer.getProfit();
average_profit = total_profit/num_customers;
}
}
}
totalprofit = profitRoutes(routes);
}
public void addCustomers()
{
List<Customer> u_copy = new ArrayList<Customer>(u);
List<Customer> u_temp = new ArrayList<Customer>(u);
for (Customer c : u_temp)
{
boolean added = false;
for (ROUTE r : routes)
{
checkCorrectNess(r, "add customers eliminator");
if (added == true)
{
break;
}
Customer customer = c;
u_copy.remove(c);
List<RouteNode> route = r.getLocations();
for (int i = 0; i < route.size()-1; i++)
{
RouteNode possibleNode = new RouteNode();
possibleNode.customer = customer;
List<Integer> distances = calculateDistances(route.get(i), possibleNode, route.get(i+1));
// Calculate shift for customer under consideration
int arrivalTime = route.get(i).timeStartService+ route.get(i).customer.getService() + distances.get(0);
int wait = Math.max(0, customer.getOpeningTW()-arrivalTime);
int serviceDuration = customer.getService();
int shift = distances.get(0) + wait + serviceDuration + distances.get(2) - distances.get(1);
// Determine Start Service
int startServiceTime = Math.max(customer.getOpeningTW(), arrivalTime);
// Obtain waiting time of next customer
int waiting_next = route.get(i+1).wait;
// Obtain MaxShift of next customer
int maxShift = route.get(i+1).maxShift;
if (shift <= (waiting_next + maxShift) & startServiceTime <= customer.getClosingTW() )
{
// Customer can be inserted
added = true;
RouteNode newNode = new RouteNode();
newNode.customer = customer;
newNode.arrivalTime = arrivalTime;
newNode.timeStartService = startServiceTime;
newNode.shift = shift;
newNode.wait = wait;
int pos_insertion = i + 1;
route = ADD(route, newNode, pos_insertion);
r.setLocations(route);
r.setDistance(distanceOneRoute(route));
r.setProfit(profitOneRoute(route));
checkCorrectNess(r, "add customers eliminator");
// exit the last for loop
break;
}
}
}
if (added == false)
{
u_copy.add(c);
}
}
u = u_copy;
totalprofit = profitRoutes(routes);
}
/**
* Returns list of unvisited customers
* @return
*/
public List<Customer> getU()
{
return u;
}
/**
* Returns list of routes
* @return
*/
public List<ROUTE> getRoutes()
{
return routes;
}
}