Package net.sf.cpsolver.tt

Source Code of net.sf.cpsolver.tt.UniTimeOptimization

/*
*  Copyright 2009 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 net.sf.cpsolver.tt;

import de.timefinder.algo.Algorithm;
import de.timefinder.algo.AlgorithmCondition;
import de.timefinder.data.algo.DataPoolSettings;
import de.timefinder.algo.MyStatusBar;
import de.timefinder.algo.util.BiMap;
import de.timefinder.data.DataPool;
import de.timefinder.data.Event;
import de.timefinder.data.Location;
import de.timefinder.data.Person;
import de.timefinder.data.access.Dao;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastMap;
import net.sf.cpsolver.ifs.model.Variable;
import net.sf.cpsolver.ifs.solution.Solution;
import net.sf.cpsolver.ifs.solver.Solver;
import net.sf.cpsolver.ifs.termination.TerminationCondition;
import net.sf.cpsolver.ifs.util.DataProperties;
import net.sf.cpsolver.ifs.util.Progress;
import net.sf.cpsolver.ifs.util.Progress.Message;
import net.sf.cpsolver.ifs.util.ProgressListener;
import net.sf.cpsolver.ifs.util.ToolBox;

/**
* @author Peter Karich, peat_hal 'at' users 'dot' sourceforge 'dot' net
*/
public class UniTimeOptimization implements Algorithm {

    private static java.text.DecimalFormat doubleFormat =
            new java.text.DecimalFormat("0.000", new java.text.DecimalFormatSymbols(Locale.US));
    private Map<UniActivity, Event> eventForActivity = FastMap.newInstance();
    private BiMap<Location, UniResource> locToRoom = new BiMap();
    private Logger logger = Logger.getLogger(getClass().getSimpleName());
    private DataPoolSettings dataPoolSettings;
    private DataPool dataPool;
    private MyStatusBar statusBar;
    private boolean initialAssignment;
    private AlgorithmCondition condition;
    private int slotsPerDay;

    public UniTimeOptimization() {
    }

    public void setInitialAssignment(boolean initialAssignment) {
        this.initialAssignment = initialAssignment;
    }

