```
##
## TWIDDLE
##
## The Origin is:
## https://puzzling.stackexchange.com/questions/47124/what-is-the-strategy-to-solve-simon-tathams-twiddle
##
## Parameters defining board, horizont,...
param n := 4; # Tablero
set N := 1..n;
set Fic := 1..n^2; # Fichas
set Mov := 1..18; # Movimientos
set Cam:= 1..8;
set V := {1..n} cross {1..n};
param M := (n+5)^2; # M suficientemente grande
param Epoc; # Movimientos a considerar
let Epoc := 16;
set H := 1..Epoc; # HORIZONTE
set H1 := 1..(Epoc-1);
# Params BB and TR (calculated offside)
# BB[peg,movement] =1 iff peg is affected by mov
# TR[peg,movement] = position to change
param BB{Fic,Mov} binary default 0;
let BB[1,1] := 1; let BB[11,6] :=1; let BB[14,7] :=1; let BB[2,2] :=1; let BB[6,1] :=1; let BB[7,5] :=1;
let BB[10,4] :=1; let BB[11,8] :=1; let BB[14,8] :=1; let BB[3,2] :=1; let BB[6,2] :=1; let BB[7,6] :=1;
let BB[10,5] :=1; let BB[11,9] :=1; let BB[15,8] :=1; let BB[3,3] :=1; let BB[6,4] :=1; let BB[8,3] :=1;
let BB[10,7] :=1; let BB[12,6] :=1; let BB[15,9] :=1; let BB[4,3] :=1; let BB[6,5] :=1; let BB[8,6] :=1;
let BB[10,8] :=1; let BB[12,9] :=1; let BB[16,9] :=1; let BB[5,1] :=1; let BB[7,2] :=1; let BB[9,4] :=1;
let BB[11,5] :=1; let BB[13,7] :=1; let BB[2,1] :=1; let BB[5,4] :=1; let BB[7,3] :=1; let BB[9,7] :=1;
let BB[1,10] :=1; let BB[11,15] :=1; let BB[14,16] :=1; let BB[2,11] :=1; let BB[6,10] :=1; let BB[7,14] :=1;
let BB[10,13] :=1; let BB[11,17] :=1; let BB[14,17] :=1; let BB[3,11] :=1; let BB[6,11] :=1; let BB[7,15] :=1;
let BB[10,14] :=1; let BB[11,18] :=1; let BB[15,17] :=1; let BB[3,12] :=1; let BB[6,13] :=1; let BB[8,12] :=1;
let BB[10,16] :=1; let BB[12,15] :=1; let BB[15,18] :=1; let BB[4,12] :=1; let BB[6,14] :=1; let BB[8,15] :=1;
let BB[10,17] :=1; let BB[12,18] :=1; let BB[16,18] :=1; let BB[5,10] :=1; let BB[7,11] :=1; let BB[9,13] :=1;
let BB[11,14] :=1; let BB[13,16] :=1; let BB[2,10] :=1; let BB[5,13] :=1; let BB[7,12] :=1; let BB[9,16] :=1;
param TR{Fic,Mov} integer default 0;
let TR[1,1] :=5; let TR[11,6] :=12; let TR[14,7] :=10; let TR[2,2] :=6; let TR[6,1] :=2; let TR[7,5] :=6;
let TR[10,4] :=6; let TR[11,8] :=10; let TR[14,8] :=15; let TR[3,2] :=2; let TR[6,2] :=7; let TR[7,6] :=11;
let TR[10,5] :=11; let TR[11,9] :=15; let TR[15,8] :=11; let TR[3,3] :=7; let TR[6,4] :=5; let TR[8,3] :=4;
let TR[10,7] :=9; let TR[12,6] :=8; let TR[15,9] :=16; let TR[4,3] :=3; let TR[6,5] :=10; let TR[8,6] :=7;
let TR[10,8] :=14; let TR[12,9] :=11; let TR[16,9] :=12; let TR[5,1] :=6; let TR[7,2] :=3; let TR[9,4] :=10;
let TR[11,5] :=7; let TR[13,7] :=14; let TR[2,1] :=1; let TR[5,4] :=9; let TR[7,3] :=8; let TR[9,7] :=13;
let TR[1,10] :=2; let TR[11,15] :=7; let TR[14,16] :=13; let TR[2,11] :=3; let TR[6,10] :=5; let TR[7,14] :=11;
let TR[10,13] :=9; let TR[11,17] :=15; let TR[14,17] :=10; let TR[3,11] :=7; let TR[6,11] :=2; let TR[7,15] :=8;
let TR[10,14] :=6; let TR[11,18] :=12; let TR[15,17] :=14; let TR[3,12] :=4; let TR[6,13] :=10; let TR[8,12] :=7;
let TR[10,16] :=14; let TR[12,15] :=11; let TR[15,18] :=11; let TR[4,12] :=8; let TR[6,14] :=7; let TR[8,15] :=12;
let TR[10,17] :=11; let TR[12,18] :=16; let TR[16,18] :=15; let TR[5,10] :=1; let TR[7,11] :=6; let TR[9,13] :=5;
let TR[11,14] :=10; let TR[13,16] :=9; let TR[2,10] :=6; let TR[5,13] :=6; let TR[7,12] :=3; let TR[9,16] :=10;
# P = position of number Fic in Board
# Z = movement (1..18) = 2 ways x 9 centers of rotation
var P{Fic,H} >=1,<=n^2 integer; # Posicion en tablero de ficha i en t (0..15)
var Z{Mov,H} binary default 0; # Movimiento elegido
# Desvs to goals
var DesvPos{Fic} >=0, <=n^2 ; # Desviaciones a meta
var DesvNeg{Fic} >=0, <=n^2 ; # Desviaciones a meta
# Some dummys during trials
# OBJETIVO
# minimize SX:
# sum{i in Fic} (DesvPos[i] + DesvNeg[i]);
# Initial board just rewired
# Configuración Inicial del Tablero
subject to TabIni {i in Fic}:
P[i,1] == 17-i;
# In use is goal positions to achieve
# Desviaciones a objetivo
# subject to Desvs {i in Fic}:
# (P[i,Epoc] + DesvPos[i] - DesvNeg[i]) == i;
# One movement per turn
# Sólo un Movimiento
subject to UnMov {t in H}:
sum{i in Mov} Z[i,t] == 1;
# Cut added
# Se cumplen valores de P
subject to CaCo {t in H} :
sum {i in Fic} P[i,t] == sum {j in Fic} j;
# Here where the problem is
# The Position P[j] change iff j is affected by move, j = TR[i,movement]....
#
# subject to S {i in Fic,t in H1}:
# P[i,t+1] == sum {m1 in Mov} (TR[i,m1]*Z[m1,t]) + sum {m1 in Mov} P[i,t]*Z[m1,t]*(1-BB[i,m1]);
# Linealizing the product of binary (Z) by integer (P)
# CONTAINS A VARIABLE
# Actualiza valores (S1,S2 = Cambian; S3,S4 = Permanecen)
subject to S1 {i in Fic,t in 2..Epoc}:
P[i,t] >= sum {m1 in Mov} TR[i,m1]*Z[m1,t-1] - M*sum {m1 in Mov} Z[m1,t-1]*(1-BB[i,m1]);
subject to S2 {i in Fic,t in 2..Epoc}:
P[i,t] <= sum {m1 in Mov} TR[i,m1]*Z[m1,t-1] + M*sum {m1 in Mov} Z[m1,t-1]*(1-BB[i,m1]);
subject to S3 {i in Fic,t in 2..Epoc}:
P[i,t] >= P[i,t-1]-sum {m1 in Mov} Z[m1,t-1]*M*BB[i,m1];
subject to S4 {i in Fic,t in 2..Epoc}:
P[i,t] <= P[i,t-1]+sum {m1 in Mov} Z[m1,t-1]*M*BB[i,m1];
```