Magic square

I need to create a magic square of order n=4 using a Matrix.

I have tried many linear equations system. Got me nowhere so far.

Robert Israel's picture

Magic square

If you want a "normal" magic square whose entries are the integers 1 to 16, you need more than just a linear system of equations.  Some searching will be necessary...

entries

Entries doesn't have to be 1 to 16, it can be anything. As long as all numbers are different.

Robert Israel's picture

entries

In that case, it's not so hard.  Just solve your set of equations, and substitute in some random values.

pan-magic square

Here's a brute force solution.  To reduce the solution space, I solved for a pan-magic square; in addition to the usual constraints, the sums of all the broken diagonals must also equal the magic number.

PanMagic := proc(L,n::posint)
local i,j,M,rng;
    rng := 0..n-1;
    M := (n^3+n)/2;
    [seq(s=M, s in [NULL
                    , seq(add(L[i,j], j=rng), i=rng)
                    , seq(add(L[i,j], i=rng), j=rng)
                    , seq(add(L[i,modp(i+j,n)],i=rng), j=rng)
                    , seq(add(L[i,modp(j-i-1,n)],i=rng), j=rng)
                   ])];
end proc:

to 1 do
    n := 4:
    eqs := PanMagic(L,n);
    sol := solve(eqs);
    vals := map(rhs,sol);
    vars := convert(indets(vals),'list');
end do:

all := {seq(1..n^2)}:

P := combinat:-permute(convert(all,'list'),nops(vars)):

found := false:
for p in P do
    eqs := Equate(vars,p);
    if subs(eqs, vals) = all then
        found := true;
        break;
    end if;
end do:

if found=true then
    M := subs(sol,eqs, Matrix(n,n,(i,j) -> L[i-1,j-1]));
end if;

                               [ 1     8    10    15]
                               [                    ]
                               [12    13     3     6]
                          M := [                    ]
                               [ 7     2    16     9]
                               [                    ]
                               [14    11     5     4]

Would it looks like that or

Would it looks like that or something around that :
 

eq1:= a+b+c+d= v
eq2:= e+f+g+h=v
eq3:= i+j+k+l=v
eq4:= m+n+o+p=v
eq5:= a+f+k+p=v
eq6:= d+g+j+m=v
eq7:= a+e+i+m=v
eq8:= b+f+j+n=v
eq9:= c+g+k+o=v
eq10:= d+h+l+p=p

Then do a matrix with all these eqs and solve with GaussJordan and I'll get an infinity of solutions?

I'd like to know if I am right or completly off the track! Thank you for help
 

Robert Israel's picture

Something like that

But it's much better, and less error-prone, if you use an indexed variable rather than 16 different names.  Let Maple do the work!

eqs:= {seq(add(a[i,j], j=1..4) = v, i=1..4), 
   seq(add(a[i,j], i=1..4) = v, j=1..4),
   add(a[i,i], i=1..4) = v,
   add(a[i,5-i], i=1..4) = v};

And then use solve.

View 6892_magicsquare.mw on

View 6892_magicsquare.mw on MapleNet or Download 6892_magicsquare.mw
View file details

I have no idea how to create a magic square with the answer it gives me. I uploaded my sheet so if you could check and let me know how to do something with that.

Thank you.
 
I don't think I have the right to use the commands you posted that's why I used this.

Robert Israel's picture

The hard way

You seem to be insisting on doing things the hard way.  Moreover, you're using the old and deprecated linalg package rather than LinearAlgebra.  But anyway:
 

> PL := convert(P, list);
   vars:= map(parse, [$"a".."p"]);

Get some arbitrary values for v and _t[1] to _t[7], and get the variable values:

> vals:= subs(map(t -> (t = rand(0..100)()), indets(PL)),zip(`=`,vars,PL));
> subs(vals, Matrix(4,4,vars));

cat

A "cleaner" way to create the list of variables directly (i.e. without, say, indets) is

vars := [cat(``,"a".."p")];

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
}