Package org.optaplanner.examples.cheaptime.solver.move.factory

Source Code of org.optaplanner.examples.cheaptime.solver.move.factory.CheapTimePillarSlideMoveIteratorFactory

/*
* Copyright 2014 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.optaplanner.examples.cheaptime.solver.move.factory;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.optaplanner.core.impl.heuristic.move.Move;
import org.optaplanner.core.impl.heuristic.selector.move.factory.MoveIteratorFactory;
import org.optaplanner.core.impl.score.director.ScoreDirector;
import org.optaplanner.examples.cheaptime.domain.CheapTimeSolution;
import org.optaplanner.examples.cheaptime.domain.Machine;
import org.optaplanner.examples.cheaptime.domain.Task;
import org.optaplanner.examples.cheaptime.domain.TaskAssignment;
import org.optaplanner.examples.cheaptime.solver.move.CheapTimePillarSlideMove;

public class CheapTimePillarSlideMoveIteratorFactory implements MoveIteratorFactory {

    @Override
    public long getSize(ScoreDirector scoreDirector) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Iterator<Move> createOriginalMoveIterator(ScoreDirector scoreDirector) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Iterator<Move> createRandomMoveIterator(ScoreDirector scoreDirector, Random workingRandom) {
        CheapTimeSolution cheapTimeSolution = (CheapTimeSolution) scoreDirector.getWorkingSolution();
        Map<Machine, List<TaskAssignment>> positivePillarMap = new LinkedHashMap<Machine, List<TaskAssignment>>(
                cheapTimeSolution.getGlobalPeriodRangeTo());
        Map<Machine, List<TaskAssignment>> negativePillarMap = new LinkedHashMap<Machine, List<TaskAssignment>>(
                cheapTimeSolution.getGlobalPeriodRangeTo());
        List<TaskAssignment> taskAssignmentList = cheapTimeSolution.getTaskAssignmentList();
        int pillarCapacity = (taskAssignmentList.size() * 2 / cheapTimeSolution.getMachineList().size()) + 1;
        for (TaskAssignment taskAssignment : taskAssignmentList) {
            Machine machine = taskAssignment.getMachine();
            Task task = taskAssignment.getTask();
            Integer startPeriod = taskAssignment.getStartPeriod();
            if (startPeriod != null) {
                if (startPeriod < task.getStartPeriodRangeTo() - 1) {
                    List<TaskAssignment> pillar = positivePillarMap.get(machine);
                    if (pillar == null) {
                        pillar = new ArrayList<TaskAssignment>(pillarCapacity);
                        positivePillarMap.put(machine, pillar);
                    }
                    pillar.add(taskAssignment);
                }
                if (startPeriod > task.getStartPeriodRangeFrom()) {
                    List<TaskAssignment> pillar = negativePillarMap.get(machine);
                    if (pillar == null) {
                        pillar = new ArrayList<TaskAssignment>(pillarCapacity);
                        negativePillarMap.put(machine, pillar);
                    }
                    pillar.add(taskAssignment);
                }
            }
        }
        List<List<TaskAssignment>> positivePillarList = new ArrayList<List<TaskAssignment>>(positivePillarMap.size());
        for (List<TaskAssignment> pillar : positivePillarMap.values()) {
            if (pillar.size() > 1) {
                positivePillarList.add(pillar);
            }
        }
        List<List<TaskAssignment>> negativePillarList = new ArrayList<List<TaskAssignment>>(negativePillarMap.size());
        for (List<TaskAssignment> pillar : negativePillarMap.values()) {
            if (pillar.size() > 1) {
                negativePillarList.add(pillar);
            }
        }
        return new RandomCheapTimePillarSlideMoveIterator(positivePillarList, negativePillarList, workingRandom);
    }

    private class RandomCheapTimePillarSlideMoveIterator implements Iterator<Move> {

        private final List<List<TaskAssignment>> positivePillarList;
        private final List<List<TaskAssignment>> negativePillarList;
        private final Random workingRandom;
        private final int totalSize;

        public RandomCheapTimePillarSlideMoveIterator(List<List<TaskAssignment>> positivePillarList,
                List<List<TaskAssignment>> negativePillarList, Random workingRandom) {
            this.positivePillarList = positivePillarList;
            this.negativePillarList = negativePillarList;
            this.workingRandom = workingRandom;
            totalSize = positivePillarList.size() + negativePillarList.size();
        }

        public boolean hasNext() {
            return totalSize > 0;
        }

        public Move next() {
            int listIndex = workingRandom.nextInt(totalSize);
            boolean positive = listIndex < positivePillarList.size();
            List<TaskAssignment> basePillar = positive ? positivePillarList.get(listIndex)
                    : negativePillarList.get(listIndex - positivePillarList.size());
            int basePillarSize = basePillar.size();
            int subPillarSize = workingRandom.nextInt(basePillarSize);
            // Random sampling: See http://eyalsch.wordpress.com/2010/04/01/random-sample/
            // Used Swapping instead of Floyd because subPillarSize is large, to avoid hashCode() hit
            TaskAssignment[] sandboxPillar = basePillar.toArray(new TaskAssignment[basePillar.size()]); // Clone to avoid changing basePillar
            List<TaskAssignment> subPillar = new ArrayList<TaskAssignment>(subPillarSize);
            int minimumAbsDiff = Integer.MAX_VALUE;
            for (int i = 0; i < subPillarSize; i++) {
                int index = i + workingRandom.nextInt(basePillarSize - i);
                TaskAssignment taskAssignment = sandboxPillar[index];
                Task task = taskAssignment.getTask();
                int absDiff = positive ? task.getStartPeriodRangeTo() - 1 - taskAssignment.getStartPeriod()
                        : taskAssignment.getStartPeriod() - task.getStartPeriodRangeFrom();
                if (absDiff < minimumAbsDiff) {
                    minimumAbsDiff = absDiff;
                }
                subPillar.add(taskAssignment);
                sandboxPillar[index] = sandboxPillar[i];
            }
            int startPeriodDiff = 1 + workingRandom.nextInt(minimumAbsDiff);
            if (!positive) {
                startPeriodDiff = -startPeriodDiff;
            }
            return new CheapTimePillarSlideMove(subPillar, startPeriodDiff);
        }

        public void remove() {
            throw new UnsupportedOperationException("The optional operation remove() is not supported.");
        }

    }

}
TOP

Related Classes of org.optaplanner.examples.cheaptime.solver.move.factory.CheapTimePillarSlideMoveIteratorFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.