package GeneticAlgorithm;
import Main.Controller;
import MapObjects.Customer;
import MapObjects.Depot;
import MapObjects.Vehicle;
import Utils.Utils;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* One Individual in Population 种群中的一个个体(染色体即路线)
* Contains Routes from all Vehicles 包括所有车辆的路线
*/
public class Individual {
private List<Depot> depots;// 几个仓库
private List<Vehicle> vehicles; // 仓库对应的车
private int durationPenaltyRate; // 持续惩罚率
private int loadPenaltyRate; // 负荷惩罚率
private double fitness; // 评价值
private boolean isValid; // 有效判断
/**
* Generates initialSolution and calculates distances Individual构造函数生成初始结果并计算距离
*
* @param depots
* @param durationPenaltyRate
* @param loadPenaltyRate
*/
public Individual(List<Depot> depots, int durationPenaltyRate, int loadPenaltyRate) {
this.depots = depots;
this.durationPenaltyRate = durationPenaltyRate;
this.loadPenaltyRate = loadPenaltyRate;
vehicles = new ArrayList<>();
calculateFitness();
}
public Individual(List<Depot> depots, int durationPenaltyRate, int loadPenaltyRate, List<Vehicle> vehicles) {
this.depots = depots;
this.durationPenaltyRate = durationPenaltyRate;
this.loadPenaltyRate = loadPenaltyRate;
this.vehicles = new ArrayList<>(vehicles);
calculateFitness();
}
public boolean generateOptimizedIndividual(boolean force) { //精英选择1
for (Depot depot : depots) {
List<Vehicle> depotVehicles = createDepotVehicles(depot);
List<Customer> depotCustomers = new ArrayList<>(depot.getCustomers()); // Current depot's customers
Collections.shuffle(depotCustomers);
for (Customer customer : depotCustomers) {
boolean customerAdded = false;
int triesLeft = 100;
while (!customerAdded && triesLeft > 0) {
double minDuration = Double.MAX_VALUE;
int minRouteIndex = -1;
Vehicle minVehicle = null;
Collections.shuffle(depotVehicles);
for (Vehicle vehicle : depotVehicles) {
double tempMinDuration = Double.MAX_VALUE;
int tempRouteIndex = -1;
if (vehicle.getCurrentLoad() + customer.getLoadDemand() <= depot.getMaxLoad()) {
if (vehicle.getRoute().size() == 0) {
tempMinDuration = vehicle.calculateRouteDurationIfCustomerAdded(0, customer);
tempRouteIndex = 0;
} else {
for (int i = 0; i < vehicle.getRoute().size(); i++) {
double tempDuration = vehicle.calculateRouteDurationIfCustomerAdded(i, customer);
if (tempDuration < tempMinDuration) {
tempMinDuration = tempDuration;
tempRouteIndex = i;
}
}
}
}
if (tempMinDuration < minDuration) {
minDuration = tempMinDuration;
minRouteIndex = tempRouteIndex;
minVehicle = vehicle;
}
}
if (minVehicle == null) {
triesLeft--;
} else {
minVehicle.addCustomerToRoute(minRouteIndex, customer);
if (depot.getMaxDuration() != 0.0 && minVehicle.calculateRouteDuration() > depot.getMaxDuration() && !force) {
minVehicle.removeCustomerFromRoute(customer);
triesLeft--;
} else {
customerAdded = true;
}
}
}
if (triesLeft == 0 && !force) { // Giving up generating this initial isValid
return false;
}
}
this.vehicles.addAll(depotVehicles);
}
return true;
}
public boolean generateOptimizedIndividual2(boolean force) { //精英选择2
for (Depot depot : depots) {
List<Vehicle> depotVehicles = createDepotVehicles(depot);
List<Customer> depotCustomers = depot.getCustomers(); // Current depot's customers
Collections.shuffle(depotCustomers);
int triesLeft = 100;
for (Customer customer : depotCustomers) { // Assign customer to random vehicle
boolean customerAdded = false;
while (!customerAdded && triesLeft > 0) {
int randomIndex = Utils.randomIndex(depotVehicles.size()); // Random vehicle index
Vehicle randomVehicle = depotVehicles.get(randomIndex);
customerAdded = randomVehicle.smartAddCustomerToRoute(customer, force);
if (!customerAdded) {
triesLeft--;
}
}
if (triesLeft == 0) { // Giving up generating this initial isValid
return false;
}
}
this.vehicles.addAll(depotVehicles);
}
return true;
}
public boolean generateRandomIndividual() { //随机选择1(灾变)
for (Depot depot : depots) {
List<Vehicle> depotVehicles = createDepotVehicles(depot);
List<Customer> depotCustomers = depot.getCustomers(); // Current depot's customers
Collections.shuffle(depotCustomers);
for (Customer customer : depotCustomers) { // Assign customer to random vehicle
boolean customerAdded = false;
int randomIndex = Utils.randomIndex(depotVehicles.size()); // Random vehicle index
Vehicle randomVehicle = depotVehicles.get(randomIndex);
while (!customerAdded) {
customerAdded = randomVehicle.addCustomerToRoute(customer);
}
}
this.vehicles.addAll(depotVehicles);
}
return true;
}
/**
* Performs n random mutations on the vehicles based on the mutationRate
* Mutation is only executed if random < crossOverRate
*/
public List<Vehicle> swapMutation() {//变异函数1
// Copy of vehicles
List<Vehicle> newVehicles = deepCopyVehicles();
int randomIndex = Utils.randomIndex(vehicles.size());
Vehicle vehicle = vehicles.get(randomIndex);
List<Customer> newRoute = vehicle.swapMutate();
Vehicle newVehicle = new Vehicle(vehicle.getStartDepot(), newRoute);
newVehicles.remove(vehicle);
newVehicles.add(newVehicle);
return newVehicles;
}
public List<Vehicle> swapMutation2() {//变异函数2
// Copy of vehicles
List<Vehicle> newVehicles = deepCopyVehicles();
int randomIndex1 = Utils.randomIndex(newVehicles.size());
int randomIndex2 = Utils.randomIndex(newVehicles.size());
Vehicle vehicle1 = newVehicles.get(randomIndex1);
Vehicle vehicle2 = newVehicles.get(randomIndex2);
randomIndex1 = Utils.randomIndex(vehicle1.getRoute().size());
randomIndex2 = Utils.randomIndex(vehicle2.getRoute().size());
Customer customer1 = null;
Customer customer2 = null;