Newsgroups: comp.lang.prolog
Path: cantaloupe.srv.cs.cmu.edu!nntp.club.cc.cmu.edu!hudson.lm.com!news.pop.psu.edu!news.cac.psu.edu!howland.reston.ans.net!Germany.EU.net!EU.net!julienas!news.fnet.fr!ilog!debacker
From: debacker@ilog.ilog.fr (Bruno de Backer)
Subject: Re: Solving Magic Squares
Message-ID: <1995Jan9.092556.9707@ilog.fr>
Sender: news@ilog.fr
Nntp-Posting-Host: courcelles
Organization: ILOG S.A., France
References:  <3ek1hq$dtt@uni4nn.iaf.nl>
Date: Mon, 9 Jan 95 09:25:56 GMT
Lines: 60

Shiva Feddema says: 

>Who can help me finding an algorithem for solving magical squares,
>that will say, matrix form squares like 5x5 where horisontal, vertical
>and diagonal sum of that row containing numbers is everywhere the
>same. Like
> 
>834 
>159 
>672 
>
>and also for squares bigger than 5x5 with accaptable solving time.
>(less than one hour).

The follwing short program, written in Ilog Solver, a C++ constraint programming 
library, allows to find the solution for a 5x5 magic square in less than 
2 seconds on a 486/66.  Basically what the program does is stating that
all the numbers in the square are integer, are all different, and that the
sums of diagonals, lines, and columns are equal.  

#include <ilsolver/ctint.h>

int main(int argc, char* argv[]) {
  CtInt i,j;
  CtInt N;
  CtInit();
  N=(argc>1?atoi(argv[1]):5);
  CtIntVar * Sum = new (CtHeap()) CtIntVar(0,1000);  
  CtEq(Sum,N*(N*N+1)/2);
  CtIntVar ** Square=new (CtHeap()) CtIntVar * [N*N];   
  for (i=0; i<N*N; i++) Square[i]=new (CtHeap()) CtIntVar(1,N*N);
  CtAllNeq(N*N,Square);                                     // all the numbers are different
  for (i=0; i<N; i++) CtEq(CtArraySum(N,&Square[N*i]),Sum); // sums on lines
  CtIntVar ** Temp = new (CtHeap()) CtIntVar * [N];
  for (i=0; i<N; i++) {
    for (j=0; j<N; j++) Temp[j]=Square[N*j+i];
    CtEq(CtArraySum(N,Temp),Sum);                           // sums on columns
  }
  for (i=0; i<N; i++) Temp[i] = Square[N*i+i];              // 1st diagonal
  CtEq(CtArraySum(N,Temp),Sum);
  for (i=0; i<N; i++) Temp[i] = Square[N*i+N-i-1];          // second diagonal
  CtEq(CtArraySum(N,Temp),Sum);
  CtSolve(CtGenerate(N*N, Square,CtChooseMinSizeInt));      // enumeration primitive
  // for printing
  for (i = 0; i < N; i++) {
    for (j = 0; j < N; j++) {
      Square[N*i+j]->setName("");
      cout << " " << *Square[N*i+j];
    } 
    cout << endl;
  }
  CtEnd();
  return 0;
}

-- 
  Bruno De Backer		 net : debacker@ilog.fr
  ILOG S.A.                      url : http://www.ilog.fr
  2 Avenue Gallieni - BP 85	 tel : +33 1 46 63 66 66
  F-94253 Gentilly Cedex FRANCE	 fax : +33 1 46 63 15 82
