Volume 6, Number 2, January 2006
gunport4.mod
 
 
/* 
 Model name   : gunport4.mod
 Description  : solves Gunport puzzles
 Source       : Martin Gardner 
 Date written : 28/3/06
 Written by   : Robert Bosch, Oberlin College
 Email        : bobb@cs.oberlin.edu 
*/

int nbRows = 7;
int nbCols = 9;
int p;

dvar boolean h[1..nbRows,1..nbCols-1];
dvar boolean v[1..nbRows-1,1..nbCols];
dvar boolean m[1..nbRows,1..nbCols];

int m3 = nbRows mod 3;
int n3 = nbCols mod 3;

int fhr;
int shr;
int fhc;
int shc;

execute {
  /* compute required number of monominoes */
  if (m3*n3==0) 
    p = nbRows*nbCols/3;
    else
      if (m3==n3)
        p = (nbRows*nbCols-4)/3;
        else
          p = (nbRows*nbCols-2)/3;

  /* compute ranges for symmetry constraints */
  fhr = Math.floor(nbRows/2);
  if (nbRows % 2 == 0) 
    shr = fhr+1;
  else
    shr = fhr+2;
  fhc = Math.floor(nbCols/2);    
  if (nbCols % 2 == 0) 
    shc = fhc+1;
  else
    shc = fhc+2;  
}

maximize sum(r in 1..nbRows, c in 1..nbCols) m[r,c];

subject to {

  /* Interior cells */
  forall (r in 2..nbRows-1, c in 2..nbCols-1)
    h[r,c-1] + h[r,c] + v[r-1,c] + v[r,c] + m[r,c] == 1;
  /* Edge cells, top row */
  forall (c in 2..nbCols-1)
    h[1,c-1] + h[1,c] + v[1,c] + m[1,c] == 1;
  /* Edge cells, bottom row */
  forall (c in 2..nbCols-1)
    h[nbRows,c-1] + h[nbRows,c] + v[nbRows-1,c] + m[nbRows,c] == 1;
  /* Edge cells, leftmost column */
  forall (r in 2..nbRows-1)
    h[r,1] + v[r-1,1] + v[r,1] + m[r,1] == 1;
  /* Edge cells, rightmost column */
  forall (r in 2..nbRows-1)
    h[r,nbCols-1] + v[r-1,nbCols] + v[r,nbCols] + m[r,nbCols] == 1;
  /* Cell (1,1) */
  h[1,1] + v[1,1] + m[1,1] == 1;
  /* Cell (1,nbCols) */
  h[1,nbCols-1] + v[1,nbCols] + m[1,nbCols] == 1;
  /* Cell (nbRows,1) */
  h[nbRows,1] + v[nbRows-1,1] + m[nbRows,1] == 1;
  /* Cell (nbRows,nbCols) */
  h[nbRows,nbCols-1] + v[nbRows-1,nbCols] + m[nbRows,nbCols] == 1;

  /* No horizontally adjacent monominoes */
  forall (r in 1..nbRows, c in 1..nbCols-1)
    m[r,c] + m[r,c+1] <= 1;
  /* No vertically adjacent monominoes */
  forall (r in 1..nbRows-1, c in 1..nbCols)
    m[r,c] + m[r+1,c] <= 1;

  /* eliminate symmetries */
  sum( r in 1..fhr, c in 1..nbCols) m[r,c] 
    <= sum( r in shr..nbRows, c in 1..nbCols) m[r,c];
  sum( r in 1..nbRows, c in 1..fhc) m[r,c]
    <= sum( r in 1..nbRows, c in shc..nbCols) m[r,c]; 

  /* place specified number of numbers */
  sum(r in 1..nbRows, c in 1..nbCols) m[r,c] == p;

}