+++ /dev/null
-/*
-* 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<V, E> extends AbstractLayout<V,E> implements IterativeContext {
-
- Map<V, ISOMVertexData> isomVertexData =
- LazyMap.decorate(new HashMap<V, ISOMVertexData>(),
- new Factory<ISOMVertexData>() {
- 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<V,E> elementAccessor =
- new RadiusGraphElementAccessor<V,E>();
-
- private double coolingFactor;
-
- private List<V> queue = new ArrayList<V>();
- private String status = null;
-
- /**
- * Returns the current number of epochs and execution status, as a string.
- */
- public String getStatus() {
- return status;
- }
-
- /**
- * Creates an <code>ISOMLayout</code> instance for the specified graph <code>g</code>.
- * @param g
- */
- public ISOMLayout(Graph<V,E> g) {
- super(g);
- }
-
- public void initialize() {
-
- setInitializer(new RandomLocationTransformer<V>(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<V> 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 <code>true</code> is the layout algorithm is incremental, <code>false</code> otherwise
- */
- public boolean isIncremental() {
- return true;
- }
-
- /**
- * Returns <code>true</code> if the vertex positions are no longer being
- * updated. Currently <code>ISOMLayout</code> stops updating vertex
- * positions after a certain number of iterations have taken place.
- * @return <code>true</code> if the vertex position updates have stopped,
- * <code>false</code> 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;
- }
-}
\ No newline at end of file