Package de.timefinder.algo.roomassignment

Source Code of de.timefinder.algo.roomassignment.PathGrowingAlgorithm

/*
* This file is part of the TimeFinder project.
* Visit http://www.timefinder.de for more information.
* Copyright 2008 the original author or authors.
* 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 de.timefinder.algo.roomassignment;

import de.timefinder.algo.graph.WeightedGraph;
import de.timefinder.algo.graph.Matching;
import javolution.util.FastMap;
import java.util.Map;
import java.util.Map.Entry;

/**
* This class implements the path growing algorithm described from
* Drake and Hougardy in their paper: "A Simple Approximation Algorithm
* for the Weighted Matching Problem"
*
* @author Peter Karich, peat_hal 'at' users 'dot' sourceforge 'dot' net
*/
public class PathGrowingAlgorithm implements AssignmentAlgorithm {

    private float[][] costMatrix;

    @Override
    public int[][] computeAssignments(float[][] costMatrixArg) {
        AssignmentArray matrix = new AssignmentArray();
        matrix.init(costMatrixArg);
        costMatrix = matrix.getCosts();
        Matching[] matching = new Matching[2];
        matching[0] = new Matching();
        matching[1] = new Matching();
        int i = 0;
        final int NO_X = costMatrix[0].length; // COLUMNS
        int NO_Y = costMatrix.length;    // ROWS

        float floatMax = AssignmentHelper.getFloatMax(Math.max(costMatrix.length, costMatrix[0].length));
        matching[0].setFloatMax(floatMax);
        matching[1].setFloatMax(floatMax);

        WeightedGraph graph = new WeightedGraph(NO_X + NO_Y);
        int ALL_NODES = NO_X + NO_Y;
        for (int x = 0; x < NO_X; x++) {
            int tmpY = 0;
            for (int y = NO_X; y < ALL_NODES; y++, tmpY++) {
                if (costMatrix[tmpY][x] < floatMax) {
                    graph.addEdge(x, y, costMatrix[tmpY][x]);
                } else {
                    // we would not need this line, if we would have a better graph.getOneNodeWithAnEdge()
                    // see within the while(true) loop
                    graph.addEdge(x, y, floatMax);
                }
            }
        }

        // x is somewhat missleading, because the x and y nodes swap
        // in every iteration (in the while(true) loop)
        int x = graph.getOneNodeWithAnEdge();
        int saveFirstNode = x;
        Map<Integer, Float> saveNeighbors =
                new FastMap<Integer, Float>(graph.getNeighbors(x));
        int yForExtremalWeight = -1;
        while (graph.getNoOfEdges() > 0) {
            while (true) {
                if (graph.getNeighbors(x).size() == 0) {
                    // EITHER return only x node if they are required (or y) via:
                    //x = graph.getOneNodeWithAnEdge();
                    //if (x < 0) { break; }
                    // OR assume a complete graph and simply break (no while(graph.getNoOfEdges() > 0) would be required)
                    break;
                }

                float minWeight = floatMax + 1;
                yForExtremalWeight = -1;
                for (Entry<Integer, Float> entry : graph.getNeighbors(x).entrySet()) {
                    if (entry.getValue() < minWeight) {
                        yForExtremalWeight = entry.getKey();
                        minWeight = entry.getValue();
                    }
                }
                assert yForExtremalWeight != -1;

                // even add it if float is floatMax, because otherwise we will
                // will have a wrong totalSum
                matching[i].addEdge(x, yForExtremalWeight, minWeight);

                i = 1 - i;
                boolean ret = graph.removeNodeAndNeighbors(x);
                assert ret;
                x = yForExtremalWeight;
            }
        }

        // determine the last egde for matching[1] and add it
        float lastWeight = saveNeighbors.get(yForExtremalWeight);

        // we don't need the two cases: saveFirstNode < NO_X and the other
        // because it is the same for both!
        matching[1].addEdge(yForExtremalWeight, saveFirstNode, lastWeight);

        if (matching[0].getTotalSum() < matching[1].getTotalSum()) {
            if (saveFirstNode < NO_X) {
                // first is matching[0] with x, y => y %= NO_X
                return matching[0].toBipartiteArrayModY(NO_X);
            } else {
                // first is matching[0] with y, x => x %= NO_X
                return matching[0].toBipartiteArrayModX(NO_X);
            }
        } else {
            if (saveFirstNode < NO_X) {
                // first is matching[0] with x, y => matching[1] with y, x
                return matching[1].toBipartiteArrayModX(NO_X);
            } else {
                // first is matching[0] with y, x => matching[1] with x, y
                return matching[1].toBipartiteArrayModY(NO_X);
            }
        }
    }
}
TOP

Related Classes of de.timefinder.algo.roomassignment.PathGrowingAlgorithm

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.