is.magichypercube {magic} | R Documentation |
magic hypercubes
Description
Returns TRUE
if a hypercube is semimagic, magic, perfect
Usage
is.semimagichypercube(a, give.answers=FALSE, func=sum, boolean=FALSE, ...)
is.diagonally.correct(a, give.answers = FALSE, func=sum, boolean=FALSE, ...)
is.magichypercube(a, give.answers = FALSE, func=sum, boolean=FALSE, ...)
is.perfect(a, give.answers = FALSE, func=sum, boolean=FALSE)
is.latinhypercube(a, give.answers=FALSE)
is.alicehypercube(a,ndim,give.answers=FALSE, func=sum, boolean=FALSE)
Arguments
a |
The hypercube (array) to be tested |
give.answers |
Boolean, with |
func |
Function to be applied across each dimension |
ndim |
In |
boolean |
Boolean, with |
... |
Further arguments passed to |
Details
(Although apparently non-standard, here a hypercube is defined to have
dimension d
and order n
—and thus has n^d
elements).
A semimagic hypercube has all “rook's move” sums equal to the magic constant (that is, each
\sum a[i_1,i_2,\ldots,i_{r-1},,i_{r+1}, \ldots,i_d]
with1\leq r\leq d
is equal to the magic constant for all values of thei
's). Inis.semimagichypercube()
, ifgive.answers
isTRUE
, the sums returned are in the form of an array of dimensionc(rep(n,d-1),d)
. The firstd-1
dimensions are the coordinates of the projection of the summed elements onto the surface hypercube. The last dimension indicates the dimension along which the sum was taken over.Optional argument
func
, defaulting tosum()
, indicates the function to be taken over each of thed
dimensions. Currently requiresfunc
to return a scalar.A Latin hypercube is one in which each line of elements whose coordinates differ in only one dimension comprises the numbers
1
ton
(or0
ton-1
), not necessarily in that order. Each integer thus appearsn^{d-1}
times.A magic hypercube is a semimagic hypercube with the additional requirement that all
2^{d-1}
long (ie extreme point-to-extreme point) diagonals sum correctly. Correct diagonal summation is tested byis.diagonally.correct()
; by specifying a function other thansum()
, criteria other than the diagonals returning the correct sum may be tested.An Alice hypercube is a different generalization of a semimagic square to higher dimensions. It is named for A. M. Hankin (“Alice”), who originally suggested it.
A semimagic hypercube has all one-dimensional subhypercubes (ie lines) summing correctly. An Alice hypercube is one in which all
ndim
-dimensional subhypercubes have the same sum, wherendim
is a fixed integer argument. Thus, ifa
is a hypercube of sizen^d
,is.alicehypercube(a,ndim)
returnsTRUE
if alln^{d-ndim}
subhypercubes have the same sum.For example, if
a
is four-dimensional with dimension5\times 5\times 5\times 5
thenis.alicehypercube(a,1)
isTRUE
if and only ifa
is a semimagic hypercube: all{4\choose 1}5^3=500
one-dimensional subhypercubes have the same sum. Thenis.alicehypercube(a,2)
isTRUE
if all 2-dimensional subhypercubes (ie all{4\choose 2}\times 5^2=150
of the5\times 5
squares, for examplea[,2,4,]
anda[1,1,,]
) have the same sum. Thenis.alicehypercube(a,3)
means that all 3d subhypercubes (ie all{4\choose 3}\times 5^1=20
of the5\times 5\times 5
cubes, for examplea[,,1,]
anda[4,,,]
) have the same sum. For any hypercubea
,is.alicehypercube(a,dim(a))
returnsTRUE
.A semimagic hypercube is an Alice hypercube for any value of
ndim
.A perfect magic hypercube (use
is.perfect()
) is a magic hypercube with all nonbroken diagonals summing correctly. This is a seriously restrictive requirement for high dimensional hypercubes. As yet, this function does not take agive.answers
argument.A pandiagonal magic hypercube, also Nasik hypercube (or sometimes just a perfect hypercube) is a semimagic hypercube with all diagonals, including broken diagonals, summing correctly. This is not implemented.
The terminology in this area is pretty confusing.
In is.magichypercube()
, if argument give.answers=TRUE
then a list is returned. The first element of this list is Boolean
with TRUE
if the array is a magic hypercube. The second
element and third elements are answers
fromis.semimagichypercube()
and is.diagonally.correct()
respectively.
In is.diagonally.correct()
, if argument
give.answers=TRUE
, the function also returns an array of
dimension c(q,rep(2,d))
(that is, q\times 2^d
elements), where q
is the length of func()
applied to a
long diagonal of a
(if q=1
, the first dimension is
dropped). If q=1
, then in dimension d
having index 1
means func()
is applied to elements of a
with the
d^{\rm th}
dimension running over 1:n
; index 2
means to run over n:1
. If q>1
, the index of the first
dimension gives the index of func()
, and subsequent dimensions
have indices of 1 or 2 as above and are interpreted in the same way.
An example of a function for which these two are not identical is given below.
If func=f
where f
is a function returning a vector of
length i
, is.diagonally.correct()
returns an array
out
of dimension c(i,rep(2,d))
, with
out[,i_1,i_2,...,i_d]
being f(x)
where x
is the
appropriate long diagonal. Thus the 2^d
equalities
out[,i_1,i_2,...,i_d]==out[,3-i_1,3-i_2,...,3-i_d]
hold if and
only if identical(f(x),f(rev(x)))
is TRUE
for each long
diagonal (a condition met, for example, by sum()
but not by the
identity function or function(x){x[1]}
).
Note
On this page, “subhypercube” is restricted to
rectangularly-oriented subarrays; see the note at subhypercubes
.
Not all subhypercubes of a magic hypercube are necessarily magic! (for
example, consider a 5-dimensional magic hypercube a
. The square
b
defined by a[1,1,1,,]
might not be magic: the diagonals
of b
are not covered by the definition of a magic hypercube).
Some subhypercubes of a magic hypercube are not even semimagic: see
below for an example.
Even in three dimensions, being perfect is pretty bad. Consider a
5\times5\times 5
(ie three dimensional), cube. Say
a=magiccube.2np1(2)
. Then the square defined by
sapply(1:n,function(i){a[,i,6-i]}, simplify=TRUE)
, which is a
subhypercube of a
, is not even semimagic: the rowsums are
incorrect (the colsums must sum correctly because a
is magic).
Note that the diagonals of this square are two of the “extreme
point-to-point” diagonals of a
.
A pandiagonal magic hypercube (or sometimes just a perfect
hypercube) is semimagic and in addition the sums of all diagonals,
including broken diagonals, are correct. This is one seriously bad-ass
requirement. I reckon that is a total of \frac{1}{2}\left(
3^d-1\right)\cdot n^{d-1}
correct summations. This
is not coded up yet; I can't see how to do it in anything like a
vectorized manner.
Author(s)
Robin K. S. Hankin
References
-
R. K. S. Hankin 2005. “Recreational mathematics with R: introducing the magic package”. R news, 5(1)
-
Richards 1980. “Generalized magic cubes”. Mathematics Magazine, volume 53, number 2, (March).
See Also
is.magic
, allsubhypercubes
, hendricks
Examples
library(abind)
is.semimagichypercube(magiccube.2np1(1))
is.semimagichypercube(magichypercube.4n(1,d=4))
is.perfect(magichypercube.4n(1,d=4))
# Now try an array with minmax(dim(a))==FALSE:
a <- abind(magiccube.2np1(1),magiccube.2np1(1),along=2)
is.semimagichypercube(a,g=TRUE)$rook.sums
# is.semimagichypercube() takes further arguments:
mymax <- function(x,UP){max(c(x,UP))}
not_mag <- array(1:81,rep(3,4))
is.semimagichypercube(not_mag,func=mymax,UP=80) # FALSE
is.semimagichypercube(not_mag,func=mymax,UP=81) # TRUE
a2 <- magichypercube.4n(m=1,d=4)
is.diagonally.correct(a2)
is.diagonally.correct(a2,g=TRUE)$diag.sums
## To extract corner elements (note func(1:n) != func(n:1)):
is.diagonally.correct(a2,func=function(x){x[1]},g=TRUE)$diag.sums
#Now for a subhypercube of a magic hypercube that is not semimagic:
is.magic(allsubhypercubes(magiccube.2np1(1))[[10]])
data(hendricks)
is.perfect(hendricks)
#note that Hendricks's magic cube also has many broken diagonals summing
#correctly:
a <- allsubhypercubes(hendricks)
ld <- function(a){length(dim(a))}
jj <- unlist(lapply(a,ld))
f <- function(i){is.perfect(a[[which(jj==2)[i]]])}
all(sapply(1:sum(jj==2),f))
#but this is NOT enough to ensure that it is pandiagonal (but I
#think hendricks is pandiagonal).
is.alicehypercube(magichypercube.4n(1,d=5),4,give.answers=TRUE)