Fr Algorithm (Fruchterman-reingold)

Source: Internet
Author: User
Tags gety

Network Diagram layout algorithm

In order to realize the automatic layout of the pre-trend diagram in the course of writing, we refer to the famous Network Diagram software Gephi, and decide to use the FR algorithm to automatically layout the nodes.

Basic idea of algorithm

The FR algorithm considers all nodes to be electrons, and each node receives two forces: 1. Coulomb Force (repulsion) of other nodes 2. Edge-to-point Hukeli (Gravity). Then under the interaction of force, the entire layout will eventually be called a state of equilibrium.

The algorithm sets the repulsion force and attraction to

? \ (f_a (d) = \frac{d^2}{k}\) \ (F_r (d) = \frac{-k^2}{d}\)

The best distance formula for the distance d between the two atoms is defined as follows

? \[k = C\sqrt{\frac{area}{number of Vectices}} \]

where \ (area = w*l\) in order to ensure that the midpoint coordinates in multiple iterations will not displace out of bounds, C uses simulated annealing to set a temperature to prevent displacement out of bounds.

In my actual time temperature set an initial value, I took the \ (temperture = w/10\)

Algorithm pseudo-code:
area:= W? L  {W and L are the width and length of the frame} G: = (V, E); {The vertices is assigned random initial positions} K: = parea/|  V |;  function fa (x): = begin return x2/k end;  function fr (x): = begin return k2/x end; For I: =1To iterations does begin {calculate repulsive forces} for the V does begin {each vertex have both vectors:. Pos and. Disp V.disp: =0; For u in V do if (U6= v) THEN BEGIN {Δis The difference vector between the positions of the vertices}δ:= V.pos?                  U.pos; V.disp: = V.disp + (δ/|δ|)?              Fr (|δ|) End END {calculate attractive forces} for E in E does begin {Each edges are an ordere D pair of vertices. vand.u}δ:= e.v.pos?              E.u.pos; E.v.disp: = E.v.disp? (δ/|δ|) ?              FA (|δ|); E.u.disp: = E.u.disp + (δ/|δ|)?          FA (|δ|) End {Limit Max displacement to temperature T and prevent from displacement outside frame} for V-v do Begin V.pos: = V.pos + (v.disp/|v.disp|)?              Min (V.disp, t); V.pos.x: = Min (w/2, Max (? w/2, v.pos.x)); V.pos.y: = min (L/2, Max (? L2, V.pos.y)) end {Reduce the temperature as the layout approaches a better configuration} t: = C Ool (t) end

My Java implementation

Package Main.model;import Java.util.HashMap;import java.util.List;import Java.util.Map;/*** @Author dyleaf* @Description: The auto-layout algorithm use Fruchterman and Reingold model* @Date: 20:23 2018/2/25 */ Public classFruchtermanreingoldlayout {Private intW//width of canvas    Private intL//Length of canvas    Private intTemperature = W/Ten;//Simulated annealing initial temperature    Private intMaxiter = +;//algorithm iteration count    Private intArea = W * L;//Layout size    Private DoubleC =1;//node Distance control factor    Private DoubleKdistance between//nodes    /*** Init fruchtermanreingoldlayout     * @param WThe wide of graph     * @param LThe length of graph     * @param maxiterThe Max iterator of the Arig     * @param Ratedefine the initial value of temperature     */     Public void Init(intWintLintMaxiter,intRateDoubleC) { This.W= W; This.L= L; This.Maxiter= Maxiter; temperature = W/rate; This.C= C; } PublicList<node>Run(list<node> nodes, list<edge> edges) {list<node> resetnodes = nodes; for(inti =0; i < Maxiter; i++) {resetnodes =Springlayout(Resetnodes, edges, i); }returnResetnodes; } PublicList<node>Springlayout(list<node> nodes, list<edge> edges,intCuriter) {//2 calculates the unit displacement (usually positive) resulting from repulsion between 22 nodes in a local area of each iteration.        DoubleDeltaX, DeltaY, deltalength; k= c* Math.sqrt(Area/(Double) nodes.size()); map<string, double> dispx =NewHashmap<string, double> (); map<string, double> dispy =NewHashmap<string, double> (); for(intv =0; V < nodes.size(); v++) {dispx.put(Nodes.Get(v).getId(),0.0); Dispy.put(Nodes.Get(v).getId(),0.0); for(intU =0; U < nodes.size(); u++) {if(U! = V) {DeltaX = nodes.Get(v).GetX()-Nodes.Get(u).GetX();if(Double.IsNaN(DeltaX)) {System. out.println("x Error"+ nodes.Get(v).GetX()); } DeltaY = nodes.Get(v).GetY()-Nodes.Get(u).GetY();if(Double.IsNaN(DeltaY)) {System. out.println("Y error"+ nodes.Get(v).GetX()); } deltalength = Math.sqrt(DeltaX * deltax + deltay * deltay);Doubleforce = k * K/DELTALENGTH;if(Double.IsNaN(Force)) {System.Err.println("Force was NaN node is"+ U +" ,"+ V +"Diflength"+ Deltalength +"x"+ DeltaX +"Y"+ DeltaY); The String id = nodes.Get(v).getId(); Dispx.put(ID, dispx.Get(ID) + (deltax/deltalength) * force); Dispy.put(ID, Dispy.Get(ID) + (deltay/deltalength) * force); }            }        }//3. Calculates the unit displacement (generally negative) generated by the gravitational force of each edge on each iteration of the two-way nodeNode visnodes =NULL, Visnodee =NULL; for(intE =0; e < edges.size(); e++) {String Estartid = edges.Get(e).Getsourceid(); String Eendid = edges.Get(e).Getendid(); Visnodes =Getnodebyid(nodes, Estartid); Visnodee =Getnodebyid(nodes, Eendid); DeltaX = Visnodes.GetX()-Visnodee.GetX(); DeltaY = Visnodes.GetY()-Visnodee.GetY(); Deltalength = Math.sqrt(DeltaX * deltax + deltay * deltay);Doubleforce = deltalength * DELTALENGTH/K;if(Double.IsNaN(Force)) {System.Err.println("Force was NaN edge is"+ Visnodes.ID+" ,"+ Visnodee.ID); }DoubleXdisp = (deltax/deltalength) * Force;DoubleYdisp = (deltay/deltalength) * Force; Dispx.put(Estartid, dispx.Get(Estartid)-xdisp); Dispy.put(Estartid, Dispy.Get(Estartid)-ydisp); Dispx.put(Eendid, dispx.Get(Eendid) + xdisp); Dispy.put(Eendid, Dispy.Get(Eendid) + ydisp); }//set x, y         for(intv =0; V < nodes.size(); v++) {Node node = nodes.Get(v); Double dx = dispx.Get(node.getId()); Double dy = dispy.Get(node.getId()); Double displength = Math.sqrt(DX * dx + dy * dy);DoubleXdisp = Dx/displength * Math.min(displength, temperature);DoubleYdisp = Dy/displength * Math.min(displength, temperature);//don ' t let nodes leave the displayNode.SetX(node.GetX() +xdisp); Node.sety(node.GetY() +ydisp); Node.SetX(Math.minW2, Math.Max(-1.0W2, node.GetX()))); Node.sety(Math.minL2, Math.Max(-1.0L2, node.GetY()))); }//cool Temperature        Cool(Curiter);//temperature*=0.95;        returnNodes }Private void Cool(intCuriter) {Temperature *= (1.0-Curiter/(Double) maxiter); }PrivateNodeGetnodebyid(list<node> nodes, String ID) { for(Node node:nodes) {if(node.getId().equals(ID)) {returnNode }        }return NULL; }}

Reference

force-directed Drawing Algorithms

Fr Algorithm (Fruchterman-reingold)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.