Skip to content

Instantly share code, notes, and snippets.

@moxious
Created August 1, 2022 11:38
Show Gist options
  • Save moxious/735e6a7bf9b6ef3957d61f5d88ed0525 to your computer and use it in GitHub Desktop.
Save moxious/735e6a7bf9b6ef3957d61f5d88ed0525 to your computer and use it in GitHub Desktop.
/* From GraphConnect 2022 Presentation: Node Art by M. David Allen
* Each Neo4j browser "favorite" query starts with //XX-Query Name
*/
//01-Make a Snake
WITH 100 as snakeSize, 3 as snakeLinkage
/* Create the nodes... */
FOREACH (id IN range(0,snakeSize) | CREATE (:SnakeNode {id:id}))
/* Link each node to the previous {snakeLinkage} nodes, creating a lattice */
WITH ['A', 'B', 'C'] as labels, snakeSize, snakeLinkage
MATCH (n:SnakeNode), (n2:SnakeNode)
WHERE n2.id > n.id and n2.id < n.id + snakeLinkage
WITH n, n2, labels
CALL apoc.create.setLabels(n, ['SnakeNode', labels[n.id%3]])
YIELD node WITH node as n, n2, labels
CALL apoc.create.setLabels(n2, ['SnakeNode', labels[n2.id%3]])
YIELD node WITH node as n2, n
CREATE (n)-[:link]->(n2);
//02-Close Snake
WITH 100 as snakeSize, 3 as snakeLinkage
/* Create the nodes... */
MATCH (head:SnakeNode) WHERE NOT ()-[:link]->(head)
MATCH (tail:SnakeNode) WHERE NOT (tail)-[:link]->()
create (tail)-[:link]->(head)
create (tail)-[:link]->(head);
//03-Make Clusters
WITH [
{ id: 0, name: "Red" },
{ id: 1, name: "Blue" },
{ id: 2, name: "Black" },
{ id: 3, name: "Green" }
] as clusters,
180 as totalNodeCount
FOREACH (x in range(0, totalNodeCount) | CREATE (m:Member { id: x }))
WITH clusters
UNWIND clusters as cluster
CREATE (c) SET c += cluster
WITH c CALL apoc.create.setLabels(c, ['ClusterCenter', c.name])
YIELD node RETURN count(node);
/* Link to clusters */
MATCH (cc:ClusterCenter)
WITH cc
MATCH (m:Member)
WHERE m.id % 4 = cc.id
MERGE (m)-[:IN]->(cc);
/* In-group links */
WITH 1.5 as inGroupRatio
MATCH (cc:ClusterCenter)<-[:IN]-(m:Member)
WITH collect(m) as clusterMembers, cc, inGroupRatio
WITH
apoc.coll.randomItems(clusterMembers,
toInteger(inGroupRatio*size(clusterMembers)), false) AS froms,
apoc.coll.randomItems(clusterMembers,
toInteger(inGroupRatio*size(clusterMembers)), false) AS tos
UNWIND apoc.coll.zip(froms, tos) as pair
CALL apoc.create.relationship(pair[0], 'INGROUP', {}, pair[1])
YIELD rel RETURN COUNT(rel);
//03b-Link Clusters
WITH 0.001 as outGroupRatio
MATCH (cc1:ClusterCenter), (cc2:ClusterCenter)
WHERE id(cc1)<id(cc2)
WITH cc1, cc2, outGroupRatio
MATCH (cc1)<-[:IN]-(m:Member),
(cc2)<-[:IN]-(m2:Member)
WITH
collect(m) as cluster1Members,
cc1,
collect(m2) as cluster2Members,
cc2,
outGroupRatio
WITH
apoc.coll.randomItems(cluster1Members,
toInteger(outGroupRatio*size(cluster1Members)), false) AS froms,
apoc.coll.randomItems(cluster2Members,
toInteger(outGroupRatio*size(cluster2Members)), false) AS tos
UNWIND apoc.coll.zip(froms, tos) as pair
CREATE (i:Interstitial { from: pair[0].id, to: pair[1].id })
WITH i, pair
CALL apoc.create.relationship(pair[0], 'INTERSTITIAL', {}, i)
YIELD rel
WITH i, pair
CALL apoc.create.relationship(i, 'INTERSTITIAL', {}, pair[1])
YIELD rel
RETURN COUNT(rel);
//04-Conway1
UNWIND range(1,25) as x
UNWIND range (1,25) as y
CREATE (c:Cell:Dead {x: x, y: y})
WITH c
MATCH (c2:Cell)
WHERE c2.x-1<=c.x<=c2.x+1
AND c2.y-1<=c.y<=c2.y+1
AND id(c)<id(c2)
MERGE (c)-[:NEIGHBOUR_OF]->(c2);
//05-Conway-Seed
:auto UNWIND range(1,200) as range
CALL {
WITH range
MATCH (c:Cell)
WHERE
c.x = round(rand()*25) AND
c.y = round(rand()*25)
SET c:Live
REMOVE c:Dead
} in transactions of 10 rows;
//06-Conway-Iterate
match (c:Cell)
with c,
case size((c)-[:NEIGHBOUR_OF]-(:Live))
when 2 then c:Live
when 3 then true
else false
end as alive
call { with c, alive
WITH *
WHERE alive
SET c:Live, c.name="😊"
REMOVE c:Dead
}
call { with c, alive
WITH *
WHERE not alive
SET c:Dead, c.name="☠️"
REMOVE c:Live
}
return labels(c), count(c);
//07-Lattice
WITH 10 as lim
WITH apoc.coll.combinations(range(0, lim) + range(0, lim), 2, 2) as out, lim
UNWIND out AS pair
MERGE (m:MM { name: pair[0] + ", " + pair[1], x: pair[0], y: pair[1] })
WITH m, lim
CALL apoc.create.setLabels(m, [
"MM",
["XEven", "XOdd"][m.x%2],
["YEven", "YOdd"][m.y%2]
]) YIELD node
WITH count(node) as whatever, lim
MATCH (m:MM)
/* Have to start one row down and one cell over to ensure all ordinal directions exist */
WHERE m.x >= 1 AND m.y >= 1 AND m.x <= lim AND m.y <= lim
WITH m.x as x, m.y as y, m
/* Example of matrix math
4,6 5,6 6,6
4,5 5,5 6,5
4,4 5,4 6,4
*/
MATCH (northwest:MM { x: x-1, y: y+1 })
MATCH (north:MM { x: x, y: y+1 })
MATCH (northeast:MM { x: x+1, y: y+1 })
MATCH (east:MM { x: x+1, y: y })
MATCH (west:MM { x: x-1, y: y })
MATCH (southwest:MM { x: x-1, y: y-1 })
MATCH (south:MM { x: x, y: y-1 })
MATCH (southeast:MM { x: x+1, y: y-1 })
MERGE (m)-[r:`W`]->(west)
MERGE (m)-[r2:`S`]->(south)
MERGE (m)-[r3:`SW`]->(southwest)
RETURN count(m);
//08-Tree
WITH 2 as branchFactor, 3 as depth
create (l:Leaf { id: rand() })
with l, branchFactor, depth
UNWIND range(0, depth) AS iteration
CALL {
WITH branchFactor
MATCH (tn:Leaf) WITH tn, branchFactor
REMOVE tn:Leaf
SET tn:TreeNode
FOREACH (id IN range(0,branchFactor) | CREATE (:Leaf { id: rand() })-[:PARENT]->(tn))
}
RETURN null
//Show Everything
MATCH (n) RETURN n;
//XX-Wipe
call apoc.periodic.iterate('MATCH (n) RETURN n', 'DETACH DELETE n', {batchSize:1000,parallel:false});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment