// Feb 8th + Feb 11th

sig City {
  roads: set City
}
one sig Pvd extends City {}
one sig Bos extends City {}
one sig Wor extends City {}

//pred noSelfLoops {
fact noSelfLoops {
  //Pvd not in Pvd.roads
  all c: City | c not in c.roads
//  no c: City | c in c.roads
// one c: City | c in c.roads
}

//pred anotherNoSelfLoops {
//  no iden & roads
//}

run {} for exactly 5 City
//run noSelfLoops for exactly 5 City

pred noSharedOut[c1, c2: City] {
  -- Note: c1, c2 can be same city if no outgoing roads!
  all c: City |
    c in c1.roads implies c not in c2.roads
}

pred noSharedOut2[c1, c2: City] {
  -- Note: c1, c2 can be same city if no outgoing roads!
  no (c1.roads & c2.roads)
}

run noSharedOut for 5
run noSharedOut2 for 5

-- In class, this had an unintentional bug.
-- I put the "not" inside the alls, rather than outside!
-- A counterexample needs to contain a particular c1, c2 such that...
pred NOTsharedOutSame {
  not  -- YES
  all c1, c2: City | {
  // not -- NOT
    (noSharedOut[c1, c2] iff noSharedOut2[c1, c2])
  }
}
run NOTsharedOutSame for 5

/*
assert sharedOutSame {
  all c1, c2: City | {
    noSharedOut[c1, c2] iff noSharedOut2[c1, c2]
  }
}
check sharedOutSame for 5*/

pred hopToStrictlyMore[c1, c2: City] {
  // c1's next hops are a strict superset of c2's next hops
  c2.roads in c1.roads
  some (c1.roads - c2.roads)
}

pred providenceInOneHop[c: City] {
  Pvd in c.roads
//  (c -> Pvd) in roads
}

pred providenceInTwoHops[c: City] {
/*  some middle: City | {
    middle in c.roads and Pvd in middle.roads
  }*/
  Pvd in c.roads.roads
}

pred provReachable[c: City] {
/*  c->Pvd in roads or
  c->Pvd in roads.roads or
  c->Pvd in roads.roads.roads // ..*/
    c->Pvd in ^roads
}

run {#roads > 9} for exactly 5 City, 6 int