HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Moduleforce-layout-0.4.0.6Haskell2010

Physics.ForceLayout

A simple, Haskell-native simulator for doing force-directed layout, e.g. of trees or graphs.

To use, just create an Ensemble like so:

import           Control.Lens        ((&), (.~))
import           Data.Default.Class  (def)
import qualified Data.Map            as M
import           Linear.Affine
import           Linear.V2
import           Physics.ForceLayout

e :: Ensemble V2 Double
e = Ensemble [ (edges,    hookeForce 0.05 4)
             , (allPairs, coulombForce 1)
             ]
             particleMap
  where edges       = [(1,2), (2,3), (2,5), (3,5), (3,4), (4,5)]
        allPairs    = [(x,y) | x <- [1..4], y <- [x+1..5]]
        particleMap = M.fromList . zip [1..]
                    . map (initParticle . P . uncurry V2)
                    $ [ (2.0, 3.1), (6.3, 7.2)
                      , (0.3, 4.2), (1.6, -1.1)
                      , (4.8, 2.9)
                      ]

Then run a simulation using either simulate (to get the list of all intermediate states) or forceLayout (to get only the ending state):

e' :: Ensemble V2 Double
e' = forceLayout (def & damping     .~ 0.8
                      & energyLimit .~ Just 0.001
                      & stepLimit   .~ Nothing
                 )
                 e

See the diagrams-contrib package (http://github.com/diagrams/diagrams-contrib/) for more examples.

  • 5 types
  • 18 values

Data structures

10 declarations
datadata Particle (v :: Type -> Type) n
#

A particle has a current position, current velocity, and current force acting on it.

Constructors

Instances1Eq
  • Eq (v n) => Eq (Particle v n)Defined in force-layout-0.4.0.6 · Physics.ForceLayout
typetype PID = Int
#

Used to uniquely identify particles.

typetype Edge = (PID, PID)
#

An edge is a pair of particle identifiers.

datadata Ensemble (v :: Type -> Type) n
#

An Ensemble is a physical configuration of particles. It consists of a mapping from particle IDs (unique integers) to particles, and a list of forces that are operative. Each force has a list of edges to which it applies, and is represented by a function giving the force between any two points.

Constructors

Pre-defined forces

3 declarations
valuehookeForce
  1. :: (Metric v, Floating n)
  2. => n
  3. -> n
  4. -> Point v n
  5. -> Point v n
  6. -> v n
#

hookeForce k l p1 p2 computes the force on p1, assuming that p1 and p2 are connected by a spring with equilibrium length l and spring constant k.

valuecoulombForce :: (Metric v, Floating n) => n -> Point v n -> Point v n -> v n
#

coulombForce k computes the electrostatic repulsive force between two charged particles, with constant of proportionality k.

valuedistForce
  1. :: (Metric v, Floating n)
  2. => n -> n
  3. -> Point v n
  4. -> Point v n
  5. -> v n
#

distForce f p1 p2 computes the force between two points as a multiple of the unit vector in the direction from p1 to p2, given a function f which computes the force's magnitude as a function of the distance between the points.

Running simulations

6 declarations
datadata ForceLayoutOpts n
#

Options for customizing a simulation.

Constructors

  • FLOpts
    • _damping :: n

      Damping factor to be applied at each step. Should be between 0 and 1. The default is 0.8.

    • _energyLimit :: Maybe n

      Kinetic energy below which simulation should stop. If Nothing, pay no attention to kinetic energy. The default is Just 0.001.

    • _stepLimit :: Maybe Int

      Maximum number of simulation steps. If Nothing, pay no attention to the number of steps. The default is Just 1000.

Instances1Default
valuesimulate
  1. :: (Metric v, Num n, Ord n)
  2. => ForceLayoutOpts n
  3. -> Ensemble v n
  4. -> [Ensemble v n]
#

Simulate a starting ensemble according to the given options, producing a list of all the intermediate ensembles. Useful for, e.g., making an animation. Note that the resulting list could be infinite, if a stepLimit is not specified and either the kinetic energy never falls below the specified threshold, or no energy threshold is specified.

valueforceLayout
  1. :: (Metric v, Num n, Ord n)
  2. => ForceLayoutOpts n
  3. -> Ensemble v n
  4. -> Ensemble v n
#

Run a simluation from a starting ensemble, yielding either the first ensemble to have kinetic energy below the energyLimit (if given), or the ensemble that results after a number of steps equal to the stepLimit (if given), whichever comes first. Otherwise forceLayout will not terminate.

Internals

4 declarations
valueparticleStep :: (Additive v, Num n) => n -> Particle v n -> Particle v n
#

Simulate one time step for a particle (assuming the force acting on it has already been computed), with the given damping factor.