Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2010 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.planner.examples.travelingtournament.solver.smart.move.factory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.drools.planner.core.heuristic.selector.move.factory.MoveListFactory;
import org.drools.planner.core.move.Move;
import org.drools.planner.core.solution.Solution;
import org.drools.planner.examples.travelingtournament.domain.Day;
import org.drools.planner.examples.travelingtournament.domain.Match;
import org.drools.planner.examples.travelingtournament.domain.Team;
import org.drools.planner.examples.travelingtournament.domain.TravelingTournament;
import org.drools.planner.examples.travelingtournament.solver.smart.move.MultipleMatchListRotateMove;
// TODO rename to MatchRotationMoveFactory
public class SmartTravelingTournamentMoveFactory implements MoveListFactory {
public List createMoveList(Solution solution) {
TravelingTournament travelingTournament = (TravelingTournament) solution;
List moveList = new ArrayList();
RotationMovesFactory rotationMovesFactory = new RotationMovesFactory(travelingTournament);
rotationMovesFactory.addDayRotation(moveList);
rotationMovesFactory.addTeamRotation(moveList);
return moveList;
}
private static class RotationMovesFactory {
private List dayList;
private List teamList;
private List matchList;
private Map> dayTeamMap;
private Map> teamDayMap;
private Map> homeTeamAwayTeamMap;
public RotationMovesFactory(TravelingTournament travelingTournament) {
dayList = travelingTournament.getDayList();
teamList = travelingTournament.getTeamList();
matchList = travelingTournament.getMatchList();
createMaps();
}
private void createMaps() {
dayTeamMap = new HashMap>(dayList.size());
for (Day day : dayList) {
// This map should be ordered so the order of the matchRotationList is the same (when it's used as tabu)
dayTeamMap.put(day, new LinkedHashMap(teamList.size()));
}
teamDayMap = new HashMap>(teamList.size());
homeTeamAwayTeamMap = new HashMap>(teamList.size());
for (Team team : teamList) {
// This map should be ordered so the order of the matchRotationList is the same (when it's used as tabu)
teamDayMap.put(team, new LinkedHashMap(dayList.size()));
homeTeamAwayTeamMap.put(team, new LinkedHashMap(teamList.size() - 1));
}
for (Match match : matchList) {
Map subTeamMap = dayTeamMap.get(match.getDay());
subTeamMap.put(match.getHomeTeam(), match);
subTeamMap.put(match.getAwayTeam(), match);
teamDayMap.get(match.getHomeTeam()).put(match.getDay(), match);
teamDayMap.get(match.getAwayTeam()).put(match.getDay(), match);
homeTeamAwayTeamMap.get(match.getHomeTeam()).put(match.getAwayTeam(), match);
}
}
private Team getOtherTeam(Match match, Team team) {
return match.getHomeTeam().equals(team) ? match.getAwayTeam() : match.getHomeTeam();
}
/**
* @TODO clean up this code
*/
private void addDayRotation(List moveList) {
for (ListIterator firstDayIt = dayList.listIterator(); firstDayIt.hasNext();) {
Day firstDay = firstDayIt.next();
Map firstDayTeamMap = dayTeamMap.get(firstDay);
for (ListIterator secondDayIt = dayList.listIterator(firstDayIt.nextIndex()); secondDayIt.hasNext();) {
Day secondDay = secondDayIt.next();
List clonedFirstDayMatchList = new ArrayList(firstDayTeamMap.values());
while (!clonedFirstDayMatchList.isEmpty()) {
List rotateList = new ArrayList(4);
Match startMatch = clonedFirstDayMatchList.remove(0);
boolean otherInFirst = false;
rotateList.add(startMatch);
Team startHomeTeam = startMatch.getHomeTeam();
Team nextTeamToFind = startMatch.getAwayTeam();
while (!startHomeTeam.equals(nextTeamToFind)) {
Map subTeamMap = dayTeamMap.get(otherInFirst ? firstDay : secondDay);
Match repairMatch = subTeamMap.get(nextTeamToFind);
if (otherInFirst) {
clonedFirstDayMatchList.remove(repairMatch);
}
rotateList.add(repairMatch);
nextTeamToFind = getOtherTeam(repairMatch, nextTeamToFind);
otherInFirst = !otherInFirst;
}
// assert(rotateList.size() % 2 == 0);
// if size is 2 then addCachedHomeAwaySwapMoves will have done it
if (rotateList.size() > 2) {
List emptyList = Collections.emptyList();
Move rotateMove = new MultipleMatchListRotateMove(rotateList, emptyList);
moveList.add(rotateMove);
}
}
}
}
}
/**
* @TODO clean up this code
*/
private void addTeamRotation(List moveList) {
for (ListIterator firstTeamIt = teamList.listIterator(); firstTeamIt.hasNext();) {
Team firstTeam = firstTeamIt.next();
Map firstTeamDayMap = teamDayMap.get(firstTeam);
for (ListIterator secondTeamIt = teamList.listIterator(firstTeamIt.nextIndex()); secondTeamIt.hasNext();) {
Team secondTeam = secondTeamIt.next();
List clonedFirstTeamMatchList = new ArrayList(firstTeamDayMap.values());
while (!clonedFirstTeamMatchList.isEmpty()) {
List firstRotateList = new ArrayList();
List secondRotateList = new ArrayList();
Match firstStartMatch = clonedFirstTeamMatchList.remove(0);
Team firstStartTeam = getOtherTeam(firstStartMatch, firstTeam);
Day startDay = firstStartMatch.getDay();
boolean firstTeamIsHomeTeam = firstStartMatch.getHomeTeam().equals(firstTeam);
Match secondStartMatch = teamDayMap.get(secondTeam).get(startDay);
if (firstStartMatch.equals(secondStartMatch)) {
break;
}
firstRotateList.add(0, firstStartMatch);
secondRotateList.add(secondStartMatch);
Map visitedTeamMap = new HashMap();
Team teamToFind = getOtherTeam(secondStartMatch, secondTeam);
while (!teamToFind.equals(firstStartTeam)) {
// boolean shortcut = visitedTeamMap.containsKey(teamToFind);
// if (shortcut) {
Match firstRepairMatch = homeTeamAwayTeamMap
.get(firstTeamIsHomeTeam ? firstTeam : teamToFind)
.get(firstTeamIsHomeTeam ? teamToFind : firstTeam);
if (!clonedFirstTeamMatchList.contains(firstRepairMatch)) {
if (visitedTeamMap.containsKey(teamToFind)) {
// shortcut splitoff is possible
Match shortcutMatch = visitedTeamMap.get(teamToFind);
int shortcutSize = firstRotateList.indexOf(shortcutMatch) + 1;
int reverseShortcutSize = firstRotateList.size() - shortcutSize;
List firstShortcutRotateList = new ArrayList(
firstRotateList.subList(0, shortcutSize));
for (Match match : firstShortcutRotateList) {
visitedTeamMap.remove(getOtherTeam(match, firstTeam));
}
List secondShortcutRotateList = new ArrayList(
secondRotateList.subList(reverseShortcutSize, secondRotateList.size()));
firstRotateList = new ArrayList(
firstRotateList.subList(shortcutSize, firstRotateList.size()));
secondRotateList = new ArrayList(
secondRotateList.subList(0, reverseShortcutSize));
addTeamRotateMove(moveList, firstShortcutRotateList, secondShortcutRotateList);
}
firstTeamIsHomeTeam = !firstTeamIsHomeTeam;
// Team firstRepairHomeTeam = (firstTeamIsHomeTeam ^ shortcut) ? firstTeam : teamToFind;
// Team firstRepairAwayTeam = (firstTeamIsHomeTeam ^ shortcut) ? teamToFind : firstTeam;
// Match firstRepairMatch = homeTeamAwayTeamMap
// .get(firstRepairHomeTeam).get(firstRepairAwayTeam);
firstRepairMatch = homeTeamAwayTeamMap
.get(firstTeamIsHomeTeam ? firstTeam : teamToFind)
.get(firstTeamIsHomeTeam ? teamToFind : firstTeam);
}
Day repairDay = firstRepairMatch.getDay();
Match secondRepairMatch = teamDayMap.get(secondTeam).get(repairDay);
clonedFirstTeamMatchList.remove(firstRepairMatch);
visitedTeamMap.put(teamToFind, firstRepairMatch);
firstRotateList.add(0, firstRepairMatch);
secondRotateList.add(secondRepairMatch);
teamToFind = getOtherTeam(secondRepairMatch, secondTeam);
}
addTeamRotateMove(moveList, firstRotateList, secondRotateList);
}
}
}
}
private void addTeamRotateMove(List moveList, List firstRotateList, List secondRotateList) {
assert (firstRotateList.size() == secondRotateList.size());
// if size is 1 then addCachedHomeAwaySwapMoves will have done it
// if size is 2 then addDayRotation will have done it by 1 list of size 4
if (firstRotateList.size() > 2) {
Move rotateMove = new MultipleMatchListRotateMove(firstRotateList, secondRotateList);
moveList.add(rotateMove);
}
}
}
}