    public UniTimeSimpleModel createModel() {
        UniTimeSimpleModel model = new UniTimeSimpleModel(dataPoolSettings.getNumberOfDays(),
                dataPoolSettings.getTimeslotsPerDay());

        slotsPerDay = dataPoolSettings.getTimeslotsPerDay();
        int nrDays = dataPoolSettings.getNumberOfDays();

        Dao<Location> locationDao = dataPool.getDao(Location.class);
        Dao<Person> personDao = dataPool.getDao(Person.class);
        Dao<Event> eventDao = dataPool.getDao(Event.class);

        int nrRooms = locationDao.getAll().size();
        UniResource rooms[] = new UniResource[nrRooms];
        int ii = 0;
        for (Location tfLoc : locationDao.getAll()) {
            rooms[ii] = new UniResource("" + tfLoc.getId(), UniResource.TYPE_ROOM, tfLoc.getName());
            locToRoom.put(tfLoc, rooms[ii]);
            model.addConstraint(rooms[ii]);
            ii++;
        }

        // avoid creating a Vector each time in UniActivity.addResourceGroup
        List<UniResource> allRooms = new ArrayList();
        for (int j = 0; j < rooms.length; j++) {
            allRooms.add(rooms[j]);
        }

        //TODO GroupsOfRooms
//        Vector groupOfRooms[] = new Vector[nrGroupsOfRooms];
//        for (int i = 0; i < nrGroupsOfRooms; i++) {
//            groupOfRooms[i] = new FastVector();
//
//            groupOfRooms[i].add(rooms[r]);
//            groupForRoom[r].add(groupOfRooms[i]);
//        }
//
//        for (int i = 0; i < nrLocations; i++) {
//            int cnt = 0;
//            for (int j = 0; j < nrGroupsOfRooms; j++) {
//                if (groupOfRooms[j].contains(rooms[i]))
//                    cnt++;
//            }
//            while (cnt < nrRoomInGroupMin) {
//                groupOfRooms[r].add(rooms[i]);
//                groupForRoom[i].add(groupOfRooms[r]);
//                cnt++;
//            }
//        }

        int nrTeachers = personDao.getAll().size();
        UniResource instructors[] = new UniResource[nrTeachers];
        Map<Person, UniResource> personToResource = FastMap.newInstance();
        ii = 0;
        for (Person p : personDao.getAll()) {
            instructors[ii] = new UniResource(p.getId() + "",
                    UniResource.TYPE_INSTRUCTOR, p.getName());
            model.addConstraint(instructors[ii]);
            personToResource.put(p, instructors[ii]);

            ii++;
        }

        List<Integer> starts = new ArrayList();
        Map<UniActivity, UniResource> activityToInitialRoom = FastMap.newInstance();

        for (Event event : eventDao.getAll()) {
            UniActivity activity = new UniActivity(event.getDuration(), ""
                    + event.getId(), event.getName());
            eventForActivity.put(activity, event);
            starts.add(event.getStart());

            UniResource roomRes = null;
            if (event.getLocation() != null)
                roomRes = locToRoom.get(event.getLocation());

            if (roomRes == null) {
                int room = ToolBox.random(nrRooms);
                activityToInitialRoom.put(activity, rooms[room]);
            } else
                activityToInitialRoom.put(activity, roomRes);

            activity.addResourceGroup(allRooms);
            for (Person p : event.getPersons()) {
                UniResource res = personToResource.get(p);
                if (res == null)
                    throw new NullPointerException("cannot find activity for:" + p.getName());
                activity.addResourceGroup(res);
            }

//            activity.addResourceGroup(classes[aclass]);
            model.addVariable(activity);
        }

        // specify dicourage slots
        for (int i = 0; i < model.variables().size(); i++) {
            UniActivity activity = (UniActivity) model.variables().elementAt(i);
            for (int day = 0; day < nrDays; day++) {
                for (int hour = 0; hour < slotsPerDay; hour++) {
                    addDiscouragedSlot(activity, day, hour, slotsPerDay);
                }
            }

            // create values/assigments
            activity.init();
        }

        for (int i = 0; i < model.variables().size(); i++) {
            UniActivity activity = (UniActivity) model.variables().elementAt(i);

            if (initialAssignment) {
                int start = starts.get(i);
                UniResource room = activityToInitialRoom.get(activity);

                // find value/assignment with specific room and slot
                UniAssignment assignment = null;
                for (Enumeration e = activity.values().elements(); e.hasMoreElements();) {
                    UniAssignment ass = (UniAssignment) e.nextElement();
                    if (ass.getSlot() == start && ass.getResource(0) == room) {
                        assignment = ass;
                        break;
                    }
                }
                if (assignment != null) {
                    Set conflicts = model.conflictValues(assignment);
                    if (!conflicts.isEmpty()) {
                        logger.warning("Unable to assign " + assignment.getName()
                                + " to " + activity.getName());
                    } else {
                        activity.assign(0, assignment);
                        activity.setInitialAssignment(assignment);
                    }
                    activity.setInitialAssignment(assignment);
                } else {
                    // initial assignment fails
                    logger.warning("Unable to assign " + activity.getName()
                            + " -- no assignment matched. slot=" + start + " room=" + room.getName());
                }
            }
        }

        logger.info("Total number of " + model.variables().size() + " activities generated.");
        return model;
    }

