private HashMap<Integer, Set<Integer>> createVesselDepartureChromosome(
     HashMap<Integer, Set<Integer>> installationDepartureChromosome) {
   HashMap<Integer, Set<Integer>> individualVesselDeparturePatterns =
       new HashMap<Integer, Set<Integer>>();
   Set<Integer> daysWithDeparture =
       getDaysWithDeparture(
           installationDepartureChromosome); // get all days that installations require a departure
   for (Vessel vessel :
       problemData
           .getVessels()) { // for each vessel, choose a random vessel pattern that fits with the
                            // installationDepartureChromosome
     Set<Integer> randomVesselDeparturePattern =
         pickRandomVesselDeparturePattern(daysWithDeparture, individualVesselDeparturePatterns);
     if (randomVesselDeparturePattern == null) { // workaround until a smarter heuristic is created
       numberOfPatternRestarts++;
       return createVesselDepartureChromosome(installationDepartureChromosome);
     }
     individualVesselDeparturePatterns.put(vessel.getNumber(), randomVesselDeparturePattern);
   }
   if (isDepotConstraintViolated(individualVesselDeparturePatterns)) {
     numberOfDepotRestarts++;
     return createVesselDepartureChromosome(installationDepartureChromosome);
   }
   return individualVesselDeparturePatterns;
 }
 private int getAlreadyVisitedDaysAvailable(
     HashMap<Integer, Set<Integer>> individualVesselDeparturePatterns,
     Set<Integer> unvisitedDays) {
   int vesselsLeft =
       problemData.getVessels().size()
           - individualVesselDeparturePatterns.keySet().size(); // number of unchartered vessels
   int maxDeparturesInPattern =
       Collections.max(
           problemData
               .getVesselDeparturePatterns()
               .keySet()); // the maximum number of departures found in any vessel pattern
   int alreadyVisitedDaysAvailable =
       (vesselsLeft * maxDeparturesInPattern
           - unvisitedDays
               .size()); // if there is 1 unchartered vessel and the patterns have maximum 3
                         // departures and there are 2 days without departures, at most 1*3 - 2 = 1
                         // day that already has a departure can be part of the new pattern
   return alreadyVisitedDaysAvailable;
 }
  private HashMap<Integer, HashMap<Integer, ArrayList<Integer>>> createGiantTourChromosome(
      HashMap<Integer, Set<Integer>> installationDepartureChromosome,
      HashMap<Integer, Set<Integer>> vesselDepartureChromosome) {
    HashMap<Integer, Set<Integer>> reversedInstallationChromosome =
        Utilities.getReversedHashMap(
            installationDepartureChromosome); // the key is a period/day and the Set<Integer> is a
                                              // set of installation numbers
    HashMap<Integer, Set<Integer>> reversedVesselChromosome =
        Utilities.getReversedHashMap(
            vesselDepartureChromosome); // the key is a period/day, and the Set<Integer> is a set of
                                        // vessel numbers

    int nDays = problemData.getLengthOfPlanningPeriod();
    int nVessels = problemData.getVessels().size();
    // initializing
    HashMap<Integer, HashMap<Integer, ArrayList<Integer>>> giantTourChromosome =
        GenotypeHGS.generateEmptyGiantTourChromosome(nDays, nVessels);

    // allocating
    for (Integer day : reversedInstallationChromosome.keySet()) {
      Set<Integer> installationsToAllocate = reversedInstallationChromosome.get(day);
      Set<Integer> availableVessels = reversedVesselChromosome.get(day);
      HashMap<Integer, ArrayList<Integer>> vesselAllocations = giantTourChromosome.get(day);
      for (Integer installation : installationsToAllocate) {
        Integer randomVessel = Utilities.pickRandomElementFromSet(availableVessels);
        ArrayList<Integer> existingInstallations = vesselAllocations.get(randomVessel);
        existingInstallations.add(installation);
        vesselAllocations.put(randomVessel, existingInstallations);
      }
      giantTourChromosome.put(day, vesselAllocations);
    }

    // shuffle sequence of visits
    for (Integer day : giantTourChromosome.keySet()) {
      for (Integer vessel : giantTourChromosome.get(day).keySet()) {
        ArrayList<Integer> installationsToVisit = giantTourChromosome.get(day).get(vessel);
        Collections.shuffle(installationsToVisit);
      }
    }

    return giantTourChromosome;
  }