Package de.timefinder.algo.graph

Source Code of de.timefinder.algo.graph.AbstractGraphAlgorithm

/*
*  Copyright 2010 Peter Karich, peat_hal 'at' users 'dot' sourceforge 'dot' net.
*
*  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.
*  under the License.
*/
package de.timefinder.algo.graph;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import javolution.util.FastSet;

/**
* @author Peter Karich, peat_hal 'at' users 'dot' sourceforge 'dot' net
*/
public abstract class AbstractGraphAlgorithm implements GraphAlgorithm {

    protected int slotsPerWeek;
    protected List<Integer> eventsDuration = new ArrayList<Integer>();
    protected List<Set<EventTree>> slotToTrees = new ArrayList<Set<EventTree>>();
    protected List<List<EventTree>> eventToTrees = new ArrayList<List<EventTree>>();

    /**
     * @param slotsPerWeek time-slots per week
     */
    public AbstractGraphAlgorithm(int slotsPerWeek) {
        this.slotsPerWeek = slotsPerWeek;
    }

    @Override
    public abstract Set<EventTree> start();

    protected List<EventTree> getTreesForEvent(int eNo) {
        if (eNo < 0)
            throw new IllegalArgumentException("specify an event number >= 0");
        else if (eNo >= eventToTrees.size())
            throw new IllegalArgumentException("add event before");
        else if (eventToTrees.size() == 0)
            throw new IllegalStateException("no events added to map!?");

        return eventToTrees.get(eNo);
    }

    protected Collection<EventTree> getTreesForSlot(int slot) {
        if (slot >= slotToTrees.size())
            throw new IllegalStateException("Add resource "
                    + slotToTrees.size() / slotsPerWeek + " before setting the weight");

        return slotToTrees.get(slot);
    }

    /**
     * @param eNo event number
     * @param choiceNo every events has at least one set of slots to choose from
     * @return tree pointing to all slots which should be assigned if the
     * tree is in the matching
     */
    EventTree getTree(int eNo, int choiceNo) {
        List<EventTree> trees = getTreesForEvent(eNo);
        int todo = choiceNo - trees.size();
        if (todo >= 0) {
            for (int i = 0; i < todo; i++) {
                trees.add(null);
            }
            // create an empty tree at the correct index
            EventTree tree = new EventTree(eNo, choiceNo);
            trees.add(tree);
            return tree;
        } else
            return trees.get(choiceNo);
    }

    private void initTreesForEvent(int eNo, int eDur) {
        if (eNo < 0)
            throw new IllegalArgumentException("event number should be >= 0");
        if (eDur <= 0)
            throw new IllegalArgumentException("event duration should be > 0");

        int todo = eNo - eventToTrees.size();
        if (todo >= 0) {
            for (int i = 0; i < todo; i++) {
                eventToTrees.add(null);
                eventsDuration.add(null);
            }
            // create an empty arrayList at the correct index 'todo'
            eventToTrees.add(new ArrayList());
            eventsDuration.add(eDur);
        }
    }

    protected ArrayList<EventTree> sortTrees() {
        ArrayList<EventTree> list = new ArrayList();
        for (List<EventTree> trees : eventToTrees) {
            for (EventTree tree : trees) {
                if (tree.isEnabled()) // && tree.getWeight() > 0)
                    list.add(tree);
            }
        }

        if (list.size() == 0)
            throw new IllegalStateException("No elements in list!?");

        // not faster:
//        LinearSort.sort(list);

        Collections.sort(list, new Comparator<EventTree>() {

            @Override
            public int compare(EventTree o1, EventTree o2) {
                return o2.getWeight() - o1.getWeight();
            }
        });

        return list;
    }

    public int findWeight(Set<EventTree> matching) {
        int w = 0;
        for (EventTree tree : matching) {
            w += tree.getWeight();
        }

        return w;
    }

    public void addEvent(int eNo, int eDur) {
        initTreesForEvent(eNo, eDur);
    }

    /**
     * Generates the necessary connections between all "choose"-trees of
     * the specified event and the slots of the specified resource
     *
     * TODO ability to remove slots from distinct tree, to avoid starting
     * at one day and ending in the other. other usecase is for example to
     * force double-hours event pattern etc.
     *
     * @param rNo number of the room to add the event
     * @param eNo number of the event
     * @param eDur event duration
     */
    public void addResourceTo(int rNo, int eNo) {
        initResource(rNo);

        Integer duration = eventsDuration.get(eNo);
        if (duration == null)
            throw new IllegalStateException("Add event to graph before specifing it in addResourceTo!");

        int slot = rNo * slotsPerWeek;
        int choice = 0;
        int max = slot + slotsPerWeek - (duration - 1);

        for (; slot < max; slot++) {
            EventTree tree = getTree(eNo, choice++);
            for (int d = 0; d < duration; d++) {
                tree.add(slot + d);
                Collection<EventTree> trees = getTreesForSlot(slot);
                trees.add(tree);
            }
        }
    }

    public void incChoiceWeight(int eNo, int choice, int weight) {
        EventTree tree = getTreesForEvent(eNo).get(choice);
        tree.incWeight(weight);
    }

    public void incSlotWeight(int eNo, int slot, int weight) {
        for (EventTree tree : getTreesForEvent(eNo)) {
            if (tree.getSlots().contains(slot))
                tree.incWeight(weight);
        }
    }

    public void setEventAllEnabled(boolean b) {
        for (List<EventTree> trees : eventToTrees) {
            for (EventTree tree : trees) {
                tree.setEnabled(b);
            }
        }
    }

    private int initResource(int rNo) {
        if (rNo < 0)
            throw new IllegalArgumentException("resource number should be >= 0");

        int todo = (rNo + 1) * slotsPerWeek;
        for (int slot = slotToTrees.size(); slot < todo; slot++) {
            slotToTrees.add((Set) FastSet.newInstance());
        }
        return rNo;
    }

    public void setEventEnableStatus(int evNo, int start) {
        if (start < 0) {
            for (EventTree tree : getTreesForEvent(evNo)) {
                tree.setEnabled(true);
            }
            return;
        }

        EventTree selected = null;
        // avoid assigned trees in the neighbourhood
        for (EventTree tree : getTreesForEvent(evNo)) {
            tree.setEnabled(false);
            if (tree.getMinSlot() % slotsPerWeek == start) {
                selected = tree;
            }
        }

        if (selected == null)
            throw new UnsupportedOperationException("Cannot find event " + evNo + " start: " + start);

        for (Integer sl : selected.getSlots()) {
            for (EventTree conflictTree : getTreesForSlot(sl)) {
                conflictTree.setEnabled(false);
            }
        }
    }

    List<Set<EventTree>> getSlots() {
        return slotToTrees;
    }

    int getChoices(int eNo) {
        return eventToTrees.get(eNo).size();
    }
}
TOP

Related Classes of de.timefinder.algo.graph.AbstractGraphAlgorithm

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.