    public void start() throws InterruptedException {
        DataProperties properties = new DataProperties();
        properties.setProperty("General.Seed", "123321");
        UniTimeSimpleModel model = createModel();
        Solver solver = new Solver(properties);
        condition.init();
        solver.setTerminalCondition(new TerminationCondition() {

            @Override
            public boolean canContinue(Solution sltn) {
                return condition.canContinue() && !statusBar.getMyProgressMonitor().isCanceled();
            }
        });
        Progress p = new Progress();
        p.addProgressListener(new ProgressListener() {

            private String status;

            @Override
            public void statusChanged(String status) {
                this.status = status;
            }

            @Override
            public void phaseChanged(String phase) {
            }

            @Override
            public void progressChanged(long currentProgress, long maxProgress) {
                statusBar.setMessage(status + " " + currentProgress * 100f / maxProgress);
            }

            @Override
            public void progressSaved() {
            }

            @Override
            public void progressRestored() {
            }

            @Override
            public void progressMessagePrinted(Message message) {
                statusBar.setMessage(message.getMessage());
            }
        });
        solver.setProgress(p);
        solver.setInitalSolution(model);
        solver.start();
        solver.getSolverThread().join();

        if (solver.lastSolution().getBestInfo() == null)
            logger.severe("No solution found :-(");

        logger.info("Last solution:" + solver.lastSolution().getInfo());
        logger.info("Best solution:" + solver.lastSolution().getBestInfo());
        Solution best = solver.lastSolution();
        best.restoreBest();
        int value = 0;
        for (Enumeration iv = best.getModel().assignedVariables().elements(); iv.hasMoreElements();) {
            value += (int) ((Variable) iv.nextElement()).getAssignment().toDouble();
        }

        logger.info("Last solution:" + best.getInfo());
        logger.info(doubleFormat.format(properties.getPropertyDouble("Generator.FillFactor", 0.0)) + ";"
                + doubleFormat.format(properties.getPropertyInt("Generator.NrRooms", 0)) + ";");
        logger.info(doubleFormat.format(best.getTime()) + ";" + best.getIteration() + ";"
                + doubleFormat.format(((double) best.getIteration()) / best.getTime()) + ";");
        logger.info(best.getModel().assignedVariables().size() + ";"
                + doubleFormat.format(100.0 * best.getModel().assignedVariables().size()
                / best.getModel().variables().size()) + ";" + value);
        logger.info("    time:         " + doubleFormat.format(best.getTime()) + " s");
        logger.info("    iteration:    " + best.getIteration());
        logger.info("    speed:        " + doubleFormat.format(((double) best.getIteration())
                / best.getTime()) + " it/s");
        logger.info("    assigned:     " + best.getModel().assignedVariables().size()
                + " (" + doubleFormat.format(100.0 * best.getModel().assignedVariables().size()
                / best.getModel().variables().size()) + "%)");
        logger.info("    value:        " + value);

        // remove previous assignments
        for (Location loc : locToRoom.keySet()) {
            for (Event ev : loc.getEvents()) {
                ev.setLocation(null);
            }
            loc.setEvents(null);
        }

        for (Object obj : model.variables()) {
            UniActivity activity = (UniActivity) obj;
            UniAssignment ass = (UniAssignment) activity.getBestAssignment();
            if (ass == null) {
                logger.severe("No best assignment found for activity:" + activity.getName());
                continue;
            }
            Event event = eventForActivity.get(activity);
            if (event == null) {
                logger.severe("No event found for activity:" + activity.getName());
                continue;
            }

            event.setStart(ass.getSlot());
            Location tfLoc = locToRoom.getSecond(ass.getResource(0));
            if (tfLoc != null) {
                event.setLocation(tfLoc);
            } else
                logger.warning("No TF-room found for activity:" + activity.getName());
        }
    }

    @Override
    public de.timefinder.data.algo.Solution doWork() {
        try {
            start();
        } catch (Exception ex) {
            statusBar.setErrorMessage(ex.getLocalizedMessage());
            logger.log(Level.SEVERE, "", ex);
        }
        // TODO return real solution
        return new de.timefinder.data.algo.Solution();
    }

    @Override
    public void setCondition(AlgorithmCondition condition) {
        this.condition = condition;
    }

    @Override
    public void setStatusBar(MyStatusBar bar) {
        this.statusBar = bar;
    }

    @Override
    public void setDataPool(DataPool pool) {
        this.dataPool = pool;
    }

    @Override
    public DataPool getDataPool() {
        return dataPool;
    }

    @Override
    public void setDataPoolSettings(DataPoolSettings settings) {
        this.dataPoolSettings = settings;
    }

    protected void addDiscouragedSlot(UniActivity activity, int day, int hour, int slotsPerDay) {
        if (hour >= slotsPerDay / 2) {
            Event ev = eventForActivity.get(activity);
            float w = hour;
            if (ev != null)
                w += ev.getPersons().size();

            activity.addDiscourage(slotsPerDay * day + hour, w);
        }
    }
}
TOP

Related Classes of net.sf.cpsolver.tt.UniTimeOptimization

TOP
Copyright © 2015 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.