open util/ordering[Time]

sig Time {
  turn: one Light
}

abstract sig Color {}
one sig Red, Yellow, Green extends Color {}

abstract sig Light {
  myColor: Time -> one Color
}
one sig Light1, Light2 extends Light {}

fact init {
  Light1.myColor[first] = Red
  Light2.myColor[first] = Red
}

fact traces {
  all t: Time - last | { -- every prestate
    let other = Light - t.turn | {
      other.myColor[t.next] = other.myColor[t]

      t.turn.myColor[t] = Red => {
        t.turn.myColor[t.next] = Green
        t.turn = t.next.turn
      }

      t.turn.myColor[t] = Yellow => {
        t.turn.myColor[t.next] = Red
        other = t.next.turn
      }

      t.turn.myColor[t] = Green => {
        t.turn.myColor[t.next] = Yellow
        t.turn = t.next.turn
      }

    }
  }
}

run {} for 3 Color, 2 Light, 5 Time

/*
pred candidate1 {
  Light.myColor.Red = Time
}

pred candidate2 {
  all t: Time |
    some l: Light |
      l.myColor[t] = Red
}

check equiv { --alwaysOneRed {
  candidate1 iff candidate2
} for 3 Color, 2 Light, 10 Time
*/

check alwaysOneRed {
   Light.myColor.Red = Time
} for 3 Color, 2 Light, 10 Time


check alwaysTurnGreenEventually {
  all l: Light |
  all t: Time | {
    l.myColor[t] = Red implies
      some t2: t.^next | {
        l.myColor[t2] = Green
      }
  }

} for 3 Color, 2 Light, 100 Time

-- uh oh!