# "Small Universes" : Pattern hunting with the Wolfram Physics Project

**URL:** <https://discourse.processing.org/t/small-universes-pattern-hunting-with-the-wolfram-physics-project/24001>\
**Category:** Gallery\
**Created:** [September 21, 2020, 12:52pm UTC](https://discourse.processing.org/t/small-universes-pattern-hunting-with-the-wolfram-physics-project/24001 "2020-09-21T12:52:33Z")\
**Posts on this page:** 1\
**Showing post:** 3

<div class="post-metadata">

**Author:** ![solub](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/solub/32/333_2.png) [@solub](https://discourse.processing.org/u/solub)\
**Post date:** [September 21, 2020, 9:24pm UTC](https://discourse.processing.org/t/small-universes-pattern-hunting-with-the-wolfram-physics-project/24001/3 "2020-09-21T21:24:01Z")

</div>

Simpler examples in 2D:

– **rule [WM148](https://www.wolframphysics.org/universes/wm148/)** : `[(x, y)] -> [(x, y), (y, z)]`

```auto
x, y, z = 0, 1, 2
arr = [(x, y)] 
steps = 4 

for step in xrange(steps):
    temp = [] #temporary array to store new pairs of nodes
    
    for i, (x, y) in enumerate(arr):
        new_pair = (y, z) #create a new pair connecting 'y' to 'z'
        idx = 2*i+1 #compute its future index in array (next generation)
        temp.append((new_pair, idx)) #store it with its index
        z += 1
        
    [arr.insert(i, p) for p, i in temp] #intertwine previous array with temporary array -> ([x, y], [y, z], [x, y], [y, z],...)

```

or in a more pythonic way:

```auto
for step in xrange(steps):
    temp = [(y, z+i+len(arr)-1) for i, (x,y) in enumerate(arr)]
    arr = sum(zip(arr, temp),())

```

Then attaching the pairs of nodes with springs using Toxiclibs:

 ![Screenshot 2020-09-21 210734](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/4/40cc7b96fb857dca2691d3123f305aa5cb12a7b6.png)

> **Full sketch**
>
> ```auto
> ### A basic implementation of rule WM148 in Python mode ###
> ### doc --> https://www.wolframphysics.org/universes/wm148/ ###
> ### explanation --> https://www.wolframphysics.org/technical-introduction/basic-form-of-models/first-example-of-a-rule/index.html ###
> 
> from collections import defaultdict
> add_library('toxiclibs')
> 
> W, H = 1000, 600 #dimensions of canvas
> x, y, z = 0, 1, 2
> a = [(x, y)] #starting axiom
> sw = []
> 
> def setup():
> size(1000, 600)
>     
> global physics, a, sw
>     
> # Instantiate Verlet Physics + set drag
> physics = VerletPhysics2D()
> physics.setDrag(.2)
>     
> # RULE: [(x, y)] --> [(x, y), (y, z)]
> for step in xrange(11):
> temp = [(y, z+i+len(a)-1) for i, (x,y) in enumerate(a)]
> a = sum(zip(a, temp),())
> 
> d = defaultdict(set)
> for n1, n2 in a:
> d[n1].add(n2)
> d[n2].add(n1)
>         
> neighbors_count = sorted(len(d[k]) for k in d)
> minl, maxl = neighbors_count[0], neighbors_count[-1]
>         
> # Get id of each node
> uniques = set(sum(a, ())) # [0, 1, 2, ..., n]
>     
> # Add particle for each node
> for id in uniques:
> p = VerletParticle2D(Vec2D.randomVector().scale(W).add(Vec2D(W>>1, H>>1)))
> physics.addParticle(p)
> physics.addBehavior(AttractionBehavior2D(p, 40, -.5))
>         
> # Create spring between each pair of nodes
> for n1, n2 in a:
> p1 = physics.particles.get(n1)
> p2 = physics.particles.get(n2)
> l = (len(d[n1]) + len(d[n2])) * .5
> f = map(l, minl, maxl, 1, 0.1)
> s = VerletSpring2D(p1, p2, l*l*f, .3)
> physics.addSpring(s)
>         
> w = l*l*.015 
> sw.append(w)
>         
>     
>     
> def draw():
> background('#FFFFFF')
>         
> physics.update() #update physics
>         
> #Draw springs + nodes
> for i, s in enumerate(physics.springs):
> strokeWeight(sw[i])
> line(s.a.x(), s.a.y(), s.b.x(), s.b.y())
>         
> pushStyle()
> strokeWeight(2)
> for p in physics.particles:
> point(p.x(), p.y())
> popStyle()
> 
> ```

– **rule [WM686](https://www.wolframphysics.org/universes/wm686/)** : `[(x, y)] --> [(y, z), (z, x)]`

This rule can be used as a simple circle growth algorithm if we update only one pair per iteration (instead of the whole stack)

 ![Screenshot 2020-09-21 193034](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/3/3c2489d52f0d3444bfcf38d9f380bf50fa3e1d3f.png)

> **Full sketch**
>
> ```auto
> 
> ### How rule WM686 can be used as a circle growth algorithm ###
> ### doc --> https://www.wolframphysics.org/universes/wm686/ ###
> 
> add_library('toxiclibs')
> 
> W, H = 1000, 600 #dimensions of canvas
> a = [(0, 1), (0, 2), (1, 2)] #starting axiom
> z = max(sum(a,()))+1 #total number of edges AND the id of the next node to add
> 
> def setup():
> size(W, H)
>     
> global physics
>         
> # Instantiate Verlet Physics + set drag
> physics = VerletPhysics2D()
> physics.setDrag(.2)
>     
> # Get id of each node
> uniques = set(sum(a, ())) # [0, 1, 2]
>     
> # Add particle for each node
> for id in uniques:
> p = VerletParticle2D(Vec2D.randomVector().add(Vec2D(W>>1, H>>1)))
> physics.addParticle(p)
> physics.addBehavior(AttractionBehavior2D(p, 10, -.5))
>         
> # Create spring between each pair of nodes
> for n1, n2 in a:
> p1 = physics.particles.get(n1)
> p2 = physics.particles.get(n2)
> s = VerletSpring2D(p1, p2, 4, .5)
> physics.addSpring(s)
> 
>     
> def draw():
> background('#FFFFFF')
>     
> global z
>         
> physics.update() #update physics
>      
> # Process rule: [(x, y)] --> [(y, z), (z, x)]
> id = int(random(z)) #pick an edge at random
> x, y = a[id] #coordinates of selected edge
> del a[id] #remove edge
> a.extend([(y, z), (z, x)]) #add 2 new edges according to replacement rule
> 
> # Manage physics accordingly
> px = physics.particles.get(x) #coordinate of node x
> py = physics.particles.get(y) #coordinate of node y
> pz = VerletParticle2D(px.add(py).scale(.5)) #create a new particle in between
>     
> s = physics.getSpring(px, py) #find spring between the deleted edge
> physics.removeSpring(s) #remove that spring
> 
> physics.addParticle(pz) #add particle
> physics.addBehavior(AttractionBehavior2D(pz, 10, -.5)) #attach a repulsion behavior to it
>     
> s1 = VerletSpring2D(py, pz, 4, .5) #create spring between 1st new edge
> s2 = VerletSpring2D(pz, px, 4, .5) #create spring between 2nd new edge
> physics.addSpring(s1) #add them to physics
> physics.addSpring(s2)
> 
> z += 1 #increment 'z' 
>         
>     
> #Draw springs
> for s in physics.springs:
> line(s.a.x(), s.a.y(), s.b.x(), s.b.y())
> 
> ```

---

_[View the full topic](https://discourse.processing.org/t/small-universes-pattern-hunting-with-the-wolfram-physics-project/24001)._
