All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.uci.ics.jung.algorithms.layout.ISOMLayout Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
/*
* Copyright (c) 2003, the JUNG Project and the Regents of the University
* of California
* All rights reserved.
*
* This software is open-source under the BSD license; see either
* "license.txt" or
* http://jung.sourceforge.net/license.txt for a description.
*/
package edu.uci.ics.jung.algorithms.layout;

import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer;
import edu.uci.ics.jung.algorithms.util.IterativeContext;
import edu.uci.ics.jung.graph.Graph;

import org.apache.commons.collections15.Factory;
import org.apache.commons.collections15.map.LazyMap;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Implements a self-organizing map layout algorithm, based on Meyer's
 * self-organizing graph methods.
 *
 * @author Yan Biao Boey
 */
public class ISOMLayout extends AbstractLayout implements IterativeContext {

	Map isomVertexData =
		LazyMap.decorate(new HashMap(),
				new Factory() {
					public ISOMVertexData create() {
						return new ISOMVertexData();
					}});

	private int maxEpoch;
	private int epoch;

	private int radiusConstantTime;
	private int radius;
	private int minRadius;

	private double adaption;
	private double initialAdaption;
	private double minAdaption;

    protected GraphElementAccessor elementAccessor =
    	new RadiusGraphElementAccessor();

	private double coolingFactor;

	private List queue = new ArrayList();
	private String status = null;

	/**
	 * Returns the current number of epochs and execution status, as a string.
	 */
	public String getStatus() {
		return status;
	}

	/**
	 * Creates an ISOMLayout instance for the specified graph g.
	 * @param g
	 */
	public ISOMLayout(Graph g) {
		super(g);
	}

	public void initialize() {

		setInitializer(new RandomLocationTransformer(getSize()));
		maxEpoch = 2000;
		epoch = 1;

		radiusConstantTime = 100;
		radius = 5;
		minRadius = 1;

		initialAdaption = 90.0D / 100.0D;
		adaption = initialAdaption;
		minAdaption = 0;

		//factor = 0; //Will be set later on
		coolingFactor = 2;

		//temperature = 0.03;
		//initialJumpRadius = 100;
		//jumpRadius = initialJumpRadius;

		//delay = 100;
	}


	/**
	* Advances the current positions of the graph elements.
	*/
	public void step() {
		status = "epoch: " + epoch + "; ";
		if (epoch < maxEpoch) {
			adjust();
			updateParameters();
			status += " status: running";

		} else {
			status += "adaption: " + adaption + "; ";
			status += "status: done";
//			done = true;
		}
	}

	private synchronized void adjust() {
		//Generate random position in graph space
		Point2D tempXYD = new Point2D.Double();

		// creates a new XY data location
        tempXYD.setLocation(10 + Math.random() * getSize().getWidth(),
                10 + Math.random() * getSize().getHeight());

		//Get closest vertex to random position
		V winner = elementAccessor.getVertex(this, tempXYD.getX(), tempXYD.getY());

		while(true) {
		    try {
		    	for(V v : getGraph().getVertices()) {
		            ISOMVertexData ivd = getISOMVertexData(v);
		            ivd.distance = 0;
		            ivd.visited = false;
		        }
		        break;
		    } catch(ConcurrentModificationException cme) {}
        }
		adjustVertex(winner, tempXYD);
	}

	private synchronized void updateParameters() {
		epoch++;
		double factor = Math.exp(-1 * coolingFactor * (1.0 * epoch / maxEpoch));
		adaption = Math.max(minAdaption, factor * initialAdaption);
		//jumpRadius = (int) factor * jumpRadius;
		//temperature = factor * temperature;
		if ((radius > minRadius) && (epoch % radiusConstantTime == 0)) {
			radius--;
		}
	}

	private synchronized void adjustVertex(V v, Point2D tempXYD) {
		queue.clear();
		ISOMVertexData ivd = getISOMVertexData(v);
		ivd.distance = 0;
		ivd.visited = true;
		queue.add(v);
		V current;

		while (!queue.isEmpty()) {
			current = queue.remove(0);
			ISOMVertexData currData = getISOMVertexData(current);
			Point2D currXYData = transform(current);

			double dx = tempXYD.getX() - currXYData.getX();
			double dy = tempXYD.getY() - currXYData.getY();
			double factor = adaption / Math.pow(2, currData.distance);

			currXYData.setLocation(currXYData.getX()+(factor*dx), currXYData.getY()+(factor*dy));

			if (currData.distance < radius) {
			    Collection s = getGraph().getNeighbors(current);
			    while(true) {
			        try {
			        	for(V child : s) {
			                ISOMVertexData childData = getISOMVertexData(child);
			                if (childData != null && !childData.visited) {
			                    childData.visited = true;
			                    childData.distance = currData.distance + 1;
			                    queue.add(child);
			                }
			            }
			            break;
			        } catch(ConcurrentModificationException cme) {}
			    }
			}
		}
	}

	protected ISOMVertexData getISOMVertexData(V v) {
		return isomVertexData.get(v);
	}

	/**
	 * This one is an incremental visualization.
	 * @return true is the layout algorithm is incremental, false otherwise
	 */
	public boolean isIncremental() {
		return true;
	}

	/**
	 * Returns true if the vertex positions are no longer being
	 * updated.  Currently ISOMLayout stops updating vertex
	 * positions after a certain number of iterations have taken place.
	 * @return true if the vertex position updates have stopped,
	 * false otherwise
	 */
	public boolean done() {
		return epoch >= maxEpoch;
	}

	protected static class ISOMVertexData {
		int distance;
		boolean visited;

		protected ISOMVertexData() {
		    distance = 0;
		    visited = false;
		}
	}

	/**
	 * Resets the layout iteration count to 0, which allows the layout algorithm to
	 * continue updating vertex positions.
	 */
	public void reset() {
		epoch = 0;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy