Commit b837a4d2 authored by Martin Maechler's avatar Martin Maechler

In tests/: if OpenBLAS | ATLAS | RMO (MKL): skip some tests

parent 97cc106e
Package: CLA
Version: 0.95-0
Date: 2019-02-04
Date: 2019-03-13
Title: Critical Line Algorithm in Pure R
Author: Yanhao Shi <syhelena@163.com>,
Martin Maechler <maechler@stat.math.ethz.ch>
......@@ -8,9 +8,9 @@ Maintainer: Martin Maechler <maechler@stat.math.ethz.ch>
Depends: R (>= 3.2.0)
Imports: stats, grDevices, graphics
Suggests: fGarch, FRAPO, Matrix
Description: Implements 'Markovitz' Critical Line Algorithm ('CLA') for
classical mean-variance portfolio optimization. Care has been taken for
correctness in light of previous buggy implementations.
Description: Implements 'Markovitz' Critical Line Algorithm ('CLA') for classical
mean-variance portfolio optimization, see Markovitz (1952) <doi:10.2307/2975974>.
Care has been taken for correctness in light of previous buggy implementations.
License: GPL (>= 3) | file LICENSE
Encoding: UTF-8
URL: https://gitlab.math.ethz.ch/maechler/CLA/
##-*- org -*--> Emacs .. [Tab] key + [Org] menu; C-c C-o to follow links
* ASAP (no longer "Before release of package")
* *Before* next CRAN release
** DONE OpenBLAS, ATLAS, etc: must fix file:tests/SP500-ex.R at least: use
R=/usr/bin/R R-pkg-check CLA # Fedora's R pkg using OpenBLAS
R=R-3.5.1_MS R-pkg-check CLA # (RMO using MKL)
R=R-ATLAS R-pkg-check CLA # using ATLAS
see files ./CLA_ATLAS.out ./CLA_MKL.out ./CLA_OpenBLAS.out
* ASAP (but possibly later than CRAN release)
** TODO check arguments e.g., lB <= uB, sum upper Bounds >= 1
** TODO References --> (mostly done)
** TODO References --> (mostly done): Make Master thesis web-available (from SfS ETHZ) ?
*** DONE 1) References from the thesis, including the "buried" python-paper with *WRONG* algo
*** TODO 2) Master thesis: I'd like the thesis to be on our web page
** TODO Improve plot() method, using hyperbolic interpolation see R/CLA.R man/plot.CLA.Rd
......
......@@ -4,7 +4,7 @@
\title{News for \R Package \pkg{CLA}}% MM: look into ../svn-log-from.all
\newcommand{\CRANpkg}{\href{https://CRAN.R-project.org/package=#1}{\pkg{#1}}}
\section{Changes in version 0.95-0 (2019-02-04)}{
\section{Changes in version 0.95-0 (2019-03-13)}{
\subsection{New Features}{
\itemize{
\item \emph{Not} back-compatible \emph{changed} result: The very
......@@ -13,6 +13,7 @@
with the litterature and other implementations.
\item Added data set \code{muS.10ex} orginally from Markowitz and Todd.
\item Added \file{NEWS} file.
}
}
......@@ -28,6 +29,9 @@
\item adapt \file{man/findSig.Rd} example to R 3.6.0's new default
\code{sample()} kind.
\item Run the \file{tests/*.R} with R versions that use one
OpenBLAS, ATLAS, or MKL (and skip some tests on these).
}
}
}
......
......@@ -77,7 +77,7 @@ CLA(mu, covar, lB, uB, tol.lambda = 1e-07,
%% \doi{10.1007/BF02282055}.
Niedermayer, A. and Niedermayer, D. (2010)
Applying markowitz’s critical line algorithm, in J. B. Guerard (ed.),
Applying Markowitz’s Critical Line Algorithm, in J. B. Guerard (ed.),
Handbook of Portfolio Construction, Springer; chapter 12, 383--400;
\doi{10.1007/978-0-387-77439-8_12}.
......@@ -85,6 +85,10 @@ CLA(mu, covar, lB, uB, tol.lambda = 1e-07,
An open-source implementation of the critical-line algorithm for portfolio
optimization, \emph{Algorithms} \bold{6}(1), 169--196;
\doi{10.3390/a6010169},
Yanhao Shi (2017)
Implementation and applications of critical line algorithm for
portfolio optimization; unpublished Master's thesis, ETH Zurich.
}
%% \note{
%% }
......
......@@ -10,9 +10,41 @@ b64nLD <- (arch == "x86_64" && .M$sizeof.longdouble != 16)
if(b64nLD) arch <- paste0(arch, "--no-long-double")
arch
## I'd want
## strict <- we_are_using_Rs_own_BLAS_and_Lapack() # but simply for now
(strict <- Sys.info()[["user"]] == "maechler")# actually
## <---> sync with ~/R/Pkgs/robustbase/tests/mc-strict.R
## ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sInfo <- sessionInfo()
if(!exists("osVersion")) osVersion <- sInfo$running
cat("osVersion:", osVersion, "\n")
if(!is.null(osVersion)) "Fedora" # last resort
BLAS.is.LAPACK <- sInfo$BLAS == sInfo$LAPACK
cat("osVersion:", osVersion, "| ",
'BLAS "is" Lapack:', BLAS.is.LAPACK, "\n")
## Find out if we are running Micrsoft R Open
is.MS.Ropen <- {
file.exists(Rpr <- file.path(R.home("etc"), "Rprofile.site")) &&
length(lnsRpr <- readLines(Rpr)) &&
## length(grep("[Mm]icrosoft", lnsRpr)) > 3 # MRO 3.5.1 has '20' times "[Mm]icrosoft"
length(grep("Microsoft R Open", lnsRpr, fixed=TRUE, value=TRUE)) > 0 ## MRO 3.5.1 has it twice
}
if(is.MS.Ropen) cat("We are running 'Microsoft R Open'\n")
## I'd really want
##
## strict <- we_are_using_Rs_own_BLAS_and_Lapack() [ ==> BLAS != Lapack ]
##
## Actually the following is currently (2019-03) equivalent to
## strict <- !(using ATLAS || OpenBLAS || MKL )
if(TRUE) {
strict <- !BLAS.is.LAPACK && !is.MS.Ropen
} else { ## workaround:
strict <- print(Sys.info()[["user"]]) == "maechler"# actually
## but not when testing with /usr/bin/R [OpenBLAS!] (as "maechler"):
if(strict && substr(osVersion, 1,6) == "Fedora" && R.home() == "/usr/lib64/R")
strict <- FALSE
}
cat("strict:", strict, "\n")
data(muS.sp500)
......@@ -27,7 +59,7 @@ system.time(# ~ 9 sec (64-bit); 13.8 sec (32-b florence); seen 27.44 sec on Winb
)
CLs5c.0.120 # -> print() method
un.call <- function(x) { x$call <- NULL ; x }
uncall <- function(x) `$<-`(x, call, NULL)
doExtras <- TRUE # for experiments, not normally
doExtras <- FALSE
......@@ -40,14 +72,14 @@ if(doExtras) system.time({
}) # 78.101 elapsed [nb-mm4] ; 46.108 [lynne 2018-10]
if(doExtras) {
identical(un.call(CLs5c.ls[["10^-7"]]), un.call(CLs5c.0.120))
identical(uncall(CLs5c.ls[["10^-7"]]), uncall(CLs5c.0.120))
for(i in seq_along(tols)[-1]) {
cat("--=--=--=--=--\n", (n1 <- names(tols[i-1])), " vs. ", (n2 <- names(tols[i])), ": ")
ae <- all.equal(un.call(CLs5c.ls[[i-1]]),
un.call(CLs5c.ls[[ i ]]))
ae <- all.equal(uncall(CLs5c.ls[[i-1]]),
uncall(CLs5c.ls[[ i ]]))
if(isTRUE(ae)) cat(" are all.equal()\n")
else {
CLA.i. <- un.call(CLs5c.ls[[i-1]]) ; wgt <- CLA.i.$weights_set
CLA.i. <- uncall(CLs5c.ls[[i-1]]) ; wgt <- CLA.i.$weights_set
cat("are different [all.equal()]: dim(..[[",n1,"]]$weights_set) =",
dim(wgt)[1],"x", dim(wgt)[2],"\n")
}
......@@ -82,23 +114,26 @@ if(require(Matrix)) withAutoprint(local = FALSE, {
}
options(op)
stopifnot(nrow(wts.non0) == 79)
if(FALSE) # once, manually (into tests/ directory
saveRDS(wts.non0, "wtsn0.rds")
file.info("wtsn0.rds")$size # 2702049
wtsn0.ref <- readRDS("wtsn0.rds")
## see on all platforms what we get
## see on all platforms what we get -- on OpenBLAS, the dim() differs !
all.equal(target = wtsn0.ref, current = wts.non0, tol=0)
# expect TRUE only on 64bit (Lnx, R's BLAS)
# 3.10416e-15 and 1.366427e-15 on other BLAS
stopifnot(all.equal(target = wtsn0.ref, current = wts.non0,
tol = 1e-13))
differWts <- ncol(wtsn0.ref) != ncol(wts.non0)
if(differWts) {
cat("Got",ncol(wts.non0), "weights from CLA() -- different than ref with",
ncol(wtsn0.ref), "\n")
strict <- FALSE # !
} else {
stopifnot(all.equal(target = wtsn0.ref, current = wts.non0,
tol = 1e-13))
}
non.0.assets <- Filter(function(.) . > 0, apply(wts.non0, 1, function(c) sum(c > 0)))
b64.n0 <-
c(AAPL = 135L, ADSK = 66L, AET = 147L, AMGN = 3L, ATI = 75L,
AYE = 56L, AZO = 26L, BAX = 95L, BCR = 35L, BDX = 36L, BIIB = 118L,
......@@ -177,18 +212,19 @@ if(all(non.0.assets == non.0.TARG)) { ## show differences:
}
## They have the same names and only differ by +/- 1:
stopifnot(
stopifnot(exprs = {
identical(names(b64.n0), names(b32.n0))
,
if(b64) !strict || identical(non.0.assets, non.0.TARG) # fails on ATLAS, MKL, OpenBLAS
if(b64) !strict || identical(non.0.assets, non.0.TARG) # identical(*) fails on ATLAS, MKL, OpenBLAS
else if(nonWindows) identical(non.0.assets, b32.n0)
else ## 32-bit Windows
TRUE ## for now
, identical(head(CLs5c.0.120$free_indices, 12),
differWts || identical(head(CLs5c.0.120$free_indices, 12),
list(c(295L, 453L), 453L, c(453L, 472L), c(19L, 453L, 472L),
c(19L, 453L), 453L, c(15L, 453L), 15L, c(15L, 320L),
c(15L, 105L, 320L), c(105L, 320L), c(105L, 320L, 472L)))
)
})
## Check some of the 'Env<n>' versions: ---------
......@@ -219,12 +255,16 @@ if(is.environment(e8 <- nsCLA$Env8)) local(withAutoprint({
system.time(r8 <- e8$cla.solve(muS.sp500$mu, muS.sp500$covar,
lB = rep(0,n), uB= rep(1/20, n)))
## lynne (2017): 9.6--9.8 sec; 2018: 6.1 sec
stopifnot(all.equal(claDrop1st(r8), rCLA, tol = 1e-14)) # they are the same!
if(ncol(claDrop1st(r8)$weights_set) == ncol(rCLA$weights_set))
stopifnot(all.equal(claDrop1st(r8), rCLA, tol = 1e-14)) # they are the same!
else cat("#{columns} differ in r8\n")
}))
if(is.environment(e9 <- nsCLA$Env9)) local(withAutoprint({
system.time(r9 <- e9$cla.solve(muS.sp500$mu, muS.sp500$covar,
lB = rep(0,n), uB= rep(1/20, n)))
## lynne(2017): 10.0 sec; 2018: 6.6 sec
stopifnot(all.equal(claDrop1st(r9), rCLA, tol = 1e-14)) # they are the same!
if(ncol(claDrop1st(r9)$weights_set) == ncol(rCLA$weights_set))
stopifnot(all.equal(claDrop1st(r9), rCLA, tol = 1e-14)) # they are the same!
else cat("#{columns} differ in r9\n")
}))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment