A complicated Soffit example

in procjam •  6 years ago  (edited)

Suppose we want to create a graph grammar that makes rectangular grids.

A first cut at it would be something like "expand outwards from any edge that hasn't already been used", something like this:

o-o     o-o-o
| |  => | | | 
o-o     o-o-o

with the appropriate tags used to keep track of whether we already expanded or not. The problem with this is that while it's locally correct (everything is a square) it's not globally correct. The toplogy is all wrong, so even if we had the rules to stitch things together, it wouldn't fit.

soffit-failed-grid.png

Instead, we need a design where there is only one rule that can be applied at any given time, and this rule maintains invariants that preserve global structure. (This strips out most of the point of using a graph grammar and makes it more like a conventional programming language, but I should at least be able to demonstrate that it's possible.)

My idea here is to work on just one edge at a time, with a "mouse" (or turtle, if you prefer) adding squares on until it reaches the end, then turning the corner to work on the next edge. I mark the nodes "e" for one on the boundary of the grid, "c" for the corners, and "i" for internal nodes.

 c-------c
 | | | | |
 v-e-i-i--
   | | | |
   e------
   | | | |
   c------

 c-------c    (moving down)
 | | | | |
 e-i------
 | | | | |
 v-e------
   | | | |
   c------

 c-------c    (down again)
 | | | | |
 e-i------
 | | | | |
 e-i------
 | | | | |
 v-c------

 c-------c   (turn the corner)
 | | | | |
 e-i------
 | | | | |
 e-i------
 | | | | |
 e-e------
 | |
 c->

Here's the Soffit grammar which implements this design:

{
    "version" : "0.1",
    "start" : "X->Y->Z [h]; X2->Y2->Z2 [h]; X->X2 [v]; Y->Y2[v]; Z->Z2[v]; X[c]; Y[c]; Z[up]; X2[c]; Y2[e]; Z2[c]",

    "C->M [h]; C[c]; M[up];" :
    "C->M [h]; C[e]; M[e]; A[left]; B[c]; A->B [h]; A->C[v]; B->M[v];",
    
    "M->R [v]; L->R [h]; L[e]; R[e]; M[left];" :
    "M->R [v]; L->R [h]; L[e]; R[i]; M[e]; N[left]; N->M[h]; N->L[v];",

    "M->R [v]; L->R [h]; L[c]; R[e]; M[left];" :
    "M->R [v]; L->R [h]; L[c]; R[i]; M[e]; N[left]; N->M[h]; N->L[v];",

    "M->C [v]; C[c]; M[left];" :
    "M->C [v]; C[e]; M[e]; A[c]; B[down]; A->M[h]; A->B[v]; B->C[h];",

    "M->T [h]; T->B [v]; T[e]; B[e]; M[down];" :
    "M->T [h]; T->B [v]; T[i]; B[e]; M[e]; N[down]; M->N[v]; N->B[h];",
    
    "M->T [h]; T->B [v]; T[e]; B[c]; M[down];" :
    "M->T [h]; T->B [v]; T[i]; B[c]; M[e]; N[down]; M->N[v]; N->B[h];",

    "M->C [h]; C[c]; M[down];" :
    "M->C [h]; C[e]; M[e]; A[c]; B[right]; M->A[v]; A->B[h]; C->B[v];",

    "M<-L [v]; L->R [h]; L[e]; R[e]; M[right];" :
    "M<-L [v]; L->R [h]; L[i]; R[e]; M[e]; N[right]; M->N[h]; R->N[v];",

    "M<-L [v]; L->R [h]; L[e]; R[c]; M[right];" :
    "M<-L [v]; L->R [h]; L[i]; R[c]; M[e]; N[right]; M->N[h]; R->N[v];",

    "C->M [v]; C[c]; M[right];" :
    "C->M [v]; C[e]; M[e]; A[up]; B[c]; M->B[h]; C->A[h]; A->B[v];",
    
    "B->M [h]; T->B [v]; T[e]; B[e]; M[up];" :
    "B->M [h]; T->B [v]; T[e]; B[i]; M[e]; N[up]; T->N[h]; N->M[v];",

    "B->M [h]; T->B [v]; T[c]; B[e]; M[up];" :
    "B->M [h]; T->B [v]; T[c]; B[i]; M[e]; N[up]; T->N[h]; N->M[v];"
}

And here's what it looks like after 40 iterations:

(Graphviz isn't smart enough to know which orientation I wanted.)

From working on examples, here's a few things I've been thinking of adding:

  • Text output, either as dot or as an ASCII diagram
    • "Save as soffit" so a large diagram can be used as a start position or pattern
  • Ruleset output / visualization
  • Run multiple rulesets
  • Wildcard on the right graph to include all elements already in the left graph, in case we're just adding some items.
  • "Why doesn't X match" --- this would be hard, but useful for debugging
  • Output stats on which rules get used.
  • Movie mode--- would need to initialize positions from the previous layout to have any chance of this working.
Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Hello! Your post has been resteemed and upvoted by @ilovecoding because we love coding! Keep up good work! Consider upvoting this comment to support the @ilovecoding and increase your future rewards! ^_^ Steem On!

Reply !stop to disable the comment. Thanks!

Congratulations @markgritter! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You published a post every day of the week

Click here to view your Board of Honor
If you no longer want to receive notifications, reply to this comment with the word STOP

Do not miss the last post from @steemitboard:

The new Steemfest³ Award is ready!
Be ready for the next contest!

Support SteemitBoard's project! Vote for its witness and get one more award!