```c
sig Bucket {
	head : lone Node
}

sig Node {
	key : one Key,
	prox : lone Node
}

sig Key {
	hash : one Hash
}

sig Hash {}

pred Invs {
	// Specify the properties that characterize 
	// hash tables using closed addressing (separate 
	// chaining) for collision resolution.

	// The points you will get is proportional to the 
	// number of correct properties. To check how many
	// points you have so far you can use the different
 	// commands. For example, if check Three is correct 
	// you will have at least 3 points.
    // The maximum is 5 points.

	// Be careful to not overspecify! 
	// If you specify a property that is not valid in 
	// these hash tables you get 0 points, 
    // even if you have some correct properties.
	// To check if you are not overspecifying you can use 
	// command NoOverspecification. If you have an invalid
	// property this command will return a valid hash table 
	// that you specification is not accepting.

  
  	//no node links to itself and its children don't link to it (no loops)
  	all x: Node | x not in x.^prox
  	//ALTERNATIVELY (INCOMPLETE)
  	//all x: Node | x not in x.prox
  	//all x, y, z:Node, w : Key | (x.key = w and y.key = w and z.key = w and x.prox = z) implies y.prox!=z


  	//for all nodes sequentially linked, they must have the same hash
  	all x, y: Node | (x.prox = y) implies x.key.hash = y.key.hash
  	//ALTERNATIVELY
  	//all x, y: Node | x.key.hash != y.key.hash implies (x.prox != y and y.prox != x)

    //keys are unique to a single node
  	all x: Key | one y: Node | y.key = x

    //heads are unique to a single bucket (UNNECESSARY)
  	all x: Bucket | lone x.head
  
  	//nodes must be prox to another node or be the head of a bucket
   	all x: Node | (x in Bucket.head) or (x in Node.prox)
  
  	//diffenrent buckets must have different heads
	all x, y: Bucket, z : Node | x != y and x.head = z implies y.head!=z
  
  	//keys must have a hash
  	all x: Key | some y: Hash | x.hash = y
  	
  	//nodes(heads) associated to different buckets, must differ in hash
  	all x, y: Bucket | (x != y and x.head != none and y.head != none ) implies x.head.key.hash != y.head.key.hash

}

```


// SOLVED
```c
sig Bucket {
	head : lone Node
}

sig Node {
	key : one Key,
	prox : lone Node
}

sig Key {
	hash : one Hash
}

sig Hash {}

pred Invs {

    // no node links to itself and its children don't link to it (no loops)
  	all x: Node | x not in x.^prox
  
  	//for all nodes sequentially linked, they must have the same hash
  	all x, y: Node | (x.prox = y) implies x.key.hash = y.key.hash
  
    //keys are unique to a single node
  	all x: Key | one y: Node | y.key = x
  
  	//nodes must be prox to another node or be the head of a bucket
   	all x: Node | (x in Bucket.head) or (x in Node.prox)
  
  	//different buckets must have different heads
	all x, y: Bucket, z : Node | x != y and x.head = z implies y.head!=z
  
  	//keys must have a hash
  	all x: Key | some y: Hash | x.hash = y
  
  	//nodes(heads) associated to different buckets, must differ in hash
  	all x, y: Bucket | (x != y and x.head != none and y.head != none ) implies x.head.key.hash != y.head.key.hash
}
```

http://alloy4fun.inesctec.pt/5yb5zPPJWP29SDSbD