abstract sig Node {
, next: lone Node
}
fact list {
some root: Node |
root.*next = Node
}
sig Red, Blue extends Node {}

For each red node, I want to find the next red node. So if the model is red1 -> blue1 -> blue2 -> red2 -> red3, the relationship next_red_node should be red1 -> red2 + red2 -> red3. Ideally I want this to also be fast, since my production model already takes almost a minute to write the CFG.

I’m open to adding an extra field if that’s the fastest way.

Your lists currently allow circularity. If that was not the case (that is, if fact list included constraint no x : Node | x in x.^next) I think you could derive next_red_node as follows:

fun next_red_node : Node -> Node {
{ x,y : Red | y in x.^next and no Red & x.^next & ^next.y}
}