private void createBedDesignationList() {
   List<AdmissionPart> admissionPartList = patientAdmissionSchedule.getAdmissionPartList();
   List<BedDesignation> bedDesignationList =
       new ArrayList<BedDesignation>(admissionPartList.size());
   long id = 0L;
   for (AdmissionPart admissionPart : admissionPartList) {
     BedDesignation bedDesignation = new BedDesignation();
     bedDesignation.setId(id);
     id++;
     bedDesignation.setAdmissionPart(admissionPart);
     // Notice that we leave the PlanningVariable properties on null
     bedDesignationList.add(bedDesignation);
   }
   patientAdmissionSchedule.setBedDesignationList(bedDesignationList);
 }
 private void readBedList() throws IOException {
   readConstantLine("BEDS:");
   List<Bed> bedList = new ArrayList<Bed>(bedListSize);
   Map<Room, Integer> roomToLastIndexInRoomMap = new HashMap<Room, Integer>(roomListSize);
   for (int i = 0; i < bedListSize; i++) {
     String line = bufferedReader.readLine();
     String[] lineTokens = splitBySpace(line, 2);
     Bed bed = new Bed();
     bed.setId(Long.parseLong(lineTokens[0]));
     Room room = idToRoomMap.get(Long.parseLong(lineTokens[1]));
     bed.setRoom(room);
     Integer indexInRoom = roomToLastIndexInRoomMap.get(room);
     if (indexInRoom == null) {
       indexInRoom = 0;
     } else {
       indexInRoom++;
     }
     bed.setIndexInRoom(indexInRoom);
     roomToLastIndexInRoomMap.put(room, indexInRoom);
     bedList.add(bed);
   }
   Collections.sort(
       bedList,
       new Comparator<Bed>() {
         public int compare(Bed a, Bed b) {
           return new CompareToBuilder()
               .append(a.getRoom().getDepartment().getId(), b.getRoom().getDepartment().getId())
               .append(a.getRoom().getId(), b.getRoom().getId())
               .append(a.getIndexInRoom(), b.getIndexInRoom())
               .append(a.getId(), b.getId())
               .toComparison();
         }
       });
   patientAdmissionSchedule.setBedList(bedList);
 }
 private void generateNightList() {
   List<Night> nightList = new ArrayList<Night>(nightListSize);
   indexToNightMap = new HashMap<Integer, Night>(nightListSize);
   long nightId = 0L;
   for (int i = 0; i < nightListSize; i++) {
     Night night = new Night();
     night.setId(nightId);
     night.setIndex(i);
     nightList.add(night);
     indexToNightMap.put(i, night);
     nightId++;
   }
   patientAdmissionSchedule.setNightList(nightList);
 }
 private void readEquipmentList() throws IOException {
   readConstantLine("ROOMPROPERTIES:");
   List<Equipment> equipmentList = new ArrayList<Equipment>(equipmentListSize);
   indexToEquipmentMap = new HashMap<Integer, Equipment>(equipmentListSize);
   for (int i = 0; i < equipmentListSize; i++) {
     String line = bufferedReader.readLine();
     String[] lineTokens = splitBySpace(line, 2);
     Equipment equipment = new Equipment();
     equipment.setId(Long.parseLong(lineTokens[0]));
     equipment.setName(lineTokens[1]);
     equipmentList.add(equipment);
     indexToEquipmentMap.put(i, equipment);
   }
   patientAdmissionSchedule.setEquipmentList(equipmentList);
 }
 private void readSpecialismList() throws IOException {
   readConstantLine("SPECIALISMS:");
   List<Specialism> specialismList = new ArrayList<Specialism>(specialismListSize);
   idToSpecialismMap = new HashMap<Long, Specialism>(specialismListSize);
   for (int i = 0; i < specialismListSize; i++) {
     String line = bufferedReader.readLine();
     String[] lineTokens = splitBySpace(line, 2);
     Specialism specialism = new Specialism();
     specialism.setId(Long.parseLong(lineTokens[0]));
     specialism.setName(lineTokens[1]);
     specialismList.add(specialism);
     idToSpecialismMap.put(specialism.getId(), specialism);
   }
   patientAdmissionSchedule.setSpecialismList(specialismList);
 }
 public Solution readSolution() throws IOException {
   patientAdmissionSchedule = new PatientAdmissionSchedule();
   patientAdmissionSchedule.setId(0L);
   readSizes();
   readEmptyLine();
   readEmptyLine();
   readSpecialismList();
   readEmptyLine();
   readDepartmentListAndDepartmentSpecialismList();
   readEmptyLine();
   readEquipmentList();
   readEmptyLine();
   readRoomListAndRoomSpecialismListAndRoomEquipmentList();
   readEmptyLine();
   readBedList();
   readEmptyLine();
   generateNightList();
   readPatientListAndAdmissionPartListAndRequiredPatientEquipmentListAndPreferredPatientEquipmentList();
   readEmptyLine();
   readConstantLine("END.");
   createBedDesignationList();
   // TODO not all nights are planned, only the "planning horizon" nights are planned
   BigInteger possibleSolutionSize =
       BigInteger.valueOf(patientAdmissionSchedule.getBedList().size())
           .pow(patientAdmissionSchedule.getAdmissionPartList().size());
   String flooredPossibleSolutionSize = "10^" + (possibleSolutionSize.toString().length() - 1);
   logger.info(
       "PatientAdmissionSchedule {} has {} specialisms, {} equipments, {} departments, {} rooms, "
           + "{} beds, {} nights, {} patients and {} admissions with a search space of {}.",
       getInputId(),
       patientAdmissionSchedule.getSpecialismList().size(),
       patientAdmissionSchedule.getEquipmentList().size(),
       patientAdmissionSchedule.getDepartmentList().size(),
       patientAdmissionSchedule.getRoomList().size(),
       patientAdmissionSchedule.getBedList().size(),
       patientAdmissionSchedule.getNightList().size(),
       patientAdmissionSchedule.getPatientList().size(),
       patientAdmissionSchedule.getAdmissionPartList().size(),
       flooredPossibleSolutionSize);
   return patientAdmissionSchedule;
 }
    private void
        readPatientListAndAdmissionPartListAndRequiredPatientEquipmentListAndPreferredPatientEquipmentList()
            throws IOException {
      readConstantLine("PATIENTS:");
      List<Patient> patientList = new ArrayList<Patient>(patientListSize);
      List<AdmissionPart> admissionPartList = new ArrayList<AdmissionPart>(patientListSize);
      List<RequiredPatientEquipment> requiredPatientEquipmentList =
          new ArrayList<RequiredPatientEquipment>(patientListSize * equipmentListSize);
      List<PreferredPatientEquipment> preferredPatientEquipmentList =
          new ArrayList<PreferredPatientEquipment>(patientListSize * equipmentListSize);
      long admissionPartId = 0L;
      long requiredPatientEquipmentId = 0L;
      long preferredPatientEquipmentId = 0L;
      for (int i = 0; i < patientListSize; i++) {
        String line = bufferedReader.readLine();
        String[] lineTokens = splitByPipelineAndTrim(line, 6);

        String[] nightTokens = splitBySpace(lineTokens[1], 2);
        int firstNightIndex = Integer.parseInt(nightTokens[0]);
        int lastNightIndex = Integer.parseInt(nightTokens[1]);
        int patientNightListSize = lastNightIndex - firstNightIndex;
        // A patient with no nights in the planning horizon or no nights at all is ignored
        if (firstNightIndex >= nightListSize || patientNightListSize == 0) {
          continue;
        }

        String[] patientTokens = splitBySpace(lineTokens[0], 4);
        Patient patient = new Patient();
        patient.setId(Long.parseLong(patientTokens[0]));
        patient.setName(patientTokens[1]);
        patient.setAge(Integer.parseInt(patientTokens[2]));
        patient.setGender(Gender.valueOfCode(patientTokens[3]));
        int preferredMaximumRoomCapacity = Integer.parseInt(lineTokens[3]);
        patient.setPreferredMaximumRoomCapacity(
            preferredMaximumRoomCapacity == 0 ? null : preferredMaximumRoomCapacity);
        patientList.add(patient);

        String[] admissionPartTokens = splitBySpace(lineTokens[2]);
        int patientAdmissionPartListSize = Integer.parseInt(admissionPartTokens[0]);
        if (admissionPartTokens.length != ((patientAdmissionPartListSize * 2) + 1)) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") is expected to contain "
                  + ((patientAdmissionPartListSize * 2) + 1)
                  + " number of tokens after 2th pipeline (|).");
        }
        int nextFirstNightIndex = firstNightIndex;
        for (int j = 1; j < admissionPartTokens.length; j += 2) {
          long specialismId = Long.parseLong(admissionPartTokens[j]);
          int admissionPartNightListSize = Integer.parseInt(admissionPartTokens[j + 1]);
          if (nextFirstNightIndex >= nightListSize || admissionPartNightListSize == 0) {
            nextFirstNightIndex += admissionPartNightListSize;
            continue;
          }
          AdmissionPart admissionPart = new AdmissionPart();
          admissionPart.setId(admissionPartId);
          admissionPart.setPatient(patient);
          Specialism specialism = (specialismId == 0) ? null : idToSpecialismMap.get(specialismId);
          if (specialism == null) {
            throw new IllegalArgumentException(
                "Read line (" + line + ") has a non existing specialismId (" + specialismId + ").");
          }
          admissionPart.setSpecialism(specialism);
          int admissionPartFirstNightIndex = nextFirstNightIndex;
          Night admissionPartFirstNight = indexToNightMap.get(admissionPartFirstNightIndex);
          if (admissionPartFirstNight == null) {
            throw new IllegalStateException(
                "The admissionPartFirstNight was not found for admissionPartFirstNightIndex("
                    + admissionPartFirstNightIndex
                    + ").");
          }
          admissionPart.setFirstNight(admissionPartFirstNight);
          int admissionPartLastNightIndex = nextFirstNightIndex + admissionPartNightListSize - 1;
          // TODO Instead of ensureEnoughNights(lastNightIndex);
          // the official score function ignores any broken constraints after the planning horizon
          if (admissionPartLastNightIndex >= nightListSize) {
            admissionPartLastNightIndex = nightListSize - 1;
          }
          Night admissionPartLastNight = indexToNightMap.get(admissionPartLastNightIndex);
          if (admissionPartLastNight == null) {
            throw new IllegalStateException(
                "The admissionPartLastNight was not found for admissionPartLastNightIndex("
                    + admissionPartLastNightIndex
                    + ").");
          }
          admissionPart.setLastNight(admissionPartLastNight);
          admissionPartList.add(admissionPart);
          admissionPartId++;
          nextFirstNightIndex += admissionPartNightListSize;
        }
        int admissionPartNightListSizeSum = nextFirstNightIndex - firstNightIndex;
        if (patientNightListSize != admissionPartNightListSizeSum) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") has patientNightListSize ("
                  + patientNightListSize
                  + ") different from admissionPartNightListSizeSum("
                  + admissionPartNightListSizeSum
                  + ")");
        }

        String[] requiredPatientEquipmentTokens = splitBySpace(lineTokens[4]);
        if (requiredPatientEquipmentTokens.length != equipmentListSize) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") is expected to contain equal number of tokens ("
                  + requiredPatientEquipmentTokens.length
                  + ") as equipmentListSize ("
                  + equipmentListSize
                  + ") after 4th pipeline (|).");
        }
        List<RequiredPatientEquipment> requiredPatientEquipmentOfPatientList =
            new ArrayList<RequiredPatientEquipment>(equipmentListSize);
        for (int j = 0; j < requiredPatientEquipmentTokens.length; j++) {
          int hasEquipment = Integer.parseInt(requiredPatientEquipmentTokens[j]);
          if (hasEquipment == 1) {
            RequiredPatientEquipment requiredPatientEquipment = new RequiredPatientEquipment();
            requiredPatientEquipment.setId(requiredPatientEquipmentId);
            requiredPatientEquipment.setPatient(patient);
            requiredPatientEquipment.setEquipment(indexToEquipmentMap.get(j));
            requiredPatientEquipmentOfPatientList.add(requiredPatientEquipment);
            requiredPatientEquipmentList.add(requiredPatientEquipment);
            requiredPatientEquipmentId++;
          } else if (hasEquipment != 0) {
            throw new IllegalArgumentException(
                "Read line ("
                    + line
                    + ") is expected to have 0 or 1 hasEquipment ("
                    + hasEquipment
                    + ").");
          }
        }
        patient.setRequiredPatientEquipmentList(requiredPatientEquipmentOfPatientList);

        String[] preferredPatientEquipmentTokens = splitBySpace(lineTokens[5]);
        if (preferredPatientEquipmentTokens.length != equipmentListSize) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") is expected to contain equal number of tokens ("
                  + preferredPatientEquipmentTokens.length
                  + ") as equipmentListSize ("
                  + equipmentListSize
                  + ") after 5th pipeline (|).");
        }
        List<PreferredPatientEquipment> preferredPatientEquipmentOfPatientList =
            new ArrayList<PreferredPatientEquipment>(equipmentListSize);
        for (int j = 0; j < preferredPatientEquipmentTokens.length; j++) {
          int hasEquipment = Integer.parseInt(preferredPatientEquipmentTokens[j]);
          if (hasEquipment == 1) {
            boolean alreadyRequired = (Integer.parseInt(requiredPatientEquipmentTokens[j]) == 1);
            // Official spec: if equipment is required
            // then a duplicate preffered constraint should be ignored
            if (!alreadyRequired) {
              PreferredPatientEquipment preferredPatientEquipment = new PreferredPatientEquipment();
              preferredPatientEquipment.setId(preferredPatientEquipmentId);
              preferredPatientEquipment.setPatient(patient);
              preferredPatientEquipment.setEquipment(indexToEquipmentMap.get(j));
              preferredPatientEquipmentOfPatientList.add(preferredPatientEquipment);
              preferredPatientEquipmentList.add(preferredPatientEquipment);
              preferredPatientEquipmentId++;
            }
          } else if (hasEquipment != 0) {
            throw new IllegalArgumentException(
                "Read line ("
                    + line
                    + ") is expected to have 0 or 1 hasEquipment ("
                    + hasEquipment
                    + ").");
          }
        }
        patient.setPreferredPatientEquipmentList(preferredPatientEquipmentOfPatientList);
      }
      patientAdmissionSchedule.setPatientList(patientList);
      patientAdmissionSchedule.setAdmissionPartList(admissionPartList);
      patientAdmissionSchedule.setRequiredPatientEquipmentList(requiredPatientEquipmentList);
      patientAdmissionSchedule.setPreferredPatientEquipmentList(preferredPatientEquipmentList);
    }
    private void readRoomListAndRoomSpecialismListAndRoomEquipmentList() throws IOException {
      readConstantLine("ROOMS:");
      List<Room> roomList = new ArrayList<Room>(roomListSize);
      idToRoomMap = new HashMap<Long, Room>(roomListSize);
      List<RoomSpecialism> roomSpecialismList = new ArrayList<RoomSpecialism>(roomListSize * 5);
      List<RoomEquipment> roomEquipmentList = new ArrayList<RoomEquipment>(roomListSize * 2);
      long roomSpecialismId = 0L;
      long roomEquipmentId = 0L;
      for (int i = 0; i < roomListSize; i++) {
        String line = bufferedReader.readLine();
        String[] lineTokens = splitByPipelineAndTrim(line, 6);

        String[] roomTokens = splitBySpace(lineTokens[0], 2);
        Room room = new Room();
        room.setId(Long.parseLong(roomTokens[0]));
        room.setName(roomTokens[1]);
        room.setCapacity(Integer.parseInt(lineTokens[1]));
        room.setDepartment(idToDepartmentMap.get(Long.parseLong(lineTokens[2])));
        room.setGenderLimitation(GenderLimitation.valueOfCode(lineTokens[3]));
        roomList.add(room);
        idToRoomMap.put(room.getId(), room);

        String[] roomSpecialismTokens = splitBySpace(lineTokens[4]);
        if (roomSpecialismTokens.length % 2 != 0) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") is expected to contain even number of tokens ("
                  + roomSpecialismTokens.length
                  + ") after 4th pipeline (|) separated by a space ( ).");
        }
        List<RoomSpecialism> roomSpecialismListOfRoom =
            new ArrayList<RoomSpecialism>(roomSpecialismTokens.length / 2);
        for (int j = 0; j < roomSpecialismTokens.length; j += 2) {
          int priority = Integer.parseInt(roomSpecialismTokens[j]);
          long specialismId = Long.parseLong(roomSpecialismTokens[j + 1]);
          if (specialismId != 0) {
            RoomSpecialism roomSpecialism = new RoomSpecialism();
            roomSpecialism.setId(roomSpecialismId);
            roomSpecialism.setRoom(room);
            Specialism specialism = idToSpecialismMap.get(specialismId);
            if (specialism == null) {
              throw new IllegalArgumentException(
                  "Read line ("
                      + line
                      + ") has a non existing specialismId ("
                      + specialismId
                      + ").");
            }
            roomSpecialism.setSpecialism(specialism);
            roomSpecialism.setPriority(priority);
            roomSpecialismListOfRoom.add(roomSpecialism);
            roomSpecialismList.add(roomSpecialism);
            roomSpecialismId++;
          }
        }
        room.setRoomSpecialismList(roomSpecialismListOfRoom);

        List<RoomEquipment> roomEquipmentListOfRoom =
            new ArrayList<RoomEquipment>(equipmentListSize);
        String[] roomEquipmentTokens = splitBySpace(lineTokens[5]);
        if (roomEquipmentTokens.length != equipmentListSize) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") is expected to contain equal number of tokens ("
                  + roomEquipmentTokens.length
                  + ") as equipmentListSize ("
                  + equipmentListSize
                  + ") after 5th pipeline (|).");
        }
        for (int j = 0; j < roomEquipmentTokens.length; j++) {
          int hasEquipment = Integer.parseInt(roomEquipmentTokens[j]);
          if (hasEquipment == 1) {
            RoomEquipment roomEquipment = new RoomEquipment();
            roomEquipment.setId(roomEquipmentId);
            roomEquipment.setRoom(room);
            roomEquipment.setEquipment(indexToEquipmentMap.get(j));
            roomEquipmentListOfRoom.add(roomEquipment);
            roomEquipmentList.add(roomEquipment);
            roomEquipmentId++;
          } else if (hasEquipment != 0) {
            throw new IllegalArgumentException(
                "Read line ("
                    + line
                    + ") is expected to have 0 or 1 hasEquipment ("
                    + hasEquipment
                    + ").");
          }
        }
        room.setRoomEquipmentList(roomEquipmentListOfRoom);
      }
      Collections.sort(
          roomList,
          new Comparator<Room>() {
            public int compare(Room a, Room b) {
              return new CompareToBuilder()
                  .append(a.getDepartment().getId(), b.getDepartment().getId())
                  .append(a.getId(), b.getId())
                  .toComparison();
            }
          });
      patientAdmissionSchedule.setRoomList(roomList);
      patientAdmissionSchedule.setRoomSpecialismList(roomSpecialismList);
      patientAdmissionSchedule.setRoomEquipmentList(roomEquipmentList);
    }
    private void readDepartmentListAndDepartmentSpecialismList() throws IOException {
      readConstantLine("DEPARTMENTS:");
      List<Department> departmentList = new ArrayList<Department>(departmentListSize);
      idToDepartmentMap = new HashMap<Long, Department>(departmentListSize);
      List<DepartmentSpecialism> departmentSpecialismList =
          new ArrayList<DepartmentSpecialism>(departmentListSize * 5);
      long departmentSpecialismId = 0L;
      for (int i = 0; i < departmentListSize; i++) {
        String line = bufferedReader.readLine();
        String[] lineTokens = splitByPipelineAndTrim(line, 2);

        String[] departmentTokens = splitBySpace(lineTokens[0], 4);
        Department department = new Department();
        department.setId(Long.parseLong(departmentTokens[0]));
        department.setName(departmentTokens[1]);
        int minimumAge = Integer.parseInt(departmentTokens[2]);
        if (minimumAge != 0) {
          department.setMinimumAge(Integer.valueOf(minimumAge));
        }
        int maximumAge = Integer.parseInt(departmentTokens[3]);
        if (maximumAge != 0) {
          department.setMaximumAge(Integer.valueOf(maximumAge));
        }
        departmentList.add(department);
        idToDepartmentMap.put(department.getId(), department);

        String[] departmentSpecialismTokens = splitBySpace(lineTokens[1]);
        if (departmentSpecialismTokens.length % 2 != 0) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") is expected to contain even number of tokens ("
                  + departmentSpecialismTokens.length
                  + ") after 1st pipeline (|) separated by a space ( ).");
        }
        for (int j = 0; j < departmentSpecialismTokens.length; j += 2) {
          long specialismId = Long.parseLong(departmentSpecialismTokens[j + 1]);
          if (specialismId != 0) {
            DepartmentSpecialism departmentSpecialism = new DepartmentSpecialism();
            departmentSpecialism.setId(departmentSpecialismId);
            departmentSpecialism.setDepartment(department);
            departmentSpecialism.setPriority(Integer.parseInt(departmentSpecialismTokens[j]));
            Specialism specialism = idToSpecialismMap.get(specialismId);
            if (specialism == null) {
              throw new IllegalArgumentException(
                  "Read line ("
                      + line
                      + ") has a non existing specialismId ("
                      + specialismId
                      + ").");
            }
            departmentSpecialism.setSpecialism(specialism);
            departmentSpecialismList.add(departmentSpecialism);
            departmentSpecialismId++;
          }
        }
      }
      Collections.sort(departmentList, new PersistableIdComparator());
      patientAdmissionSchedule.setDepartmentList(departmentList);
      patientAdmissionSchedule.setDepartmentSpecialismList(departmentSpecialismList);
    }