private Set<Integer> getPossibleNumberOfDepartures(
     Set<Integer> unvisitedDays,
     HashMap<Integer, Set<Integer>> individualVesselDeparturePatterns,
     int alreadyVisitedDaysAvailable) {
   int maxDeparturesInPattern =
       Collections.max(
           problemData
               .getVesselDeparturePatterns()
               .keySet()); // the maximum number of departures found in any vessel pattern
   int minimumNumberOfDepartures =
       Math.max(
           0,
           maxDeparturesInPattern
               - alreadyVisitedDaysAvailable); // e.g. if the patterns have max 3 visits and only 1
                                               // day that is already visited can be a part of the
                                               // pattern, the minimum pattern size is 2 (since
                                               // there are 2 unvisited days)
   Set<Integer> allNumberOfDepartures = problemData.getVesselDeparturePatterns().keySet();
   Set<Integer> possibleNumberOfDepartures = new HashSet<Integer>();
   for (Integer numberOfDepartures : allNumberOfDepartures) {
     if (numberOfDepartures >= minimumNumberOfDepartures) {
       possibleNumberOfDepartures.add(numberOfDepartures);
     }
   }
   return possibleNumberOfDepartures;
 }
 private Set<Integer> pickRandomVesselDeparturePattern(
     Set<Integer> daysWithDeparture,
     HashMap<Integer, Set<Integer>> individualVesselDeparturePatterns) {
   Set<Integer> unvisitedDays =
       getUnvisitedDays(
           daysWithDeparture,
           individualVesselDeparturePatterns); // the set of days that installations require a
                                               // departure and no vessel depart on
   int alreadyVisitedDaysAvailable =
       getAlreadyVisitedDaysAvailable(
           individualVesselDeparturePatterns,
           unvisitedDays); // the number of days that already have visits that the vessel pattern
                           // can contain
   Set<Integer> possibleNumberOfDepartures =
       getPossibleNumberOfDepartures(
           unvisitedDays,
           individualVesselDeparturePatterns,
           alreadyVisitedDaysAvailable); // the set of number of departures that a valid vessel
                                         // pattern can have, e.g. if it's the last vessel and
                                         // there are still 3 unvisited days, the vessel pattern
                                         // must have 3 depatures
   int unvisitedDaysThatNeedsVisit = Collections.min(possibleNumberOfDepartures);
   int numberOfVesselDepartures =
       Utilities.pickRandomElementFromSet(
           possibleNumberOfDepartures); // select a random number from the set of possible number
                                        // of departures
   Set<Set<Integer>> allPatternsForNumberOfDepartures =
       problemData.getVesselDeparturePatterns().get(numberOfVesselDepartures);
   Set<Set<Integer>> possibleVesselDeparturePatterns =
       getPossibleVesselPatterns(
           allPatternsForNumberOfDepartures,
           individualVesselDeparturePatterns,
           unvisitedDays,
           unvisitedDaysThatNeedsVisit); // get all vessel patterns with the selected number of
                                         // departures that visit enough of the unvisited
                                         // installations, e.g. if it's the last vessel the pattern
                                         // has to visit all unvisited installations
   if (possibleVesselDeparturePatterns.size()
       == 0) { // workaround until a smarter heuristic is fixed
     System.out.println("No possible patterns, start over!");
     return null;
   }
   return Utilities.pickRandomElementFromSet(possibleVesselDeparturePatterns);
 }
 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;
 }