is.magichypercube {magic} | R Documentation |
Returns TRUE
if a hypercube is semimagic, magic, perfect
is.semimagichypercube(a, give.answers=FALSE, FUN=sum, boolean=FALSE) is.diagonally.correct(a, give.answers = FALSE, FUN=sum, boolean=FALSE) is.magichypercube(a, give.answers = FALSE, FUN=sum, boolean=FALSE) is.perfect(a, give.answers = FALSE, FUN=sum, boolean=FALSE) is.latinhypercube(a, give.answers=FALSE)
a |
The hypercube (array) to be tested |
give.answers |
Boolean, with TRUE meaning to also return
the sums |
FUN |
Function to be applied across each dimension |
boolean |
Boolean, with TRUE meaning that the hypercube is
deemed magic, semimagic, etc, if all applications of FUN
evaluate to TRUE . If boolean is FALSE , the
hypercube is magic etc if all applications of FUN are identical |
(Although apparently non-standard, here a hypercube is defined to have dimension d and order n—and thus has n^d elements).
is.semimagichypercube()
, if
give.answers
is TRUE
, the sums returned are in the
form of an array of dimension c(rep(n,d-1),d)
. The first
d-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 FUN
, defaulting to sum()
, indicates
the function to be taken over each of the d
dimensions.
Currently requires FUN
to return a scalar.
is.diagonally.correct()
; by
specifying a function other than sum()
, criteria other than
the diagonals returning the correct sum may be tested.
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 a
give.answers
argument.
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*2^d
elements), where q is the length of FUN()
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 FUN()
is applied to elements of a
with the
d-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 FUN()
, 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 FUN=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 that not all subhypercubes 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
5x5x5 (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 (3^d-1)n^(d-1)/2 correct summations. This is not coded up yet; I can't see how to do it in anything like a vectorized manner.
Robin K. S. Hankin
is.magic
, allsubhypercubes
, hendricks
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 #argument boolean can be confusing: zero <- array(0,rep(3,4)) is.semimagichypercube(a,FUN=is.ok,boolean=FALSE) # TRUE, because all # applications of is.ok() # return the same value! a2 <- magichypercube.4n(m=1,d=4) is.diagonally.correct(a2) is.diagonally.correct(a2,g=TRUE)$diag.sums ## To extract corner elements (note FUN(1:n) != FUN(n:1)): is.diagonally.correct(a2,FUN=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).