Download
%
% Magic squares in MiniZinc
%
% 
% This MiniZinc model was created by Hakan Kjellerstrand, hakank@gmail.com
% See also my MiniZinc page: http://www.hakank.org/minizinc
%

% Licenced under CC-BY-4.0 : http://creativecommons.org/licenses/by/4.0/

include "globals.mzn";

int: n = 3;

int: total = ( n * (n*n + 1)) div 2;
array[1..n,1..n] of var 1..n*n: magic;


% solve satisfy;
solve :: int_search(
        [magic[i,j] | i in 1..n, j in 1..n], 
        first_fail,
        indomain_min,
        complete) 
    satisfy;


constraint

        all_different([magic[i,j] | i in 1..n, j in 1..n]) :: domain
        /\
        forall(k in 1..n) (
           sum(i in 1..n) (magic[k,i]) = total % :: domain
           /\
           sum(i in 1..n) (magic[i,k]) = total %:: domain
        )
       /\ % diagonal
       sum(i in 1..n) (magic[i,i]) = total  %:: domain
       /\ % diagonal
       sum(i in 1..n) (magic[i,n-i+1]) = total %:: domain
;

% symmetry breaking
% Activating all these constraints we get the
% "standard" way of counting the number of solutions:
%    1, 0, 1, 880, 275305224
% i.e. this sequence: http://oeis.org/A006052
%
% Without the constraints the number of solutions are:
%  N  #solutions
%  -------------
%  1     1
%  2     0
%  3     8
%  4  7040
%  5  many... 
%
% constraint
%    magic[1,1] < magic[1,n]
%    /\ magic[1,n] < magic[n,1]
%    /\ magic[1,1] < magic[n,n]
% ;


output [
  "Total: " ++ show(total) ++ "\n"
] ++
[
    %   show(magic)
  if j = 1 then "\n" else "" endif ++
    if fix(magic[i,j]) < 10 then " " else "" endif ++
    show(magic[i,j]) ++ " "
  | i,j in 1..n
] 
++ 
["\n"];