mclust/ 0000755 0001762 0000144 00000000000 13510710262 011556 5 ustar ligges users mclust/inst/ 0000755 0001762 0000144 00000000000 13510412701 012530 5 ustar ligges users mclust/inst/CITATION 0000644 0001762 0000144 00000001651 13323700137 013675 0 ustar ligges users citHeader("To cite 'mclust' R package in publications, please use::")
citEntry(entry = "Article",
title = "{mclust} 5: clustering, classification and density estimation using {G}aussian finite mixture models",
author = personList(person(given="Luca", family="Scrucca"),
person(given="Michael", family="Fop"),
person(given=c("Thomas", "Brendan"), family="Murphy"),
person(given=c("Adrian", "E."), family="Raftery")),
journal = "The {R} Journal",
year = "2016",
volume = "8",
number = "1",
pages = "205--233",
url="https://journal.r-project.org/archive/2016-1/scrucca-fop-murphy-etal.pdf",
#
textVersion =
paste("Scrucca L., Fop M., Murphy T. B. and Raftery A. E. (2016)",
"mclust 5: clustering, classification and density estimation using Gaussian finite mixture models",
"The R Journal",
"8/1, pp. 205-233"))
mclust/inst/NEWS 0000644 0001762 0000144 00000033637 13375040702 013252 0 ustar ligges users Version 5.4.2
o Add mclustBICupdate() to merge the best values from two BIC results as
returned by mclustBIC().
o Add mclustLoglik() to compute the maximal log-likelihood values from
BIC results as returned by mclustBIC().
o Add option type = "level" to plot.densityMclust() and surfacePlot() to
draw highest density regions.
o Add meXXI() and meXXX() to exported functions.
o Update vignette.
Version 5.4.1
o Add parametric bootstrap option (type = "pb") in MclustBootstrap().
o Add the options to get averages of resampling distributions in
summary.MclustBootstrap() and to plot resampling-based confidence
intervals in plot.MclustBootstrap().
o Add function catwrap() for wrapping printed lines at getOption("width")
when using cat().
o mclust.options() now modify the variable .mclust in the namespace of
the package, so it should work even inside an mclust function call.
o Fix a bug in covw() when normalize = TRUE.
o Fix a bug in estepVEV() estepVEE() when parameters contains Vinv.
o Fix a bug in plotDensityMclustd() when drawing marginal axes.
o Fix a bug in summary.MclustDA() when computing classification error
in the extreme case of a minor class of assignment.
o Fix a bug in the initialisation of mclustBIC() when a noise component
is present for 1-dimensional data.
o fix bugs in some examples documenting clustCombi() and related
functions.
Version 5.4
o Model-based hierarchical clustering used to start the EM-algorithm
is now based on the scaled SVD transformation proposed by Scrucca and
Raftery (2016).
This change is not backward compatible. However, previous results can
be easily obtained by issuing the command:
mclust.options(hcUse = "VARS")
For more details see help("mclust.options").
o Added 'subset' parameter in mclust.options() to control the maximal
sample size to be used in the initial model-based hierarchical phase.
o predict.densityMclust() can optionally returns the density on a
logarithm scale.
o Removed normalization of mixing proportions for new models in single
mstep.
o Internal rewrite of code used by packageStartupMessage().
o Fix a small bug in MclustBootstrap() in the univariate data case.
o Fix bugs when both the noise and subset are provided for initialization.
o Vignette updated to include references, startup message, css style, etc.
o Various bugs fix in plotting methods when noise is present.
o Update references in citation() and man pages.
Version 5.3 (2017-05)
o added gmmhd() function and relative methods.
o added MclustDRsubsel() function and relative methods.
o added option to use subset in the hierarchical initialization step when
a noise component is present.
o plot.clustCombi() presents a menu in interactive sessions, no more
need of data for classification plots but extract the data from the
'clustCombi' object.
o added combiTree() plot for 'clustCombi' objects.
o clPairs() now produces a single scatterplot in the bivariate case.
o fix a bug in imputeData() when seed is provided. Now if a seed is
provided the data matrix is reproducible.
o in imputeData() and imputePairs() some name of arguments have been
modified to be coherent with the rest of the package.
o added functions matchCluster() and majorityVote().
o rewriting of print and summary methods for 'clustCombi' class object.
o added clustCombiOptim().
o fix a bug in randomPairs() when nrow of input data is odd.
o fix a bug in plotDensityMclust2(), plotDensityMclustd() and
surfacePlot() when a noise component is present.
Version 5.2.3 (2017-03)
o added native routine registration for Fortran code.
o fix lowercase argument PACKAGE in .Fortran() calls.
Version 5.2.2 (2017-01)
o fix a bug in rare case when performing an extra M step at the end of
EM algorithm.
Version 5.2.1 (2017-01)
o replaced "structure(NULL, *)" with "structure(list(), *)"
Version 5.2 (2016-03)
o added argument 'x' to Mclust() to use BIC values from previous
computations to avoid recomputing for the same models. The same
argument and functionality was already available in mclustBIC().
o added argument 'x' to mclustICL() to use ICL values from previous
computations to avoid recomputing for the same models.
o corrected a bug on plot.MclustBootstrap for the "mean" and "var" in
the univariate case.
o modified uncertainty plots.
o introduction of as.Mclust and as.densityMclust to convert object to
specific mclust classes.
o solved a numerical accuracy problem in qclass when the scale of x is
(very) large by making the tolerance eps scale dependent.
o use transpose subroutine instead of non-Fortran 77 TRANSPOSE function
in mclustaddson.f
o predict.Mclust and predict.MclustDR implement a more efficient and
accurate algorithm for computing the densities.
Version 5.1 (2015-10)
o fix slow convergence for VVE and EVE models.
o fix a bug in orientation for model VEE.
o add an extra M-step and parameters update in Mclust call via
summaryMclustBIC.
Version 5.0.2 (2015-07)
o add option to MclustBootstrap for using weighted likelihood bootstrap.
o add a plot method to MclustBootstrap.
o add errorBars function.
o add clPairsLegend function.
o add covw function.
o fix rescaling of mixing probabilities in new models.
o bug fixes.
Version 5.0.1 (2015-04)
o bug fixes.
o add print method to hc.
Version 5.0.0 (2015-03)
o added the four missing models (EVV, VEE, EVE, VVE) to the mclust
family. A noise component is allowed, but no prior is available.
o added mclustBootstrapLRT function (and print and plot methods) for
selecting the number of mixture components based on the bootstrap
sequential likelihood ratio test.
o added MclustBootstrap function (and print and summary methods) for
performing bootstrap inference. This provides standard errors for
parameters and confidence intervals.
o a "A quick tour of mclust" vignette is included as html generated using
rmarkdown and knitr. Older vignettes are included as other
documentation for the package.
o modified arguments to mvn2plot to control colour, lty, lwd, and pch of
ellipses and mean point.
o added functions emX, emXII, emXXI, emXXX, cdensX, cdensXII, cdensXXI,
and cdensXXX, to deal with single-component cases, so calling the em
function works even if G = 1.
o small changes to icl.R, now icl is a generic method, with specialized
methods for 'Mclust' and 'MclustDA' objects.
o bug fixes for transformations in the initialization step when some
variables are constant (i.e. the variance is zero) or a one-dimensional
data is provided.
o change the order of arguments in hc (and all the functions calling it).
o small modification to CITATION file upon request of CRAN maintainers.
o small bug fixes.
Version 4.4 (2014-09)
o add option for using transformation of variables in the hierarchical
initialization step.
o add quantileMclust for computing the quantiles from a univariate
Gaussian mixture distribution.
o bug fixes on summaryMclustBIC, summaryMclustBICn, Mclust to return a
matrix of 1s on a single column for z even in the case of G = 1. This
is to avoid error on some plots.
o pdf files (previously included as vignettes) moved to inst/doc with
corresponding index.html.
Version 4.3 (2014-03)
o bug fix for logLik.MclustDA() in the univariate case.
o add argument "what" to predict.densityMclust() function for choosing
what to retrieve, the mixture density or component density.
o hc function has an additional parameter to control if the original
variables or a transformation of them should be used for
hierarchical clustering.
o included "hcUse" in mclust.options to be passed as default to hc().
o original data (and class for classification models) are stored in the
object returned by the main functions.
o add component "hypvol"" to Mclust object which provide the hypervolume
of the noise component when required, otherwise is set to NA.
o add a warning when prior is used and BIC returns NAs.
o bug fixes for summary.Mclust(), print.summary.Mclust(), plot.Mclust()
and icl() in the case of presence of a noise component.
o some plots on plot.MclustDR() require plot.new() before calling
plot.window().
o bug fixes for MclustDR() when p=1.
o correction to Mclust man page.
o bug fixes.
Version 4.2 (2013-07)
o fix bug in sim* functions when no obs are assigned to a component.
o MclustDA allows to fit a single class model.
o fix bug in summary.Mclust when a subset is used for initialization.
o fix a bug in the function qclass when ties are present in quantiles,
so it always return the required number of classes.
o various small bug fixes.
Version 4.1 (2013-04)
o new icl function for computing the integrated complete-data likelihood
o new mclustICL function with associated print and plot methods
o print.mclustBIC shows also the top models based on BIC
o modified summary.Mclust to return also the icl
o rewrite of adjustedRandIndex function. This version is more efficient
for large vectors
o updated help for adjustedRandIndex
o modifications to MclustDR and its summary method
o changed behavior of plot.MclustDR(..., what = "contour")
o improved plot of uncertainty for plot.MclustDR(..., what = "boundaries")
o corrected a bug for malformed GvHD data
o corrected version of qclass for selecting initial values in
case of 1D data when successive quantiles coincide
o corrected version of plot BIC values when only a single G component
models are fitted
o various bug fixes
Version 4.0 (2012-08)
o new summary and print methods for Mclust.
o new summary and print methods for densityMclust.
o included MclustDA function and methods.
o included MclustDR function and methods.
o included me.weighted function.
o restored hierarchical clustering capability for the EEE model (hcEEE).
o included vignettes for mclust version 4 from Technical Report No. 597
and for using weights in mclust.
o adoption of GPL (>= 2) license.
Version 3.5 (2012-07)
o added summary.Mclust
o new functions for plotting and summarizing density estimation
o various bug fixes
o clustCombi (code and doc provided by Jean-Patrick Baudry)
o bug fix: variable names lost when G = 1
Version 3.4.11 (2012-01)
o added NAMESPACE
Version 3.4.10 (2011-05)
o removed intrinsic gamma
Version 3.4.9 (2011-05)
o fixed hypvol function to avoid overflow
o fixed hypvol helpfile value description
o removed unused variables and tabs from source code
o switched to intrinsic gamma in source code
o fixed default warning in estepVEV and mstepVEV
Version 3.4.8 (2010-12)
o fixed output when G = 1 (it had NA for the missing "z" component)
Version 3.4.7 (2010-10)
o removed hierarchical clustering capability for the EEE model (hcEEE)
o The R 2.12.0 build failed due to a 32-bit Windows compiler error,
forcing removal of the underlying Fortran code for hcEEE from the
package, which does not contain errors and compiles on other platforms.
Version 3.4.6 (2010-08)
o added description of parameters output component to Mclust and
o summary.mclustBIC help files
Version 3.4.5 (2010-07)
o added densityMclust function
Version 3.4.4 (2010-04)
o fixed bug in covariance matrix output for EEV and VEV models
Version 3.4.3 (2010-02)
o bug fixes
Version 3.4.2 (2010-02)
o moved CITATION to inst and used standard format
o BibTex entries are in inst/cite
o fixed bug in handling missing classes in mclustBIC
o clarified license wording
Version 3.4.1 (2010-01)
o corrected output description in mclustModel help file
o updated mclust manual reference to show revision
Version 3.4 (2009-12)
o updated defaultPrior help file
o added utility functions for imputing missing data with the mix package
o changed default max # of mixture components in each class from 9 to 3
Version 3.3.2 (2009-10)
o fixed problems with \cr in mclustOptions help file
Version 3.3.1 (2009-06)
o fixed plot.mclustBIC/plot.Mclust to handle modelNames
o changed "orientation" for VEV, VVV models to be consistent with R
eigen() and the literature
o fixed some problems including doc for the noise option
o updated the unmap function to optionally include missing groups
Version 3.3 (2009-06)
o fixed bug in the "errors" option for randProj
o fixed boundary cases for the "noise" option
Version 3.2 (2009-04)
o added permission for CRAN distribution to LICENSE
o fixed problems with help files found by new parser
o changed PKG_LIBS order in src/Makevars
o fixed Mclust to handle sampling in data expression in call
Version 3.1.10 (2008-11)
o added EXPR = to all switch functions that didn't already have it
Version 3.1.9 (2008-10)
o added pro component to parameters in dens help file
o fixed some problems with the noise option
Version 3.1.1 (2007-03)
o Default seed changed in sim functions.
o Model name check added to various functions.
o Otherwise backward compatible with version 3.0
Version 3.1 (2007-01)
o Most plotting functions changed to use color.
o Mclust/mclustBIC fixed to work with G=1
o Otherwise backward compatible with version 3.0.
Version 3.0 (2006-10)
o New functionality added, including conjugate priors for Bayesian
regularization.
o Backward compatibility is not guaranteed since the implementation
of some functions has changed to make them easier to use or maintain.
mclust/inst/doc/ 0000755 0001762 0000144 00000000000 13510412700 013274 5 ustar ligges users mclust/inst/doc/mclust.R 0000644 0001762 0000144 00000012757 13510412677 014757 0 ustar ligges users ## ----setup, include=FALSE------------------------------------------------
library(knitr)
opts_chunk$set(fig.align = "center",
out.width = "90%",
fig.width = 6, fig.height = 5.5,
dev.args=list(pointsize=10),
par = TRUE, # needed for setting hook
collapse = TRUE, # collapse input & ouput code in chunks
warning = FALSE)
knit_hooks$set(par = function(before, options, envir)
{ if(before && options$fig.show != "none")
par(family = "sans", mar=c(4.1,4.1,1.1,1.1), mgp=c(3,1,0), tcl=-0.5)
})
set.seed(1) # for exact reproducibility
## ---- message = FALSE, echo=-2-------------------------------------------
library(mclust)
cat(mclust:::mclustStartupMessage(), sep="")
## ------------------------------------------------------------------------
data(diabetes)
class <- diabetes$class
table(class)
X <- diabetes[,-1]
head(X)
clPairs(X, class)
BIC <- mclustBIC(X)
plot(BIC)
summary(BIC)
mod1 <- Mclust(X, x = BIC)
summary(mod1, parameters = TRUE)
plot(mod1, what = "classification")
table(class, mod1$classification)
plot(mod1, what = "uncertainty")
ICL <- mclustICL(X)
summary(ICL)
plot(ICL)
LRT <- mclustBootstrapLRT(X, modelName = "VVV")
LRT
## ------------------------------------------------------------------------
(hc1 <- hc(X, modelName = "VVV", use = "SVD"))
BIC1 <- mclustBIC(X, initialization = list(hcPairs = hc1)) # default
summary(BIC1)
(hc2 <- hc(X, modelName = "VVV", use = "VARS"))
BIC2 <- mclustBIC(X, initialization = list(hcPairs = hc2))
summary(BIC2)
(hc3 <- hc(X, modelName = "EEE", use = "SVD"))
BIC3 <- mclustBIC(X, initialization = list(hcPairs = hc3))
summary(BIC3)
## ------------------------------------------------------------------------
BIC <- mclustBICupdate(BIC1, BIC2, BIC3)
summary(BIC)
plot(BIC)
## ---- echo=-1------------------------------------------------------------
set.seed(20181116)
data(galaxies, package = "MASS")
galaxies <- galaxies / 1000
BIC <- NULL
for(j in 1:20)
{
rBIC <- mclustBIC(galaxies, verbose = FALSE,
initialization = list(hcPairs = randomPairs(galaxies)))
BIC <- mclustBICupdate(BIC, rBIC)
}
summary(BIC)
plot(BIC)
mod <- Mclust(galaxies, x = BIC)
summary(mod)
## ------------------------------------------------------------------------
data(iris)
class <- iris$Species
table(class)
X <- iris[,1:4]
head(X)
mod2 <- MclustDA(X, class, modelType = "EDDA")
summary(mod2)
plot(mod2, what = "scatterplot")
plot(mod2, what = "classification")
## ------------------------------------------------------------------------
data(banknote)
class <- banknote$Status
table(class)
X <- banknote[,-1]
head(X)
mod3 <- MclustDA(X, class)
summary(mod3)
plot(mod3, what = "scatterplot")
plot(mod3, what = "classification")
## ------------------------------------------------------------------------
cv <- cvMclustDA(mod2, nfold = 10)
str(cv)
unlist(cv[3:4])
cv <- cvMclustDA(mod3, nfold = 10)
str(cv)
unlist(cv[3:4])
## ------------------------------------------------------------------------
data(acidity)
mod4 <- densityMclust(acidity)
summary(mod4)
plot(mod4, what = "BIC")
plot(mod4, what = "density", data = acidity, breaks = 15)
plot(mod4, what = "diagnostic", type = "cdf")
plot(mod4, what = "diagnostic", type = "qq")
## ------------------------------------------------------------------------
data(faithful)
mod5 <- densityMclust(faithful)
summary(mod5)
plot(mod5, what = "BIC")
plot(mod5, what = "density")
plot(mod5, what = "density", type = "hdr")
plot(mod5, what = "density", type = "hdr",
data = faithful, points.cex = 0.5)
plot(mod5, what = "density", type = "persp")
## ------------------------------------------------------------------------
boot1 <- MclustBootstrap(mod1, nboot = 999, type = "bs")
summary(boot1, what = "se")
summary(boot1, what = "ci")
par(mfrow=c(4,3))
plot(boot1, what = "pro")
plot(boot1, what = "mean")
par(mfrow=c(1,1))
## ------------------------------------------------------------------------
boot4 <- MclustBootstrap(mod4, nboot = 999, type = "bs")
summary(boot4, what = "se")
summary(boot4, what = "ci")
par(mfrow=c(2,2))
plot(boot4, what = "pro")
plot(boot4, what = "mean")
par(mfrow=c(1,1))
## ------------------------------------------------------------------------
mod1dr <- MclustDR(mod1)
summary(mod1dr)
plot(mod1dr, what = "pairs")
plot(mod1dr, what = "boundaries", ngrid = 200)
mod1dr <- MclustDR(mod1, lambda = 1)
summary(mod1dr)
plot(mod1dr, what = "scatterplot")
plot(mod1dr, what = "boundaries", ngrid = 200)
## ------------------------------------------------------------------------
mod2dr <- MclustDR(mod2)
summary(mod2dr)
plot(mod2dr, what = "scatterplot")
plot(mod2dr, what = "boundaries", ngrid = 200)
mod3dr <- MclustDR(mod3)
summary(mod3dr)
plot(mod3dr, what = "scatterplot")
plot(mod3dr, what = "boundaries", ngrid = 200)
## ------------------------------------------------------------------------
mclust.options("bicPlotColors")
mclust.options("classPlotColors")
## ------------------------------------------------------------------------
cbPalette <- c("#E69F00", "#56B4E9", "#009E73", "#999999", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
bicPlotColors <- mclust.options("bicPlotColors")
bicPlotColors[1:14] <- c(cbPalette, cbPalette[1:6])
mclust.options("bicPlotColors" = bicPlotColors)
mclust.options("classPlotColors" = cbPalette)
clPairs(iris[,-5], iris$Species)
mod <- Mclust(iris[,-5])
plot(mod, what = "BIC")
plot(mod, what = "classification")
## ------------------------------------------------------------------------
sessionInfo()
mclust/inst/doc/mclust.Rmd 0000644 0001762 0000144 00000017267 13427502265 015301 0 ustar ligges users ---
title: "A quick tour of mclust"
author: "Luca Scrucca"
date: "`r format(Sys.time(), '%d %b %Y')`"
output:
rmarkdown::html_vignette:
toc: true
number_sections: false
css: "vignette.css"
vignette: >
%\VignetteIndexEntry{A quick tour of mclust}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r setup, include=FALSE}
library(knitr)
opts_chunk$set(fig.align = "center",
out.width = "90%",
fig.width = 6, fig.height = 5.5,
dev.args=list(pointsize=10),
par = TRUE, # needed for setting hook
collapse = TRUE, # collapse input & ouput code in chunks
warning = FALSE)
knit_hooks$set(par = function(before, options, envir)
{ if(before && options$fig.show != "none")
par(family = "sans", mar=c(4.1,4.1,1.1,1.1), mgp=c(3,1,0), tcl=-0.5)
})
set.seed(1) # for exact reproducibility
```
# Introduction
**mclust** is a contributed R package for model-based clustering, classification, and density estimation based on finite normal mixture modelling. It provides functions for parameter estimation via the EM algorithm for normal mixture models with a variety of covariance structures, and functions for simulation from these models. Also included are functions that combine model-based hierarchical clustering, EM for mixture estimation and the Bayesian Information Criterion (BIC) in comprehensive strategies for clustering, density estimation and discriminant analysis. Additional functionalities are available for displaying and visualizing fitted models along with clustering, classification, and density estimation results.
This document gives a quick tour of **mclust** (version `r packageVersion("mclust")`) functionalities. It was written in R Markdown, using the [knitr](https://cran.r-project.org/package=knitr) package for production.
See `help(package="mclust")` for further details and references provided by `citation("mclust")`.
```{r, message = FALSE, echo=-2}
library(mclust)
cat(mclust:::mclustStartupMessage(), sep="")
```
# Clustering
```{r}
data(diabetes)
class <- diabetes$class
table(class)
X <- diabetes[,-1]
head(X)
clPairs(X, class)
BIC <- mclustBIC(X)
plot(BIC)
summary(BIC)
mod1 <- Mclust(X, x = BIC)
summary(mod1, parameters = TRUE)
plot(mod1, what = "classification")
table(class, mod1$classification)
plot(mod1, what = "uncertainty")
ICL <- mclustICL(X)
summary(ICL)
plot(ICL)
LRT <- mclustBootstrapLRT(X, modelName = "VVV")
LRT
```
## Initialisation
EM algorithm is used by **mclust** for maximum likelihood estimation. Initialisation of EM is performed using the partitions obtained from agglomerative hierarchical clustering. For details see `help(mclustBIC)` or `help(Mclust)`, and `help(hc)`.
```{r}
(hc1 <- hc(X, modelName = "VVV", use = "SVD"))
BIC1 <- mclustBIC(X, initialization = list(hcPairs = hc1)) # default
summary(BIC1)
(hc2 <- hc(X, modelName = "VVV", use = "VARS"))
BIC2 <- mclustBIC(X, initialization = list(hcPairs = hc2))
summary(BIC2)
(hc3 <- hc(X, modelName = "EEE", use = "SVD"))
BIC3 <- mclustBIC(X, initialization = list(hcPairs = hc3))
summary(BIC3)
```
Update BIC by merging the best results:
```{r}
BIC <- mclustBICupdate(BIC1, BIC2, BIC3)
summary(BIC)
plot(BIC)
```
Univariate fit using random starting points obtained by creating random agglomerations (see `help(randomPairs)`) and merging best results:
```{r, echo=-1}
set.seed(20181116)
data(galaxies, package = "MASS")
galaxies <- galaxies / 1000
BIC <- NULL
for(j in 1:20)
{
rBIC <- mclustBIC(galaxies, verbose = FALSE,
initialization = list(hcPairs = randomPairs(galaxies)))
BIC <- mclustBICupdate(BIC, rBIC)
}
summary(BIC)
plot(BIC)
mod <- Mclust(galaxies, x = BIC)
summary(mod)
```
# Classification
## EDDA
```{r}
data(iris)
class <- iris$Species
table(class)
X <- iris[,1:4]
head(X)
mod2 <- MclustDA(X, class, modelType = "EDDA")
summary(mod2)
plot(mod2, what = "scatterplot")
plot(mod2, what = "classification")
```
## MclustDA
```{r}
data(banknote)
class <- banknote$Status
table(class)
X <- banknote[,-1]
head(X)
mod3 <- MclustDA(X, class)
summary(mod3)
plot(mod3, what = "scatterplot")
plot(mod3, what = "classification")
```
## Cross-validation error
```{r}
cv <- cvMclustDA(mod2, nfold = 10)
str(cv)
unlist(cv[3:4])
cv <- cvMclustDA(mod3, nfold = 10)
str(cv)
unlist(cv[3:4])
```
# Density estimation
## Univariate
```{r}
data(acidity)
mod4 <- densityMclust(acidity)
summary(mod4)
plot(mod4, what = "BIC")
plot(mod4, what = "density", data = acidity, breaks = 15)
plot(mod4, what = "diagnostic", type = "cdf")
plot(mod4, what = "diagnostic", type = "qq")
```
## Multivariate
```{r}
data(faithful)
mod5 <- densityMclust(faithful)
summary(mod5)
plot(mod5, what = "BIC")
plot(mod5, what = "density")
plot(mod5, what = "density", type = "hdr")
plot(mod5, what = "density", type = "hdr",
data = faithful, points.cex = 0.5)
plot(mod5, what = "density", type = "persp")
```
# Bootstrap inference
```{r}
boot1 <- MclustBootstrap(mod1, nboot = 999, type = "bs")
summary(boot1, what = "se")
summary(boot1, what = "ci")
par(mfrow=c(4,3))
plot(boot1, what = "pro")
plot(boot1, what = "mean")
par(mfrow=c(1,1))
```
```{r}
boot4 <- MclustBootstrap(mod4, nboot = 999, type = "bs")
summary(boot4, what = "se")
summary(boot4, what = "ci")
par(mfrow=c(2,2))
plot(boot4, what = "pro")
plot(boot4, what = "mean")
par(mfrow=c(1,1))
```
# Dimension reduction
## Clustering
```{r}
mod1dr <- MclustDR(mod1)
summary(mod1dr)
plot(mod1dr, what = "pairs")
plot(mod1dr, what = "boundaries", ngrid = 200)
mod1dr <- MclustDR(mod1, lambda = 1)
summary(mod1dr)
plot(mod1dr, what = "scatterplot")
plot(mod1dr, what = "boundaries", ngrid = 200)
```
## Classification
```{r}
mod2dr <- MclustDR(mod2)
summary(mod2dr)
plot(mod2dr, what = "scatterplot")
plot(mod2dr, what = "boundaries", ngrid = 200)
mod3dr <- MclustDR(mod3)
summary(mod3dr)
plot(mod3dr, what = "scatterplot")
plot(mod3dr, what = "boundaries", ngrid = 200)
```
# Using colorblind-friendly palettes
Most of the graphs produced by **mclust** use colors that by default are defined in the following options:
```{r}
mclust.options("bicPlotColors")
mclust.options("classPlotColors")
```
The first option controls colors used for plotting BIC, ICL, etc. curves, whereas the second option is used to assign colors for indicating clusters or classes when plotting data.
Color-blind-friendly palettes can be defined and assigned to the above options as follows:
```{r}
cbPalette <- c("#E69F00", "#56B4E9", "#009E73", "#999999", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
bicPlotColors <- mclust.options("bicPlotColors")
bicPlotColors[1:14] <- c(cbPalette, cbPalette[1:6])
mclust.options("bicPlotColors" = bicPlotColors)
mclust.options("classPlotColors" = cbPalette)
clPairs(iris[,-5], iris$Species)
mod <- Mclust(iris[,-5])
plot(mod, what = "BIC")
plot(mod, what = "classification")
```
The above color definitions are adapted from http://www.cookbook-r.com/Graphs/Colors_(ggplot2)/, but users can easily define their own palettes if needed.
# References
Scrucca L., Fop M., Murphy T. B. and Raftery A. E. (2016) mclust 5: clustering, classification and density estimation using Gaussian finite mixture models, *The R Journal*, 8/1, pp. 205-233. https://journal.r-project.org/archive/2016/RJ-2016-021/RJ-2016-021.pdf
Fraley C. and Raftery A. E. (2002) Model-based clustering, discriminant analysis and density estimation, *Journal of the American Statistical Association*, 97/458, pp. 611-631.
Fraley C., Raftery A. E., Murphy T. B. and Scrucca L. (2012) mclust Version 4 for R: Normal Mixture Modeling for Model-Based Clustering, Classification, and Density Estimation. *Technical Report* No. 597, Department of Statistics, University of Washington.
----
```{r}
sessionInfo()
``` mclust/inst/doc/mclust.html 0000644 0001762 0000144 00013776642 13510412700 015523 0 ustar ligges users
A quick tour of mclust
A quick tour of mclust
Luca Scrucca
07 Jul 2019
Introduction
mclust is a contributed R package for model-based clustering, classification, and density estimation based on finite normal mixture modelling. It provides functions for parameter estimation via the EM algorithm for normal mixture models with a variety of covariance structures, and functions for simulation from these models. Also included are functions that combine model-based hierarchical clustering, EM for mixture estimation and the Bayesian Information Criterion (BIC) in comprehensive strategies for clustering, density estimation and discriminant analysis. Additional functionalities are available for displaying and visualizing fitted models along with clustering, classification, and density estimation results.
This document gives a quick tour of mclust (version 5.4.5) functionalities. It was written in R Markdown, using the knitr package for production. See help(package="mclust")
for further details and references provided by citation("mclust")
.
library(mclust)
## __ ___________ __ _____________
## / |/ / ____/ / / / / / ___/_ __/
## / /|_/ / / / / / / / /\__ \ / /
## / / / / /___/ /___/ /_/ /___/ // /
## /_/ /_/\____/_____/\____//____//_/ version 5.4.5
## Type 'citation("mclust")' for citing this R package in publications.
Clustering
data(diabetes)
class <- diabetes$class
table(class)
## class
## Chemical Normal Overt
## 36 76 33
X <- diabetes[,-1]
head(X)
## glucose insulin sspg
## 1 80 356 124
## 2 97 289 117
## 3 105 319 143
## 4 90 356 199
## 5 90 323 240
## 6 86 381 157
clPairs(X, class)

BIC <- mclustBIC(X)
plot(BIC)

summary(BIC)
## Best BIC values:
## VVV,3 VVV,4 EVE,6
## BIC -4751.316 -4784.32213 -4785.24591
## BIC diff 0.000 -33.00573 -33.92951
mod1 <- Mclust(X, x = BIC)
summary(mod1, parameters = TRUE)
## ----------------------------------------------------
## Gaussian finite mixture model fitted by EM algorithm
## ----------------------------------------------------
##
## Mclust VVV (ellipsoidal, varying volume, shape, and orientation) model
## with 3 components:
##
## log-likelihood n df BIC ICL
## -2303.496 145 29 -4751.316 -4770.169
##
## Clustering table:
## 1 2 3
## 81 36 28
##
## Mixing probabilities:
## 1 2 3
## 0.5368974 0.2650129 0.1980897
##
## Means:
## [,1] [,2] [,3]
## glucose 90.96239 104.5335 229.42136
## insulin 357.79083 494.8259 1098.25990
## sspg 163.74858 309.5583 81.60001
##
## Variances:
## [,,1]
## glucose insulin sspg
## glucose 57.18044 75.83206 14.73199
## insulin 75.83206 2101.76553 322.82294
## sspg 14.73199 322.82294 2416.99074
## [,,2]
## glucose insulin sspg
## glucose 185.0290 1282.340 -509.7313
## insulin 1282.3398 14039.283 -2559.0251
## sspg -509.7313 -2559.025 23835.7278
## [,,3]
## glucose insulin sspg
## glucose 5529.250 20389.09 -2486.208
## insulin 20389.088 83132.48 -10393.004
## sspg -2486.208 -10393.00 2217.533
plot(mod1, what = "classification")

table(class, mod1$classification)
##
## class 1 2 3
## Chemical 9 26 1
## Normal 72 4 0
## Overt 0 6 27
plot(mod1, what = "uncertainty")

ICL <- mclustICL(X)
summary(ICL)
## Best ICL values:
## VVV,3 EVE,6 EVE,7
## ICL -4770.169 -4797.38232 -4797.50566
## ICL diff 0.000 -27.21342 -27.33677
plot(ICL)

LRT <- mclustBootstrapLRT(X, modelName = "VVV")
LRT
## -------------------------------------------------------------
## Bootstrap sequential LRT for the number of mixture components
## -------------------------------------------------------------
## Model = VVV
## Replications = 999
## LRTS bootstrap p-value
## 1 vs 2 361.16739 0.001
## 2 vs 3 123.49685 0.001
## 3 vs 4 16.76161 0.498
Initialisation
EM algorithm is used by mclust for maximum likelihood estimation. Initialisation of EM is performed using the partitions obtained from agglomerative hierarchical clustering. For details see help(mclustBIC)
or help(Mclust)
, and help(hc)
.
(hc1 <- hc(X, modelName = "VVV", use = "SVD"))
## Call:
## hc(data = X, modelName = "VVV", use = "SVD")
##
## Model-Based Agglomerative Hierarchical Clustering
## Model name = VVV
## Use = SVD
## Number of objects = 145
BIC1 <- mclustBIC(X, initialization = list(hcPairs = hc1)) # default
summary(BIC1)
## Best BIC values:
## VVV,3 VVV,4 EVE,6
## BIC -4751.316 -4784.32213 -4785.24591
## BIC diff 0.000 -33.00573 -33.92951
(hc2 <- hc(X, modelName = "VVV", use = "VARS"))
## Call:
## hc(data = X, modelName = "VVV", use = "VARS")
##
## Model-Based Agglomerative Hierarchical Clustering
## Model name = VVV
## Use = VARS
## Number of objects = 145
BIC2 <- mclustBIC(X, initialization = list(hcPairs = hc2))
summary(BIC2)
## Best BIC values:
## VVV,3 VVE,3 EVE,4
## BIC -4760.091 -4775.53693 -4793.26143
## BIC diff 0.000 -15.44628 -33.17079
(hc3 <- hc(X, modelName = "EEE", use = "SVD"))
## Call:
## hc(data = X, modelName = "EEE", use = "SVD")
##
## Model-Based Agglomerative Hierarchical Clustering
## Model name = EEE
## Use = SVD
## Number of objects = 145
BIC3 <- mclustBIC(X, initialization = list(hcPairs = hc3))
summary(BIC3)
## Best BIC values:
## VVV,3 VVE,4 VVE,3
## BIC -4751.354 -4757.091572 -4775.69587
## BIC diff 0.000 -5.737822 -24.34212
Update BIC by merging the best results:
BIC <- mclustBICupdate(BIC1, BIC2, BIC3)
summary(BIC)
## Best BIC values:
## VVV,3 VVE,4 VVE,3
## BIC -4751.316 -4757.091572 -4775.53693
## BIC diff 0.000 -5.775172 -24.22053
plot(BIC)

Univariate fit using random starting points obtained by creating random agglomerations (see help(randomPairs)
) and merging best results:
data(galaxies, package = "MASS")
galaxies <- galaxies / 1000
BIC <- NULL
for(j in 1:20)
{
rBIC <- mclustBIC(galaxies, verbose = FALSE,
initialization = list(hcPairs = randomPairs(galaxies)))
BIC <- mclustBICupdate(BIC, rBIC)
}
summary(BIC)
## Best BIC values:
## V,3 V,4 V,5
## BIC -441.6122 -443.399746 -446.34966
## BIC diff 0.0000 -1.787536 -4.73745
plot(BIC)

mod <- Mclust(galaxies, x = BIC)
summary(mod)
## ----------------------------------------------------
## Gaussian finite mixture model fitted by EM algorithm
## ----------------------------------------------------
##
## Mclust V (univariate, unequal variance) model with 3 components:
##
## log-likelihood n df BIC ICL
## -203.1792 82 8 -441.6122 -441.6126
##
## Clustering table:
## 1 2 3
## 3 7 72
Classification
EDDA
data(iris)
class <- iris$Species
table(class)
## class
## setosa versicolor virginica
## 50 50 50
X <- iris[,1:4]
head(X)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1 5.1 3.5 1.4 0.2
## 2 4.9 3.0 1.4 0.2
## 3 4.7 3.2 1.3 0.2
## 4 4.6 3.1 1.5 0.2
## 5 5.0 3.6 1.4 0.2
## 6 5.4 3.9 1.7 0.4
mod2 <- MclustDA(X, class, modelType = "EDDA")
summary(mod2)
## ------------------------------------------------
## Gaussian finite mixture model for classification
## ------------------------------------------------
##
## EDDA model summary:
##
## log-likelihood n df BIC
## -187.7097 150 36 -555.8024
##
## Classes n % Model G
## setosa 50 33.33 VEV 1
## versicolor 50 33.33 VEV 1
## virginica 50 33.33 VEV 1
##
## Training confusion matrix:
## Predicted
## Class setosa versicolor virginica
## setosa 50 0 0
## versicolor 0 47 3
## virginica 0 0 50
## Classification error = 0.02
## Brier score = 0.0127
plot(mod2, what = "scatterplot")

plot(mod2, what = "classification")

MclustDA
data(banknote)
class <- banknote$Status
table(class)
## class
## counterfeit genuine
## 100 100
X <- banknote[,-1]
head(X)
## Length Left Right Bottom Top Diagonal
## 1 214.8 131.0 131.1 9.0 9.7 141.0
## 2 214.6 129.7 129.7 8.1 9.5 141.7
## 3 214.8 129.7 129.7 8.7 9.6 142.2
## 4 214.8 129.7 129.6 7.5 10.4 142.0
## 5 215.0 129.6 129.7 10.4 7.7 141.8
## 6 215.7 130.8 130.5 9.0 10.1 141.4
mod3 <- MclustDA(X, class)
summary(mod3)
## ------------------------------------------------
## Gaussian finite mixture model for classification
## ------------------------------------------------
##
## MclustDA model summary:
##
## log-likelihood n df BIC
## -646.0798 200 66 -1641.849
##
## Classes n % Model G
## counterfeit 100 50 EVE 2
## genuine 100 50 XXX 1
##
## Training confusion matrix:
## Predicted
## Class counterfeit genuine
## counterfeit 100 0
## genuine 0 100
## Classification error = 0
## Brier score = 0
plot(mod3, what = "scatterplot")

plot(mod3, what = "classification")

Cross-validation error
cv <- cvMclustDA(mod2, nfold = 10)
str(cv)
## List of 5
## $ classification: Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ z : num [1:150, 1:3] 1 1 1 1 1 1 1 1 1 1 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : NULL
## .. ..$ : chr [1:3] "setosa" "versicolor" "virginica"
## $ error : num 0.0267
## $ brier : logi NA
## $ se : num 0.0109
unlist(cv[3:4])
## error brier
## 0.02666667 NA
cv <- cvMclustDA(mod3, nfold = 10)
str(cv)
## List of 5
## $ classification: Factor w/ 2 levels "counterfeit",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ z : num [1:200, 1:2] 6.72e-05 3.69e-19 5.13e-28 3.32e-20 2.26e-29 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : NULL
## .. ..$ : chr [1:2] "counterfeit" "genuine"
## $ error : num 0
## $ brier : logi NA
## $ se : num 0
unlist(cv[3:4])
## error brier
## 0 NA
Density estimation
Univariate
data(acidity)
mod4 <- densityMclust(acidity)
summary(mod4)
## -------------------------------------------------------
## Density estimation via Gaussian finite mixture modeling
## -------------------------------------------------------
##
## Mclust E (univariate, equal variance) model with 2 components:
##
## log-likelihood n df BIC ICL
## -185.9493 155 4 -392.0723 -398.5554
plot(mod4, what = "BIC")

plot(mod4, what = "density", data = acidity, breaks = 15)

plot(mod4, what = "diagnostic", type = "cdf")

plot(mod4, what = "diagnostic", type = "qq")

Multivariate
data(faithful)
mod5 <- densityMclust(faithful)
summary(mod5)
## -------------------------------------------------------
## Density estimation via Gaussian finite mixture modeling
## -------------------------------------------------------
##
## Mclust EEE (ellipsoidal, equal volume, shape and orientation) model with 3
## components:
##
## log-likelihood n df BIC ICL
## -1126.326 272 11 -2314.316 -2357.824
plot(mod5, what = "BIC")

plot(mod5, what = "density")

plot(mod5, what = "density", type = "hdr")
plot(mod5, what = "density", type = "hdr",
data = faithful, points.cex = 0.5)

plot(mod5, what = "density", type = "persp")

Bootstrap inference
boot1 <- MclustBootstrap(mod1, nboot = 999, type = "bs")
summary(boot1, what = "se")
## ----------------------------------------------------------
## Resampling standard errors
## ----------------------------------------------------------
## Model = VVV
## Num. of mixture components = 3
## Replications = 999
## Type = nonparametric bootstrap
##
## Mixing probabilities:
## 1 2 3
## 0.05185780 0.05058160 0.03559685
##
## Means:
## 1 2 3
## glucose 1.042239 3.444948 16.340816
## insulin 7.554105 29.047203 63.483315
## sspg 7.669033 31.684647 9.926121
##
## Variances:
## [,,1]
## glucose insulin sspg
## glucose 10.78177 51.28084 51.61617
## insulin 51.28084 529.62298 416.38176
## sspg 51.61617 416.38176 623.81098
## [,,2]
## glucose insulin sspg
## glucose 65.66172 616.6785 442.0993
## insulin 616.67852 7279.0671 3240.3558
## sspg 442.09927 3240.3558 7070.4152
## [,,3]
## glucose insulin sspg
## glucose 1045.6542 4178.685 667.2709
## insulin 4178.6846 18873.253 2495.0278
## sspg 667.2709 2495.028 506.8173
summary(boot1, what = "ci")
## ----------------------------------------------------------
## Resampling confidence intervals
## ----------------------------------------------------------
## Model = VVV
## Num. of mixture components = 3
## Replications = 999
## Type = nonparametric bootstrap
## Confidence level = 0.95
##
## Mixing probabilities:
## 1 2 3
## 2.5% 0.4490043 0.1510533 0.1324862
## 97.5% 0.6518326 0.3548749 0.2688038
##
## Means:
## [,,1]
## glucose insulin sspg
## 2.5% 89.13950 344.9890 150.8405
## 97.5% 93.16603 374.7221 181.8322
## [,,2]
## glucose insulin sspg
## 2.5% 98.82567 447.4121 257.9011
## 97.5% 112.28459 561.3273 374.6194
## [,,3]
## glucose insulin sspg
## 2.5% 198.5986 969.6231 63.22103
## 97.5% 263.2932 1226.2654 101.09078
##
## Variances:
## [,,1]
## glucose insulin sspg
## 2.5% 38.65508 1234.198 1514.416
## 97.5% 79.43401 3287.722 4146.024
## [,,2]
## glucose insulin sspg
## 2.5% 88.35268 3514.662 12583.92
## 97.5% 358.15175 31416.557 39228.47
## [,,3]
## glucose insulin sspg
## 2.5% 3377.773 47477.74 1317.041
## 97.5% 7379.344 120297.75 3229.747
par(mfrow=c(4,3))
plot(boot1, what = "pro")
plot(boot1, what = "mean")

boot4 <- MclustBootstrap(mod4, nboot = 999, type = "bs")
summary(boot4, what = "se")
## ----------------------------------------------------------
## Resampling standard errors
## ----------------------------------------------------------
## Model = E
## Num. of mixture components = 2
## Replications = 999
## Type = nonparametric bootstrap
##
## Mixing probabilities:
## 1 2
## 0.04130937 0.04130937
##
## Means:
## 1 2
## 0.04669993 0.06719883
##
## Variances:
## 1 2
## 0.02376885 0.02376885
summary(boot4, what = "ci")
## ----------------------------------------------------------
## Resampling confidence intervals
## ----------------------------------------------------------
## Model = E
## Num. of mixture components = 2
## Replications = 999
## Type = nonparametric bootstrap
## Confidence level = 0.95
##
## Mixing probabilities:
## 1 2
## 2.5% 0.5364895 0.3004131
## 97.5% 0.6995869 0.4635105
##
## Means:
## 1 2
## 2.5% 4.279055 6.184439
## 97.5% 4.461108 6.449465
##
## Variances:
## 1 2
## 2.5% 0.1395796 0.1395796
## 97.5% 0.2317769 0.2317769
par(mfrow=c(2,2))
plot(boot4, what = "pro")
plot(boot4, what = "mean")

Dimension reduction
Clustering
mod1dr <- MclustDR(mod1)
summary(mod1dr)
## -----------------------------------------------------------------
## Dimension reduction for model-based clustering and classification
## -----------------------------------------------------------------
##
## Mixture model type: Mclust (VVV, 3)
##
## Clusters n
## 1 81
## 2 36
## 3 28
##
## Estimated basis vectors:
## Dir1 Dir2 Dir3
## glucose -0.988671 0.76532 -0.966565
## insulin 0.142656 -0.13395 0.252109
## sspg -0.046689 0.62955 0.046837
##
## Dir1 Dir2 Dir3
## Eigenvalues 1.3506 0.75608 0.53412
## Cum. % 51.1440 79.77436 100.00000
plot(mod1dr, what = "pairs")

plot(mod1dr, what = "boundaries", ngrid = 200)

mod1dr <- MclustDR(mod1, lambda = 1)
summary(mod1dr)
## -----------------------------------------------------------------
## Dimension reduction for model-based clustering and classification
## -----------------------------------------------------------------
##
## Mixture model type: Mclust (VVV, 3)
##
## Clusters n
## 1 81
## 2 36
## 3 28
##
## Estimated basis vectors:
## Dir1 Dir2
## glucose 0.764699 0.86359
## insulin -0.643961 -0.22219
## sspg 0.023438 -0.45260
##
## Dir1 Dir2
## Eigenvalues 1.2629 0.35218
## Cum. % 78.1939 100.00000
plot(mod1dr, what = "scatterplot")

plot(mod1dr, what = "boundaries", ngrid = 200)

Classification
mod2dr <- MclustDR(mod2)
summary(mod2dr)
## -----------------------------------------------------------------
## Dimension reduction for model-based clustering and classification
## -----------------------------------------------------------------
##
## Mixture model type: EDDA
##
## Classes n Model G
## setosa 50 VEV 1
## versicolor 50 VEV 1
## virginica 50 VEV 1
##
## Estimated basis vectors:
## Dir1 Dir2 Dir3 Dir4
## Sepal.Length 0.17425 -0.193663 0.64081 -0.46231
## Sepal.Width 0.45292 0.066561 0.34852 0.57110
## Petal.Length -0.61629 -0.311030 -0.42366 0.46256
## Petal.Width -0.62024 0.928076 0.53703 -0.49613
##
## Dir1 Dir2 Dir3 Dir4
## Eigenvalues 0.94747 0.68835 0.076141 0.052607
## Cum. % 53.69408 92.70374 97.018700 100.000000
plot(mod2dr, what = "scatterplot")

plot(mod2dr, what = "boundaries", ngrid = 200)

mod3dr <- MclustDR(mod3)
summary(mod3dr)
## -----------------------------------------------------------------
## Dimension reduction for model-based clustering and classification
## -----------------------------------------------------------------
##
## Mixture model type: MclustDA
##
## Classes n Model G
## counterfeit 100 EVE 2
## genuine 100 XXX 1
##
## Estimated basis vectors:
## Dir1 Dir2 Dir3 Dir4 Dir5 Dir6
## Length -0.10027 -0.327553 0.79718 -0.033721 -0.317043 0.084618
## Left -0.21760 -0.305350 -0.30266 -0.893676 0.371043 -0.565611
## Right 0.29180 -0.018877 -0.49600 0.406605 -0.861020 0.481331
## Bottom 0.57603 0.445501 0.12002 -0.034570 0.004359 -0.078688
## Top 0.57555 0.385645 0.10093 -0.103629 0.136005 0.625416
## Diagonal -0.44088 0.672251 -0.04781 -0.151473 -0.044035 0.209542
##
## Dir1 Dir2 Dir3 Dir4 Dir5 Dir6
## Eigenvalues 0.87241 0.55372 0.48603 0.13301 0.053113 0.027239
## Cum. % 41.04429 67.09530 89.96182 96.21965 98.718473 100.000000
plot(mod3dr, what = "scatterplot")

plot(mod3dr, what = "boundaries", ngrid = 200)

Using colorblind-friendly palettes
Most of the graphs produced by mclust use colors that by default are defined in the following options:
mclust.options("bicPlotColors")
## EII VII EEI EVI VEI VVI EEE
## "gray" "black" "#218B21" "#41884F" "#508476" "#58819C" "#597DC3"
## EVE VEE VVE EEV VEV EVV VVV
## "#5178EA" "#716EE7" "#9B60B8" "#B2508B" "#C03F60" "#C82A36" "#CC0000"
## E V
## "gray" "black"
mclust.options("classPlotColors")
## [1] "dodgerblue2" "red3" "green3" "slateblue"
## [5] "darkorange" "skyblue1" "violetred4" "forestgreen"
## [9] "steelblue4" "slategrey" "brown" "black"
## [13] "darkseagreen" "darkgoldenrod3" "olivedrab" "royalblue"
## [17] "tomato4" "cyan2" "springgreen2"
The first option controls colors used for plotting BIC, ICL, etc. curves, whereas the second option is used to assign colors for indicating clusters or classes when plotting data.
Color-blind-friendly palettes can be defined and assigned to the above options as follows:
cbPalette <- c("#E69F00", "#56B4E9", "#009E73", "#999999", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
bicPlotColors <- mclust.options("bicPlotColors")
bicPlotColors[1:14] <- c(cbPalette, cbPalette[1:6])
mclust.options("bicPlotColors" = bicPlotColors)
mclust.options("classPlotColors" = cbPalette)
clPairs(iris[,-5], iris$Species)

mod <- Mclust(iris[,-5])
plot(mod, what = "BIC")

plot(mod, what = "classification")

The above color definitions are adapted from http://www.cookbook-r.com/Graphs/Colors_(ggplot2)/, but users can easily define their own palettes if needed.
References
Scrucca L., Fop M., Murphy T. B. and Raftery A. E. (2016) mclust 5: clustering, classification and density estimation using Gaussian finite mixture models, The R Journal, 8/1, pp. 205-233. https://journal.r-project.org/archive/2016/RJ-2016-021/RJ-2016-021.pdf
Fraley C. and Raftery A. E. (2002) Model-based clustering, discriminant analysis and density estimation, Journal of the American Statistical Association, 97/458, pp. 611-631.
Fraley C., Raftery A. E., Murphy T. B. and Scrucca L. (2012) mclust Version 4 for R: Normal Mixture Modeling for Model-Based Clustering, Classification, and Density Estimation. Technical Report No. 597, Department of Statistics, University of Washington.
sessionInfo()
## R version 3.6.0 (2019-04-26)
## Platform: x86_64-apple-darwin15.6.0 (64-bit)
## Running under: macOS Sierra 10.12.5
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] mclust_5.4.5 knitr_1.23
##
## loaded via a namespace (and not attached):
## [1] compiler_3.6.0 magrittr_1.5 htmltools_0.3.6 tools_3.6.0
## [5] yaml_2.2.0 Rcpp_1.0.1 stringi_1.4.3 rmarkdown_1.13
## [9] stringr_1.4.0 digest_0.6.19 xfun_0.8 evaluate_0.14
mclust/src/ 0000755 0001762 0000144 00000000000 13510412701 012342 5 ustar ligges users mclust/src/Makevars 0000644 0001762 0000144 00000000060 13475427014 014047 0 ustar ligges users PKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
mclust/src/mclustaddson.f 0000644 0001762 0000144 00000214531 13507676041 015236 0 ustar ligges users * =====================================================================
subroutine transpose(X, p)
*
* Compute transpose of a matrix
*
* =====================================================================
implicit NONE
integer :: p, i, j
double precision :: X(p,p), temp
do j = 2, p
do i = 1, j-1
temp = X(i,j)
X(i,j) = X(j,i)
X(j,i) = temp
end do
end do
return
end
* =====================================================================
subroutine crossprodf(X, Y, n, p, q, XTY)
*
* Given matrices X and Y of dimension (n x p) and (n x q) computes
* the matrix of cross-product, i.e. X' Y
*
* =====================================================================
implicit NONE
integer n, p, q
double precision X(n,p), Y(n,q), XTY(p,q)
* Compute X'Y using DGEMM blas subroutine
call DGEMM('T', 'N', p, q, n, 1.d0, X, n, Y, n, 0.d0, XTY, p)
end
* ======================================================================
subroutine covwf ( X, Z, n, p, G, M, S, W )
*
* Given data matrix X(n x p) and weight matrix Z(n x G) computes
* weighted means M(p x G), weighted covariance matrices S(p x p x G)
* and weighted scattering matrices W(p x p x G)
*
* ======================================================================
implicit none
integer :: n, p, G
double precision :: X(n,p), Z(n,G)
double precision :: M(p,G), S(p,p,G), W(p,p,G)
integer :: j, k
double precision :: sumZ(G), temp(n,p)
* compute X'Z using BLAS
call dgemm('T', 'N', p, G, n, 1.d0, X, n, Z, n, 0.d0, M, p)
* compute row sums of Z
sumZ = sum(Z, DIM = 1)
do k = 1,G
* compute means
call dscal(p, (1.d0/sumZ(k)), M(:,k), 1)
do j = 1,p
* compute sqrt(Z) * (X - M)
temp(:,j) = sqrt(Z(:,k)) * (X(:,j) - M(j,k))
end do
* compute scattering matrix
call dgemm('T', 'N', p, p, n, 1.d0, temp, n, temp, n,
* 0.d0, W(:,:,k), p)
* compute covariance matrix
S(:,:,k) = W(:,:,k)/sumZ(k)
end do
return
end
************************************************************************
**** EVV model
************************************************************************
* ======================================================================
subroutine msevv (x,z, n,p,G, mu,O,U,scale,shape,pro, lwork,info,
* eps)
* Maximization step for model EEV
* ======================================================================
implicit none
integer :: n, p, G
double precision :: x(n,p), z(n,G)
double precision :: mu(p,G), O(p,p,*), U(p,p,*), pro(G)
double precision :: scale(G), shape(p,G)
double precision :: sumz(G)
integer :: i, j, k, info, lwork, l
double precision :: temp(p), wrk(lwork), eps, dummy
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
*
* double precision :: BIGLOG
* parameter (BIGLOG = 709.d0)
*
* double precision :: SMALOG
* parameter (SMALOG = -708.d0)
*-----------------------------------------------------------------------
* colsums of z
sumz = sum(z, dim = 1)
* a priori probabilities
pro = sumz / dble(n)
* pro = sumz / sum(sumz)
* if there is noise sum(sumz) does not sum to n. See help(mstep)
do k = 1,G
do j = 1,p
mu(j,k) = sum(x(:,j)*z(:,k))/sumz(k)
end do
do i = 1,n
temp = ( x(i,:) - mu(:,k) ) * sqrt(z(i,k))
* U(:,:,k) = U(:,:,k) +
* * spread(temp, dim = 2, ncopies = p)*
* * spread(temp, dim = 1, ncopies = p)
* outer product, Press et al. (1992), p. 970
call dger(p, p, 1.d0, temp, 1, temp, 1, U(:,:,k), p)
* more efficient
end do
* U contains the weighted scattering matrix
O(:,:,k) = U(:,:,k)
* call dgesvd('O', 'N', p, p, O(:,:,k), p, shape(:,k),
* * dummy, 1, dummy, 1, wrk, lwork, info)
call dgesvd('N', 'O', p, p, O(:,:,k), p, shape(:,k),
* dummy, 1, dummy, 1, wrk, lwork, info)
* O now contains eigenvectors of the scattering matrix
* ##### NOTE: O is transposed
* shape contains the eigenvalues
* check if dgesvd converged (info == 0)
if (info .ne. 0) then
l = info
else
scale(k) = exp( sum( log(shape(:,k)) ) )**(1.d0/p)
call dscal(p*p, 1.d0/scale(k), U(:,:,k), 1)
call dscal(p, 1.d0/scale(k), shape(:,k), 1)
* now U is the matrix Ck (Celeux, Govaert 1995, p.787)
* and shape is the proper scaled shape (matrix A)
end if
end do
* check very small eigenvalues (singular covariance)
if (minval(shape) .le. sqrt(eps) .or.
* minval(scale) .le. sqrt(eps)) then
shape = FLMAX
scale = FLMAX
return
end if
scale(1) = sum(scale) / sum(sumz)
return
end
* ======================================================================
subroutine esevv (x,z, n,p,G,Gnoise, mu,O,scale,shape,pro, Vinv,
* loglik, eps)
* Expectation step for model EVV
* ======================================================================
implicit none
integer :: n, p, G, Gnoise
double precision :: x(n,p), z(n,Gnoise)
double precision :: mu(p,G), O(p,p,G), scale, shape(p,G)
double precision :: Vinv, pro(Gnoise)
double precision :: temp1(p), temp2(p), temp3
integer :: i, k, j
double precision :: const, logdet, loglik, eps
double precision :: log2pi
parameter (log2pi = 1.837877066409345d0)
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
* double precision :: smalog
* parameter (smalog = -708.d0)
*-----------------------------------------------------------------------
* check very small eigenvalues (singular covariance)
if (minval(shape) .le. sqrt(eps) .or. scale .le. sqrt(eps)) then
loglik = FLMAX
return
end if
const = (-dble(p)/2.d0)*log2pi
do k = 1,G
logdet = 0.d0
do j = 1,p
logdet = logdet + ( log(shape(j,k)) + log(scale) )
end do
* compute mahalanobis distance for each observation
* ##### NOTE: O is transposed
do i = 1,n
temp1 = ( x(i,:) - mu(:,k) )
call dcopy(p, 0.d0, 0, temp2, 1)
call dgemv('N', p, p, 1.d0,
* O(:,:,k), p, temp1, 1, 0.d0, temp2, 1)
temp2 = temp2/sqrt(scale*shape(:,k))
temp3 = ddot(p, temp2, 1, temp2, 1)
* temp3 contains the mahalanobis distance
* z(i,k) = const - logdet/2.d0 - temp3/2.d0 + log(pro(k))
z(i,k) = const - logdet/2.d0 - temp3/2.d0
* help(cdens) --> The densities are not scaled by mixing proportions
end do
* z contains the log-density log(N(x|theta_k))
end do
if ( pro(1) .lt. 0.d0 ) return
* cdens function
* noise component
if (Vinv .gt. 0.d0) then
call dcopy( n, log(Vinv), 0, z(:,Gnoise), 1)
end if
* now column Gnoise of z contains log(Vinv)
do i = 1,n
z(i,:) = z(i,:) + log( pro(:) )
* Numerical Recipes pag.844
temp3 = maxval(z(i,:))
temp1(1) = temp3 + log( sum(exp(z(i,:) - temp3)) )
loglik = loglik + temp1(1)
* ##### NOTE: do we need to check if (z - zmax) is too small?
z(i,:) = exp( z(i,:) - temp1(1) )
* re-normalize probabilities
temp3 = sum( z(i,:) )
call dscal( Gnoise, 1.d0/temp3, z(i,:), 1 )
end do
return
end
* ======================================================================
subroutine meevv (x,z, n,p,G,Gnoise, mu,O,U,scale,shape,pro,Vinv,
* loglik, eqpro,itmax,tol,eps,
* niterout,errout,lwork,info)
* Maximization-expectation algorithm for model EVV
* ======================================================================
implicit none
logical :: eqpro
integer :: n, p, G, Gnoise
double precision :: x(n,p), z(n,Gnoise)
double precision :: mu(p,G), O(p,p,G),scale(G),shape(p,G)
double precision :: Vinv, pro(Gnoise)
double precision :: U(p,p,G), sumz(Gnoise)
double precision :: temp1(p), temp2(p), temp3, scsh(p)
* double precision :: temp(*)
integer :: i, j, k, info, lwork, l, itmax, niterout
double precision :: tol, eps, errout, rteps, dummy
double precision :: const, logdet, loglik, lkprev, wrk(lwork)
double precision :: log2pi
parameter (log2pi = 1.837877066409345d0)
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
* double precision :: smalog
* parameter (smalog = -708.d0)
*-----------------------------------------------------------------------
l = 0
rteps = sqrt(eps)
niterout = 0
errout = FLMAX
lkprev = FLMAX/2
loglik = FLMAX
const = (-dble(p)/2.d0)*log2pi
* WHILE loop using goto statement
100 continue
niterout = niterout + 1
sumz = sum(z, dim = 1)
if ( eqpro ) then
if ( Vinv .gt. 0 ) then
pro(Gnoise) = sumz(Gnoise) / dble(n)
pro(1:G) = ( 1 - pro(Gnoise) ) / dble(G)
sumz = pro * dble(n)
else
pro = 1 / dble(G)
sumz = pro * dble(n)
end if
else
pro = sumz / dble(n)
end if
* re-initialise U
call dcopy(p*p*G, 0.d0, 0, U, 1)
* M step..........................................................
do k = 1,G
do j = 1,p
mu(j,k) = sum(x(:,j)*z(:,k))/sumz(k)
end do
do i = 1,n
temp1 = ( x(i,:) - mu(:,k) ) * sqrt(z(i,k))
call dger(p, p, 1.d0, temp1, 1, temp1, 1, U(:,:,k), p)
end do
* U contains the weighted scattering matrix
O(:,:,k) = U(:,:,k)
call dgesvd('N', 'O', p, p, O(:,:,k), p, shape(:,k),
* dummy, 1, dummy, 1, wrk, lwork, info)
* O now contains eigenvectors of the scattering matrix
* ##### NOTE: O is transposed
* shape contains the eigenvalues
* check if dgesvd converged (info == 0)
if (info .ne. 0) then
l = info
return
else
scale(k) = exp( sum( log(shape(:,k)) ) )**(1.d0/dble(p))
call dscal(p*p, 1.d0/scale(k), U(:,:,k), 1)
call dscal(p, 1.d0/scale(k), shape(:,k), 1)
* now U is the matrix Ck (Celeux, Govaert 1995, p.787)
* and shape is the proper scaled shape (matrix A)
end if
end do
if ( Vinv .gt. 0.d0 ) then
scale(1) = sum(scale) / sum(sumz(1:G))
else
scale(1) = sum(scale)/dble(n)
end if
* if noise lambda = num/sum_{k=1}^{G} n_k; pag. 787 Celeux, Govaert
* ................................................................
* check very small eigenvalues (singular covariance)
if (minval(shape) .le. rteps .or. minval(scale) .le. rteps) then
loglik = FLMAX
return
end if
* E step..........................................................
do k = 1,G
logdet = 0.d0
do j = 1,p
logdet = logdet + ( log(shape(j,k)) + log(scale(1)) )
end do
* compute mahalanobis distance for each observation
* ##### NOTE: O is transposed
scsh = sqrt(scale(1)*shape(:,k))
do i = 1,n
temp1 = ( x(i,:) - mu(:,k) )
call dcopy(p, 0.d0, 0, temp2, 1)
call dgemv('N', p, p, 1.d0,
* O(:,:,k), p, temp1, 1, 0.d0, temp2, 1)
temp2 = temp2/scsh
temp3 = ddot(p, temp2, 1, temp2, 1)
* temp3 contains the mahalanobis distance
z(i,k) = const - logdet/2.d0 - temp3/2.d0 + log(pro(k))
end do
* z contains the log-density log(N(x|theta_k)) + log(p_k)
end do
* noise component
if (Vinv .gt. 0.d0) then
* call dcopy( n, log(Vinv) + log(pro(Gnoise)), 0, z(:,Gnoise), 1)
z(:,Gnoise) = log(Vinv) + log( pro(Gnoise) )
end if
* now column Gnoise of z contains log(Vinv) + log(p_0)
* with p_0 the proportion of noise
loglik = 0.d0
do i = 1,n
* Numerical Recipes pag.844
temp3 = maxval(z(i,:))
temp1(1) = temp3 + log( sum(exp(z(i,:) - temp3)) )
loglik = loglik + temp1(1)
* ##### NOTE: do we need to check if (z - zmax) is too small?
z(i,:) = exp( z(i,:) - temp1(1) )
* re-normalize probabilities
temp3 = sum( z(i,:) )
call dscal( Gnoise, 1.d0/temp3, z(i,:), 1 )
end do
* ................................................................
errout = abs(loglik - lkprev)/(1.d0 + abs(loglik))
* errout = abs(loglik - lkprev)
lkprev = loglik
* temp(niterout) = loglik
* Chris F (June 2015): pro should not be computed in the E-step
* sumz = sum(z, dim = 1)
* if ( eqpro ) then
* if ( Vinv .gt. 0 ) then
* pro(Gnoise) = sumz(Gnoise) / dble(n)
* pro(1:G) = ( 1 - pro(Gnoise) ) / dble(G)
* sumz = pro * dble(n)
* else
* pro = 1 / dble(G)
* sumz = pro * dble(n)
* end if
* else
* pro = sumz / dble(n)
* end if
* check if empty components
* if ( minval(pro) .lt. rteps ) then
if ( any(sumz .lt. rteps, 1) ) then
loglik = -FLMAX
return
end if
* WHILE condition
if ( errout .gt. tol .and. niterout .lt. itmax ) goto 100
return
end
************************************************************************
**** VEE model
************************************************************************
* ======================================================================
subroutine msvee (x,z, n,p,G, mu,U,C,scale,pro, lwork,info,
* itmax,tol, niterin,errin)
* Maximization step for model VEE
* ======================================================================
implicit none
integer :: n, p, G
double precision :: x(n,p), z(n,G)
double precision :: mu(p,G), U(p,p,G), C(p,p), pro(G)
* ### NOTE: shape and orientation parameters are computed in R
double precision :: scale(G)
double precision :: sumz(G)
integer :: i, j, k, info, lwork, l
* integer :: dummy
double precision :: temp1(p), temp2(p,p), temp3
double precision :: wrk(lwork), tol, errin, trgt, trgtprev
integer :: itmax, niterin
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
*-----------------------------------------------------------------------
* colsums of z
sumz = sum(z, dim = 1)
* a priori probabilities
pro = sumz / dble(n)
* pro = sumz / sum(sumz)
* if there is noise sum(sumz) does not sum to n. See help(mstep)
* compute weighted scattering matrix and means
do k = 1,G
do j = 1,p
mu(j,k) = sum(x(:,j)*z(:,k))/sumz(k)
end do
do i = 1,n
temp1 = ( x(i,:) - mu(:,k) ) * sqrt(z(i,k))
call dger(p, p, 1.d0, temp1, 1, temp1, 1, U(:,:,k), p)
end do
* U contains the weighted scattering matrix
* check if U is positive definite (see help of dpotrf)
* (through Choleski is more efficient)
temp2 = U(:,:,k)
call dpotrf('U', p, temp2, p, info)
if ( info .ne. 0 ) then
if ( info .lt. 0) then
l = info
return
else if ( info .gt. 0 ) then
info = 0
scale = FLMAX
return
end if
end if
end do
* covariance matrix components estimation
niterin = 0
errin = FLMAX
trgt = FLMAX
trgtprev = FLMAX/2
* WHILE loop using goto statement
100 continue
niterin = niterin + 1
* initialise C
call dcopy(p*p, 0.d0, 0, C, 1)
* ### NOTE: scale is initialised in R
do k = 1,G
C = C + U(:,:,k)/scale(k)
end do
* C contains the numerator of matrix C in pag.785, Celeux, Govaert
temp2 = C
call dsyev('N', 'U', p, temp2, p, temp1, wrk, lwork, info)
temp1 = temp1(p:1:-1)
* temp1 contains the (decreasing) ordered eigenvalues of C
* check if dsyev converged or illegal value
if ( info .ne. 0 ) then
l = info
return
end if
temp3 = exp( sum(log(temp1)) )**(1/dble(p))
* temp3 is the denominator of C
C = C/temp3
* C is now the actual matrix C of pag.785
* compute the inverse of C via Choleski
temp2 = C
call dpotrf('U', p, temp2, p, info)
if ( info .ne. 0 ) then
if ( info .lt. 0) then
l = info
return
else if ( info .gt. 0 ) then
info = 0
scale = FLMAX
return
end if
end if
call dpotri('U', p, temp2, p, info)
if ( info .ne. 0 ) return
do j = 2,p
do k = 1,(j-1)
temp2(j,k) = temp2(k,j)
end do
end do
* temp2 is now the inverse of C
scale = 0.d0
do k = 1,G
do j = 1,p
scale(k) = scale(k) + ddot(p, U(j,:,k), 1, temp2(:,j), 1)
end do
scale(k) = scale(k) / (dble(p)*sumz(k))
end do
* scale contains now the lambdas (pag.784 of Celeux, Govaert)
* evaluate target function
* trgt = dble(n)*dble(p) + dble(p)*SUM(log(scale)*sumz)
trgt = sum(sumz)*dble(p) + dble(p)*SUM(log(scale)*sumz)
* error
errin = abs(trgt - trgtprev)/(1.d0 + abs(trgt))
trgtprev = trgt
* WHILE condition
if ( errin .gt. tol .and. niterin .lt. itmax ) goto 100
return
end
* ======================================================================
subroutine esvee (x,z, n,p,G,Gnoise, mu,O,scale,shape,pro, Vinv,
* loglik, eps)
* Expectation step for model VEE
* ======================================================================
implicit none
integer :: n,p,G,Gnoise
double precision :: x(n,p), z(n,Gnoise), pro(Gnoise), Vinv
double precision :: mu(p,G), O(p,p), scale(G), shape(p)
double precision :: temp1(p), temp2(p), temp3
integer :: i, k, j
double precision :: const, logdet, loglik, eps
double precision :: log2pi
parameter (log2pi = 1.837877066409345d0)
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
* double precision :: smalog
* parameter (smalog = -708.d0)
*-----------------------------------------------------------------------
* check very small eigenvalues (cannot compute E step)
if ( minval(shape) .le. sqrt(eps) .or.
* minval(scale) .le. sqrt(eps) ) then
loglik = FLMAX
return
end if
const = (-dble(p)/2.d0)*log2pi
do k = 1,G
logdet = 0.d0
do j = 1,p
logdet = logdet + ( log(shape(j)) + log(scale(k)) )
end do
* compute mahalanobis distance for each observation
* ##### NOTE: O is transposed
do i = 1,n
temp1 = ( x(i,:) - mu(:,k) )
call dcopy(p, 0.d0, 0, temp2, 1)
call dgemv('N', p, p, 1.d0,
* O, p, temp1, 1, 0.d0, temp2, 1)
temp2 = temp2/sqrt(scale(k)*shape)
temp3 = ddot(p, temp2, 1, temp2, 1)
* temp3 contains the mahalanobis distance
* z(i,k) = const - logdet/2.d0 - temp3/2.d0 + log(pro(k))
z(i,k) = const - logdet/2.d0 - temp3/2.d0
* help(cdens) --> The densities are not scaled by mixing proportions
end do
* z contains the log-density log(N(x|theta_k))
end do
if ( pro(1) .lt. 0.d0 ) return
* cdens function
* noise component
if (Vinv .gt. 0.d0) then
call dcopy( n, log(Vinv), 0, z(:,Gnoise), 1)
end if
* now column Gnoise of z contains log(Vinv)
do i = 1,n
z(i,:) = z(i,:) + log( pro(:) )
* Numerical Recipes pag.844
temp3 = maxval(z(i,:))
temp1(1) = temp3 + log( sum(exp(z(i,:) - temp3)) )
loglik = loglik + temp1(1)
z(i,:) = exp( z(i,:) - temp1(1) )
* re-normalize probabilities
temp3 = sum( z(i,:) )
call dscal( Gnoise, 1.d0/temp3, z(i,:), 1 )
end do
return
end
* ======================================================================
subroutine mevee ( x,z, n,p,G,Gnoise, mu,C,U,scale,shape,pro,Vinv,
* loglik, eqpro,itmaxin,tolin,itmaxout,tolout,eps,
* niterin,errin,niterout,errout,lwork,info )
* Maximization-expectation algorithm for model VEE
* ======================================================================
implicit none
logical :: eqpro
integer :: n,p,G,Gnoise
double precision :: x(n,p), z(n,Gnoise), pro(Gnoise), Vinv
double precision :: mu(p,G), C(p,p), scale(G), shape(p)
double precision :: U(p,p,G), sumz(Gnoise)
double precision :: temp1(p), temp2(p,p), temp3, temp4(p)
integer :: i, j, k, info, lwork, l
* integer :: dummy
integer :: itmaxin, itmaxout, niterin, niterout
double precision :: tolin, tolout, errin, errout, eps, rteps
double precision :: const, logdet, loglik, lkprev, wrk(lwork)
double precision :: trgt, trgtprev
double precision :: log2pi
parameter (log2pi = 1.837877066409345d0)
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
* double precision :: smalog
* parameter (smalog = -708.d0)
*-----------------------------------------------------------------------
l = 0
rteps = sqrt(eps)
niterout = 0
errout = FLMAX
lkprev = FLMAX/2
loglik = FLMAX
const = (-dble(p)/2.d0)*log2pi
* WHILE loop for EM algorithm
100 continue
niterout = niterout + 1
sumz = sum(z, dim = 1)
if ( eqpro ) then
if ( Vinv .gt. 0 ) then
pro(Gnoise) = sumz(Gnoise) / dble(n)
pro(1:G) = ( 1 - pro(Gnoise) ) / dble(G)
sumz = pro * dble(n)
else
pro = 1 / dble(G)
sumz = pro * dble(n)
end if
else
pro = sumz / dble(n)
end if
* re-initialise U
call dcopy(p*p*G, 0.d0, 0, U, 1)
* compute weighted scattering matrix and means
do k = 1,G
do j = 1,p
mu(j,k) = sum(x(:,j)*z(:,k))/sumz(k)
end do
do i = 1,n
temp1 = ( x(i,:) - mu(:,k) ) * sqrt(z(i,k))
call dger(p, p, 1.d0, temp1, 1, temp1, 1, U(:,:,k), p)
end do
* U contains the weighted scattering matrix
* check if U is positive definite (see help of dpotrf)
* (through Choleski is more efficient)
temp2 = U(:,:,k)
call dpotrf('U', p, temp2, p, info)
if ( info .ne. 0 ) then
if ( info .lt. 0) then
l = info
return
else if ( info .gt. 0 ) then
info = 0
loglik = FLMAX
return
end if
end if
end do
* M step..........................................................
* covariance matrix components estimation
niterin = 0
errin = FLMAX
trgt = FLMAX
trgtprev = FLMAX/2
* initialise scale
call dcopy(G, 1.d0, 0, scale, 1)
* WHILE loop for M step
110 continue
niterin = niterin + 1
* initialise C
call dcopy(p*p, 0.d0, 0, C, 1)
do k = 1,G
C = C + U(:,:,k)/scale(k)
end do
* C contains the numerator of matrix C in pag.785, Celeux, Govaert
temp2 = C
call dsyev('N', 'U', p, temp2, p, temp1, wrk, lwork, info)
temp1 = temp1(p:1:-1)
* temp1 contains the (decreasing) ordered eigenvalues of C
* check if dsyev converged or illegal value
if ( info .ne. 0 ) then
l = info
return
end if
temp3 = exp( sum(log(temp1)) )**(1/dble(p))
* temp3 is the denominator of C
C = C/temp3
* C is now the actual matrix C of pag.785
* compute the inverse of C via Choleski
temp2 = C
call dpotrf('U', p, temp2, p, info)
if ( info .ne. 0 ) then
if ( info .lt. 0) then
l = info
return
else if ( info .gt. 0 ) then
info = 0
loglik = FLMAX
return
end if
end if
call dpotri('U', p, temp2, p, info)
if ( info .ne. 0 ) return
do j = 2,p
do k = 1,(j-1)
temp2(j,k) = temp2(k,j)
end do
end do
* temp2 is now the inverse of C
scale = 0.d0
do k = 1,G
do j = 1,p
scale(k) = scale(k) + ddot(p, U(j,:,k), 1, temp2(:,j), 1)
end do
scale(k) = scale(k) / (dble(p)*sumz(k))
end do
* scale contains now the lambdas (pag.784 of Celeux, Govaert)
* evaluate target function
* trgt = dble(n)*dble(p) + dble(p)*SUM(log(scale)*sumz)
trgt = sum(sumz(1:G))*dble(p) + dble(p)*SUM(log(scale)*sumz(1:G))
* error
errin = abs(trgt - trgtprev)/(1.d0 + abs(trgt))
trgtprev = trgt
* WHILE condition for M step
if ( errin .gt. tolin .and. niterin .lt. itmaxin ) goto 110
* ................................................................
* eigenvalues of C
shape = temp1 / temp3
* check very small eigenvalues (singular covariance)
if (minval(shape) .le. rteps .or. minval(scale) .le. rteps) then
loglik = FLMAX
return
end if
* E step..........................................................
do k = 1,G
logdet = 0.d0
do j = 1,p
logdet = logdet + log(shape(j)) + log(scale(k))
end do
* compute mahalanobis distance for each observation
do i = 1,n
temp1 = ( x(i,:) - mu(:,k) )
call dcopy(p, 0.d0, 0, temp4, 1)
call dgemv('N', p, p, 1.d0,
* temp2, p, temp1, 1, 0.d0, temp4, 1)
temp4 = temp4/scale(k)
temp3 = ddot(p, temp4, 1, temp1, 1)
* temp3 contains the mahalanobis distance
z(i,k) = const - logdet/2.d0 - temp3/2.d0 + log(pro(k))
* z(i,k) = const - logdet/2.d0 - temp3/2.d0
end do
* z contains the log-density log(N(x|theta_k)) + log(p_k)
end do
* if ( pro(1) .lt. 0.d0 ) return
* cdens function
* noise component
if (Vinv .gt. 0.d0) then
z(:,Gnoise) = log(Vinv) + log( pro(Gnoise) )
end if
* now column Gnoise of z contains log(Vinv) + log(p_0)
* with p_0 the proportion of noise
loglik = 0.d0
do i = 1,n
* Numerical Recipes pag.844
temp3 = maxval(z(i,:))
temp1(1) = temp3 + log( sum(exp(z(i,:) - temp3)) )
loglik = loglik + temp1(1)
z(i,:) = exp( z(i,:) - temp1(1) )
* re-normalize probabilities
temp3 = sum( z(i,:) )
call dscal( Gnoise, 1.d0/temp3, z(i,:), 1 )
end do
* ................................................................
errout = abs(loglik - lkprev)/(1.d0 + abs(loglik))
* errout = abs(loglik - lkprev)
lkprev = loglik
* temp(niterout) = loglik
* Chris F (June 2015): pro should not be computed in the E-step
* sumz = sum(z, dim = 1)
* if ( eqpro ) then
* if ( Vinv .gt. 0 ) then
* pro(Gnoise) = sumz(Gnoise) / dble(n)
* pro(1:G) = ( 1 - pro(Gnoise) ) / dble(G)
* sumz = pro * dble(n)
* else
* pro = 1 / dble(G)
* sumz = pro * dble(n)
* end if
* else
* pro = sumz / dble(n)
* end if
* check if empty components
if ( minval(sumz) .lt. rteps ) then
loglik = -FLMAX
return
end if
* WHILE condition EM
if ( errout .gt. tolout .and. niterout .lt. itmaxout ) goto 100
return
end
************************************************************************
**** EVE model
************************************************************************
* ======================================================================
subroutine mseve (x,z, n,p,G, mu,U,O,scale,shape,pro, lwork,info,
* itmax,tol, niterin,errin, eps)
* Maximization step for model EVE
* ======================================================================
implicit none
integer :: n, p, G
double precision :: x(n,p), z(n,G)
double precision :: mu(p,G), U(p,p,G), pro(G), O(p,p)
double precision :: scale, shape(p,G)
double precision :: sumz(G), omega(G)
integer :: i, j, k, info, lwork
double precision :: temp1(p,p), temp2(p,p), temp3(p,p), temp4(p)
double precision :: wrk(lwork), tol, errin, trgt, trgtprev, eps
integer :: itmax, niterin
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
*-----------------------------------------------------------------------
* colsums of z
sumz = sum(z, dim = 1)
* a priori probabilities
pro = sumz / dble(n)
* pro = sumz / sum(sumz)
* if there is noise sum(sumz) does not sum to n. See help(mstep)
* compute weighted scattering matrix and means
do k = 1,G
do j = 1,p
mu(j,k) = sum(x(:,j)*z(:,k))/sumz(k)
end do
do i = 1,n
temp1(:,1) = ( x(i,:) - mu(:,k) ) * sqrt(z(i,k))
call dger(p, p, 1.d0, temp1(:,1), 1, temp1(:,1), 1,
* U(:,:,k), p)
end do
* U contains the weighted scattering matrix
* compute the eigenvalues of U to be stored in omega
temp2 = U(:,:,k)
call dsyev('N', 'U', p, temp2, p, temp1(:,1), wrk, lwork, info)
* now temp1 contains all the eigenvalues of U
* check if dsyev converged and positive definite
if ( info .ne. 0 ) then
return
else
if ( minval(temp1(:,1)) .lt. sqrt(eps) ) then
info = 0
scale = FLMAX
return
end if
end if
omega(k) = temp1(p,1)
end do
* omega contains the largest eigenvalue of each scattering matrix
niterin = 0
errin = FLMAX
trgt = FLMAX
trgtprev = FLMAX/2
* covariance matrix components estimation
* we consider algorithm MM 1 and MM 2 of Browne, McNicholas 2013
* with a modification in computing the orientation matrix in the MM 2 step
* shape (matrix A) and orientation (matrix D) initialised in R
* shape = matrix(1, p,G)
* O = diag(p)
* WHILE loop using goto statement
100 continue
* ### NOTE: O is transposed
niterin = niterin + 1
temp2 = 0.d0
temp3 = 0.d0
* temp3 will contain matrix F
* Algorithm MM 1 ......................................
do k = 1,G
do j = 1,p
* temp1(j,:) = O(:,j) / shape(j,k)
temp1(j,:) = O(j,:) / shape(j,k)
end do
* temp1 contains inv(A)t(D)
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, U(:,:,k),p,
* 0.d0, temp2,p )
* temp2 contains inv(A) %*% t(D) %*% W
temp1 = temp2 - omega(k)*temp1
temp3 = temp3 + temp1
* temp3 contains the matrix F
end do
* compute matrices P and R where svd(F) = P %*% B %*% t(R)
call dgesvd('A','A', p,p, temp3,p, temp4, temp1,p, temp2,p,
* wrk, lwork, info)
* now temp1 contains matrix P, temp2 contains matrix t(R)
* temp4 contains the singular values
* check if dgesvd converged
if ( info .ne. 0 ) return
* NOTE: t(O) = t( R %*% t(P) ) = P %*% t(R)
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, temp2,p,
* 0.d0, O,p )
* O contains TRANSPOSED matrix D of Browne, McNicholas
* .....................................................
* Algorithm MM 2 ......................................
* call dgemm( 'T','T', p,p,p, 1.d0, temp2,p, temp1,p,
* * 0.d0, O,p )
call transpose(O, p)
* O contains matrix D of Browne, McNicholas
* Algorithm MM 2
temp1 = 0.d0
temp3 = 0.d0
do k = 1,G
call dgemm( 'N','N', p,p,p, 1.d0, U(:,:,k),p, O,p,
* 0.d0, temp1,p )
* temp1 contains W %*% D
do j = 1,p
temp2(:,j) = temp1(:,j) / shape(j,k)
end do
* temp2 contains W %*% D %*% inv(A)
temp1 = temp2 - maxval( 1/shape(:,k) )*temp1
temp3 = temp3 + temp1
* temp3 contains the matrix F
end do
* compute matrices P and R where svd(F) = P %*% B %*% t(R)
call dgesvd('A','A', p,p, temp3,p, temp4, temp1,p, temp2,p,
* wrk, lwork, info)
* now temp1 contains matrix P, temp2 contains matrix t(R)
* temp4 contains the singular values
* check if dgesvd converged
if ( info .ne. 0 ) return
* NOTE: t(O) = R %*% t(P)
* call dgemm( 'T','T', p,p,p, 1.d0, temp2,p, temp1,p,
* * 0.d0, O,p )
O = 0.d0
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, temp2,p,
* 0.d0, O,p )
* NOTE: we compute the TRANSPOSED of the matrix in the output in the paper
call transpose(O, p)
* O contains TRANSPOSED matrix D of Browne, McNicholas
* .....................................................
* compute shape (matrix A) and target function
trgt = 0.d0
do k = 1,G
temp1 = 0.d0
call dgemm( 'N','N', p,p,p, 1.d0, O,p, U(:,:,k),p,
* 0.d0, temp1,p )
* temp1 contains t(D) %*% W
do j = 1,p
shape(j,k) = ddot(p, temp1(j,:), 1, O(j,:), 1)
end do
shape(:,k) = shape(:,k)/
* exp( sum( log(shape(:,k)) ) )**(1.d0/dble(p))
* now shape contains matrix A of Celeux, Govaert pag. 785
* check positive values
if ( minval(shape(:,k)) .lt. sqrt(eps) ) then
info = 0
shape = FLMAX
return
end if
temp4(1) = 0.d0
do j = 1,p
* temp2(:,j) = O(:,j) * 1.d0/shape(j,k)
temp2(:,j) = O(j,:) * 1.d0/shape(j,k)
temp4(1) = temp4(1) + ddot(p, temp1(j,:), 1, temp2(:,j), 1)
end do
trgt = trgt + temp4(1)
end do
* error
errin = abs(trgt - trgtprev)/(1.d0 + abs(trgt))
trgtprev = trgt
* WHILE condition
if ( errin .gt. tol .and. niterin .lt. itmax ) goto 100
scale = trgt / ( sum(sumz)*dble(p) )
return
end
* ======================================================================
subroutine eseve (x,z, n,p,G,Gnoise, mu,O,scale,shape,pro, Vinv,
* loglik, eps)
* Expectation step for model EVE
* ======================================================================
implicit none
integer :: n, p, G, Gnoise
double precision :: x(n,p), z(n,Gnoise)
double precision :: mu(p,G), O(p,p), scale, shape(p,G)
double precision :: Vinv, pro(Gnoise)
double precision :: temp1(p), temp2(p), temp3, temp4(n)
integer :: i, k, j
double precision :: const, logdet, loglik, eps
double precision :: log2pi
parameter (log2pi = 1.837877066409345d0)
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
* double precision :: smalog
* parameter (smalog = -708.d0)
*-----------------------------------------------------------------------
* check very small eigenvalues (singular covariance)
if (minval(shape) .le. sqrt(eps) .or. scale .le. sqrt(eps)) then
loglik = FLMAX
return
end if
const = (-dble(p)/2.d0)*log2pi
do k = 1,G
logdet = 0.d0
do j = 1,p
logdet = logdet + ( log(shape(j,k)) + log(scale) )
end do
* compute mahalanobis distance for each observation
* ##### NOTE: O is transposed
do i = 1,n
temp1 = ( x(i,:) - mu(:,k) )
call dcopy(p, 0.d0, 0, temp2, 1)
call dgemv('N', p, p, 1.d0,
* O, p, temp1, 1, 0.d0, temp2, 1)
temp2 = temp2/sqrt(scale*shape(:,k))
temp3 = ddot(p, temp2, 1, temp2, 1)
temp4(i) = temp3
* temp3 contains the mahalanobis distance
* z(i,k) = const - logdet/2.d0 - temp3/2.d0 + log(pro(k))
z(i,k) = const - logdet/2.d0 - temp3/2.d0
* help(cdens) --> The densities are not scaled by mixing proportions
end do
* z contains the log-density log(N(x|theta_k))
end do
if ( pro(1) .lt. 0.d0 ) return
* cdens function
* noise component
if (Vinv .gt. 0.d0) then
call dcopy( n, log(Vinv), 0, z(:,Gnoise), 1)
end if
* now column Gnoise of z contains log(Vinv)
do i = 1,n
z(i,:) = z(i,:) + log( pro )
* Numerical Recipes pag.844
temp3 = maxval(z(i,:))
temp1(1) = temp3 + log( sum(exp(z(i,:) - temp3)) )
loglik = loglik + temp1(1)
* ##### NOTE: do we need to check if (z - zmax) is too small?
z(i,:) = exp( z(i,:) - temp1(1) )
* re-normalize probabilities
temp3 = sum( z(i,:) )
call dscal( Gnoise, 1.d0/temp3, z(i,:), 1 )
end do
return
end
* ======================================================================
subroutine meeve ( x,z, n,p,G,Gnoise, mu,O,U,scale,shape,pro,Vinv,
* loglik, eqpro,itmaxin,tolin,itmaxout,tolout,eps,
* niterin,errin,niterout,errout,lwork,info )
* Maximization-expectation algorithm for model EVE
* ======================================================================
implicit none
logical :: eqpro
integer :: n,p,G,Gnoise
double precision :: x(n,p), z(n,Gnoise), pro(Gnoise), Vinv
double precision :: mu(p,G), O(p,p), scale, shape(p,G)
double precision :: U(p,p,G), sumz(Gnoise), omega(G)
double precision :: temp1(p,p), temp2(p,p), temp3(p,p), temp4(p)
integer :: i, j, k, info, lwork
integer :: itmaxin, itmaxout, niterin, niterout
double precision :: tolin, tolout, errin, errout, eps, rteps
double precision :: const, logdet, loglik, lkprev, wrk(lwork)
double precision :: trgt, trgtprev
double precision :: log2pi
parameter (log2pi = 1.837877066409345d0)
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
* double precision :: smalog
* parameter (smalog = -708.d0)
*-----------------------------------------------------------------------
rteps = sqrt(eps)
niterout = 0
errout = FLMAX
lkprev = FLMAX/2
loglik = FLMAX
const = (-dble(p)/2.d0)*log2pi
* WHILE loop for EM algorithm
100 continue
niterout = niterout + 1
sumz = sum(z, dim = 1)
if ( eqpro ) then
if ( Vinv .gt. 0 ) then
pro(Gnoise) = sumz(Gnoise) / dble(n)
pro(1:G) = ( 1 - pro(Gnoise) ) / dble(G)
sumz = pro * dble(n)
else
pro = 1 / dble(G)
sumz = pro * dble(n)
end if
else
pro = sumz / dble(n)
end if
* re-initialise U
call dcopy(p*p*G, 0.d0, 0, U, 1)
* compute weighted scattering matrix and means
do k = 1,G
do j = 1,p
mu(j,k) = sum(x(:,j)*z(:,k))/sumz(k)
end do
do i = 1,n
temp1(:,1) = ( x(i,:) - mu(:,k) ) * sqrt(z(i,k))
call dger(p, p, 1.d0, temp1(:,1), 1, temp1(:,1), 1,
* U(:,:,k), p)
end do
* U contains the weighted scattering matrix
* compute the eigenvalues of U to be stored in omega
temp2 = U(:,:,k)
call dsyev('N', 'U', p, temp2, p, temp1(:,1), wrk, lwork, info)
* now temp1 contains all the eigenvalues of U
* check if dsyev converged and positive definite
if ( info .ne. 0 ) then
return
else
if ( minval(temp1(:,1)) .lt. rteps ) then
info = 0
scale = FLMAX
return
end if
end if
omega(k) = temp1(p,1)
end do
* omega contains the largest eigenvalue of each scattering matrix
* M step..........................................................
niterin = 0
errin = FLMAX
trgt = FLMAX
trgtprev = FLMAX/2
* covariance matrix components estimation
* we consider algorithm MM 1 and MM 2 of Browne, McNicholas 2013
* with a modification in computing the orientation matrix in the MM 2 step
* shape (matrix A) and orientation (matrix D) initialised in R
* shape = matrix(1, p,G)
* O = diag(p)
* ### NOTE: we don't re-initialize shape and orientation at each
* outer iteration of the EM algorithm
* WHILE loop for M step
110 continue
* ### NOTE: O is transposed
niterin = niterin + 1
temp2 = 0.d0
temp3 = 0.d0
* temp3 will contain matrix F
* Algorithm MM 1 ......................................
do k = 1,G
do j = 1,p
* temp1(j,:) = O(:,j) / shape(j,k)
temp1(j,:) = O(j,:) / shape(j,k)
end do
* temp1 contains inv(A)t(D)
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, U(:,:,k),p,
* 0.d0, temp2,p )
* temp2 contains inv(A) %*% t(D) %*% W
temp1 = temp2 - omega(k)*temp1
temp3 = temp3 + temp1
* temp3 contains the matrix F
end do
* compute matrices P and R where svd(F) = P %*% B %*% t(R)
call dgesvd('A','A', p,p, temp3,p, temp4, temp1,p, temp2,p,
* wrk, lwork, info)
* now temp1 contains matrix P, temp2 contains matrix t(R)
* temp4 contains the singular values
* check if dgesvd converged
if ( info .ne. 0 ) return
* NOTE: t(O) = t( R %*% t(P) ) = P %*% t(R)
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, temp2,p,
* 0.d0, O,p )
* O contains TRANSPOSED matrix D of Browne, McNicholas
* .....................................................
* Algorithm MM 2 ......................................
* call dgemm( 'T','T', p,p,p, 1.d0, temp2,p, temp1,p,
* * 0.d0, O,p )
call transpose(O, p)
* O contains matrix D of Browne, McNicholas
* Algorithm MM 2
temp1 = 0.d0
temp3 = 0.d0
do k = 1,G
call dgemm( 'N','N', p,p,p, 1.d0, U(:,:,k),p, O,p,
* 0.d0, temp1,p )
* temp1 contains W %*% D
do j = 1,p
temp2(:,j) = temp1(:,j) / shape(j,k)
end do
* temp2 contains W %*% D %*% inv(A)
temp1 = temp2 - maxval( 1/shape(:,k) )*temp1
temp3 = temp3 + temp1
* temp3 contains the matrix F
end do
* compute matrices P and R where svd(F) = P %*% B %*% t(R)
call dgesvd('A','A', p,p, temp3,p, temp4, temp1,p, temp2,p,
* wrk, lwork, info)
* now temp1 contains matrix P, temp2 contains matrix t(R)
* temp4 contains the singular values
* check if dgesvd converged
if ( info .ne. 0 ) return
* NOTE: t(O) = R %*% t(P)
* call dgemm( 'T','T', p,p,p, 1.d0, temp2,p, temp1,p,
* * 0.d0, O,p )
O = 0.d0
* NOTE: we compute the TRANSPOSED of the matrix in the output in the paper
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, temp2,p,
* 0.d0, O,p )
call transpose(O, p)
* O contains TRANSPOSED matrix D of Browne, McNicholas
* .....................................................
* compute shape (matrix A) and target function
trgt = 0.d0
do k = 1,G
temp1 = 0.d0
call dgemm( 'N','N', p,p,p, 1.d0, O,p, U(:,:,k),p,
* 0.d0, temp1,p )
* temp1 contains t(D) %*% W
do j = 1,p
shape(j,k) = ddot(p, temp1(j,:), 1, O(j,:), 1)
end do
shape(:,k) = shape(:,k)/
* exp( sum( log(shape(:,k)) ) )**(1.d0/dble(p))
* now shape contains matrix A of Celeux, Govaert pag. 785
* check positive values
if ( minval(shape(:,k)) .lt. rteps ) then
info = 0
loglik = FLMAX
return
end if
temp4(1) = 0.d0
do j = 1,p
* temp2(:,j) = O(:,j) * 1.d0/shape(j,k)
temp2(:,j) = O(j,:) * 1.d0/shape(j,k)
temp4(1) = temp4(1) + ddot(p, temp1(j,:), 1, temp2(:,j), 1)
end do
trgt = trgt + temp4(1)
end do
* error
errin = abs(trgt - trgtprev)/(1.d0 + abs(trgt))
trgtprev = trgt
* WHILE condition M step
if ( errin .gt. tolin .and. niterin .lt. itmaxin ) goto 110
scale = trgt / ( sum(sumz(1:G))*dble(p) )
* ................................................................
* E step..........................................................
const = (-dble(p)/2.d0)*log2pi
do k = 1,G
logdet = 0.d0
do j = 1,p
logdet = logdet + ( log(shape(j,k)) + log(scale) )
end do
* compute mahalanobis distance for each observation
* ##### NOTE: O is transposed
do i = 1,n
temp1(:,1) = ( x(i,:) - mu(:,k) )
call dcopy(p, 0.d0, 0, temp2(:,1), 1)
call dgemv('N', p, p, 1.d0,
* O, p, temp1(:,1), 1, 0.d0, temp2(:,1), 1)
temp2(:,1) = temp2(:,1)/sqrt(scale*shape(:,k))
temp3(1,1) = ddot(p, temp2(:,1), 1, temp2(:,1), 1)
* temp3 contains the mahalanobis distance
z(i,k) = const - logdet/2.d0 - temp3(1,1)/2.d0 + log(pro(k))
* z(i,k) = const - logdet/2.d0 - temp3(1,1)/2.d0
end do
* z contains the log-density log(N(x|theta_k)) + log(p_k)
end do
* noise component
if (Vinv .gt. 0.d0) then
z(:,Gnoise) = log(Vinv) + log( pro(Gnoise) )
end if
* now column Gnoise of z contains log(Vinv) + log(p_0)
loglik = 0.d0
do i = 1,n
* Numerical Recipes pag.844
temp3(1,1) = maxval(z(i,:))
temp1(1,1) = temp3(1,1) + log( sum(exp(z(i,:) - temp3(1,1))) )
loglik = loglik + temp1(1,1)
* ##### NOTE: do we need to check if (z - zmax) is too small?
z(i,:) = exp( z(i,:) - temp1(1,1) )
* re-normalize probabilities
temp3(1,1) = sum( z(i,:) )
call dscal( Gnoise, 1.d0/temp3(1,1), z(i,:), 1 )
end do
* ................................................................
errout = abs(loglik - lkprev)/(1.d0 + abs(loglik))
lkprev = loglik
* Chris F (June 2015): pro should not be computed in the E-step
* sumz = sum(z, dim = 1)
* if ( eqpro ) then
* if ( Vinv .gt. 0 ) then
* pro(Gnoise) = sumz(Gnoise) / dble(n)
* pro(1:G) = ( 1 - pro(Gnoise) ) / dble(G)
* sumz = pro * dble(n)
* else
* pro = 1 / dble(G)
* sumz = pro * dble(n)
* end if
* else
* pro = sumz / dble(n)
* end if
* check if empty components
if ( minval(sumz) .lt. rteps ) then
loglik = -FLMAX
return
end if
* WHILE condition EM
if ( errout .gt. tolout .and. niterout .lt. itmaxout ) goto 100
return
end
************************************************************************
**** VVE model
************************************************************************
* ======================================================================
subroutine msvve (x,z, n,p,G, mu,U,O,scale,shape,pro, lwork,info,
* itmax,tol, niterin,errin, eps)
* Maximization step for model VVE
* ======================================================================
implicit none
integer :: n, p, G
double precision :: x(n,p), z(n,G)
double precision :: mu(p,G), U(p,p,G), pro(G), O(p,p)
double precision :: scale(G), shape(p,G)
double precision :: sumz(G), omega(G)
integer :: i, j, k, info, lwork
double precision :: temp1(p,p), temp2(p,p), temp3(p,p), temp4(p)
double precision :: wrk(lwork), tol, errin, trgt, trgtprev, eps
integer :: itmax, niterin
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
*-----------------------------------------------------------------------
* colsums of z
sumz = sum(z, dim = 1)
* a priori probabilities
pro = sumz / dble(n)
* pro = sumz / sum(sumz)
* if there is noise sum(sumz) does not sum to n. See help(mstep)
* compute weighted scattering matrix and means
do k = 1,G
do j = 1,p
mu(j,k) = sum(x(:,j)*z(:,k))/sumz(k)
end do
do i = 1,n
temp1(:,1) = ( x(i,:) - mu(:,k) ) * sqrt(z(i,k))
call dger(p, p, 1.d0, temp1(:,1), 1, temp1(:,1), 1,
* U(:,:,k), p)
end do
* U contains the weighted scattering matrix
* compute the eigenvalues of U to be stored in omega
temp2 = U(:,:,k)
call dsyev('N', 'U', p, temp2, p, temp1(:,1), wrk, lwork, info)
* now temp1 contains all the eigenvalues of U
* check if dsyev converged and positive definite
if ( info .ne. 0 ) then
return
else
if ( minval(temp1(:,1)) .lt. sqrt(eps) ) then
info = 0
scale = FLMAX
return
end if
end if
omega(k) = temp1(p,1)
end do
* omega contains the largest eigenvalue of each scattering matrix
niterin = 0
errin = FLMAX
trgt = FLMAX
trgtprev = FLMAX/2
* covariance matrix components estimation
* we consider algorithm MM 1 and MM 2 of Browne, McNicholas 2013
* with a modification in computing the orientation matrix in the MM 2 step
* shape (matrix A) and orientation (matrix D) initialised in R
* shape = matrix(1, p,G)
* O = diag(p)
* WHILE loop using goto statement
100 continue
* ### NOTE: O is transposed
niterin = niterin + 1
temp2 = 0.d0
temp3 = 0.d0
* temp3 will contain matrix F
* Algorithm MM 1 ......................................
do k = 1,G
do j = 1,p
* temp1(j,:) = O(:,j) / shape(j,k)
temp1(j,:) = O(j,:) / shape(j,k)
end do
* temp1 contains inv(A)t(D)
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, U(:,:,k),p,
* 0.d0, temp2,p )
* temp2 contains inv(A) %*% t(D) %*% W
temp1 = temp2 - omega(k)*temp1
temp3 = temp3 + temp1
* temp3 contains the matrix F
end do
* compute matrices P and R where svd(F) = P %*% B %*% t(R)
call dgesvd('A','A', p,p, temp3,p, temp4, temp1,p, temp2,p,
* wrk, lwork, info)
* now temp1 contains matrix P, temp2 contains matrix t(R)
* temp4 contains the singular values
* check if dgesvd converged
if ( info .ne. 0 ) return
* NOTE: t(P %*% t(R)) = R %*% t(P)
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, temp2,p,
* 0.d0, O,p )
* O contains TRANSPOSED matrix D of Browne, McNicholas
* .....................................................
* Algorithm MM 2 ......................................
call transpose(O, p)
* O contains matrix D of Browne, McNicholas
* Algorithm MM 2
temp1 = 0.d0
temp3 = 0.d0
do k = 1,G
call dgemm( 'N','N', p,p,p, 1.d0, U(:,:,k),p, O,p,
* 0.d0, temp1,p )
* temp1 contains W %*% D
do j = 1,p
temp2(:,j) = temp1(:,j) / shape(j,k)
end do
* temp2 contains W %*% D %*% inv(A)
temp1 = temp2 - maxval( 1/shape(:,k) )*temp1
temp3 = temp3 + temp1
* temp3 contains the matrix F
end do
* compute matrices P and R where svd(F) = P %*% B %*% t(R)
call dgesvd('A','A', p,p, temp3,p, temp4, temp1,p, temp2,p,
* wrk, lwork, info)
* now temp1 contains matrix P, temp2 contains matrix t(R)
* temp4 contains the singular values
* check if dgesvd converged
if ( info .ne. 0 ) return
* NOTE: t(O) = R %*% t(P)
O = 0.d0
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, temp2,p,
* 0.d0, O,p )
call transpose(O, p)
* O contains TRANSPOSED matrix D of Browne, McNicholas
* .....................................................
* compute shape (matrix A) and target function
trgt = 0.d0
do k = 1,G
temp1 = 0.d0
call dgemm( 'N','N', p,p,p, 1.d0, O,p, U(:,:,k),p,
* 0.d0, temp1,p )
* temp1 contains t(D) %*% W
do j = 1,p
shape(j,k) = ddot(p, temp1(j,:), 1, O(j,:), 1)
end do
* shape(:,k) = shape(:,k)/
* * exp( sum( log(shape(:,k)) ) )**(1.d0/dble(p))
shape(:,k) = shape(:,k)/sumz(k)
* now shape contains matrix A (scale*A) of Celeux, Govaert pag. 785
* compute scale parameter and shape matrix A
scale(k) = exp( sum( log(shape(:,k)) ) )**(1/dble(p))
shape(:,k) = shape(:,k)/scale(k)
* check positive values
if ( minval(shape(:,k)) .lt. sqrt(eps) ) then
info = 0
shape = FLMAX
return
end if
temp4(1) = 0.d0
do j = 1,p
* temp2(:,j) = O(:,j) * 1.d0/shape(j,k)
temp2(:,j) = O(j,:) * 1.d0/shape(j,k)
temp4(1) = temp4(1) + ddot(p, temp1(j,:), 1, temp2(:,j), 1)
end do
trgt = trgt + temp4(1)
end do
* error
errin = abs(trgt - trgtprev)/(1.d0 + abs(trgt))
trgtprev = trgt
* WHILE condition
if ( errin .gt. tol .and. niterin .lt. itmax ) goto 100
return
end
* ======================================================================
subroutine esvve (x,z, n,p,G,Gnoise, mu,O,scale,shape,pro, Vinv,
* loglik, eps)
* Expectation step for model VVE
* ======================================================================
implicit none
integer :: n, p, G, Gnoise
double precision :: x(n,p), z(n,Gnoise)
double precision :: mu(p,G), O(p,p), scale(G), shape(p,G)
double precision :: Vinv, pro(Gnoise)
double precision :: temp1(p), temp2(p), temp3, temp4(n)
integer :: i, k, j
double precision :: const, logdet, loglik, eps
double precision :: log2pi
parameter (log2pi = 1.837877066409345d0)
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
* double precision :: smalog
* parameter (smalog = -708.d0)
*-----------------------------------------------------------------------
* check very small eigenvalues (singular covariance)
if ( minval(shape) .le. sqrt(eps) .or.
* minval(scale) .le. sqrt(eps) ) then
loglik = FLMAX
return
end if
const = (-dble(p)/2.d0)*log2pi
do k = 1,G
logdet = 0.d0
do j = 1,p
logdet = logdet + ( log(shape(j,k)) + log(scale(k)) )
end do
* compute mahalanobis distance for each observation
* ##### NOTE: O is transposed
do i = 1,n
temp1 = ( x(i,:) - mu(:,k) )
call dcopy(p, 0.d0, 0, temp2, 1)
call dgemv('N', p, p, 1.d0,
* O, p, temp1, 1, 0.d0, temp2, 1)
temp2 = temp2/sqrt(scale(k)*shape(:,k))
temp3 = ddot(p, temp2, 1, temp2, 1)
temp4(i) = temp3
* temp3 contains the mahalanobis distance
* z(i,k) = const - logdet/2.d0 - temp3/2.d0 + log(pro(k))
z(i,k) = const - logdet/2.d0 - temp3/2.d0
* help(cdens) --> The densities are not scaled by mixing proportions
end do
* z contains the log-density log(N(x|theta_k))
end do
if ( pro(1) .lt. 0.d0 ) return
* cdens function
* noise component
if (Vinv .gt. 0.d0) then
call dcopy( n, log(Vinv), 0, z(:,Gnoise), 1)
end if
* now column Gnoise of z contains log(Vinv)
do i = 1,n
z(i,:) = z(i,:) + log( pro )
* Numerical Recipes pag.844
temp3 = maxval(z(i,:))
temp1(1) = temp3 + log( sum(exp(z(i,:) - temp3)) )
loglik = loglik + temp1(1)
* ##### NOTE: do we need to check if (z - zmax) is too small?
z(i,:) = exp( z(i,:) - temp1(1) )
* re-normalize probabilities
temp3 = sum( z(i,:) )
call dscal( Gnoise, 1.d0/temp3, z(i,:), 1 )
end do
return
end
* ======================================================================
subroutine mevve ( x,z, n,p,G,Gnoise, mu,O,U,scale,shape,pro,Vinv,
* loglik, eqpro,itmaxin,tolin,itmaxout,tolout,eps,
* niterin,errin,niterout,errout,lwork,info)
* Maximization-expectation algorithm for model VVE
* ======================================================================
implicit none
logical :: eqpro
integer :: n,p,G,Gnoise
double precision :: x(n,p), z(n,Gnoise), pro(Gnoise), Vinv
double precision :: mu(p,G), O(p,p), scale(G), shape(p,G)
double precision :: U(p,p,G), sumz(Gnoise), omega(G)
double precision :: temp1(p,p), temp2(p,p), temp3(p,p), temp4(p)
integer :: i, j, k, info, lwork
integer :: itmaxin, itmaxout, niterin, niterout
double precision :: tolin, tolout, errin, errout, eps, rteps
double precision :: const, logdet, loglik, lkprev, wrk(lwork)
double precision :: trgt, trgtprev
double precision :: log2pi
parameter (log2pi = 1.837877066409345d0)
double precision :: FLMAX
parameter (FLMAX = 1.7976931348623157d308)
external :: ddot
double precision :: ddot
* double precision :: smalog
* parameter (smalog = -708.d0)
*-----------------------------------------------------------------------
rteps = sqrt(eps)
niterout = 0
errout = FLMAX
lkprev = FLMAX/2
loglik = FLMAX
const = (-dble(p)/2.d0)*log2pi
* WHILE loop for EM algorithm
100 continue
niterout = niterout + 1
sumz = sum(z, dim = 1)
if ( eqpro ) then
if ( Vinv .gt. 0 ) then
pro(Gnoise) = sumz(Gnoise) / dble(n)
pro(1:G) = ( 1 - pro(Gnoise) ) / dble(G)
sumz = pro * dble(n)
else
pro = 1 / dble(G)
sumz = pro * dble(n)
end if
else
pro = sumz / dble(n)
end if
* re-initialise U
call dcopy(p*p*G, 0.d0, 0, U, 1)
* compute weighted scattering matrix and means
do k = 1,G
do j = 1,p
mu(j,k) = sum(x(:,j)*z(:,k))/sumz(k)
end do
do i = 1,n
temp1(:,1) = ( x(i,:) - mu(:,k) ) * sqrt(z(i,k))
call dger(p, p, 1.d0, temp1(:,1), 1, temp1(:,1), 1,
* U(:,:,k), p)
end do
* U contains the weighted scattering matrix
* compute the eigenvalues of U to be stored in omega
temp2 = U(:,:,k)
call dsyev('N', 'U', p, temp2, p, temp1(:,1), wrk, lwork, info)
* now temp1 contains all the eigenvalues of U
* check if dsyev converged and positive definite
if ( info .ne. 0 ) then
return
else
if ( minval(temp1(:,1)) .lt. rteps ) then
info = 0
scale = FLMAX
return
end if
end if
omega(k) = temp1(p,1)
end do
* omega contains the largest eigenvalue of each scattering matrix
* M step..........................................................
niterin = 0
errin = FLMAX
trgt = FLMAX
trgtprev = FLMAX/2
* covariance matrix components estimation
* we consider algorithm MM 1 and MM 2 of Browne, McNicholas 2013
* with a modification in computing the orientation matrix in the MM 2 step
* shape (matrix A) and orientation (matrix D) initialised in R
* shape = matrix(1, p,G)
* O = diag(p)
* ### NOTE: we don't re-initialize shape and orientation at each
* outer iteration of the EM algorithm
* WHILE loop for M step
110 continue
* ### NOTE: O is transposed
niterin = niterin + 1
temp2 = 0.d0
temp3 = 0.d0
* temp3 will contain matrix F
* Algorithm MM 1 ......................................
do k = 1,G
do j = 1,p
* temp1(j,:) = O(:,j) / shape(j,k)
temp1(j,:) = O(j,:) / shape(j,k)
end do
* temp1 contains inv(A)t(D)
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, U(:,:,k),p,
* 0.d0, temp2,p )
* temp2 contains inv(A) %*% t(D) %*% W
temp1 = temp2 - omega(k)*temp1
temp3 = temp3 + temp1
* temp3 contains the matrix F
end do
* compute matrices P and R where svd(F) = P %*% B %*% t(R)
call dgesvd('A','A', p,p, temp3,p, temp4, temp1,p, temp2,p,
* wrk, lwork, info)
* now temp1 contains matrix P, temp2 contains matrix t(R)
* temp4 contains the singular values
* check if dgesvd converged
if ( info .ne. 0 ) return
* NOTE: t(P %*% t(R)) = R %*% t(P)
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, temp2,p,
* 0.d0, O,p )
* O contains TRANSPOSED orientation (matrix D of Browne, McNicholas)
* .....................................................
* Algorithm MM 2 ......................................
call transpose(O, p)
* O contains matrix D of Browne, McNicholas
* Algorithm MM 2
temp1 = 0.d0
temp3 = 0.d0
do k = 1,G
call dgemm( 'N','N', p,p,p, 1.d0, U(:,:,k),p, O,p,
* 0.d0, temp1,p )
* temp1 contains W %*% D
do j = 1,p
temp2(:,j) = temp1(:,j) / shape(j,k)
end do
* temp2 contains W %*% D %*% inv(A)
temp1 = temp2 - maxval( 1/shape(:,k) )*temp1
temp3 = temp3 + temp1
* temp3 contains the matrix F
end do
* compute matrices P and R where svd(F) = P %*% B %*% t(R)
call dgesvd('A','A', p,p, temp3,p, temp4, temp1,p, temp2,p,
* wrk, lwork, info)
* now temp1 contains matrix P, temp2 contains matrix t(R)
* temp4 contains the singular values
* check if dgesvd converged
if ( info .ne. 0 ) return
* NOTE: t(O) = R %*% t(P)
O = 0.d0
call dgemm( 'N','N', p,p,p, 1.d0, temp1,p, temp2,p,
* 0.d0, O,p )
call transpose(O, p)
* O contains TRANSPOSED matrix D of Browne, McNicholas
* .....................................................
* compute shape (matrix A) and target function
trgt = 0.d0
do k = 1,G
temp1 = 0.d0
call dgemm( 'N','N', p,p,p, 1.d0, O,p, U(:,:,k),p,
* 0.d0, temp1,p )
* temp1 contains t(D) %*% W
do j = 1,p
shape(j,k) = ddot(p, temp1(j,:), 1, O(j,:), 1)
end do
* shape(:,k) = shape(:,k)/
* * exp( sum( log(shape(:,k)) ) )**(1.d0/dble(p))
shape(:,k) = shape(:,k)/sumz(k)
* now shape contains matrix A (scale*A) of Celeux, Govaert pag. 785
* compute scale parameter and shape matrix A
scale(k) = exp( sum( log(shape(:,k)) ) )**(1/dble(p))
shape(:,k) = shape(:,k)/scale(k)
* check positive values
if (minval(shape(:,k)) .lt. rteps .or.
* scale(k) .lt. rteps) then
info = 0
loglik = FLMAX
return
end if
temp4(1) = 0.d0
do j = 1,p
* temp2(:,j) = O(:,j) * 1.d0/shape(j,k)
temp2(:,j) = O(j,:) * 1.d0/shape(j,k)
temp4(1) = temp4(1) + ddot(p, temp1(j,:), 1, temp2(:,j), 1)
end do
trgt = trgt + temp4(1)
end do
* error
errin = abs(trgt - trgtprev)/(1.d0 + abs(trgt))
trgtprev = trgt
* WHILE condition M step
if ( errin .gt. tolin .and. niterin .lt. itmaxin ) goto 110
* do k = 1,G
* scale(k) = exp( sum( log(shape(:,k)) ) )**(1/dble(p))
* shape(:,k) = shape(:,k)/scale(k)
* end do
* ................................................................
* E step..........................................................
const = (-dble(p)/2.d0)*log2pi
do k = 1,G
logdet = 0.d0
do j = 1,p
logdet = logdet + ( log(shape(j,k)) + log(scale(k)) )
end do
* compute mahalanobis distance for each observation
* ##### NOTE: O is transposed
do i = 1,n
temp1(:,1) = ( x(i,:) - mu(:,k) )
call dcopy(p, 0.d0, 0, temp2(:,1), 1)
call dgemv('N', p, p, 1.d0,
* O, p, temp1(:,1), 1, 0.d0, temp2(:,1), 1)
temp2(:,1) = temp2(:,1)/sqrt(scale(k)*shape(:,k))
temp3(1,1) = ddot(p, temp2(:,1), 1, temp2(:,1), 1)
* temp3 contains the mahalanobis distance
z(i,k) = const - logdet/2.d0 - temp3(1,1)/2.d0 + log(pro(k))
* z(i,k) = const - logdet/2.d0 - temp3(1,1)/2.d0
end do
* z contains the log-density log(N(x|theta_k)) + log(p_k)
end do
* noise component
if (Vinv .gt. 0.d0) then
z(:,Gnoise) = log(Vinv) + log( pro(Gnoise) )
end if
* now column Gnoise of z contains log(Vinv) + log(p_0)
loglik = 0.d0
do i = 1,n
* Numerical Recipes pag.844
temp3(1,1) = maxval(z(i,:))
temp1(1,1) = temp3(1,1) + log( sum(exp(z(i,:) - temp3(1,1))) )
loglik = loglik + temp1(1,1)
* ##### NOTE: do we need to check if (z - zmax) is too small?
z(i,:) = exp( z(i,:) - temp1(1,1) )
* re-normalize probabilities
temp3(1,1) = sum( z(i,:) )
call dscal( Gnoise, 1.d0/temp3(1,1), z(i,:), 1 )
end do
* ................................................................
errout = abs(loglik - lkprev)/(1.d0 + abs(loglik))
lkprev = loglik
* Chris F (June 2015): pro should not be computed in the E-step
* sumz = sum(z, dim = 1)
* if ( eqpro ) then
* if ( Vinv .gt. 0 ) then
* pro(Gnoise) = sumz(Gnoise) / dble(n)
* pro(1:G) = ( 1 - pro(Gnoise) ) / dble(G)
* sumz = pro * dble(n)
* else
* pro = 1 / dble(G)
* sumz = pro * dble(n)
* end if
* else
* pro = sumz / dble(n)
* end if
* check if empty components
if ( minval(sumz) .lt. rteps ) then
loglik = -FLMAX
return
end if
* WHILE condition EM
if ( errout .gt. tolout .and. niterout .lt. itmaxout ) goto 100
return
end
mclust/src/dmvnorm.f 0000644 0001762 0000144 00000003771 13463252677 014230 0 ustar ligges users * =====================================================================
subroutine dmvnorm ( x, mu, Sigma, n, p, w, hood, logdens)
*
* Compute log-density of multivariate Gaussian
*
* =====================================================================
implicit NONE
integer n, p
double precision hood
double precision x(n,p), w(*), logdens(n)
double precision mu(p), Sigma(p,p)
integer info, i, j
double precision detlog, umin, umax, const, temp
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMAX
parameter (RTMAX = 1.340780792994260d154)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision ddot
external ddot
* ---------------------------------------------------------------------------
* Cholesky factorization
call dpotrf('U', p, Sigma, p, info)
if (info .ne. 0) then
w(1) = dble(info)
hood = FLMAX
return
end if
call absrng( p, Sigma, (p+1), umin, umax)
if (umax .le. one .and. umax .ge. umin*RTMAX) then
w(1) = zero
hood = FLMAX
return
end if
if (umax .ge. one .and. umin .le. umax*RTMIN) then
w(1) = zero
hood = FLMAX
return
end if
detlog = zero
do j = 1, p
detlog = detlog + log(abs(Sigma(j,j)))
end do
const = dble(p)*pi2log/two + detlog
do i = 1, n
call dcopy(p, x(i,1), n, w, 1)
call daxpy(p, (-one), mu(1), 1, w, 1)
call dtrsv('U', 'T', 'N', p, Sigma, p, w, 1)
temp = ddot(p, w, 1, w, 1)/two
logdens(i) = -(const+temp)
end do
w(1) = zero
return
end
mclust/src/init.c 0000644 0001762 0000144 00000043316 13507677506 013506 0 ustar ligges users #include
#include // for NULL
#include
/*
Routines registration obtained with
tools::package_native_routine_registration_skeleton("~/R/mclust")
FIXME: Check these declarations against the C/Fortran source code.
*/
/* .Fortran calls */
extern void F77_NAME(dmvnorm)(void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(covwf)(void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(crossprodf)(void *, void *, void *, void *, void *, void *);
extern void F77_NAME(d2norm)(void *, void *, void *, void *);
extern void F77_NAME(es1e)(void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(es1v)(void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(eseee)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(eseei)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(eseev)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(eseii)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(eseve)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(esevi)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(esevv)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(esvee)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(esvei)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(esvev)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(esvii)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(esvve)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(esvvi)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(esvvv)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(hc1e)(void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(hc1v)(void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(hceee)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(hceii)(void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(hcvii)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(hcvvv)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mcltrw)(void *, void *, void *, void *, void *);
extern void F77_NAME(me1e)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(me1ep)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(me1v)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(me1vp)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meeee)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meeeep)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meeei)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meeeip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meeev)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meeevp)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meeii)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meeiip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meeve)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meevi)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meevip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meevv)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mevee)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mevei)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meveip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mevev)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mevevp)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mevii)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(meviip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mevve)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mevvi)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mevvip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mevvv)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mevvvp)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mnxiip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mnxxip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mnxxxp)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(ms1e)(void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(ms1ep)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(ms1v)(void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(ms1vp)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mseee)(void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mseeep)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mseei)(void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mseeip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mseev)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mseevp)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mseii)(void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mseiip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mseve)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msevi)(void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msevip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msevv)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msvee)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msvei)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msveip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msvev)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msvevp)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msvii)(void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msviip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msvve)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msvvi)(void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msvvip)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msvvv)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(msvvvp)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mvn1d)(void *, void *, void *, void *, void *);
extern void F77_NAME(mvn1p)(void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mvnxii)(void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mvnxxi)(void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(mvnxxx)(void *, void *, void *, void *, void *, void *);
extern void F77_NAME(shapeo)(void *, void *, void *, void *, void *, void *, void *);
extern void F77_NAME(uncholf)(void *, void *, void *, void *, void *);
static const R_FortranMethodDef FortranEntries[] = {
{"dmvnorm", (DL_FUNC) &F77_NAME(dmvnorm), 8},
{"covwf", (DL_FUNC) &F77_NAME(covwf), 8},
{"crossprodf", (DL_FUNC) &F77_NAME(crossprodf), 6},
{"d2norm", (DL_FUNC) &F77_NAME(d2norm), 4},
{"es1e", (DL_FUNC) &F77_NAME(es1e), 9},
{"es1v", (DL_FUNC) &F77_NAME(es1v), 9},
{"eseee", (DL_FUNC) &F77_NAME(eseee), 12},
{"eseei", (DL_FUNC) &F77_NAME(eseei), 11},
{"eseev", (DL_FUNC) &F77_NAME(eseev), 14},
{"eseii", (DL_FUNC) &F77_NAME(eseii), 10},
{"eseve", (DL_FUNC) &F77_NAME(eseve), 14},
{"esevi", (DL_FUNC) &F77_NAME(esevi), 11},
{"esevv", (DL_FUNC) &F77_NAME(esevv), 14},
{"esvee", (DL_FUNC) &F77_NAME(esvee), 14},
{"esvei", (DL_FUNC) &F77_NAME(esvei), 11},
{"esvev", (DL_FUNC) &F77_NAME(esvev), 14},
{"esvii", (DL_FUNC) &F77_NAME(esvii), 10},
{"esvve", (DL_FUNC) &F77_NAME(esvve), 14},
{"esvvi", (DL_FUNC) &F77_NAME(esvvi), 11},
{"esvvv", (DL_FUNC) &F77_NAME(esvvv), 12},
{"hc1e", (DL_FUNC) &F77_NAME(hc1e), 7},
{"hc1v", (DL_FUNC) &F77_NAME(hc1v), 8},
{"hceee", (DL_FUNC) &F77_NAME(hceee), 12},
{"hceii", (DL_FUNC) &F77_NAME(hceii), 9},
{"hcvii", (DL_FUNC) &F77_NAME(hcvii), 10},
{"hcvvv", (DL_FUNC) &F77_NAME(hcvvv), 14},
{"mcltrw", (DL_FUNC) &F77_NAME(mcltrw), 5},
{"me1e", (DL_FUNC) &F77_NAME(me1e), 12},
{"me1ep", (DL_FUNC) &F77_NAME(me1ep), 16},
{"me1v", (DL_FUNC) &F77_NAME(me1v), 12},
{"me1vp", (DL_FUNC) &F77_NAME(me1vp), 16},
{"meeee", (DL_FUNC) &F77_NAME(meeee), 14},
{"meeeep", (DL_FUNC) &F77_NAME(meeeep), 18},
{"meeei", (DL_FUNC) &F77_NAME(meeei), 14},
{"meeeip", (DL_FUNC) &F77_NAME(meeeip), 18},
{"meeev", (DL_FUNC) &F77_NAME(meeev), 18},
{"meeevp", (DL_FUNC) &F77_NAME(meeevp), 22},
{"meeii", (DL_FUNC) &F77_NAME(meeii), 13},
{"meeiip", (DL_FUNC) &F77_NAME(meeiip), 17},
{"meeve", (DL_FUNC) &F77_NAME(meeve), 26},
{"meevi", (DL_FUNC) &F77_NAME(meevi), 14},
{"meevip", (DL_FUNC) &F77_NAME(meevip), 18},
{"meevv", (DL_FUNC) &F77_NAME(meevv), 22},
{"mevee", (DL_FUNC) &F77_NAME(mevee), 26},
{"mevei", (DL_FUNC) &F77_NAME(mevei), 17},
{"meveip", (DL_FUNC) &F77_NAME(meveip), 21},
{"mevev", (DL_FUNC) &F77_NAME(mevev), 18},
{"mevevp", (DL_FUNC) &F77_NAME(mevevp), 22},
{"mevii", (DL_FUNC) &F77_NAME(mevii), 13},
{"meviip", (DL_FUNC) &F77_NAME(meviip), 17},
{"mevve", (DL_FUNC) &F77_NAME(mevve), 26},
{"mevvi", (DL_FUNC) &F77_NAME(mevvi), 14},
{"mevvip", (DL_FUNC) &F77_NAME(mevvip), 18},
{"mevvv", (DL_FUNC) &F77_NAME(mevvv), 15},
{"mevvvp", (DL_FUNC) &F77_NAME(mevvvp), 19},
{"mnxiip", (DL_FUNC) &F77_NAME(mnxiip), 10},
{"mnxxip", (DL_FUNC) &F77_NAME(mnxxip), 11},
{"mnxxxp", (DL_FUNC) &F77_NAME(mnxxxp), 11},
{"ms1e", (DL_FUNC) &F77_NAME(ms1e), 7},
{"ms1ep", (DL_FUNC) &F77_NAME(ms1ep), 11},
{"ms1v", (DL_FUNC) &F77_NAME(ms1v), 7},
{"ms1vp", (DL_FUNC) &F77_NAME(ms1vp), 11},
{"mseee", (DL_FUNC) &F77_NAME(mseee), 9},
{"mseeep", (DL_FUNC) &F77_NAME(mseeep), 13},
{"mseei", (DL_FUNC) &F77_NAME(mseei), 9},
{"mseeip", (DL_FUNC) &F77_NAME(mseeip), 13},
{"mseev", (DL_FUNC) &F77_NAME(mseev), 12},
{"mseevp", (DL_FUNC) &F77_NAME(mseevp), 16},
{"mseii", (DL_FUNC) &F77_NAME(mseii), 8},
{"mseiip", (DL_FUNC) &F77_NAME(mseiip), 12},
{"mseve", (DL_FUNC) &F77_NAME(mseve), 18},
{"msevi", (DL_FUNC) &F77_NAME(msevi), 9},
{"msevip", (DL_FUNC) &F77_NAME(msevip), 13},
{"msevv", (DL_FUNC) &F77_NAME(msevv), 14},
{"msvee", (DL_FUNC) &F77_NAME(msvee), 16},
{"msvei", (DL_FUNC) &F77_NAME(msvei), 14},
{"msveip", (DL_FUNC) &F77_NAME(msveip), 18},
{"msvev", (DL_FUNC) &F77_NAME(msvev), 14},
{"msvevp", (DL_FUNC) &F77_NAME(msvevp), 18},
{"msvii", (DL_FUNC) &F77_NAME(msvii), 8},
{"msviip", (DL_FUNC) &F77_NAME(msviip), 12},
{"msvve", (DL_FUNC) &F77_NAME(msvve), 18},
{"msvvi", (DL_FUNC) &F77_NAME(msvvi), 9},
{"msvvip", (DL_FUNC) &F77_NAME(msvvip), 13},
{"msvvv", (DL_FUNC) &F77_NAME(msvvv), 10},
{"msvvvp", (DL_FUNC) &F77_NAME(msvvvp), 14},
{"mvn1d", (DL_FUNC) &F77_NAME(mvn1d), 5},
{"mvn1p", (DL_FUNC) &F77_NAME(mvn1p), 9},
{"mvnxii", (DL_FUNC) &F77_NAME(mvnxii), 6},
{"mvnxxi", (DL_FUNC) &F77_NAME(mvnxxi), 7},
{"mvnxxx", (DL_FUNC) &F77_NAME(mvnxxx), 6},
{"shapeo", (DL_FUNC) &F77_NAME(shapeo), 7},
{"uncholf", (DL_FUNC) &F77_NAME(uncholf), 5},
{NULL, NULL, 0}
};
void R_init_mclust(DllInfo *dll)
{
R_registerRoutines(dll, NULL, NULL, FortranEntries, NULL);
R_useDynamicSymbols(dll, FALSE);
}
mclust/src/mclust.f 0000644 0001762 0000144 00001436405 13504406167 014051 0 ustar ligges users C modified to avoid printing for calls from Fortran within R
double precision function dgam (x)
c jan 1984 edition. w. fullerton, c3, los alamos scientific lab.
c jan 1994 wpp@ips.id.ethz.ch, ehg@research.att.com declare xsml
c jun 2019 renamed function from dgamma to avoid warning with intrinsic
c function already named dgamma
double precision x, gamcs(42), dxrel, pi, sinpiy, sq2pil, xmax,
1 xmin, y, d9lgmc, dcsevl, d1mach, xsml
C external d1mach, d9lgmc, dcsevl, dexp, dint, dlog, dsin, dsqrt,
C 1 initds
external d1mach, d9lgmc, dcsevl
c
c series for gam on the interval 0. to 1.00000e+00
c with weighted error 5.79e-32
c log weighted error 31.24
c significant figures required 30.00
c decimal places required 32.05
c
data gam cs( 1) / +.8571195590 9893314219 2006239994 2 d-2 /
data gam cs( 2) / +.4415381324 8410067571 9131577165 2 d-2 /
data gam cs( 3) / +.5685043681 5993633786 3266458878 9 d-1 /
data gam cs( 4) / -.4219835396 4185605010 1250018662 4 d-2 /
data gam cs( 5) / +.1326808181 2124602205 8400679635 2 d-2 /
data gam cs( 6) / -.1893024529 7988804325 2394702388 6 d-3 /
data gam cs( 7) / +.3606925327 4412452565 7808221722 5 d-4 /
data gam cs( 8) / -.6056761904 4608642184 8554829036 5 d-5 /
data gam cs( 9) / +.1055829546 3022833447 3182350909 3 d-5 /
data gam cs( 10) / -.1811967365 5423840482 9185589116 6 d-6 /
data gam cs( 11) / +.3117724964 7153222777 9025459316 9 d-7 /
data gam cs( 12) / -.5354219639 0196871408 7408102434 7 d-8 /
data gam cs( 13) / +.9193275519 8595889468 8778682594 0 d-9 /
data gam cs( 14) / -.1577941280 2883397617 6742327395 3 d-9 /
data gam cs( 15) / +.2707980622 9349545432 6654043308 9 d-10 /
data gam cs( 16) / -.4646818653 8257301440 8166105893 3 d-11 /
data gam cs( 17) / +.7973350192 0074196564 6076717535 9 d-12 /
data gam cs( 18) / -.1368078209 8309160257 9949917230 9 d-12 /
data gam cs( 19) / +.2347319486 5638006572 3347177168 8 d-13 /
data gam cs( 20) / -.4027432614 9490669327 6657053469 9 d-14 /
data gam cs( 21) / +.6910051747 3721009121 3833697525 7 d-15 /
data gam cs( 22) / -.1185584500 2219929070 5238712619 2 d-15 /
data gam cs( 23) / +.2034148542 4963739552 0102605193 2 d-16 /
data gam cs( 24) / -.3490054341 7174058492 7401294910 8 d-17 /
data gam cs( 25) / +.5987993856 4853055671 3505106602 6 d-18 /
data gam cs( 26) / -.1027378057 8722280744 9006977843 1 d-18 /
data gam cs( 27) / +.1762702816 0605298249 4275966074 8 d-19 /
data gam cs( 28) / -.3024320653 7353062609 5877211204 2 d-20 /
data gam cs( 29) / +.5188914660 2183978397 1783355050 6 d-21 /
data gam cs( 30) / -.8902770842 4565766924 4925160106 6 d-22 /
data gam cs( 31) / +.1527474068 4933426022 7459689130 6 d-22 /
data gam cs( 32) / -.2620731256 1873629002 5732833279 9 d-23 /
data gam cs( 33) / +.4496464047 8305386703 3104657066 6 d-24 /
data gam cs( 34) / -.7714712731 3368779117 0390152533 3 d-25 /
data gam cs( 35) / +.1323635453 1260440364 8657271466 6 d-25 /
data gam cs( 36) / -.2270999412 9429288167 0231381333 3 d-26 /
data gam cs( 37) / +.3896418998 0039914493 2081663999 9 d-27 /
data gam cs( 38) / -.6685198115 1259533277 9212799999 9 d-28 /
data gam cs( 39) / +.1146998663 1400243843 4761386666 6 d-28 /
data gam cs( 40) / -.1967938586 3451346772 9510399999 9 d-29 /
data gam cs( 41) / +.3376448816 5853380903 3489066666 6 d-30 /
data gam cs( 42) / -.5793070335 7821357846 2549333333 3 d-31 /
c
data pi / 3.1415926535 8979323846 2643383279 50 d0 /
c sq2pil is 0.5*alog(2*pi) = alog(sqrt(2*pi))
data sq2pil / 0.9189385332 0467274178 0329736405 62 d0 /
data ngam, xmin, xmax, xsml, dxrel / 0, 4*0.d0 /
c
if (ngam.ne.0) go to 10
ngam = initds (gamcs, 42, 0.1*sngl(d1mach(3)) )
c
call d9gaml (xmin, xmax)
xsml = exp (max (log(d1mach(1)), -log(d1mach(2)))+0.01d0)
dxrel = sqrt (d1mach(4))
c
10 y = abs(x)
if (y.gt.10.d0) go to 50
c
c compute gamma(x) for -xbnd .le. x .le. xbnd. reduce interval and find
c gamma(1+y) for 0.0 .le. y .lt. 1.0 first of all.
c
n = int(x)
if (x.lt.0.d0) n = n - 1
y = x - dble(float(n))
n = n - 1
dgam = 0.9375d0 + dcsevl (2.d0*y-1.d0, gamcs, ngam)
if (n.eq.0) return
c
if (n.gt.0) go to 30
c
c compute gamma(x) for x .lt. 1.0
c
n = -n
if (x.eq.0.d0) then
dgam = d1mach(2)
return
endif
if (x.lt.0.0d0 .and. x+dble(float(n-2)).eq.0.d0) then
dgam = -d1mach(2)
return
endif
if (y.lt.xsml) then
dgam = d1mach(2)
return
endif
c
do 20 i=1,n
dgam = dgam/(x+dble(float(i-1)) )
20 continue
return
c
c gamma(x) for x .ge. 2.0 and x .le. 10.0
c
30 do 40 i=1,n
dgam = (y+dble(float(i))) * dgam
40 continue
return
c
c gamma(x) for dabs(x) .gt. 10.0. recall y = dabs(x).
c
50 if (x.gt.xmax) then
dgam = d1mach(2)
return
endif
c
dgam = 0.d0
if (x.lt.xmin) return
c
dgam = exp ((y-0.5d0)*log(y) - y + sq2pil + d9lgmc(y) )
if (x.gt.0.d0) return
c
sinpiy = sin (pi*y)
c
if (sinpiy.eq.0.d0) then
dgam = -d1mach(2)
return
endif
c
dgam = -pi/(y*sinpiy*dgam)
c
return
end
C modified to omit priniting for calls from Fortran within R
subroutine d9gaml (xmin, xmax)
c june 1977 edition. w. fullerton, c3, los alamos scientific lab.
c
c calculate the minimum and maximum legal bounds for x in gamma(x).
c xmin and xmax are not the only bounds, but they are the only non-
c trivial ones to calculate.
c
c output arguments --
c xmin dble prec minimum legal value of x in gamma(x). any smaller
c value of x might result in underflow.
c xmax dble prec maximum legal value of x in gamma(x). any larger
c value of x might cause overflow.
c
double precision xmin, xmax, alnbig, alnsml, xln, xold, d1mach
C external d1mach, dlog
external d1mach
c
alnsml = log(d1mach(1))
xmin = -alnsml
do 10 i=1,10
xold = xmin
xln = log(xmin)
xmin = xmin - xmin*((xmin+0.5d0)*xln - xmin - 0.2258d0 + alnsml)
1 / (xmin*xln+0.5d0)
if (abs(xmin-xold).lt.0.005d0) go to 20
10 continue
C call seteru (27hd9gaml unable to find xmin, 27, 1, 2)
xmin = d1mach(2)
xmax = -d1mach(2)
return
c
20 xmin = -xmin + 0.01d0
c
alnbig = log (d1mach(2))
xmax = alnbig
do 30 i=1,10
xold = xmax
xln = log(xmax)
xmax = xmax - xmax*((xmax-0.5d0)*xln - xmax + 0.9189d0 - alnbig)
1 / (xmax*xln-0.5d0)
if (abs(xmax-xold).lt.0.005d0) go to 40
30 continue
C call seteru (27hd9gaml unable to find xmax, 27, 2, 2)
xmin = d1mach(2)
xmax = -d1mach(2)
return
c
40 xmax = xmax - 0.01d0
xmin = dmax1 (xmin, -xmax+1.d0)
c
return
end
double precision function dcsevl (x, a, n)
double precision a(n), x, twox, b0, b1, b2
double precision d1mach
external d1mach
c
if (n.lt.1) then
dcsevl = -d1mach(2)
return
endif
if (n.gt.1000) then
dcsevl = d1mach(2)
return
endif
if (x.lt.(-1.1d0) .or. x.gt.1.1d0) then
dcsevl = d1mach(2)
return
endif
C added by CF to avoid uninitialized warnings
b2 = 0
c
twox = 2.0d0*x
b1 = 0.d0
b0 = 0.d0
do 10 i=1,n
b2 = b1
b1 = b0
ni = n - i + 1
b0 = twox*b1 - b2 + a(ni)
10 continue
c
dcsevl = 0.5d0 * (b0-b2)
c
return
end
double precision function d9lgmc (x)
double precision x, algmcs(15), xbig, xmax, dcsevl, d1mach
external d1mach, dcsevl, initds
c
data algmcs( 1) / +.1666389480 4518632472 0572965082 2 d+0 /
data algmcs( 2) / -.1384948176 0675638407 3298605913 5 d-4 /
data algmcs( 3) / +.9810825646 9247294261 5717154748 7 d-8 /
data algmcs( 4) / -.1809129475 5724941942 6330626671 9 d-10 /
data algmcs( 5) / +.6221098041 8926052271 2601554341 6 d-13 /
data algmcs( 6) / -.3399615005 4177219443 0333059966 6 d-15 /
data algmcs( 7) / +.2683181998 4826987489 5753884666 6 d-17 /
data algmcs( 8) / -.2868042435 3346432841 4462239999 9 d-19 /
data algmcs( 9) / +.3962837061 0464348036 7930666666 6 d-21 /
data algmcs( 10) / -.6831888753 9857668701 1199999999 9 d-23 /
data algmcs( 11) / +.1429227355 9424981475 7333333333 3 d-24 /
data algmcs( 12) / -.3547598158 1010705471 9999999999 9 d-26 /
data algmcs( 13) / +.1025680058 0104709120 0000000000 0 d-27 /
data algmcs( 14) / -.3401102254 3167487999 9999999999 9 d-29 /
data algmcs( 15) / +.1276642195 6300629333 3333333333 3 d-30 /
c
data nalgm, xbig, xmax / 0, 2*0.d0 /
c
if (nalgm.ne.0) go to 10
nalgm = initds (algmcs, 15, sngl(d1mach(3)) )
xbig = 1.0d0/sqrt(d1mach(3))
xmax = exp (dmin1(log(d1mach(2)/12.d0), -log(12.d0*d1mach(1))))
c
10 if (x.lt.10.d0) then
d9lgmc = d1mach(2)
return
endif
c
if (x.ge.xmax) go to 20
c
d9lgmc = 1.d0/(12.d0*x)
if (x.lt.xbig) d9lgmc = dcsevl (2.0d0*(10.d0/x)**2-1.d0, algmcs,
1 nalgm) / x
return
c
20 d9lgmc = 0.d0
C call seteru (34hd9lgmc x so big d9lgmc underflows, 34, 2, 0)
return
c
end
double precision function dlngam (x)
double precision x, y, xmax, dxrel, pi
double precision sinpiy, sqpi2l, sq2pil
double precision d1mach, d9lgmc
external d1mach, d9lgmc
double precision dgam
c external dgamma
c
data sq2pil / 0.9189385332 0467274178 0329736405 62 d0 /
c sq2pil = alog (sqrt(2*pi)), sqpi2l = alog(sqrt(pi/2))
data sqpi2l / +.2257913526 4472743236 3097614947 441 d+0 /
data pi / 3.1415926535 8979323846 2643383279 50 d0 /
c
data xmax, dxrel / 2*0.d0 /
c
C added by CF to avoid uninitialized warnings
dlngam = 0.d0
if (xmax.ne.0.d0) go to 10
xmax = d1mach(2)/dlog(d1mach(2))
dxrel = dsqrt (d1mach(4))
c
10 y = abs (x)
if (y.gt.10.d0) go to 20
c
c dlog (dabs (dgam(x)) ) for dabs(x) .le. 10.0
c
dlngam = log (abs (dgam(x)) )
return
c
c dlog ( dabs (dgam(x)) ) for dabs(x) .gt. 10.0
c
C20 if (y.gt.xmax) call seteru (
C 1 39hdlngam dabs(x) so big dlngam overflows, 39, 2, 2)
20 if (y.gt.xmax) dlngam = d1mach(2)
if (y.gt.xmax) return
c
if (x.gt.0.d0) dlngam = sq2pil + (x-0.5d0)*log(x) - x + d9lgmc(y)
if (x.gt.0.d0) return
c
sinpiy = abs (sin(pi*y))
C if (sinpiy.eq.0.d0) call seteru (
C 1 31hdlngam x is a negative integer, 31, 3, 2)
if (sinpiy.eq.0.d0) dlngam = -d1mach(2)
if (sinpiy.eq.0.d0) return
c
dlngam = sqpi2l + (x-0.5d0)*log(y) - x - log(sinpiy) - d9lgmc(y)
c
C if (dabs((x-dint(x-0.5d0))*dlngam/x).lt.dxrel) call seteru (
C 1 68hdlngam answer lt half precision because x too near negative
C 2integer, 68, 1, 1)
return
c
end
function initds (dos, nos, eta)
double precision dos(nos)
integer i1mach
external i1mach
c
C if (nos.lt.1) call seteru (
C 1 35hinitds number of coefficients lt 1, 35, 2, 2)
if (nos.lt.1) initds = i1mach(9)
c
C added by CF to avoid uninitialized warnings
i = 0
err = 0.
do 10 ii=1,nos
i = nos + 1 - ii
err = err + abs(sngl(dos(i)))
if (err.gt.eta) go to 20
10 continue
c
C20 if (i.eq.nos) call seteru (28hinitds eta may be too small, 28,
C 1 1, 2)
20 continue
initds = i
c
return
end
subroutine absrng( l, v, i, vmin, vmax)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
double precision v(*)
integer i, j, k, l
double precision temp, vmin, vmax
c----------------------------------------------------------------------------
temp = abs(v(1))
vmin = temp
vmax = temp
if (l .eq. 1) return
if (i .eq. 1) then
do j = 2, l
temp = abs(v(j))
vmin = min(vmin,temp)
vmax = max(vmax,temp)
end do
else
k = 1 + i
do j = 2, l
temp = abs(v(k))
vmin = min(vmin,temp)
vmax = max(vmax,temp)
k = k + i
end do
end if
return
end
SUBROUTINE D2NORM ( N, X, INCX, VALUE )
* .. Scalar Arguments ..
INTEGER INCX, N
* .. Array Arguments ..
DOUBLE PRECISION X( * ), VALUE
* ..
*
* DNRM2 returns the euclidean norm of a vector via the function
* name, so that
*
* DNRM2 := sqrt( x'*x )
*
* THIS FUNCTION MODELLED AFTER DNRM2 BUT WRITTEN AS A SUBROUTINE
*
* -- This version written on 25-October-1982.
* Modified on 14-October-1993 to inline the call to DLASSQ.
* Sven Hammarling, Nag Ltd.
*
*
* .. Parameters ..
DOUBLE PRECISION ONE , ZERO
PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
* .. Local Scalars ..
INTEGER IX
DOUBLE PRECISION ABSXI, NORM, SCALE, SSQ
* .. Intrinsic Functions ..
INTRINSIC ABS, SQRT
* ..
* .. Executable Statements ..
IF( N.LT.1 .OR. INCX.LT.1 )THEN
NORM = ZERO
ELSE IF( N.EQ.1 )THEN
NORM = ABS( X( 1 ) )
ELSE
SCALE = ZERO
SSQ = ONE
* The following loop is equivalent to this call to the LAPACK
* auxiliary routine:
* CALL DLASSQ( N, X, INCX, SCALE, SSQ )
*
DO 10, IX = 1, 1 + ( N - 1 )*INCX, INCX
IF( X( IX ).NE.ZERO )THEN
ABSXI = ABS( X( IX ) )
IF( SCALE.LT.ABSXI )THEN
SSQ = ONE + SSQ*( SCALE/ABSXI )**2
SCALE = ABSXI
ELSE
SSQ = SSQ + ( ABSXI/SCALE )**2
END IF
END IF
10 CONTINUE
NORM = SCALE * SQRT( SSQ )
END IF
*
VALUE = NORM
RETURN
*
* End of D2NORM.
*
END
subroutine mclrup( l, n, v, r, lr)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer l, n, lr
double precision cs, sn
c double precision v(n), r(lr,n)
double precision v(*), r(lr,*)
integer i, j, k, m
if (l .eq. 1) return
k = l - 1
if (k .le. n) then
call dcopy( n, v, 1, r(k,1), lr)
if (k .eq. 1) return
if (n .gt. 1) then
i = 1
m = n
do j = 2, k
call drotg( r(i,i), r(k,i), cs, sn)
m = m - 1
call drot( m, r(i,j), lr, r(k,j), lr, cs, sn)
i = j
end do
else
call drotg( r(1,1), r(k,1), cs, sn)
end if
else
if (n .gt. 1) then
i = 1
m = n
do j = 2, n
call drotg( r(i,i), v(i), cs, sn)
m = m - 1
call drot( m, r(i,j), lr, v(j), 1, cs, sn)
i = j
end do
end if
call drotg( r(n,n), v(n), cs, sn)
end if
return
end
subroutine mcltrw( x, n, p, u, ss)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n, p
integer n, p
double precision ss
c double precision x(n,p), u(p)
double precision x(n,*), u(*)
double precision ddot
external ddot
integer i, j
double precision fac
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
c------------------------------------------------------------------------------
c form mean
fac = one / sqrt(dble(n))
call dcopy( p, zero, 0, u, 1)
do i = 1, n
call daxpy( p, fac, x(i,1), n, u, 1)
end do
c subtract mean and form sum of squares
ss = zero
do j = 1, p
call daxpy( n, (-fac), u(j), 0, x(1,j), 1)
ss = ss + ddot(n, x(1,j), 1, x(1,j), 1)
end do
return
end
subroutine mclvol( x, n, p, u, v, w,
* work, lwork, iwork, liwork,
* info)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, lwork, liwork, info
c integer iwork(liwork)
integer iwork(*)
c double precision x(n,p), u(p), v(p,p), w(p,p), work(lwork),
double precision x(n,*), u(*), v(p,*), w(p,p), work(*)
integer i, j
double precision temp, dummy, cmin, cmax
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision EPSMAX
parameter (EPSMAX = 2.2204460492503131d-16)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157D+308)
c------------------------------------------------------------------------------
c form mean
temp = one / dble(n)
call dcopy( p, zero, 0, u, 1)
do i = 1, n
call daxpy( p, temp, x(i,1), n, u, 1)
end do
c subtract mean
do j = 1, p
call daxpy( n, (-one), u(j), 0, x(1,j), 1)
end do
c if (.false.) then
c this gets the eigenvectors but x is overwritten
c get right singular vectors
c call dgesvd( 'N', 'A', n, p, x, n, u,
c * dummy, 1, w, p, work, lwork, info)
c if (info .lt. 0) return
c if (info .eq. 0) then
c lwork = int(work(1))
c do i = 1, p
c v(i,i) = w(i,i)
c if (i .gt. 1) then
c do j = 1, (i-1)
c v(i,j) = w(j,i)
c v(j,i) = w(i,j)
c end do
c end if
c end do
c goto 100
c end if
c end if
c form crossproduct
call dsyrk( 'U', 'T', p, n, one, x, n, zero, w, p)
c get eigenvectors
do j = 1, p
do i = 1, j
v(i,j) = w(i,j)
end do
end do
call dsyevd( 'V', 'U', p, v, p, u,
* work, lwork, iwork, liwork, info)
if (info .lt. 0) return
if (info .eq. 0) then
lwork = int(work(1))
liwork = iwork(1)
goto 100
end if
c EPSMAX = d1mach(4)
call dsyevx( 'V', 'A', 'U', p, w, p, dummy, dummy, i, i,
* sqrt(EPSMAX), j, u, v, p,
* work, lwork, iwork(p+1), iwork, info)
if (info .ne. 0) return
lwork = int(work(1))
liwork = -1
100 continue
c FLMAX = d1mach(2)
c form xv
c vol = one
do j = 1, p
call dgemv( 'N', n, p, one, x, n, v(1,j), 1, zero, work, 1)
cmax = -FLMAX
cmin = FLMAX
do i = 1, n
temp = work(i)
if (temp .gt. cmax) cmax = temp
if (temp .lt. cmin) cmin = temp
end do
u(j) = cmax - cmin
c vol = vol * (cmax - cmin)
end do
return
end
subroutine sgnrng( l, v, i, vmin, vmax)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
double precision v(*)
integer i, j, k, l
double precision temp, vmin, vmax
c----------------------------------------------------------------------------
temp = v(1)
vmin = temp
vmax = temp
if (l .eq. 1) return
if (i .eq. 1) then
do j = 2, l
temp = v(j)
vmin = min(vmin,temp)
vmax = max(vmax,temp)
end do
else
k = 1 + i
do j = 2, l
temp = v(k)
vmin = min(vmin,temp)
vmax = max(vmax,temp)
k = k + i
end do
end if
return
end
subroutine shapeo( TRANSP, s, O, l, m, w, info)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical TRANSP
integer l, m, info
c double precision s(l), O(l,l,m), w(l,l)
double precision s(*), O(l,l,*), w(l,*)
integer j, k
double precision temp
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
c------------------------------------------------------------------------------
if (TRANSP) then
do j = 1, l
temp = sqrt(s(j))
do k = 1, m
call dscal( l, temp, O(j,1,k), l)
end do
end do
do k = 1, m
call dsyrk( 'U', 'T', l, l, one, O(1,1,k), l, zero, w, l)
do j = 1, l
call dcopy( j, w(1,j), 1, O(1,j,k), 1)
end do
do j = 2, l
call dcopy( j-1, w(1,j), 1, O(j,1,k), l)
end do
end do
info = 0
return
end if
if (.not. TRANSP) then
do j = 1, l
temp = sqrt(s(j))
do k = 1, m
call dscal( l, temp, O(1,j,k), 1)
end do
end do
do k = 1, m
call dsyrk( 'U', 'N', l, l, one, O(1,1,k), l, zero, w, l)
do j = 1, l
call dcopy( j, w(1,j), 1, O(1,j,k), 1)
end do
do j = 2, l
call dcopy( j-1, w(1,j), 1, O(j,1,k), l)
end do
end do
info = 0
return
end if
info = -1
return
end
subroutine uncholf ( UPPER, T, l, n, info)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical UPPER
integer l, n, info
c double precision T(abs(n), abs(n))
double precision T( l , * )
integer i, j, k
double precision ddot
external ddot
c------------------------------------------------------------------------------
if (UPPER) then
do i = 2, n
do j = 1, (i-1)
T(i,j) = ddot( j, T(1,i), 1, T(1,j), 1)
end do
end do
do k = 1, n
T(k,k) = ddot( k, T(1,k), 1, T(1,k), 1)
end do
do k = 1, n-1
call dcopy( n-k, T(k+1,k), 1, T(k,k+1), l)
end do
info = 0
return
end if
if (.not. UPPER) then
do i = 2, n
do j = 1, (i-1)
T(j,i) = ddot( j, T(i,1), l, T(j,1), l)
end do
end do
do k = 1, n
T(k,k) = ddot( k, T(k,1), l, T(k,1), l)
end do
do k = 2, n
call dcopy( k-1, T(1,k), 1, T(k,1), l)
end do
return
end if
info = -1
return
end
subroutine wardsw( i, n, d)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer i, n
double precision d(*)
integer i1, n1, ii, nn, k
double precision temp
double precision FLMAX
parameter (FLMAX = 1.7976931348623157D+308)
*-----------------------------------------------------------------------------
i1 = i - 1
ii = (i1*(i1-1))/2 + 1
n1 = n - 1
nn = (n1*(n1-1))/2 + 1
c if (i .gt. 1) then
call dswap( i1, d(nn), 1, d(ii), 1)
c call dcopy( i1, FLMAX, 0, d(nn), 1)
ii = ii + i1 + i1
nn = nn + i
c end if
if (n1 .eq. i) return
k = i
100 continue
temp = d(ii)
d(ii) = d(nn)
d(nn) = temp
c d(nn) = FLMAX
ii = ii + k
nn = nn + 1
k = k + 1
if (k .lt. n1) goto 100
c d(nn) = FLMAX
return
end
subroutine es1e ( x, mu, sigsq, pro, n, G, Vinv, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, G
double precision sigsq, hood, Vinv
c double precision x(n), mu(G), pro(G[+1]), z(n,G[+1])
double precision x(*), mu(*), pro( * ), z(n, * )
integer i, k, nz
double precision temp, const, muk, prok, tmin, tmax, sum
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMAX
parameter (RTMAX = 1.340780792994260d154)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
if (sigsq .le. zero) then
hood = FLMAX
return
end if
const = pi2log + log(sigsq)
do k = 1, G
muk = mu(k)
c prok = pro(k)
do i = 1, n
temp = x(i) - muk
c z(i,k) = prok*exp(-(const+(temp*temp)/sigsq)/two)
if (sigsq .lt. one .and.
* abs(temp) .ge. sqrt(sigsq)*RTMAX) then
hood = FLMAX
return
end if
z(i,k) = -(const+(temp*temp)/sigsq)/two
end do
end do
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c temp = zero
c do k = 1, nz
c temp = temp + z(i,k)
c end do
c hood = hood + log(temp)
c call dscal( nz, (one/temp), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
return
end
subroutine hc1e ( x, n, ic, ng, ns, nd, d)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, ic(n), ng, ns, nd
c double precision x(n), d(ng*(ng-1)/2)
double precision x(*), d(*)
integer lg, ld, ll, lo, ls
integer i, j, k, m
integer ni, nj, nij, iopt, jopt, iold, jold
integer ij, ici, icj, ii, ik, jk
double precision ri, rj, rij, si, sj, sij
double precision temp, dij, dopt, dold
external wardsw
double precision one
parameter (one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
c------------------------------------------------------------------------------
iopt = 0
jopt = 0
lg = ng
ld = (ng*(ng-1))/2
ll = nd-ng
lo = nd
c call intpr( 'ic', -1, ic, n)
c call intpr( 'no. of groups', -1, lg, 1)
c group heads should be first among rows of x
i = 1
j = 2
1 continue
icj = ic(j)
if (icj .ne. j) goto 2
if (j .eq. lg) goto 3
i = j
j = j + 1
goto 1
2 continue
k = i
m = j + 1
do j = m, n
icj = ic(j)
if (icj .gt. k) then
k = k + 1
c call dswap( p, x(k,1), n, x(j,1), n)
temp = x(k)
x(k) = x(j)
x(j) = temp
ic(j) = ic(k)
ic(k) = icj
end if
end do
3 continue
c call intpr( 'ic', -1, ic, n)
do j = 1, n
i = ic(j)
if (i .ne. j) then
ic(j) = 0
ni = ic(i)
nij = ni + 1
ic(i) = nij
ri = dble(ni)
rij = dble(nij)
sj = sqrt(one/rij)
si = sqrt(ri)*sj
c update column sum in kth row
c call dscal( p, si, x(i,1), n)
c call daxpy( p, sj, x(j,1), n, x(i,1), n)
x(i) = si*x(i) + sj*x(j)
else
ic(j) = 1
end if
end do
c call intpr( 'ic', -1, ic, n)
dopt = FLMAX
ij = 0
do j = 2, lg
nj = ic(j)
rj = dble(nj)
do i = 1, (j-1)
ni = ic(i)
ri = dble(ni)
nij = ni + nj
rij = dble(nij)
si = sqrt(ri/rij)
sj = sqrt(rj/rij)
c call dcopy( p, x(i,1), n, v, 1)
c call dscal( p, sj, v, 1)
c call daxpy( p, (-si), x(j,1), n, v, 1)
c dij = ddot(p, v, 1, v, 1)
temp = sj*x(i) - si*x(j)
dij = temp*temp
ij = ij + 1
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
iopt = i
jopt = j
end if
end do
end do
c if (.false.) then
c i = 1
c ij = 1
c do j = 2, ng
c call dblepr( 'dij', -1, d(ij), i)
c ij = ij + i
c i = j
c end do
c end if
if (ns .eq. 1) then
if (iopt .lt. jopt) then
x(1) = dble(iopt)
ic(1) = jopt
else
x(1) = dble(jopt)
ic(1) = iopt
end if
d(1) = dopt
return
end if
ls = 1
100 continue
ni = ic(iopt)
nj = ic(jopt)
nij = ni + nj
ic(iopt) = nij
ic(jopt) = -iopt
if (jopt .ne. lg) then
call wardsw( jopt, lg, d)
m = ic(jopt)
ic(jopt) = ic(lg)
ic(lg) = m
end if
si = dble(ni)
sj = dble(nj)
sij = dble(nij)
dold = dopt
iold = iopt
jold = jopt
iopt = -1
jopt = -1
dopt = FLMAX
lg = lg - 1
ld = ld - lg
ii = (iold*(iold-1))/2
if (iold .gt. 1) then
ik = ii - iold + 1
do j = 1, (iold - 1)
nj = ic(j)
rj = dble(nj)
ik = ik + 1
jk = ld + j
dij = (rj+si)*d(ik)+(rj+sj)*d(jk)
dij = (dij-rj*dold)/(rj+sij)
d(ik) = dij
end do
end if
if (iold .lt. lg) then
ik = ii + iold
i = iold
do j = (iold + 1), lg
nj = ic(j)
rj = dble(nj)
jk = ld + j
dij = (rj+si)*d(ik)+(rj+sj)*d(jk)
dij = (dij-rj*dold)/(rj+sij)
d(ik) = dij
ik = ik + i
i = j
end do
end if
d(lo) = dold
lo = lo - 1
d(lo) = dble(iold)
lo = lo - 1
d(lo) = dble(jold)
lo = lo - 1
c update d and find max
jopt = 2
iopt = 1
dopt = d(1)
if (lg .eq. 2) goto 900
ij = 1
do i = 2, ld
si = d(i)
if (si .le. dopt) then
ij = i
dopt = si
end if
end do
if (ij .gt. 1) then
do i = 2, ij
iopt = iopt + 1
if (iopt .ge. jopt) then
jopt = jopt + 1
iopt = 1
end if
end do
end if
ls = ls + 1
if (ls .eq. ns) goto 900
goto 100
900 continue
d(lo) = dopt
lo = lo - 1
d(lo) = dble(iopt)
lo = lo - 1
d(lo) = dble(jopt)
do i = 1, ng
ic(i) = i
end do
lo = nd - 1
ld = lo
si = d(lo)
lo = lo - 1
sj = d(lo)
ic(int(sj)) = ng
if (si .lt. sj) then
x(1) = si
d(ld) = sj
else
x(1) = sj
d(ld) = si
end if
ld = ld - 1
lg = ng + 1
do k = 2, ns
lo = lo - 1
d(ld) = d(lo)
ld = ld - 1
lo = lo - 1
i = int(d(lo))
ici = ic(i)
lo = lo - 1
j = int(d(lo))
icj = ic(j)
if (ici .gt. icj) ic(i) = icj
ic(j) = ic(lg-k)
if (ici .lt. icj) then
x(k) = dble(ici)
d(ld) = dble(icj)
else
x(k) = dble(icj)
d(ld) = dble(ici)
end if
ld = ld - 1
end do
ld = nd
lo = nd - 1
do k = 1, ns
ic(k) = int(d(lo))
lo = lo - 1
ld = ld - 1
d(ld) = d(lo)
lo = lo - 1
end do
ld = nd
lo = 1
do k = 1, ns
si = d(lo)
d(lo) = d(ld)
d(ld) = si
ld = ld - 1
lo = lo + 1
end do
return
end
subroutine me1e ( EQPRO, x, n, G, Vinv, z, maxi, tol, eps,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, G, maxi
double precision Vinv, eps, tol
c double precision x(n), z(n,G[+1]), mu(G), sigsq, pro(G[+1])
double precision x(*), z(n, * ), mu(*), sigsq, pro( * )
integer nz, iter, k, i
double precision hold, hood, err, prok, tmin, tmax, ViLog
double precision const, sum, sumz, smu, temp, term, zsum
double precision rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( nz, one/dble(nz), 0, pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
sumz = zero
sigsq = zero
zsum = one
do k = 1, G
sum = zero
smu = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
smu = smu + temp*x(i)
end do
sumz = sumz + sum
if (.not. EQPRO) pro(k) = sum / dble(n)
zsum = min(sum,zsum)
if (sum .gt. rteps) then
smu = smu / sum
mu(k) = smu
do i = 1, n
temp = x(i) - smu
temp = temp*temp
sigsq = sigsq + z(i,k)*temp
z(i,k) = temp
end do
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
if (Vinv .le. zero) then
sigsq = sigsq / dble(n)
else
sigsq = sigsq / sumz
end if
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
if (sigsq .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
const = pi2log + log(sigsq)
do k = 1, G
c temp = pro(k)
do i = 1, n
c z(i,k) = temp*exp(-(const+(z(i,k)/sigsq))/two)
z(i,k) = -(const+(z(i,k)/sigsq))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine me1ep ( EQPRO, x, n, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, G, maxi
double precision pshrnk, pmu, pscale, pdof
double precision Vinv, eps, tol
c double precision x(n), z(n,G[+1]), mu(G), sigsq, pro(G[+1])
double precision x(*), z(n, * ), mu(*), sigsq, pro( * )
integer nz, iter, k, i
double precision hold, hood, err, prok, tmin, tmax, ViLog
double precision const, sum, sumz, smu, temp, term, zsum
double precision pmupmu, cgam, cmu, rmu, rgam, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision dlngam
external dlngam
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( nz, one/dble(nz), 0, pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
pmupmu = pmu*pmu
iter = 0
100 continue
iter = iter + 1
sigsq = zero
zsum = one
do k = 1, G
sumz = zero
smu = zero
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
smu = smu + temp*x(i)
end do
if (.not. EQPRO) pro(k) = sumz / dble(n)
zsum = min(zsum,sumz)
if (sumz .gt. rteps) then
smu = smu/sumz
sum = zero
do i = 1, n
term = x(i) - smu
term = term*term
sum = sum + z(i,k)*term
end do
term = (pshrnk*sumz)/(pshrnk+sumz)
temp = (pmupmu + smu*smu) - two*pmu*smu
sigsq = sigsq + sum + term*temp
term = sumz/(pshrnk+sumz)
temp = pshrnk/(pshrnk+sumz)
mu(k) = term*smu + temp*pmu
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
sigsq = (pscale + sigsq)/(pdof + dble(n+G) + two)
c if (Vinv .le. zero) then
c sigsq = sigsq / dble(n)
c else
c sigsq = sigsq / sumz
c end if
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
if (sigsq .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
const = pi2log + log(sigsq)
do k = 1, G
c temp = pro(k)
do i = 1, n
term = x(i) - mu(k)
z(i,k) = -(const+((term*term)/sigsq))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
cmu = dble(G)*(pi2log-log(pshrnk))/two
sum = zero
do k = 1, G
temp = pmu - mu(k)
temp = temp*temp
sum = sum - (pshrnk/sigsq)*temp
end do
term = log(sigsq)
rmu = (sum - dble(G)*term)/two
temp = pdof/two
cgam = temp*log(pscale/two) - dlngam(temp)
rgam = -(temp+one)*term - (pscale/sigsq)/two
pdof = (cmu+cgam) + (rmu+rgam)
return
end
subroutine ms1e ( x, z, n, G, mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, G
c double precision x(n), z(n,G), mu(G), sigsq, pro(G)
double precision x(*), z(n,*), mu(*), sigsq, pro(*)
integer i, k
double precision sum, smu, sumz, temp
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
c------------------------------------------------------------------------------
sumz = zero
sigsq = zero
do k = 1, G
sum = zero
smu = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
smu = smu + temp*x(i)
end do
sumz = sumz + sum
pro(k) = sum / dble(n)
if (sigsq .gt. one .or. smu .le. sum*FLMAX) then
smu = smu / sum
mu(k) = smu
if (sigsq .ne. FLMAX) then
do i = 1, n
temp = abs(x(i) - smu)
sigsq = sigsq + z(i,k)*(temp*temp)
end do
end if
else
mu(k) = FLMAX
sigsq = FLMAX
end if
end do
c sumz .eq. n when no noise
if (sigsq .ne. FLMAX) sigsq = sigsq / sumz
return
end
subroutine ms1ep ( x, z, n, G,
* pshrnk, pmu, pscale, pdof,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, G
double precision pshrnk, pmu, pscale, pdof
c double precision x(n), z(n,G), mu(G), sigsq, pro(G)
double precision x(*), z(n,*), mu(*), sigsq, pro(*)
integer k, i
double precision pmupmu
double precision sum, sumz, smu, temp, term
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
pmupmu = pmu*pmu
sigsq = zero
do k = 1, G
sumz = zero
smu = zero
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
smu = smu + temp*x(i)
end do
pro(k) = sumz / dble(n)
if (sumz .gt. one .or. smu .lt. sumz*FLMAX) then
smu = smu/sumz
sum = zero
term = sumz/(pshrnk+sumz)
temp = pshrnk/(pshrnk+sumz)
mu(k) = term*smu + temp*pmu
if (sigsq .ne. FLMAX) then
do i = 1, n
term = abs(x(i) - smu)
sum = sum + z(i,k)*(term*term)
end do
term = (pshrnk*sumz)/(pshrnk+sumz)
temp = (pmupmu + smu*smu) - two*pmu*smu
sigsq = sigsq + sum + term*temp
end if
else
mu(k) = FLMAX
sigsq = FLMAX
end if
end do
if (sigsq .ne. FLMAX) then
temp = pdof + dble(n) + two
if (pshrnk .gt. zero) temp = temp + dble(G)
sigsq = (pscale + sigsq)/temp
end if
return
end
subroutine eseee ( CHOL, x, mu, Sigma, pro, n, p, G, Vinv,
* w, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c character CHOL
logical CHOL
c integer n, p, G
integer n, p, G
double precision hood, Vinv
c double precision x(n,p), w(p), z(n,G[+1])
double precision x(n,*), w(*), z(n, * )
c double precision mu(p,G), Sigma(p,p), pro(G[+1])
double precision mu(p,*), Sigma(p,*), pro( * )
integer info, i, j, k, nz
double precision detlog, prok, tmin, tmax
double precision umin, umax, const, temp, sum
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMAX
parameter (RTMAX = 1.340780792994260d154)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
c if (CHOL .eq. 'N') then
if (.not. CHOL) then
c Cholesky factorization
call dpotrf( 'U', p, Sigma, p, info)
if (info .ne. 0) then
w(1) = dble(info)
hood = FLMAX
return
end if
end if
call absrng( p, Sigma, (p+1), umin, umax)
c rc = umin/(one+umax)
if (umax .le. one .and. umax .ge. umin*RTMAX) then
w(1) = zero
hood = FLMAX
return
end if
if (umax .ge. one .and. umin .le. umax*RTMIN) then
w(1) = zero
hood = FLMAX
return
end if
detlog = zero
do j = 1, p
detlog = detlog + log(abs(Sigma(j,j)))
end do
const = dble(p)*pi2log/two + detlog
do k = 1, G
c prok = pro(k)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dtrsv( 'U', 'T', 'N', p, Sigma, p, w, 1)
temp = ddot( p, w, 1, w, 1)/two
c z(i,k) = prok*exp(-(const+temp))
z(i,k) = -(const+temp)
end do
end do
w(1) = zero
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c sum = zero
c do k = 1, nz
c sum = sum + z(i,k)
c end do
c hood = hood + log(sum)
c call dscal( nz, (one/sum), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
w(1) = zero
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
w(1) = zero
return
end
double precision function detmc2( n, u)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer k, n
double precision q
double precision u(n,*)
double precision zero, two
parameter (zero = 0.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
detmc2 = zero
do k = 1, n
q = u(k,k)
if (q .eq. zero) then
detmc2 = -FLMAX
return
end if
detmc2 = detmc2 + log(abs(q))
end do
detmc2 = two*detmc2
return
end
subroutine meeee ( EQPRO, x, n, p, G, Vinv, z, maxi, tol, eps,
* mu, U, pro, w)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
double precision Vinv, eps, tol
c double precision x(n,p), z(n,G), w(p)
double precision x(n,*), z(n,*), w(*)
c double precision mu(p,G), U(p,p), pro(G)
double precision mu(p,*), U(p,*), pro(*)
integer nz, p1, iter, i, j, k, j1
double precision piterm, sclfac, sumz, sum, zsum
double precision cs, sn, umin, umax, rc, detlog, rteps
double precision const, hold, hood, err, temp, term
double precision prok, tmin, tmax, ViLog
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
piterm = dble(p)*pi2log/two
p1 = p + 1
eps = max(eps,zero)
rteps = sqrt(eps)
tol = max(tol,zero)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
c zero out the lower triangle
i = 1
do j = 2, p
call dcopy( p-i, zero, 0, U(j,i), 1)
i = j
end do
iter = 0
100 continue
iter = iter + 1
do j = 1, p
call dcopy( j, zero, 0, U(1,j), 1)
end do
sumz = zero
zsum = one
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
sum = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
if (.not. EQPRO) pro(k) = sum / dble(n)
zsum = min(zsum,sum)
if (sum .gt. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( U(j,j), w(j), cs, sn)
call drot( p-j, U(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( U(p,p), w(p), cs, sn)
end do
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
hood = eps
maxi = iter
return
end if
if (Vinv .le. zero) then
sclfac = one/sqrt(dble(n))
else
sclfac = one/sqrt(sumz)
end if
do j = 1, p
call dscal( j, sclfac, U(1,j), 1)
end do
c condition number
call absrng( p, U, p1, umin, umax)
rc = umin/(one+umax)
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
if (rc .le. rteps) then
tol = err
eps = FLMAX
hood = eps
maxi = iter
return
end if
detlog = zero
do j = 1, p
detlog = detlog + log(abs(U(j,j)))
end do
const = piterm + detlog
do k = 1, G
c temp = pro(k)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dtrsv( 'U', 'T', 'N', p, U, p, w, 1)
sum = ddot( p, w, 1, w, 1)/two
c z(i,k) = temp * exp(-(const+sum))
z(i,k) = -(const+sum)
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine meeeep( EQPRO, x, n, p, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps,
* mu, U, pro, w)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
double precision Vinv, eps, tol
c double precision pshrnk, pmu(p), pscale(p,p), pdof
double precision pshrnk, pmu(*), pscale(p,*), pdof
c double precision x(n,p), z(n,G), w(p)
double precision x(n,*), z(n,*), w(*)
c double precision mu(p,G), U(p,p), pro(G)
double precision mu(p,*), U(p,*), pro(*)
integer nz, p1, iter, i, j, k, j1
double precision piterm, sclfac, sumz, sum, zsum
double precision cs, sn, umin, umax, rc, detlog, rteps
double precision const, hold, hood, err, temp, term
double precision prok, tmin, tmax, ViLog
double precision cmu, cgam, rmu, rgam
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision twolog
parameter (twolog = 0.6931471805599453d0)
double precision pilog
parameter (pilog = 1.144729885849400d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision ddot, dlngam
external ddot, dlngam
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
piterm = dble(p)*pi2log/two
p1 = p + 1
sclfac = one/sqrt(dble(n))
eps = max(eps,zero)
rteps = sqrt(eps)
tol = max(tol,zero)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
c copy pscale to U
do j = 1, p
call dcopy( p, pscale(1,j), 1, U(1,j), 1)
end do
sumz = zero
zsum = one
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
if (.not. EQPRO) pro(k) = sum / dble(n)
zsum = min(zsum,sum)
if (sum .gt. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( U(j,j), w(j), cs, sn)
call drot( p-j, U(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( U(p,p), w(p), cs, sn)
end do
call dcopy( p, pmu, 1, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
const = sum + pshrnk
temp = (sum*pshrnk)/const
call dscal( p, sqrt(temp), w, 1)
j = 1
do j1 = 2, p
call drotg( U(j,j), w(j), cs, sn)
call drot( p-j, U(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( U(p,p), w(p), cs, sn)
call dscal( p, sum/const, mu(1,k), 1)
call daxpy( p, pshrnk/const, pmu, 1, mu(1,k), 1)
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
term = pdof + dble(p) + one
if (pshrnk .gt. zero) term = term + dble(G)
if (Vinv .le. zero) then
sclfac = one/sqrt(term+dble(n))
else
sclfac = one/sqrt(term+dble(sumz))
end if
do j = 1, p
call dscal( j, sclfac, U(1,j), 1)
end do
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
c condition number
call absrng( p, U, p1, umin, umax)
rc = umin/(one+umax)
if (rc .le. rteps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
detlog = zero
do j = 1, p
detlog = detlog + log(abs(U(j,j)))
end do
const = piterm + detlog
do k = 1, G
c temp = pro(k)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dtrsv( 'U', 'T', 'N', p, U, p, w, 1)
sum = ddot( p, w, 1, w, 1)/two
c z(i,k) = temp * exp(-(const+sum))
z(i,k) = -(const+sum)
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
if (pshrnk .gt. zero) then
cmu = dble(p)*(log(pshrnk) - pi2log)/two
rmu = zero
do k = 1, G
call daxpy( p, (-one), mu(1,k), 1, pmu, 1)
call dtrsv('U','T','N',p,U,p,pmu,1)
rmu = rmu + ddot( p, pmu, 1, pmu, 1)
end do
sum = zero
term = zero
temp = zero
do j = 1, p
call dcopy( p, pscale(j,1), p, pmu, 1)
c call dtrsv('U','T','N', p, U, p, pmu, 1)
i = p-j+1
c call dtrsv('U','T','N', i, U(j,j),i,pmu(j),1)
call dtrsv('U','T','N', i, U(j,j),p,pmu(j),1)
sum = sum + ddot(i, pmu(j), 1, pmu(j), 1)
temp = temp + log(abs(pscale(j,j)))
term = term + dlngam((pdof+one-dble(j))/two)
end do
rmu = -(detlog+pshrnk*rmu/two)
const = -dble(p)*(pdof*twolog+(dble(p)-one)*pilog/two)
cgam = (const/two-pdof*temp) - term
rgam = -((pdof+dble(p)+one)*detlog + sum/two)
pdof = (dble(G)*cmu+rmu) + (cgam+rgam)
else
pdof = FLMAX
end if
return
end
subroutine mseee ( x, z, n, p, G, w, mu, U, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision x(n,p), z(n,G), w(p)
double precision x(n,*), z(n,*), w(*)
c double precision mu(p,G), U(p,p), pro(G)
double precision mu(p,*), U(p,*), pro(*)
c------------------------------------------------------------------------------
c
c x double (input) (n,p) matrix of observations.
c z double (input) (n,G) conditional probabilities.
c n integer (input) number of observations.
c p integer (input) dimension of the data.
c G integer (input) number of Gaussian clusters in the mixture.
c w double (scratch) (p)
c mu double (output) (p,G) mean for each group.
c U double (output) (p,p) upper triangular Cholesky factor of the
c common covariance matrix for the groups: transpose(U) * U = Sigma.
c pro double (output) (G) mixing proportions (ignore result if equal).
integer i, j, k, j1
double precision sum, sumz, zsum, temp, cs, sn
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
c------------------------------------------------------------------------------
do j = 1, p
call dcopy( p, zero, 0, U(1,j), 1)
end do
sumz = zero
zsum = one
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
pro(k) = sum / dble(n)
if (sum .gt. one .or. one .gt. sum*FLMAX) then
zsum = min(zsum,sum)
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( U(j,j), w(j), cs, sn)
call drot( p-j, U(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( U(p,p), w(p), cs, sn)
end do
else
zsum = zero
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (zsum .eq. zero) return
c sumz .eq. n when no noise
do j = 1, p
call dscal( j, one/sqrt(sumz), U(1,j), 1)
end do
return
end
subroutine mseeep( x, z, n, p, G,
* pshrnk, pmu, pscale, pdof,
* w, mu, U, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision x(n,p), z(n,G), w(p)
double precision x(n,*), z(n,*), w(*)
c double precision pshrnk, pmu(p), pscale(p,p), pdof
double precision pshrnk, pmu(*), pscale(p,*), pdof
c double precision mu(p,G), U(p,p), pro(G)
double precision mu(p,*), U(p,*), pro(*)
integer i, j, k, j1
double precision sclfac, const, temp
double precision sum, sumz, zsum, cs, sn
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
c------------------------------------------------------------------------------
if (pshrnk .le. zero) pshrnk = zero
do j = 1, p
call dcopy( p, pscale(1,j), 1, U(1,j), 1)
end do
sumz = zero
zsum = one
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
pro(k) = sum / dble(n)
if (sum .ge. one .or. one .gt. sum*FLMAX) then
zsum = min(zsum,sum)
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( U(j,j), w(j), cs, sn)
call drot( p-j, U(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( U(p,p), w(p), cs, sn)
end do
call dcopy( p, pmu, 1, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
const = sum + pshrnk
temp = (sum*pshrnk)/const
call dscal( p, sqrt(temp), w, 1)
j = 1
do j1 = 2, p
call drotg( U(j,j), w(j), cs, sn)
call drot( p-j, U(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( U(p,p), w(p), cs, sn)
call dscal( p, sum/const, mu(1,k), 1)
call daxpy( p, pshrnk/const, pmu, 1, mu(1,k), 1)
else
zsum = zero
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (zsum .eq. zero) return
temp = pdof+dble(n+p+1)
if (pshrnk .gt. zero) temp = temp + dble(G)
sclfac = one/sqrt(temp)
do j = 1, p
call dscal( j, sclfac, U(1,j), 1)
end do
return
end
subroutine eseei ( x, mu, scale, shape, pro, n, p, G,
* Vinv, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
double precision scale, hood, Vinv
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), shape(p), pro(G[+1])
double precision mu(p,*), shape(*), pro( * )
integer i, j, k, nz
double precision sum, temp, const, tmin, tmax
double precision smin, smax, prok
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
if (scale .le. zero) then
hood = FLMAX
return
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
hood = FLMAX
return
end if
temp = sqrt(scale)
do j = 1, p
shape(j) = temp*sqrt(shape(j))
end do
const = dble(p)*(pi2log+log(scale))
do k = 1, G
c prok = pro(k)
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
if (abs(temp) .ge. shape(j)*FLMAX) then
hood = FLMAX
return
end if
temp = temp/shape(j)
if (abs(temp) .gt. RTMIN) sum = sum + temp*temp
end do
c z(i,k) = prok*exp(-(const+sum)/two)
z(i,k) = -(const+sum)/two
end do
end do
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c sum = zero
c do k = 1, nz
c sum = sum + z(i,k)
c end do
c hood = hood + log(sum)
c call dscal( nz, (one/sum), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
return
end
subroutine meeei ( EQPRO, x, n, p, G, Vinv, z, maxi, tol, eps,
* mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
double precision Vinv, eps, tol, scale
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), shape(p), pro(G[+1])
double precision mu(p,*), shape(*), pro( * )
integer nz, iter, i, j, k
double precision sum, sumz, temp, term, zsum
double precision const, hold, hood, err, smin, smax
double precision prok, tmin, tmax, ViLog, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
call dcopy( p, zero, 0, shape, 1)
sumz = zero
zsum = one
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
sum = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
z(i,k) = sqrt(temp)
end do
sumz = sumz + sum
if (.not. EQPRO) pro(k) = sum/dble(n)
zsum = min(zsum,sum)
if (sum .gt. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
do j = 1, p
sum = zero
do i = 1, n
temp = z(i,k)*(x(i,j) - mu(j,k))
sum = sum + temp*temp
end do
shape(j) = shape(j) + sum
end do
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. zero) then
scale = zero
tol = err
eps = FLMAX
maxi = iter
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
scale = FLMAX
tol = err
eps = FLMAX
maxi = iter
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (Vinv .le. zero) then
scale = temp/dble(n)
else
scale = temp/sumz
end if
if (temp .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
call dscal( p, one/temp, shape, 1)
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. eps .or. scale .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
const = dble(p)*(pi2log+log(scale))
do k = 1, G
c prok = pro(k)
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + (temp*temp)/shape(j)
end do
c z(i,k) = prok*exp(-(const+(sum/scale))/two)
z(i,k) = -(const+(sum/scale))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine meeeip( EQPRO, x, n, p, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps,
* mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
double precision Vinv, eps, tol, scale
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), shape(p), pro(G[+1])
double precision mu(p,*), shape(*), pro( * )
integer nz, iter, i, j, k
double precision sum, sumz, temp, term, zsum
double precision const, hold, hood, err, smin, smax
double precision prok, tmin, tmax, ViLog, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
call dcopy( p, pscale, 0, shape, 1)
sumz = zero
zsum = one
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
z(i,k) = sqrt(temp)
end do
sumz = sumz + sum
if (.not. EQPRO) pro(k) = sum/dble(n)
zsum = min(zsum,sum)
if (sum .gt. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
term = pshrnk + sum
const = (pshrnk*sum)/term
do j = 1, p
sum = zero
do i = 1, n
temp = z(i,k)*(x(i,j) - mu(j,k))
sum = sum + (temp*temp)
end do
shape(j) = shape(j) + sum
temp = pmu(j) - mu(j,k)
shape(j) = shape(j) + const*(temp*temp)
end do
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. zero) then
scale = zero
tol = err
eps = FLMAX
maxi = iter
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
scale = FLMAX
tol = err
eps = FLMAX
maxi = iter
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
term = pdof + one
if (pshrnk .gt. zero) term = term + one
if (Vinv .le. zero) then
scale = temp/(term + dble(n))
else
scale = temp/(term + sumz)
end if
if (temp .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
call dscal( p, one/temp, shape, 1)
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. eps .or. scale .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
const = dble(p)*(pi2log+log(scale))
do k = 1, G
c prok = pro(k)
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + (temp*temp)/shape(j)
end do
c z(i,k) = prok*exp(-(const+(sum/scale))/two)
z(i,k) = -(const+(sum/scale))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine mseei ( x, z, n, p, G, mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision x(n,p), z(n,G)
double precision x(n,*), z(n,*)
c double precision mu(p,G), scale, shape(p), pro(G)
double precision mu(p,*), scale, shape(*), pro(*)
integer i, j, k
double precision sum, sumz, temp, smin, smax
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
sumz = zero
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
z(i,k) = sqrt(temp)
end do
sumz = sumz + sum
pro(k) = sum/dble(n)
if (sum .gt. one .or. one .lt. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
else
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
call dcopy( p, zero, 0, shape, 1)
do j = 1, p
sum = zero
do i = 1, n
do k = 1, G
if (mu(1,k) .eq. FLMAX) then
scale = FLMAX
return
end if
temp = z(i,k)*(x(i,j) - mu(j,k))
if (abs(temp) .gt. RTMIN) sum = sum + temp*temp
end do
end do
shape(j) = shape(j) + sum
end do
call sgnrng(p, shape, 1, smin, smax)
if (smin .eq. zero) then
scale = zero
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (sumz .lt. one .and. temp .ge. sumz*FLMAX) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
scale = temp/sumz
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
call dscal( p, one/temp, shape, 1)
return
end
subroutine mseeip( x, z, n, p, G,
* pshrnk, pmu, pscale, pdof,
* mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
c double precision x(n,p), z(n,G)
double precision x(n,*), z(n,*)
c double precision mu(p,G), scale, shape(p), pro(G[+1])
double precision mu(p,*), scale, shape(*), pro( * )
integer i, j, k
double precision sum, sumz, temp, term
double precision const, smin, smax
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
call dcopy( p, pscale, 0, shape, 1)
sumz = zero
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
z(i,k) = sqrt(temp)
end do
sumz = sumz + sum
pro(k) = sum/dble(n)
if (sum .gt. one .or. one .lt. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
term = pshrnk + sum
const = (pshrnk*sum)/term
do j = 1, p
sum = zero
do i = 1, n
temp = z(i,k)*(x(i,j) - mu(j,k))
if (abs(temp) .gt. RTMIN) sum = sum + temp*temp
end do
shape(j) = shape(j) + sum
temp = pmu(j) - mu(j,k)
shape(j) = shape(j) + const*(temp*temp)
end do
else
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
call sgnrng(p, shape, 1, smin, smax)
if (smin .eq. zero) then
scale = zero
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .ge. BIGLOG) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
if (temp .gt. SMALOG) then
smin = exp(temp)
else
smin = zero
end if
term = pdof + sumz + two
if (pshrnk .gt. zero) term = term + dble(G)
scale = smin/term
if (smin .lt. one .and. one .ge. smin*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
call dscal( p, one/smin, shape, 1)
return
end
subroutine eseev ( x, mu, scale, shape, O, pro, n, p, G,
* Vinv, v, w, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n, p, G
integer n, p, G
double precision scale, Vinv, hood
c double precision x(n,p), v(p), w(p), z(n,G[+1])
double precision x(n,*), v(*), w(*), z(n, * )
c double precision mu(p,G), shape(p), O(p,p,G), pro(G[+1])
double precision mu(p,*), shape(*), O(p,p,*), pro( * )
integer i, j, k, nz
double precision const, temp, tmin, tmax
double precision smin, smax, prok, sum
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
if (scale .le. zero) then
hood = FLMAX
return
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
hood = FLMAX
return
end if
temp = sqrt(scale)
do j = 1, p
shape(j) = temp*sqrt(shape(j))
end do
const = dble(p)*(pi2log + log(scale))
do k = 1, G
c prok = pro(k)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dgemv( 'N', p, p, one, O(1,1,k), p,
* w, 1, zero, v, 1)
do j = 1, p
if (shape(j) .lt. one .and.
* abs(v(j)) .ge. shape(j)*FLMAX) then
hood = FLMAX
return
end if
v(j) = v(j)/shape(j)
end do
temp = ddot( p, v, 1, v, 1)
c z(i,k) = prok*exp(-(const+temp)/two)
z(i,k) = -(const+temp)/two
end do
end do
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c sum = zero
c do k = 1, nz
c sum = sum + z(i,k)
c end do
c hood = hood + log(sum)
c call dscal( nz, (one/sum), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
return
end
subroutine meeev ( EQPRO, x, n, p, G, Vinv, z, maxi, tol, eps,
* lwork, mu, scale, shape, O, pro, w, s)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi, lwork
double precision Vinv, eps, tol, scale
double precision x(n,*), z(n, * ), w( * ), s(*)
double precision mu(p,*), shape(*), O(p,p,*), pro( * )
integer nz, p1, iter, i, j, k, l, j1, info
double precision dnp, dummy, temp, term, rteps
double precision sumz, sum, smin, smax, cs, sn
double precision const, rc, hood, hold, err
double precision prok, tmin, tmax, ViLog, zsum
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
p1 = p + 1
dnp = dble(n*p)
eps = max(eps,zero)
rteps = sqrt(eps)
tol = max(tol,zero)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
call dcopy( p, zero, 0, shape, 1)
sumz = zero
zsum = one
l = 0
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
do j = 1, p
call dcopy( p, zero, 0, O(1,j,k), 1)
end do
sum = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
zsum = min(zsum,sum)
if (.not. EQPRO) pro(k) = sum / dble(n)
if (sum .ge. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
end do
call dgesvd( 'N', 'O', p, p, O(1,1,k), p, s,
* dummy, 1, dummy, 1, w, lwork, info)
if (info .ne. 0) then
l = info
else
do j = 1, p
temp = s(j)
shape(j) = shape(j) + temp*temp
end do
end if
end if
end do
if (l .ne. 0 .or. zsum .lt. rteps) then
lwork = l
c w(1) = FLMAX
tol = err
if (l .ne. 0) then
eps = FLMAX
else
eps = -FLMAX
end if
maxi = iter
return
end if
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
lwork = 0
c w(1) = smin
tol = err
eps = FLMAX
maxi = iter
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
tol = err
eps = FLMAX
maxi = iter
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (Vinv .le. zero) then
scale = temp/dble(n)
else
scale = temp/sumz
end if
if (temp .le. eps) then
lwork = 0
c w(1) = temp
tol = err
eps = FLMAX
maxi = iter
return
end if
call dscal( p, one/temp, shape, 1)
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. eps) then
lwork = 0
c w(1) = -smin
tol = err
eps = FLMAX
maxi = iter
return
end if
if (scale .le. eps) then
c w(1) = -scale
lwork = 0
tol = err
eps = FLMAX
maxi = iter
return
end if
temp = sqrt(scale)
do j = 1, p
w(j) = temp*sqrt(shape(j))
end do
call absrng( p, w, 1, smin, smax)
rc = smin / (one + smax)
if (smin .le. rteps) then
c w(1) = -smin
lwork = 0
tol = err
eps = FLMAX
maxi = iter
return
end if
const = dble(p)*(pi2log + log(scale))/two
do k = 1, G
c temp = pro(k)
do i = 1, n
call dcopy( p, x(i,1), n, w(p1), 1)
call daxpy( p, (-one), mu(1,k), 1, w(p1), 1)
call dgemv( 'N', p, p, one, O(1,1,k), p, w(p1), 1, zero, s, 1)
do j = 1, p
s(j) = s(j) / w(j)
end do
sum = ddot( p, s, 1, s, 1)/two
c z(i,k) = temp*exp(-(const+sum))
z(i,k) = -(const+sum)
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
lwork = 0
c w(1) = rc
tol = err
eps = hood
maxi = iter
return
end
subroutine meeevp( EQPRO, x, n, p, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps,
* lwork, mu, scale, shape, O, pro, w, s)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi, lwork
c double precision pshrnk, pmu(p), pscale(p,p), pdof
double precision pshrnk, pmu(*), pscale(p,*), pdof
double precision Vinv, eps, tol, scale
c double precision x(n,p), z(n,G[+1]), w(lwork), s(p)
double precision x(n,*), z(n, * ), w( * ), s(*)
c double precision mu(p,G), shape(p), O(p,p,G), pro(G[+1])
double precision mu(p,*), shape(*), O(p,p,*), pro( * )
integer nz, p1, iter, i, j, k, l, j1, info
double precision dnp, dummy, temp, term, rteps
double precision sumz, sum, smin, smax, cs, sn
double precision const, rc, hood, hold, err
double precision prok, tmin, tmax, ViLog, zsum
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
p1 = p + 1
dnp = dble(n*p)
eps = max(eps,zero)
rteps = sqrt(eps)
tol = max(tol,zero)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
call dcopy( p, zero, 0, shape, 1)
zsum = one
sumz = zero
l = 0
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
do j = 1, p
call dcopy( p, pscale(1,j), 1, O(1,j,k), 1)
end do
sum = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
if (.not. EQPRO) pro(k) = sum / dble(n)
zsum = min(zsum,sum)
if (sum .gt. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
end do
call dcopy( p, pmu, 1, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
term = sum+pshrnk
const = (sum*pshrnk)/term
call dscal( p, sqrt(const), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
call dscal( p, sum/term, mu(1,k), 1)
call daxpy( p, pshrnk/term, pmu, 1, mu(1,k), 1)
call dgesvd( 'N', 'O', p, p, O(1,1,k), p, s,
* dummy, 1, dummy, 1, w, lwork, info)
if (info .ne. 0) then
l = info
else
do j = 1, p
temp = s(j)
shape(j) = shape(j) + temp*temp
end do
end if
end if
end do
if (l .ne. 0 .or. zsum .le. rteps) then
lwork = l
c w(1) = FLMAX
tol = err
if (l .ne. 0) then
eps = FLMAX
else
eps = -FLMAX
end if
maxi = iter
return
end if
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .eq. zero) then
c w(1) = smin
tol = err
eps = FLMAX
maxi = iter
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
tol = err
eps = FLMAX
maxi = iter
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
term = pdof + dble(p) + one
if (pshrnk .gt. zero) term = term + one
if (Vinv .le. zero) then
scale = temp/(term + dble(n))
else
scale = temp/(term + sumz)
end if
if (temp .le. eps) then
c w(1) = temp
tol = err
eps = FLMAX
maxi = iter
return
end if
call dscal( p, one/temp, shape, 1)
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. eps) then
c w(1) = -smin
tol = err
eps = FLMAX
maxi = iter
return
end if
if (scale .le. eps) then
c w(1) = -scale
tol = err
eps = FLMAX
maxi = iter
return
end if
temp = sqrt(scale)
do j = 1, p
w(j) = temp*sqrt(shape(j))
end do
call sgnrng( p, w, 1, smin, smax)
rc = smin / (one + smax)
if (smin .le. rteps) then
c w(1) = -smin
tol = err
eps = FLMAX
maxi = iter
return
end if
const = dble(p)*(pi2log + log(scale))/two
do k = 1, G
c temp = pro(k)
do i = 1, n
call dcopy( p, x(i,1), n, w(p1), 1)
call daxpy( p, (-one), mu(1,k), 1, w(p1), 1)
call dgemv( 'N', p, p, one, O(1,1,k), p, w(p1), 1, zero, s, 1)
do j = 1, p
s(j) = s(j) / w(j)
end do
sum = ddot( p, s, 1, s, 1)/two
c z(i,k) = temp*exp(-(const+sum))
z(i,k) = -(const+sum)
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
lwork = 0
c w(1) = rc
tol = err
eps = hood
maxi = iter
return
end
subroutine mseev ( x, z, n, p, G, w, lwork,
* mu, scale, shape, O, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G, lwork
double precision scale
c double precision x(n,p), z(n,G), w(lwork)
double precision x(n,*), z(n,*), w( * )
c double precision shape(p), O(p,p,G), mu(p,G), pro(G)
double precision shape(*), O(p,p,*), mu(p,*), pro(*)
integer i, j, k, j1, l, info
double precision dummy, sum, sumz, temp
double precision cs, sn, smin, smax
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision BIGLOG
parameter (BIGLOG = 709.d0)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
call dcopy( p, zero, 0, shape, 1)
l = 0
sumz = zero
scale = zero
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
do j = 1, p
call dcopy( p, zero, 0, O(1,j,k), 1)
end do
sum = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
pro(k) = sum / dble(n)
if (sum .ge. one .or. one .lt. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
end do
call dgesvd( 'N', 'O', p, p, O(1,1,k), p, z(1,k),
* dummy, 1, dummy, 1, w, lwork, info)
if (info .ne. 0) then
l = info
else if (scale .ne. FLMAX) then
do j = 1, p
temp = z(j,k)
shape(j) = shape(j) + temp*temp
end do
end if
else
scale = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (scale .eq. FLMAX .or. l .ne. 0) then
lwork = l
if (l .ne. 0) then
scale = FLMAX
else
scale = -FLMAX
end if
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
lwork = 0
call sgnrng( p, shape, 1, smin, smax)
if (smin .eq. zero) then
scale = FLMAX
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (temp .ge. sumz*FLMAX) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
scale = temp/sumz
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
call dscal( p, one/temp, shape, 1)
return
end
subroutine mseevp( x, z, n, p, G,
* pshrnk, pmu, pscale, pdof,
* w, lwork, mu, scale, shape, O, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G, lwork
c double precision pshrnk, pmu(p), pscale(p,p), pdof
double precision pshrnk, pmu(*), pscale(p,*), pdof
double precision scale
c double precision x(n,p), z(n,G), w(lwork)
double precision x(n,*), z(n,*), w( * )
c double precision mu(p,G), shape(p), O(p,p,G), pro(G)
double precision mu(p,*), shape(*), O(p,p,*), pro(*)
integer p1, i, j, k, l, j1, info
double precision dummy, temp, term, const
double precision sumz, sum, smin, smax, cs, sn
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision BIGLOG
parameter (BIGLOG = 709.d0)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
if (pshrnk .gt. zero) pshrnk = zero
p1 = p + 1
call dcopy( p, zero, 0, shape, 1)
l = 0
sumz = zero
scale = zero
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
do j = 1, p
call dcopy( p, pscale(1,j), 1, O(1,j,k), 1)
end do
sum = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
pro(k) = sum / dble(n)
if (sum .ge. one .or. one .lt. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
end do
call dcopy( p, pmu, 1, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
term = sum+pshrnk
const = (sum*pshrnk)/term
call dscal( p, sqrt(const), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
call dscal( p, sum/term, mu(1,k), 1)
call daxpy( p, pshrnk/term, pmu, 1, mu(1,k), 1)
call dgesvd( 'N', 'O', p, p, O(1,1,k), p, z(1,k),
* dummy, 1, dummy, 1, w, lwork, info)
if (info .ne. 0) then
l = info
else if (scale .ne. FLMAX) then
do j = 1, p
temp = z(j,k)
shape(j) = shape(j) + temp*temp
end do
end if
else
scale = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (scale .eq. FLMAX .or. l .ne. 0) then
lwork = l
if (l .ne. 0) then
scale = FLMAX
else
scale = -FLMAX
end if
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
lwork = 0
call sgnrng( p, shape, 1, smin, smax)
if (smin .eq. zero) then
scale = FLMAX
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
term = pdof + dble(p) + one
if (pshrnk .gt. zero) term = term + one
scale = temp/(term + sumz)
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
return
end if
call dscal( p, one/temp, shape, 1)
return
end
subroutine eseii ( x, mu, sigsq, pro, n, p, G, Vinv, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
double precision sigsq, hood, Vinv
c double precision x(n,p), mu(p,G), pro(G[+1]), z(n,G[+1])
double precision x(n,*), mu(p,*), pro( * ), z(n, * )
integer i, j, k, nz
double precision sum, temp, const, prok, tmin, tmax
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
if (sigsq .le. zero) then
hood = FLMAX
return
end if
const = dble(p)*(pi2log+log(sigsq))
do k = 1, G
c prok = pro(k)
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + temp*temp
end do
c z(i,k) = prok*exp(-(const+sum/sigsq)/two)
if (sigsq .lt. one .and. sum .ge. sigsq*FLMAX) then
hood = FLMAX
return
end if
z(i,k) = -(const+sum/sigsq)/two
end do
end do
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c sum = zero
c do k = 1, nz
c sum = sum + z(i,k)
c end do
c hood = hood + log(sum)
c call dscal( nz, (one/sum), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
return
end
subroutine hceii ( x, n, p, ic, ng, ns, v, nd, d)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, ic(n), ng, ns, nd
c double precision x(n,p), v(p), d(ng*(ng-1)/2)
double precision x(n,*), v(*), d(*)
integer lg, ld, ll, lo, ls
integer i, j, k, m
integer ni, nj, nij, iopt, jopt, iold, jold
integer ij, ici, icj, ii, ik, jk
double precision ri, rj, rij, si, sj, sij
double precision dij, dopt, dold
external wardsw
double precision one
parameter (one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision ddot
external ddot
c------------------------------------------------------------------------------
iopt = 0
lg = ng
ld = (ng*(ng-1))/2
ll = nd-ng
lo = nd
c call intpr( 'ic', -1, ic, n)
c call intpr( 'no. of groups', -1, lg, 1)
c group heads should be first among rows of x
i = 1
j = 2
1 continue
icj = ic(j)
if (icj .ne. j) goto 2
if (j .eq. lg) goto 3
i = j
j = j + 1
goto 1
2 continue
k = i
m = j + 1
do j = m, n
icj = ic(j)
if (icj .gt. k) then
k = k + 1
call dswap( p, x(k,1), n, x(j,1), n)
ic(j) = ic(k)
ic(k) = icj
end if
end do
3 continue
c call intpr( 'ic', -1, ic, n)
do j = 1, n
i = ic(j)
if (i .ne. j) then
ic(j) = 0
ni = ic(i)
nij = ni + 1
ic(i) = nij
ri = dble(ni)
rij = dble(nij)
sj = sqrt(one/rij)
si = sqrt(ri)*sj
c update column sum in kth row
call dscal( p, si, x(i,1), n)
call daxpy( p, sj, x(j,1), n, x(i,1), n)
else
ic(j) = 1
end if
end do
c call intpr( 'ic', -1, ic, n)
dopt = FLMAX
ij = 0
do j = 2, lg
nj = ic(j)
rj = dble(nj)
do i = 1, (j-1)
ni = ic(i)
ri = dble(ni)
nij = ni + nj
rij = dble(nij)
si = sqrt(ri/rij)
sj = sqrt(rj/rij)
call dcopy( p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
dij = ddot(p, v, 1, v, 1)
ij = ij + 1
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
iopt = i
jopt = j
end if
end do
end do
c if (.false.) then
c i = 1
c ij = 1
c do j = 2, ng
c call dblepr( 'dij', -1, d(ij), i)
c ij = ij + i
c i = j
c end do
c end if
if (ns .eq. 1) then
if (iopt .lt. jopt) then
x(1,1) = iopt
x(1,2) = jopt
else
x(1,1) = jopt
x(1,2) = iopt
end if
d(1) = dopt
return
end if
ls = 1
100 continue
ni = ic(iopt)
nj = ic(jopt)
nij = ni + nj
ic(iopt) = nij
ic(jopt) = -iopt
if (jopt .ne. lg) then
call wardsw( jopt, lg, d)
m = ic(jopt)
ic(jopt) = ic(lg)
ic(lg) = m
end if
si = dble(ni)
sj = dble(nj)
sij = dble(nij)
dold = dopt
iold = iopt
jold = jopt
iopt = -1
jopt = -1
dopt = FLMAX
lg = lg - 1
ld = ld - lg
ii = (iold*(iold-1))/2
if (iold .gt. 1) then
ik = ii - iold + 1
do j = 1, (iold - 1)
nj = ic(j)
rj = dble(nj)
ik = ik + 1
jk = ld + j
dij = (rj+si)*d(ik)+(rj+sj)*d(jk)
dij = (dij-rj*dold)/(rj+sij)
d(ik) = dij
end do
end if
if (iold .lt. lg) then
ik = ii + iold
i = iold
do j = (iold + 1), lg
nj = ic(j)
rj = dble(nj)
jk = ld + j
dij = (rj+si)*d(ik)+(rj+sj)*d(jk)
dij = (dij-rj*dold)/(rj+sij)
d(ik) = dij
ik = ik + i
i = j
end do
end if
d(lo) = dold
lo = lo - 1
d(lo) = dble(iold)
lo = lo - 1
d(lo) = dble(jold)
lo = lo - 1
c update d and find max
jopt = 2
iopt = 1
dopt = d(1)
if (lg .eq. 2) goto 900
ij = 1
do i = 2, ld
si = d(i)
if (si .le. dopt) then
ij = i
dopt = si
end if
end do
if (ij .gt. 1) then
do i = 2, ij
iopt = iopt + 1
if (iopt .ge. jopt) then
jopt = jopt + 1
iopt = 1
end if
end do
end if
ls = ls + 1
if (ls .eq. ns) goto 900
goto 100
900 continue
d(lo) = dopt
lo = lo - 1
d(lo) = dble(iopt)
lo = lo - 1
d(lo) = dble(jopt)
do i = 1, ng
ic(i) = i
end do
lo = nd - 1
ld = lo
si = d(lo)
lo = lo - 1
sj = d(lo)
ic(int(sj)) = ng
if (si .lt. sj) then
x(1,1) = si
x(1,2) = sj
else
x(1,1) = sj
x(1,2) = si
end if
lg = ng + 1
do k = 2, ns
lo = lo - 1
d(ld) = d(lo)
ld = ld - 1
lo = lo - 1
i = int(d(lo))
ici = ic(i)
lo = lo - 1
j = int(d(lo))
icj = ic(j)
if (ici .gt. icj) ic(i) = icj
ic(j) = ic(lg-k)
if (ici .lt. icj) then
x(k,1) = dble(ici)
x(k,2) = dble(icj)
else
x(k,1) = dble(icj)
x(k,2) = dble(ici)
end if
end do
ld = nd
lo = 1
do k = 1, ns
si = d(lo)
d(lo) = d(ld)
d(ld) = si
ld = ld - 1
lo = lo + 1
end do
return
end
subroutine meeii ( EQPRO, x, n, p, G, Vinv, z, maxi, tol, eps,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
double precision Vinv, eps, tol, sigsq
c double precision x(n,p), z(n,G[+1]), mu(p,G), pro(G[+1])
double precision x(n,*), z(n, * ), mu(p,*), pro( * )
integer nz, iter, i, j, k
double precision sum, sumz, temp, term, prok, tmax, tmin, rteps
double precision const, hold, hood, err, dnp, ViLog, zsum
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
if (maxi .le. 0) return
dnp = dble(n*p)
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
sigsq = zero
sumz = zero
zsum = one
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
if (.not. EQPRO) pro(k) = sum/dble(n)
zsum = min(sum,zsum)
if (sum .gt. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
sum = zero
do j = 1, p
temp = abs(x(i,j) - mu(j,k))
if (temp .gt. RTMIN) sum = sum + temp*temp
end do
if (sqrt(z(i,k))*sqrt(sum) .gt. RTMIN)
* sigsq = sigsq + z(i,k)*sum
z(i,k) = sum
end do
else
sigsq = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
if (Vinv .le. zero) then
sigsq = sigsq / dnp
else
sigsq = sigsq / (dble(p)*sumz)
end if
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
if (sigsq .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
const = dble(p)*(pi2log+log(sigsq))
do k = 1, G
c temp = pro(k)
do i = 1, n
c z(i,k) = temp*exp(-(const+(z(i,k)/sigsq))/two)
z(i,k) = -(const+(z(i,k)/sigsq))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine meeiip( EQPRO, x, n, p, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
double precision Vinv, eps, tol, sigsq
c double precision x(n,p), z(n,G[+1]), mu(p,G), pro(G[+1])
double precision x(n,*), z(n, * ), mu(p,*), pro( * )
integer nz, iter, i, j, k
double precision sum, sumk, sumz, temp, term, tmax, tmin
double precision const, hold, hood, err, dnp, ViLog, prok
double precision pmupmu, cmu, cgam, rmu, rgam, zsum, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMLOG
parameter (SMLOG = -708.d0)
double precision ddot, dlngam
external ddot, dlngam
c------------------------------------------------------------------------------
if (maxi .le. 0) return
dnp = dble(n*p)
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
pmupmu = ddot( p, pmu, 1, pmu, 1)
100 continue
iter = iter + 1
sigsq = zero
sumz = zero
zsum = one
do k = 1, G
sumk = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sumk = sumk + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sumk
if (.not. EQPRO) pro(k) = sumk/dble(n)
zsum = min(zsum,sumk)
if (sumk .gt. rteps) then
call dscal( p, (one/sumk), mu(1,k), 1)
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + temp*temp
end do
sigsq = sigsq + z(i,k)*sum
end do
temp = pmupmu + ddot( p, mu(1,k), 1, mu(1,k), 1)
temp = temp - two*ddot( p, mu(1,k), 1, pmu, 1)
const = sumk+pshrnk
sigsq = sigsq + ((pshrnk*sumk)/const)*temp
call dscal( p, (sumk/const), mu(1,k), 1)
call daxpy(p, (pshrnk/const), pmu, 1, mu(1,k), 1)
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
term = zero
if (Vinv .le. zero) then
sigsq = sigsq / (pdof + dble((n+G)*p) + two)
else
sigsq = sigsq / (pdof + (sumz+dble(G))*dble(p) + two)
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
if (sigsq .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
const = dble(p)*(pi2log+log(sigsq))
do i = 1, n
do k = 1, G
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + temp*temp
end do
z(i,k) = -(const+(sum/sigsq))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMLOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
cmu = dble(p)*(log(pshrnk)-pi2log)/two
const = pdof/two
cgam = const*log(pscale/two)-dlngam(const)
rmu = zero
do k = 1, G
temp = pmupmu + ddot( p, mu(1,k), 1, mu(1,k), 1)
temp = temp - two*ddot( p, mu(1,k), 1, pmu, 1)
rmu = rmu + (pshrnk*temp)/sigsq
end do
term = log(sigsq)
rmu = -(rmu + dble(p)*term)/two
rgam = -(const+one)*term - (pscale/sigsq)/two
pdof = (dble(G)*cmu+cgam) + (rmu+rgam)
return
end
subroutine mseii ( x, z, n, p, G, mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision x(n,p), z(n,G), mu(p,G), sigsq, pro(G)
double precision x(n,*), z(n,*), mu(p,*), sigsq, pro(*)
integer i, j, k
double precision sum, sumz, temp
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
c------------------------------------------------------------------------------
sumz = zero
sigsq = zero
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
pro(k) = sum/dble(n)
if (sum .ge. one .or. one .lt. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
if (sigsq .ne. FLMAX) then
do i = 1, n
sum = zero
do j = 1, p
temp = abs(x(i,j) - mu(j,k))
if (temp .gt. RTMIN) sum = sum + temp*temp
end do
if (sqrt(z(i,k))*sqrt(sum) .gt. RTMIN)
* sigsq = sigsq + z(i,k)*sum
end do
end if
else
sigsq = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
c sumz .eq. n when no noise
if (sigsq .ne. FLMAX) sigsq = sigsq / (sumz*dble(p))
return
end
subroutine mseiip( x, z, n, p, G,
* pshrnk, pmu, pscale, pdof,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
c double precision x(n,p), z(n,G), mu(p,G), sigsq, pro(G)
double precision x(n,*), z(n,*), mu(p,*), sigsq, pro(*)
integer i, j, k
double precision sum, sumz, pmupmu
double precision const, temp, dnp
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision ddot
external ddot
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
pscale = pscale*1.d0
dnp = dble(n*p)
pmupmu = ddot( p, pmu, 1, pmu, 1)
sumz = zero
sigsq = zero
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
pro(k) = sum/dble(n)
if (sum .gt. one .or. one .le. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
temp = pmupmu + ddot( p, mu(1,k), 1, mu(1,k), 1)
temp = temp - two*ddot( p, mu(1,k), 1, pmu, 1)
const = sum+pshrnk
call dscal( p, (sum/const), mu(1,k), 1)
call daxpy(p, (pshrnk/const), pmu, 1, mu(1,k), 1)
if (sigsq .ne. FLMAX) then
sigsq = sigsq + ((pshrnk*sum)/const)*temp
do i = 1, n
sum = zero
do j = 1, p
temp = abs(x(i,j) - mu(j,k))
if (temp .gt. RTMIN) sum = sum + temp*temp
end do
if (sqrt(z(i,k))*sqrt(sum) .gt. RTMIN)
* sigsq = sigsq + z(i,k)*sum
end do
end if
else
sigsq = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (sigsq .eq. FLMAX) return
temp = pdof + sumz*dble(p) + two
if (pshrnk .gt. zero) temp = temp + dble(G*p)
sigsq = sigsq / temp
return
end
subroutine esevi ( x, mu, scale, shape, pro, n, p, G,
* Vinv, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
double precision scale, hood, Vinv
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), shape(p,G), pro(G[+1])
double precision mu(p,*), shape(p,*), pro( * )
integer i, j, k, nz
double precision sum, temp, const, tmin, tmax
double precision smin, smax, prok
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMAX
parameter (RTMAX = 1.340780792994260d154)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
if (scale .le. zero) then
hood = FLMAX
return
end if
do k = 1, G
call sgnrng( p, shape(1,k), 1, smin, smax)
if (smin .eq. zero) then
hood = FLMAX
return
end if
end do
temp = sqrt(scale)
do k = 1, G
do j = 1, p
shape(j,k) = temp*sqrt(shape(j,k))
end do
end do
const = dble(p)*(pi2log+log(scale))
do k = 1, G
c prok = pro(k)
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
if (shape(j,k) .lt. one .and.
* abs(temp) .ge. shape(j,k)*FLMAX) then
hood = FLMAX
return
end if
temp = temp/shape(j,k)
if (abs(temp) .ge. RTMAX) then
hood = FLMAX
return
end if
if (abs(temp) .gt. RTMIN) sum = sum + temp*temp
end do
c z(i,k) = prok*exp(-(const+sum)/two)
z(i,k) = -(const+sum)/two
end do
end do
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c sum = zero
c do k = 1, nz
c sum = sum + z(i,k)
c end do
c hood = hood + log(sum)
c call dscal( nz, (one/sum), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
return
end
subroutine meevi ( EQPRO, x, n, p, G, Vinv, z, maxi, tol, eps,
* mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
double precision Vinv, eps, tol, scale
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), shape(p,G), pro(G[+1])
double precision mu(p,*), shape(p,*), pro( * )
integer nz, iter, i, j, k
double precision sum, sumz, temp, term, epsmin
double precision hold, hood, err, smin, smax, const
double precision prok, tmin, tmax, ViLog, zsum, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dscal( G, one/dble(G), pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
sumz = zero
zsum = one
do k = 1, G
call dcopy( p, zero, 0, shape(1,k), 1)
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
if (.not. EQPRO) pro(k) = sum /dble(n)
zsum = min(sum,zsum)
if (sum .gt. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
do j = 1, p
sum = zero
do i = 1, n
temp = x(i,j) - mu(j,k)
if (sqrt(z(i,k))*abs(temp) .gt. RTMIN)
* sum = sum + z(i,k)*(temp*temp)
end do
shape(j,k) = shape(j,k) + sum
end do
else
call dcopy( p, FLMAX, 0, mu(1,k), 1)
call dcopy( p, FLMAX, 0, shape(1,k), 1)
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
scale = zero
epsmin = FLMAX
do k = 1, G
call sgnrng(p, shape(1,k), 1, smin, smax)
epsmin = min(smin,epsmin)
if (smin .gt. zero) then
sum = zero
do j = 1, p
sum = sum + log(shape(j,k))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
tol = err
eps = FLMAX
maxi = iter
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
scale = scale + temp
epsmin = min(temp,epsmin)
if (temp .lt. eps) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
tol = err
eps = FLMAX
maxi = iter
return
end if
call dscal( p, one/temp, shape(1,k), 1)
end if
end do
term = zero
if (Vinv .gt. zero) then
scale = scale /sumz
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
else
scale = scale /dble(n)
end if
if (scale .le. eps) then
tol = epsmin
eps = FLMAX
maxi = iter
return
end if
do k = 1, G
call sgnrng( p, shape(1,k), 1, smin, smax)
if (smin .le. eps) then
tol = smin
eps = FLMAX
maxi = iter
return
end if
end do
const = dble(p)*(pi2log + log(scale))
do k = 1, G
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + (temp*temp)/shape(j,k)
end do
c z(i,k) = pro(k)*exp(-(const+(sum/scale))/two)
z(i,k) = -(const+(sum/scale))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine meevip( EQPRO, x, n, p, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps,
* mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
double precision Vinv, eps, tol, scale
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), shape(p,G), pro(G[+1])
double precision mu(p,*), shape(p,*), pro( * )
integer nz, iter, i, j, k
double precision sum, sumz, temp, term, epsmin, zsum
double precision hold, hood, err, smin, smax, const
double precision prok, tmin, tmax, ViLog, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dscal( G, one/dble(G), pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
sumz = zero
zsum = one
do k = 1, G
call dcopy( p, pscale, 0, shape(1,k), 1)
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
if (.not. EQPRO) pro(k) = sum /dble(n)
zsum = min(sum,zsum)
if (sum .gt. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
term = pshrnk + sum
const = (pshrnk*sum)/term
do j = 1, p
do i = 1, n
temp = x(i,j) - mu(j,k)
if (abs(temp)*sqrt(z(i,k)) .gt. RTMIN)
* shape(j,k) = shape(j,k) + z(i,k)*(temp*temp)
end do
temp = pmu(j) - mu(j,k)
shape(j,k) = shape(j,k) + const*(temp*temp)
end do
call dscal( p, sum/term, mu(1,k), 1)
call daxpy( p, pshrnk/term, pmu, 1, mu(1,k), 1)
else
call dcopy( p, FLMAX, 0, mu(1,k), 1)
call dcopy( p, FLMAX, 0, shape(1,k), 1)
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
scale = zero
epsmin = FLMAX
do k = 1, G
call sgnrng(p, shape(1,k), 1, smin, smax)
epsmin = min(smin,epsmin)
if (smin .gt. zero) then
sum = zero
do j = 1, p
sum = sum + log(shape(j,k))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
tol = err
eps = FLMAX
maxi = iter
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
scale = scale + temp
epsmin = min(temp,epsmin)
if (temp .lt. eps) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
tol = err
eps = FLMAX
maxi = iter
return
end if
call dscal( p, one/temp, shape(1,k), 1)
end if
end do
term = pdof + one
if (Vinv .le. zero) then
term = term + dble(n)
else
term = term + sumz
end if
if (pshrnk .gt. zero) term = term + one
scale = scale/term
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
if (scale .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
do k = 1, G
call sgnrng( p, shape(1,k), 1, smin, smax)
if (smin .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
end do
const = dble(p)*(pi2log + log(scale))
do k = 1, G
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + (temp*temp)/shape(j,k)
end do
c z(i,k) = pro(k)*exp(-(const+(sum/scale))/two)
z(i,k) = -(const+(sum/scale))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine msevi ( x, z, n, p, G, mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision x(n,p), z(n,G)
double precision x(n,*), z(n,*)
c double precision mu(p,G), scale, shape(p,G), pro(G)
double precision mu(p,*), scale, shape(p,*), pro(*)
integer i, j, k
double precision smin, smax
double precision sum, sumz, temp
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
scale = zero
sumz = zero
do k = 1, G
call dcopy( p, zero, 0, shape(1,k), 1)
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
z(i,k) = sqrt(temp)
end do
sumz = sumz + sum
pro(k) = sum/dble(n)
if (sum .ge. one .or. one .lt. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
else
scale = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
call dcopy( p, FLMAX, 0, shape(1,k), 1)
end if
end do
if (scale .eq. FLMAX) return
c pro(k) now contains n_k
do j = 1, p
do k = 1, G
sum = zero
do i = 1, n
temp = z(i,k)*(x(i,j) - mu(j,k))
if (abs(temp) .gt. RTMIN) sum = sum + temp*temp
end do
shape(j,k) = shape(j,k) + sum
end do
end do
scale = zero
do k = 1, G
call sgnrng(p, shape(1,k), 1, smin, smax)
if (smin .le. zero) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j,k))
end do
temp = sum/dble(p)
if (temp .ge. BIGLOG) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (scale .ne. FLMAX) scale = scale + temp
if (temp .lt. one .and. one .ge. temp*FLMAX) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
call dscal( p, one/temp , shape(1,k), 1)
100 continue
end do
if (sumz .lt. one .and. one .ge. sumz*FLMAX) then
scale = FLMAX
return
end if
scale = scale/sumz
return
end
subroutine msevip( x, z, n, p, G,
* pshrnk, pmu, pscale, pdof,
* mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
c double precision x(n,p), z(n,G)
double precision x(n,*), z(n,*)
c double precision mu(p,G), scale, shape(p,G), pro(G)
double precision mu(p,*), scale, shape(p,*), pro(*)
integer i, j, k
double precision sum, sumz, temp, term
double precision smin, smax, const
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
sumz = zero
scale = zero
do k = 1, G
call dcopy( p, pscale, 0, shape(1,k), 1)
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
pro(k) = sum /dble(n)
if (sum .ge. one .or. one .lt. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
term = pshrnk + sum
const = (pshrnk*sum)/term
do j = 1, p
do i = 1, n
temp = x(i,j) - mu(j,k)
if (abs(temp)*sqrt(z(i,k)) .gt. RTMIN)
* shape(j,k) = shape(j,k) + z(i,k)*(temp*temp)
end do
temp = pmu(j) - mu(j,k)
shape(j,k) = shape(j,k) + const*(temp*temp)
end do
call dscal( p, sum/term, mu(1,k), 1)
call daxpy( p, pshrnk/term, pmu, 1, mu(1,k), 1)
else
scale = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
call dcopy( p, FLMAX, 0, shape(1,k), 1)
end if
end do
if (scale .eq. FLMAX) return
scale = zero
do k = 1, G
call sgnrng(p, shape(1,k), 1, smin, smax)
if (smin .le. zero) then
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j,k))
end do
temp = sum/dble(p)
if (temp .ge. BIGLOG) then
scale = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
endif
if (scale .ne. FLMAX) scale = scale + temp
if (temp .le. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
call dscal( p, one/temp, shape(1,k), 1)
100 continue
end do
term = pdof + sumz + two
if (pshrnk .gt. zero) term = term + dble(G)
scale = scale/term
return
end
subroutine es1v ( x, mu, sigsq, pro, n, G, Vinv, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, G
double precision hood, Vinv
c double precision x(n), mu(G), sigsq(G), pro(G[+1]), z(n,G[+1])
double precision x(*), mu(*), sigsq(*), pro( * ), z(n, * )
integer i, k, nz
double precision temp, const, tmin, tmax, sum
double precision muk, sigsqk, prok, sigmin
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMAX
parameter (RTMAX = 1.340780792994260d154)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
call sgnrng( G, sigsq, 1, sigmin, temp)
if (sigmin .le. zero) then
hood = FLMAX
return
end if
do k = 1, G
c prok = pro(k)
muk = mu(k)
sigsqk = sigsq(k)
const = pi2log + log(sigsqk)
do i = 1, n
temp = x(i) - muk
c z(i,k) = prok*exp(-(const+(temp*temp)/sigsqk)/two)
if (sigsqk .lt. one .and.
* abs(temp) .ge. sqrt(sigsqk)*RTMAX) then
hood = FLMAX
return
end if
z(i,k) = -(const+(temp*temp)/sigsqk)/two
end do
end do
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c temp = zero
c do k = 1, nz
c temp = temp + z(i,k)
c end do
c hood = hood + log(temp)
c call dscal( nz, (one/temp), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
return
end
subroutine hc1v ( x, n, ic, ng, ns, ALPHA, nd, d)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n, ic(n), ng, ns, nd
integer n, ic(*), ng, ns, nd
c double precision x(n), ALPHA, d(ng*(ng-1)/2)
double precision x(*), ALPHA, d(*)
integer lg, ld, ll, lo, ls, i, j, k, m
integer ni, nj, nij, nopt, niop, njop
integer ij, ici, icj, iopt, jopt, iold
double precision ALFLOG
double precision qi, qj, qij, ri, rj, rij, si, sj
double precision tracei, tracej, trcij, trop
double precision termi, termj, trmij, tmop
double precision temp, dij, dopt, siop, sjop
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision sqrthf
parameter (sqrthf = .70710678118654757274d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision EPSMAX
parameter (EPSMAX = 2.2204460492503131d-16)
double precision ddot
external ddot
c------------------------------------------------------------------------------
c call dblepr( 'x', -1, x, n)
c call intpr( 'n', -1, n, 1)
c call intpr( 'ic', -1, ic, n)
c call intpr( 'ng', -1, ng, 1)
c call intpr( 'ns', -1, ns, 1)
c call dblepr( 'alpha', -1, alpha, 1)
c call intpr( 'nd', -1, nd, 1)
iopt = 0
jopt = 0
niop = 0
njop = 0
nopt = 0
siop = 0
sjop = 0
tmop = 0.d0
trop = 0.d0
lg = ng
ld = (ng*(ng-1))/2
ll = nd-ng
lo = nd
if (ng .eq. 1) return
ALPHA = max(ALPHA,EPSMAX)
ALFLOG = log(ALPHA)
c group heads should be first among rows of x
i = 1
j = 2
1 continue
icj = ic(j)
if (icj .ne. j) goto 2
if (j .eq. lg) goto 3
i = j
j = j + 1
goto 1
2 continue
k = i
m = j + 1
do j = m, n
icj = ic(j)
if (icj .gt. k) then
k = k + 1
c call dswap( p, x(k,1), n, x(j,1), n)
temp = x(k)
x(k) = x(j)
x(j) = temp
ic(j) = ic(k)
ic(k) = icj
end if
end do
3 continue
c set up pointers
do j = 1, n
i = ic(j)
if (i .ne. j) then
c update sum of squares
k = ic(i)
if (k .eq. 1) then
ic(i) = j
ic(j) = 2
c call dscal( p, sqrthf, x(i,1), n)
c call dscal( p, sqrthf, x(j,1), n)
c call dcopy( p, x(j,1), n, v, 1)
c call daxpy( p, (-one), x(i,1), n, v, 1)
c call daxpy( p, one, x(j,1), n, x(i,1), n)
c x(j,1) = ddot( p, v, 1, v, 1)
temp = sqrthf*(x(j) - x(i))
x(i) = sqrthf*(x(j) + x(i))
x(j) = temp*temp
else
ic(j) = 0
ni = ic(k)
ic(k) = ni + 1
ri = dble(ni)
rij = dble(ni+1)
qj = one/rij
qi = ri*qj
si = sqrt(qi)
sj = sqrt(qj)
c call dcopy( p, x(j,1), n, v, 1)
c call dscal( p, si, v, 1)
c call daxpy( p, (-sj), x(i,1), n, v, 1)
c x(k,1) = x(k,1) + ddot(p, v, 1, v, 1)
c call dscal( p, si, x(i,1), n)
c call daxpy( p, sj, x(j,1), n, x(i,1), n)
temp = si*x(j) - sj*x(i)
x(k) = x(k) + temp*temp
x(i) = si*x(i) + sj*x(j)
end if
else
ic(j) = 1
end if
end do
c store terms also so as not to recompute them
do k = 1, ng
i = ic(k)
if (i .ne. 1) then
ni = ic(i)
ri = dble(ni)
d(nd-k+1) = ri*log((x(i)+ALPHA)/ri)
end if
end do
c call intpr( 'ic', -1, ic, n)
c compute change in likelihood and determine minimum
dopt = FLMAX
ij = 0
do j = 2, ng
nj = ic(j)
if (nj .eq. 1) then
tracej = zero
termj = ALFLOG
rj = one
else
tracej = x(nj)
nj = ic(nj)
rj = dble(nj)
termj = d(nd-j+1)
end if
do i = 1, (j-1)
ni = ic(i)
if (ni .eq. 1) then
tracei = zero
termi = ALFLOG
ri = one
else
tracei = x(ni)
ni = ic(ni)
ri = dble(ni)
termi = d(nd-i+1)
end if
nij = ni + nj
rij = dble(nij)
qij = one/rij
qi = ri*qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
c call dcopy(p, x(i,1), n, v, 1)
c call dscal( p, sj, v, 1)
c call daxpy( p, (-si), x(j,1), n, v, 1)
temp = sj*x(i) - si*x(j)
c trcij = (tracei + tracej) + ddot(p,v,1,v,1)
trcij = (tracei + tracej) + temp*temp
trmij = rij*log((trcij+ALPHA)/rij)
dij = trmij - (termi + termj)
ij = ij + 1
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
trop = trcij
tmop = trmij
nopt = nij
niop = ni
njop = nj
siop = si
sjop = sj
iopt = i
jopt = j
end if
end do
end do
c call dblepr( 'dij', -1, d, (ng*(ng-1))/2)
if (ns .eq. 1) then
if (iopt .lt. jopt) then
x(1) = dble(iopt)
ic(1) = jopt
else
x(1) = dble(jopt)
ic(1) = iopt
end if
d(1) = dopt
return
end if
if (niop .ne. 1) ic(ic(iopt)) = 0
if (njop .ne. 1) ic(ic(jopt)) = 0
ls = 1
100 continue
c if (.false.) then
c ij = 1
c jj = 1
c do j = 2, n
c nj = ic(j)
c if (nj .ne. 0 .and. abs(nj) .le. n) then
c call dblepr( 'dij', -1, d(ij), jj)
c ij = ij + jj
c jj = jj + 1
c end if
c end do
c end if
c call dscal( p, siop, x(iopt,1), n)
c call daxpy( p, sjop, x(jopt,1), n, x(iopt,1), n)
x(iopt) = siop*x(iopt)+sjop*x(jopt)
if (jopt .ne. lg) then
call wardsw( jopt, lg, d)
c call dcopy( p, x(lg,1), n, x(jopt,1), n)
x(jopt) = x(lg)
m = ic(jopt)
ic(jopt) = ic(lg)
ic(lg) = m
end if
ic(iopt) = lg
c ic(lg) = nopt
c x(lg,1) = trop
x(lg) = trop
c x(lg,2) = tmop
d(lo) = dopt
lo = lo - 1
ic(lg) = lo
d(lo) = tmop
lo = lo - 1
d(lo) = dble(nopt)
lo = lo - 1
d(lo) = dble(iopt)
lo = lo - 1
d(lo) = dble(jopt)
lo = lo - 1
lg = lg - 1
ld = ld - lg
iold = iopt
iopt = -1
jopt = -1
dopt = FLMAX
ni = nopt
ri = dble(ni)
tracei = trop
termi = tmop
ij = ((iold-1)*(iold-2))/2
if (iold .gt. 1) then
do j = 1, (iold - 1)
nj = ic(j)
if (nj .ne. 1) then
c tracej = x(nj,1)
tracej = x(nj)
k = ic(nj)
termj = d(k)
nj = int(d(k-1))
rj = dble(nj)
else
tracej = zero
termj = ALFLOG
rj = one
end if
nij = ni + nj
rij = dble(nij)
qij = one/rij
qi = ri*qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
c call dcopy( p, x(iold,1), n, v, 1)
c call dscal( p, sj, v, 1)
c call daxpy( p, (-si), x(j,1), n, v, 1)
temp = sj*x(iold)-si*x(j)
c trcij = (tracei + tracej) + ddot(p,v,1,v,1)
trcij = (tracei + tracej) + temp*temp
trmij = rij*log((trcij+ALPHA)/rij)
dij = trmij - (termi + termj)
ij = ij + 1
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
trop = trcij
tmop = trmij
iopt = j
jopt = iold
nopt = nij
niop = ni
njop = nj
sjop = si
siop = sj
end if
end do
end if
if (iold .lt. lg) then
i = iold
ij = ij + i
do j = (iold + 1), lg
nj = ic(j)
if (nj .ne. 1) then
c tracej = x(nj,1)
tracej = x(nj)
k = ic(nj)
termj = d(k)
nj = int(d(k-1))
rj = dble(nj)
else
tracej = zero
termj = ALFLOG
rj = one
end if
nij = ni + nj
rij = dble(nij)
qij = one /rij
qi = ri*qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
c call dcopy( p, x(iold,1), n, v, 1)
c call dscal( p, sj, v, 1)
c call daxpy( p, (-si), x(j,1), n, v, 1)
temp = sj*x(iold) - si*x(j)
c trcij = (tracei + tracej) + ddot(p,v,1,v,1)
trcij = (tracei + tracej) + temp*temp
trmij = rij*log((trcij+ALPHA)/rij)
dij = trmij - (termi + termj)
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
trop = trcij
tmop = trmij
iopt = iold
jopt = j
nopt = nij
niop = ni
njop = nj
siop = si
sjop = sj
end if
ij = ij + i
i = j
end do
end if
c update d and find max
jopt = 2
iopt = 1
dopt = d(1)
if (lg .eq. 2) goto 900
ij = 1
dopt = d(1)
do i = 2, ld
qi = d(i)
if (qi .le. dopt) then
ij = i
dopt = qi
end if
end do
if (ij .gt. 1) then
do i = 2, ij
iopt = iopt + 1
if (iopt .ge. jopt) then
jopt = jopt + 1
iopt = 1
end if
end do
end if
i = ic(iopt)
j = ic(jopt)
if (iopt .ne. iold .and. jopt .ne. iold) then
if (i .ne. 1) then
tracei = x(i)
ici = ic(i)
termi = d(ici)
niop = int(d(ici-1))
ri = dble(niop)
else
tracei = zero
termi = ALFLOG
niop = 1
ri = one
end if
if (j .ne. 1) then
c tracej = x(j,1)
tracej = x(j)
icj = ic(j)
termj = d(icj)
njop = int(d(icj-1))
rj = dble(njop)
else
tracej = zero
termj = ALFLOG
njop = 1
rj = one
end if
nopt = niop + njop
rij = dble(nopt)
qij = one/rij
qi = ri*qij
qj = rj*qij
siop = sqrt(qi)
sjop = sqrt(qj)
c call dcopy( p, x(iopt,1), n, v, 1)
c call dscal( p, sjop, v, 1)
c call daxpy( p, (-siop), x(jopt,1), n, v, 1)
temp = sjop*x(iopt)-siop*x(jopt)
c trop = (tracei + tracej) + ddot(p,v,1,v,1)
trop = (tracei + tracej) + temp*temp
tmop = rij*log((trop+ALPHA)/rij)
end if
ls = ls + 1
if (ls .eq. ns) goto 900
goto 100
900 continue
d(lo) = dopt
lo = lo - 1
d(lo) = tmop
lo = lo - 1
d(lo) = dble(nopt)
lo = lo - 1
d(lo) = dble(iopt)
lo = lo - 1
d(lo) = dble(jopt)
do i = 1, ng
ic(i) = i
end do
lo = nd - 3
ld = nd - 1
si = d(lo)
lo = lo - 1
sj = d(lo)
lo = lo - 1
ic(int(sj)) = ng
if (si .lt. sj) then
x(1) = si
d(ld) = sj
else
x(1) = sj
d(ld) = si
end if
ld = ld - 1
lg = ng + 1
do k = 2, ns
d(ld) = d(lo)
ld = ld - 1
lo = lo - 3
i = int(d(lo))
ici = ic(i)
lo = lo - 1
j = int(d(lo))
lo = lo - 1
icj = ic(j)
if (ici .gt. icj) ic(i) = icj
ic(j) = ic(lg-k)
if (ici .lt. icj) then
x(k) = dble(ici)
d(ld) = dble(icj)
else
x(k) = dble(icj)
d(ld) = dble(ici)
end if
ld = ld - 1
end do
ld = nd
lo = nd - 1
do k = 1, ns
ic(k) = int(d(lo))
lo = lo - 1
ld = ld - 1
d(ld) = d(lo)
lo = lo - 1
end do
ld = nd
lo = 1
do k = 1, ns
si = d(lo)
d(lo) = d(ld)
d(ld) = si
ld = ld - 1
lo = lo + 1
end do
return
end
subroutine me1v ( EQPRO, x, n, G, Vinv, z, maxi, tol, eps,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, G, maxi
double precision Vinv, eps, tol
c double precision x(n), z(n,G[+1]), mu(G), sigsq(G), pro(G[+1])
double precision x(*), z(n, * ), mu(*), sigsq(*), pro( * )
integer nz, iter, k, i
double precision hold, hood, err, sum, smu, zsum
double precision const, temp, term, sigmin, sigsqk
double precision prok, tmin, tmax, ViLog, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
zsum = one
do k = 1, G
sum = zero
smu = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
smu = smu + temp*x(i)
end do
if (.not. EQPRO) pro(k) = sum / dble(n)
zsum = min(sum,zsum)
if (sum .gt. rteps) then
smu = smu / sum
mu(k) = smu
sigsqk = zero
do i = 1, n
temp = x(i) - smu
temp = temp*temp
sigsqk = sigsqk + z(i,k)*temp
z(i,k) = temp
end do
sigsq(k) = sigsqk / sum
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
sigmin = FLMAX
do k = 1, G
sigmin = min(sigmin,sigsq(k))
end do
if (sigmin .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
do k = 1, G
sigsqk = sigsq(k)
const = pi2log + log(sigsqk)
do i = 1, n
c z(i,k) = temp*exp(-(const+(z(i,k)/sigsqk))/two)
z(i,k) = -(const+(z(i,k)/sigsqk))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine me1vp ( EQPRO, x, n, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps, mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, G, maxi
double precision pshrnk, pmu, pscale, pdof
double precision Vinv, eps, tol
c double precision x(n), z(n,G[+1]), mu(G), sigsq(G), pro(G[+1])
double precision x(*), z(n, * ), mu(*), sigsq(*), pro( * )
integer nz, iter, k, i
double precision hold, hood, err, pmupmu
double precision sumz, sum, smu, zsum, rteps
double precision const, temp, term, sigmin, sigsqk
double precision prok, tmin, tmax, ViLog
double precision cmu, cgam, rmu, rgam
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision three
parameter (three = 3.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision dlngam
external dlngam
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
pmupmu = pmu*pmu
iter = 0
100 continue
iter = iter + 1
zsum = one
do k = 1, G
sumz = zero
smu = zero
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
smu = smu + temp*x(i)
end do
if (.not. EQPRO) pro(k) = sumz / dble(n)
zsum = min(zsum,sumz)
if (sumz .gt. rteps) then
smu = smu/sumz
sum = zero
do i = 1, n
term = abs(x(i) - smu)
if (term .ge. eps .or. sqrt(z(i,k))*term .gt. RTMIN)
* sum = sum + z(i,k)*(term*term)
end do
term = (pshrnk*sumz)/(pshrnk+sumz)
temp = (pmupmu + smu*smu) - two*pmu*smu
sigsq(k) = (pscale + sum + term*temp)/(pdof+sumz+three)
term = sumz/(pshrnk+sumz)
temp = pshrnk/(pshrnk+sumz)
mu(k) = term*smu + temp*pmu
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
sigmin = FLMAX
do k = 1, G
sigmin = min(sigmin,sigsq(k))
end do
if (sigmin .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
do k = 1, G
sigsqk = sigsq(k)
const = pi2log + log(sigsqk)
do i = 1, n
term = abs(x(i) - mu(k))
if (term .gt. RTMIN) then
z(i,k) = -(const+((term*term)/sigsqk))/two
else
z(i,k) = -const/two
end if
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
cmu = dble(G)*(pi2log-log(pshrnk))/two
const = pdof/two
cgam = dble(G)*(const*log(pscale/two) - dlngam(const))
rmu = zero
rgam = zero
do k = 1, G
temp = pmu - mu(k)
temp = temp*temp
term = log(sigsq(k))
rmu = rmu + (term + (pshrnk/sigsq(k))*temp)
rgam = rgam + ((pdof+3.d0)*term + pscale/sigsq(k))
end do
rmu = -rmu /two
rgam = -rgam/two
pdof = (cmu+cgam) + (rmu+rgam)
return
end
subroutine ms1v ( x, z, n, G, mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, G
c double precision x(n), z(n,G), mu(G), sigsq(G), pro(G)
double precision x(*), z(n,*), mu(*), sigsq(*), pro(*)
integer i, k
double precision sum, smu, temp, sigsqk
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
c------------------------------------------------------------------------------
do k = 1, G
sum = zero
smu = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
smu = smu + temp*x(i)
end do
pro(k) = sum / dble(n)
if (sum .gt. one .or. smu .le. sum*FLMAX) then
smu = smu / sum
mu(k) = smu
sigsqk = zero
do i = 1, n
temp = abs(x(i) - smu)
sigsqk = sigsqk + z(i,k)*(temp*temp)
end do
sigsq(k) = sigsqk / sum
else
mu(k) = FLMAX
sigsq(k) = FLMAX
end if
end do
return
end
subroutine ms1vp ( x, z, n, G,
* pshrnk, pmu, pscale, pdof,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, G
double precision pshrnk, pmu, pscale, pdof
c double precision x(n), z(n,G), mu(G), sigsq(G), pro(G)
double precision x(*), z(n,*), mu(*), sigsq(*), pro(*)
integer k, i
double precision pmupmu
double precision sumz, sum, smu
double precision temp, term
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
pmupmu = pmu*pmu
do k = 1, G
sumz = zero
smu = zero
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
smu = smu + temp*x(i)
end do
pro(k) = sumz / dble(n)
if (sumz .gt. one .or. smu .le. sumz*FLMAX) then
smu = smu/sumz
term = sumz/(pshrnk+sumz)
temp = pshrnk/(pshrnk+sumz)
mu(k) = term*smu + temp*pmu
sum = zero
do i = 1, n
term = abs(x(i) - smu)
sum = sum + z(i,k)*(term*term)
end do
term = (pshrnk*sumz)/(pshrnk+sumz)
temp = (pmupmu + smu*smu) - two*pmu*smu
if (pshrnk .gt. zero) then
sigsq(k) = (pscale + sum + term*temp)/(pdof+sumz+3.d0)
else
sigsq(k) = (pscale + sum + term*temp)/(pdof+sumz+two)
end if
else
mu(k) = FLMAX
sigsq(k) = FLMAX
end if
end do
return
end
subroutine esvei ( x, mu, scale, shape, pro, n, p, G,
* Vinv, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
double precision hood, Vinv
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), scale(G), shape(p), pro(G[+1])
double precision mu(p,*), scale(*), shape(*), pro( * )
integer i, j, k, nz
double precision sum, temp, const, tmin, tmax
double precision smin, smax, prok, scalek
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMAX
parameter (RTMAX = 1.340780792994260d154)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
call sgnrng( G, scale, 1, smin, smax)
if (smin .le. zero) then
hood = FLMAX
return
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
hood = FLMAX
return
end if
do j = 1, p
shape(j) = sqrt(shape(j))
end do
do k = 1, G
c prok = pro(k)
scalek = scale(k)
const = dble(p)*(pi2log+log(scalek))
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
if (shape(j) .lt. one .and.
* abs(temp) .ge. shape(j)*FLMAX) then
hood = FLMAX
return
end if
temp = temp/shape(j)
if (abs(temp) .ge. RTMAX) then
hood = FLMAX
return
end if
if (abs(temp) .gt. RTMIN) sum = sum + temp*temp
end do
c z(i,k) = prok*exp(-(const+sum/scalek)/two)
if (scalek .lt. one .and.
* sum .ge. scalek*FLMAX) then
hood = FLMAX
return
end if
z(i,k) = -(const+sum/scalek)/two
end do
end do
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c sum = zero
c do k = 1, nz
c sum = sum + z(i,k)
c end do
c hood = hood + log(sum)
c call dscal( nz, (one/sum), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and.
* one .le. sum*FLMAX) then
hood = FLMAX
return
end if
if (sum .lt. one .and. one .ge. sum*FLMAX) then
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
return
end
subroutine mevei ( EQPRO, x, n, p, G, Vinv, z, maxi, tol, eps,
* mu, scale, shape, pro, scl, shp, w)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi(2)
double precision Vinv, eps, tol(2)
c double precision x(n,p), z(n,G[+1]), scl(G), shp(p), w(p,G)
double precision x(n,*), z(n, * ), scl(*), shp(*), w(p,*)
c double precision mu(p,G), scale(G), shape(p), pro(G[+1])
double precision mu(p,*), scale(*), shape(*), pro( * )
integer nz, i, j, k
integer iter, maxi1, maxi2, inner, inmax
double precision tol1, tol2, sum, temp, term, tmin, tmax
double precision prok, scalek, smin, smax, const, zsum
double precision hold, hood, err, errin, dnp, ViLog, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
maxi1 = maxi(1)
maxi2 = max(maxi(2),0)
if (maxi1 .le. 0) return
dnp = dble(n*p)
inmax = 0
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
end if
eps = max(eps,zero)
tol1 = max(tol(1),zero)
tol2 = max(tol(2),zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
errin = FLMAX
c start with shape and scale equal to 1
call dcopy(p, one, 0, shape, 1)
call dcopy(G, one, 0, scale, 1)
iter = 0
100 continue
inner = 0
zsum = one
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sum
zsum = min(zsum,sum)
if (sum .gt. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
do j = 1, p
sum = zero
do i = 1, n
temp = x(i,j) - mu(j,k)
sum = sum + z(i,k)*(temp*temp)
end do
w(j,k) = sum
end do
end if
end do
call dscal( G, dble(p), pro, 1)
if (zsum .le. rteps) then
eps = -FLMAX
tol(1) = zsum
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
if (maxi2 .le. 0) goto 120
110 continue
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
inner = inner + 1
c scale estimate
call dcopy( G, scale, 1, scl, 1)
do k = 1, G
sum = zero
do j = 1, p
sum = sum + w(j,k)/shape(j)
end do
scale(k) = sum/pro(k)
end do
call sgnrng(G, scale, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
c shape estimate
call dcopy( p, shape, 1, shp, 1)
do j = 1, p
sum = zero
do k = 1, G
sum = sum + w(j,k)/scale(k)
end do
shape(j) = sum
end do
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (temp .le. eps) then
eps = temp
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
call dscal( p, one/temp, shape, 1)
errin = zero
do k = 1, G
errin = max(errin, abs(scl(k)-scale(k))/(one + scale(k)))
end do
do j = 1, p
errin = max(errin, abs(shp(j)-shape(j))/(one + shape(j)))
end do
if (errin .gt. tol2 .and. inner .le. maxi2) goto 110
120 continue
iter = iter + 1
inmax = max(inner, inmax)
if (.not. EQPRO) call dscal( G, one/dnp, pro, 1)
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
else
if (EQPRO) call dscal( G, one/dble(G), pro, 1)
end if
call sgnrng( G, scale, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = inmax
return
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = inmax
return
end if
do k = 1, G
c prok = pro(k)
scalek = scale(k)
const = dble(p)*(pi2log+log(scalek))
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + (temp*temp)/shape(j)
end do
c z(i,k) = prok*exp(-(const+sum/scalek)/two)
z(i,k) = -(const+sum/scalek)/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol1 .and. iter .lt. maxi1) goto 100
tol(1) = err
tol(2) = errin
eps = hood
maxi(1) = iter
maxi(2) = inmax
return
end
subroutine meveip( EQPRO, x, n, p, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps,
* mu, scale, shape, pro, scl, shp, w)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi(2)
double precision Vinv, eps, tol(2)
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
c double precision x(n,p), z(n,G[+1]), scl(G), shp(p), w(p,G)
double precision x(n,*), z(n, * ), scl(*), shp(*), w(p,*)
c double precision mu(p,G), scale(G), shape(p), pro(G[+1])
double precision mu(p,*), scale(*), shape(*), pro( * )
integer nz, i, j, k
integer iter, maxi1, maxi2, inner, inmax
double precision tol1, tol2, sum, temp, term, tmin, tmax
double precision prok, scalek, smin, smax, const, sumz
double precision hold, hood, err, errin, dnp, ViLog, zsum
double precision rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
maxi1 = maxi(1)
maxi2 = max(maxi(2),0)
if (maxi1 .le. 0) return
dnp = dble(n*p)
inmax = 0
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
end if
eps = max(eps,zero)
tol1 = max(tol(1),zero)
tol2 = max(tol(2),zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
errin = FLMAX
c start with shape and scale equal to 1
call dcopy(p, one, 0, shape, 1)
call dcopy(G, one, 0, scale, 1)
iter = 0
100 continue
inner = 0
zsum = one
do k = 1, G
sumz = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sumz
zsum = min(zsum,sumz)
if (sumz .gt. rteps) then
term = pshrnk + sumz
const = (pshrnk*sumz)/term
call dscal( p, (one/sumz), mu(1,k), 1)
do j = 1, p
sum = zero
do i = 1, n
temp = x(i,j) - mu(j,k)
sum = sum + z(i,k)*(temp*temp)
end do
temp = pmu(j) - mu(j,k)
w(j,k) = pscale + sum + const*(temp*temp)
end do
call dscal( p, sumz/term, mu(1,k), 1)
call daxpy( p, pshrnk/term, pmu, 1, mu(1,k), 1)
end if
end do
call dscal( G, dble(p), pro, 1)
if (zsum .le. rteps) then
eps = -FLMAX
tol(1) = zsum
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
if (maxi2 .le. 0) goto 120
110 continue
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
inner = inner + 1
c scale estimate
call dcopy( G, scale, 1, scl, 1)
temp = pdof + two
if (pshrnk .gt. zero) temp = temp + one
do k = 1, G
sum = zero
do j = 1, p
sum = sum + w(j,k)/shape(j)
end do
scale(k) = sum/(pro(k)+temp)
end do
call sgnrng(G, scale, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
c shape estimate
call dcopy( p, shape, 1, shp, 1)
do j = 1, p
sum = zero
do k = 1, G
sum = sum + w(j,k)/scale(k)
end do
shape(j) = sum
end do
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (temp .le. eps) then
eps = temp
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
call dscal( p, one/temp, shape, 1)
errin = zero
do k = 1, G
errin = max(errin, abs(scl(k)-scale(k))/(one + scale(k)))
end do
do j = 1, p
errin = max(errin, abs(shp(j)-shape(j))/(one + shape(j)))
end do
if (errin .gt. tol2 .and. inner .le. maxi2) goto 110
120 continue
iter = iter + 1
inmax = max(inner, inmax)
if (.not. EQPRO) call dscal( G, one/dnp, pro, 1)
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
else
if (EQPRO) call dscal( G, one/dble(G), pro, 1)
end if
call sgnrng( G, scale, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = inmax
return
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = inmax
return
end if
do k = 1, G
c prok = pro(k)
scalek = scale(k)
const = dble(p)*(pi2log+log(scalek))
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + (temp*temp)/shape(j)
end do
c z(i,k) = prok*exp(-(const+sum/scalek)/two)
z(i,k) = -(const+sum/scalek)/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol1 .and. iter .lt. maxi1) goto 100
tol(1) = err
tol(2) = errin
eps = hood
maxi(1) = iter
maxi(2) = inmax
return
end
subroutine msvei ( x, z, n, p, G, maxi, tol,
* mu, scale, shape, pro, scl, shp, w)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G, maxi
double precision tol
c double precision x(n,p), z(n,G), scl(G), shp(p), w(p,G)
double precision x(n,*), z(n,*), scl(*), shp(*), w(p,*)
c double precision mu(p,G), scale(G), shape(p), pro(G)
double precision mu(p,*), scale(*), shape(*), pro(*)
integer i, j, k, inner
double precision sum, temp, smin, smax, err
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
tol = max(tol,zero)
err = FLMAX
c start with the equal volume and shape estimate
do k = 1, G
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sum
if (sum .gt. one .or. one .lt. sum*FLMAX) then
err = min(err,sum)
call dscal( p, (one/sum), mu(1,k), 1)
do j = 1, p
sum = zero
do i = 1, n
temp = x(i,j) - mu(j,k)
temp = temp*temp
temp = z(i,k)*temp
sum = sum + temp
end do
w(j,k) = sum
end do
else
err = -FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (err .lt. zero) then
call dscal( G, one/dble(n), pro, 1)
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
tol = FLMAX
maxi = 0
return
end if
call dcopy( p, one, 0, shape, 1)
call dcopy( G, one, 0, scale, 1)
call dscal( G, dble(p), pro, 1)
inner = 0
err = FLMAX
100 continue
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. zero) goto 200
inner = inner + 1
c scale estimate
call dcopy( G, scale, 1, scl, 1)
do k = 1, G
sum = zero
do j = 1, p
if (shape(j) .gt. one .or.
* w(j,k) .lt. shape(j)*FLMAX) then
sum = sum + w(j,k)/shape(j)
else
scale(k) = FLMAX
goto 110
end if
end do
scale(k) = sum/pro(k)
110 continue
end do
call sgnrng(G, scale, 1, smin, smax)
if (smin .le. zero .or. smax .eq. FLMAX) goto 200
c shape estimate
call dcopy( p, shape, 1, shp, 1)
do j = 1, p
sum = zero
do k = 1, G
if (scale(k) .gt. one .or. w(j,k) .lt. scale(k)*FLMAX) then
sum = sum + w(j,k)/scale(k)
else
shape(j) = FLMAX
goto 120
end if
end do
shape(j) = sum
120 continue
end do
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. zero .or. smax .eq. FLMAX) goto 200
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
call dcopy( G, FLMAX, 0, scale, 1)
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
call dscal( p, one/temp, shape, 1)
err = zero
do k = 1, G
err = max(err, abs(scl(k) - scale(k))/(one + scale(k)))
end do
do j = 1, p
err = max(err, abs(shp(j) - shape(j))/(one + shape(j)))
end do
if (err .gt. tol .and. inner .le. maxi) goto 100
200 continue
call dscal( G, one/dble(n*p), pro, 1)
tol = err
maxi = inner
return
end
subroutine msveip( x, z, n, p, G,
* pshrnk, pmu, pscale, pdof,
* maxi, tol,
* mu, scale, shape, pro, scl, shp, w)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G, maxi
double precision tol
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
c double precision x(n,p), z(n,G), scl(G), shp(p), w(p,G)
double precision x(n,*), z(n,*), scl(*), shp(*), w(p,*)
c double precision mu(p,G), scale(G), shape(p), pro(G)
double precision mu(p,*), scale(*), shape(*), pro(*)
integer i, j, k, inner
double precision sum, temp, term, err
double precision smin, smax, const, sumz
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
tol = max(tol,zero)
err = FLMAX
c start with shape and scale equal to 1
do k = 1, G
sumz = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sumz
if (sumz .gt. one .or. one .lt. sumz*FLMAX) then
err = min(err,sumz)
term = pshrnk + sumz
const = (pshrnk*sumz)/term
call dscal( p, (one/sumz), mu(1,k), 1)
do j = 1, p
sum = zero
do i = 1, n
temp = x(i,j) - mu(j,k)
sum = sum + z(i,k)*(temp*temp)
end do
temp = pmu(j) - mu(j,k)
w(j,k) = pscale + sum + const*(temp*temp)
end do
call dscal( p, sumz/term, mu(1,k), 1)
call daxpy( p, pshrnk/term, pmu, 1, mu(1,k), 1)
else
err = -FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (err .lt. zero) then
call dscal( G, one/dble(n), pro, 1)
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
tol = FLMAX
maxi = 0
return
end if
call dcopy(p, one, 0, shape, 1)
call dcopy(G, one, 0, scale, 1)
call dscal( G, dble(p), pro, 1)
if (maxi .le. 0) return
inner = 0
err = FLMAX
100 continue
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. zero) goto 200
inner = inner + 1
c scale estimate
call dcopy( G, scale, 1, scl, 1)
do k = 1, G
sum = zero
do j = 1, p
if (shape(j) .ge. one .or.
* w(j,k) .le. shape(j)*FLMAX) then
sum = sum + w(j,k)/shape(j)
else
scale(k) = FLMAX
goto 110
end if
end do
temp = pdof + pro(k) + two
if (pshrnk .gt. zero) temp = temp + one
scale(k) = sum/temp
110 continue
end do
call sgnrng(G, scale, 1, smin, smax)
if (smin .le. zero .or. smax .ge. FLMAX) then
call dcopy( G, FLMAX, 0, scale, 1)
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
c shape estimate
call dcopy( p, shape, 1, shp, 1)
do j = 1, p
sum = zero
do k = 1, G
if (scale(k) .gt. w(j,k) .or.
* w(j,k) .lt. scale(k)*FLMAX) then
sum = sum + w(j,k)/scale(k)
else
shape(j) = FLMAX
goto 120
end if
end do
shape(j) = sum
120 continue
end do
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. zero .or. smax .ge. FLMAX) then
call dcopy( G, FLMAX, 0, scale, 1)
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .ge. BIGLOG) then
call dcopy( G, FLMAX, 0, scale, 1)
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
call dscal( p, one/temp, shape, 1)
err = zero
do k = 1, G
err = max(err, abs(scl(k)-scale(k))/(one + scale(k)))
end do
do j = 1, p
err = max(err, abs(shp(j)-shape(j))/(one + shape(j)))
end do
if (err .gt. tol .and. inner .le. maxi) goto 100
200 continue
call dscal( G, one/dble(n*p), pro, 1)
tol = err
maxi = inner
return
end
subroutine esvev ( x, mu, scale, shape, O, pro, n, p, G,
* Vinv, v, w, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n, p, G
integer n, p, G
double precision Vinv, hood
c double precision x(n,p), z(n,G[+1]), mu(p,G), pro(G[+1])
double precision x(n,*), z(n, * ), mu(p,*), pro( * )
c double precision v(p), w(p)
double precision v(*), w(*)
c double precision scale(G), shape(p), O(p,p,G)
double precision scale(*), shape(*), O(p,p,*)
integer i, j, k, nz
double precision const, temp, tmin, tmax
double precision smin, smax, scalek, prok, sum
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
call sgnrng( G, scale, 1, smin, smax)
if (smin .le. zero) then
hood = FLMAX
return
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
hood = FLMAX
return
end if
do j = 1, p
shape(j) = sqrt(shape(j))
end do
do k = 1, G
scalek = scale(k)
const = dble(p)*(pi2log+log(scalek))
c prok = pro(k)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dgemv( 'N', p, p, one, O(1,1,k), p,
* w, 1, zero, v, 1)
do j = 1, p
if (shape(j) .lt. one .and.
* abs(v(j)) .ge. shape(j)*FLMAX) then
hood = FLMAX
return
end if
v(j) = v(j)/shape(j)
end do
temp = ddot( p, v, 1, v, 1)
if (scalek .lt. one .and. temp .ge. scalek*FLMAX) then
hood = FLMAX
return
end if
temp = temp/scalek
c z(i,k) = prok*exp(-(const+temp)/two)
z(i,k) = -(const+temp)/two
end do
end do
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c sum = zero
c do k = 1, nz
c sum = sum + z(i,k)
c end do
c hood = hood + log(sum)
c call dscal( nz, (one/sum), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
return
end
subroutine mevev ( EQPRO, x, n, p, G, Vinv, z,
* maxi, tol, eps, lwork,
* mu, scale, shape, O, pro, w, s)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi(2), lwork
double precision Vinv, eps, tol(2)
double precision x(n,*), z(n, * ), w( * ), s(*)
double precision mu(p,*), pro( * )
double precision scale(*), shape(*), O(p,p,*)
integer maxi1, maxi2, p1, inmax, iter
integer nz, i, j, k, l, j1, info, inner
double precision tol1, tol2, dnp, term, rteps, ViLog
double precision errin, smin, smax, sumz, tmin, tmax
double precision cs, sn, dummy, hold, hood, err, zsum
double precision const, temp, sum, prok, scalek
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
maxi1 = maxi(1)
maxi2 = maxi(2)
if (maxi1 .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
end if
eps = max(eps,zero)
rteps = sqrt(eps)
tol1 = max(tol(1),zero)
tol2 = max(tol(2),zero)
p1 = p + 1
dnp = dble(n*p)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
errin = FLMAX
inmax = 0
iter = 0
100 continue
sumz = zero
zsum = one
l = 0
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
do j = 1, p
call dcopy( p, zero, 0, O(1,j,k), 1)
end do
sum = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
sumz = sumz + sum
zsum = min(zsum,sum)
pro(k) = sum
if (sum .ge. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
end do
call dgesvd( 'N', 'O', p, p, O(1,1,k), p, z(1,k),
* dummy, 1, dummy, 1, w, lwork, info)
if (info .ne. 0) then
l = info
else
do j = 1, p
temp = z(j,k)
z(j,k) = temp*temp
end do
end if
end if
end do
iter = iter + 1
if (l .ne. 0 .or. zsum .lt. rteps) then
if (Vinv .ge. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
else
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
lwork = l
c w(1) = FLMAX
tol(1) = err
tol(2) = errin
if (l .ne. 0) then
eps = FLMAX
else
eps = -FLMAX
end if
maxi(1) = -1
maxi(2) = -1
return
end if
if (iter .eq. 1) then
call dcopy( p, zero, 0, shape, 1)
do j = 1, p
sum = zero
do k = 1, G
sum = sum + z(j,k)
end do
shape(j) = sum
end do
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
if (.not. EQPRO) call dscal( G, one/dble(n), pro, 1)
if (Vinv .ge. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
else if (EQPRO) then
call dcopy( G, one/dble(G), 0, pro, 1)
end if
lwork = 0
c w(1) = smin
tol(1) = err
tol(2) = errin
eps = FLMAX
maxi(1) = -1
maxi(2) = -1
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
tol(1) = err
tol(2) = errin
eps = FLMAX
maxi(1) = -1
maxi(2) = -1
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (Vinv .le. zero) then
call dcopy (G, temp/dble(n), 0, scale, 1)
else
call dcopy (G, temp/sumz, 0, scale, 1)
end if
if (temp .le. eps) then
if (.not. EQPRO) call dscal( G, one/dble(n), pro, 1)
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
else
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
lwork = 0
c w(1) = temp
c w(2) = zero
tol(1) = err
tol(2) = errin
eps = FLMAX
maxi(1) = -1
maxi(2) = -1
return
end if
call dscal( p, one/temp, shape, 1)
end if
c inner iteration to estimate scale and shape
c pro now contains n*pro
inner = 0
errin = zero
if (maxi2 .le. 0) goto 120
110 continue
call dcopy( p, shape, 1, w , 1)
call dcopy( G, scale, 1, w(p1), 1)
call dcopy( p, zero, 0, shape, 1)
do k = 1, G
sum = zero
do j = 1, p
sum = sum + z(j,k)/w(j)
end do
temp = sum/(pro(k)*dble(p))
scale(k) = temp
if (temp .le. eps) then
lwork = 0
c w(1) = temp
tol(1) = err
tol(2) = errin
eps = FLMAX
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
do j = 1, p
shape(j) = shape(j) + z(j,k)/temp
end do
end do
inner = inner + 1
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
if (.not. EQPRO) call dscal( G, one/dble(n), pro, 1)
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
else
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
lwork = 0
c w(1) = smin
tol(1) = err
tol(2) = errin
eps = FLMAX
maxi(1) = iter
maxi(2) = max(inner,inmax)
return
end if
c normalize the shape matrix
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
tol(1) = err
tol(2) = errin
eps = FLMAX
maxi(1) = -1
maxi(2) = -1
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (temp .le. eps) then
if (.not. EQPRO) call dscal( G, one/dble(n), pro, 1)
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
else
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
lwork = 0
c w(1) = temp
tol(1) = err
tol(2) = errin
eps = FLMAX
maxi(1) = iter
maxi(2) = max(inner,inmax)
end if
call dscal( p, one/temp, shape, 1)
errin = zero
do j = 1, p
errin = max(abs(w(j)-shape(j))/(one+shape(j)), errin)
end do
do k = 1, G
errin = max(abs(scale(k)-w(p+k))/(one+scale(k)), errin)
end do
if (errin .ge. tol2 .and. inner .lt. maxi2) goto 110
120 continue
inmax = max(inner,inmax)
smin = smin/temp
smax = smax/temp
if (.not. EQPRO) call dscal( G, one/dble(n), pro, 1)
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
else
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. eps) then
lwork = 0
c w(1) = -smin
tol(1) = err
tol(2) = errin
eps = FLMAX
maxi(1) = iter
maxi(2) = inmax
return
end if
call sgnrng( G, scale, 1, smin, smax)
if (smin .le. eps) then
lwork = 0
c w(1) = -smin
tol(1) = err
tol(2) = errin
eps = FLMAX
maxi(1) = iter
maxi(2) = inmax
return
end if
do j = 1, p
s(j) = sqrt(shape(j))
end do
call sgnrng( p, s, 1, smin, smax)
if (smin .le. rteps) then
lwork = 0
c w(1) = -smin
tol(1) = err
tol(2) = errin
eps = FLMAX
maxi(1) = iter
maxi(2) = inmax
return
end if
do k = 1, G
c prok = pro(k)
scalek = scale(k)
const = dble(p)*(pi2log + log(scalek))
do i = 1, n
call dcopy( p, x(i,1), n, w(p1), 1)
call daxpy( p, (-one), mu(1,k), 1, w(p1), 1)
call dgemv( 'N', p, p, one, O(1,1,k), p, w(p1), 1, zero, w, 1)
do j = 1, p
w(j) = w(j) / s(j)
end do
sum = ddot(p,w,1,w,1)/scalek
c z(i,k) = prok*exp(-(const+sum)/two)
z(i,k) = -(const+sum)/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol1 .and. iter .lt. maxi1) goto 100
c smin = sqrt(smin)
c smax = sqrt(smax)
c rcmin = FLMAX
c do k = 1, G
c temp = sqrt(scale(k))
c rcmin = min(rcmin,(temp*smin)/(one+temp*smax))
c end do
lwork = 0
c w(1) = rcmin
tol(1) = err
tol(2) = errin
eps = hood
maxi(1) = iter
maxi(2) = inmax
return
end
subroutine mevevp( EQPRO, x, n, p, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps, lwork,
* mu, scale, shape, O, pro, w, s)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi(2), lwork
c double precision pshrnk, pmu(p), pscale(p,p), pdof
double precision pshrnk, pmu(*), pscale(p,*), pdof
double precision Vinv, eps, tol(2)
c double precision x(n,p), z(n,G[+1]), w(lwork), s(p)
double precision x(n,*), z(n, * ), w( * ), s(*)
c double precision mu(p,G), pro(G[+1])
double precision mu(p,*), pro( * )
c double precision scale(G), shape(p), O(p,p,G)
double precision scale(*), shape(*), O(p,p,*)
integer maxi1, maxi2, p1, inmax, iter
integer nz, i, j, k, l, j1, info, inner
double precision tol1, tol2, dnp, term, rteps, ViLog
double precision errin, smin, smax, sumz, tmin, tmax
double precision cs, sn, dummy, hold, hood, err, zsum
double precision const, temp, sum, prok, scalek
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
pdof = pdof*1.d0
maxi1 = maxi(1)
maxi2 = maxi(2)
if (maxi1 .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
end if
eps = max(eps,zero)
rteps = sqrt(eps)
tol1 = max(tol(1),zero)
tol2 = max(tol(2),zero)
p1 = p + 1
dnp = dble(n*p)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
errin = FLMAX
inmax = 0
inner = 0
iter = 0
100 continue
zsum = one
l = 0
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
do j = 1, p
call dcopy( p, pscale(1,j), 1, O(1,j,k), 1)
end do
sumz = zero
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sumz / dble(n)
zsum = min(zsum,sumz)
if (sumz .gt. rteps) then
call dscal( p, (one/sumz), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
end do
call dcopy( p, pmu, 1, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
term = sumz+pshrnk
const = (sumz*pshrnk)/term
call dscal( p, sqrt(const), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
call dscal( p, sumz/term, mu(1,k), 1)
call daxpy( p, pshrnk/term, pmu, 1, mu(1,k), 1)
call dgesvd( 'N', 'O', p, p, O(1,1,k), p, z(1,k),
* dummy, 1, dummy, 1, w, lwork, info)
if (info .ne. 0) then
l = info
else
do j = 1, p
temp = z(j,k)
z(j,k) = temp*temp
end do
end if
end if
end do
iter = iter + 1
if (l .ne. 0 .or. zsum .le. rteps) then
lwork = l
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
if (l .ne. 0) then
eps = FLMAX
else
eps = -FLMAX
end if
goto 200
end if
if (iter .eq. 1) then
call dcopy( p, zero, 0, shape, 1)
do j = 1, p
sum = zero
do k = 1, G
sum = sum + z(j,k)
end do
shape(j) = sum
end do
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
eps = FLMAX
goto 200
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
eps = FLMAX
goto 200
return
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
do k = 1, G
scale(k) = temp / (pro(k)*dble(n))
end do
if (temp .le. eps) then
eps = FLMAX
goto 200
return
end if
call dscal( p, one/temp, shape, 1)
end if
inner = 0
errin = zero
if (maxi2 .le. 0) goto 120
110 continue
call dcopy( p, shape, 1, w , 1)
call dcopy( G, scale, 1, w(p1), 1)
call sgnrng( p+G, w, 1, smin, smax)
if (smin .le. zero) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
call dcopy( p, zero, 0, shape, 1)
do k = 1, G
sum = zero
do j = 1, p
if (w(j) .le. z(j,k) .and. z(j,k) .lt. w(j)*rteps) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
sum = sum + z(j,k)/w(j)
end do
temp = sum/(pro(k)*dble(n*p))
scale(k) = temp
do j = 1, p
if (temp .le. z(j,k) .and. z(j,k) .lt. temp*rteps) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
shape(j) = shape(j) + z(j,k)/temp
end do
end do
inner = inner + 1
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
eps = FLMAX
goto 200
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
eps = FLMAX
goto 200
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (temp .le. eps) then
eps = FLMAX
goto 200
end if
call dscal( p, one/temp, shape, 1)
errin = zero
do j = 1, p
errin = max(abs(w(j)-shape(j))/(one+shape(j)), errin)
end do
do k = 1, G
errin = max(abs(scale(k)-w(p+k))/(one+scale(k)), errin)
end do
if (errin .ge. tol2 .and. inner .lt. maxi2) goto 110
120 continue
inmax = max(inner,inmax)
smin = smin/temp
smax = smax/temp
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
else
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
goto 200
return
end if
call sgnrng( G, scale, 1, smin, smax)
if (smin .le. eps) then
eps = FLMAX
goto 200
return
end if
do j = 1, p
s(j) = sqrt(shape(j))
end do
call sgnrng( p, s, 1, smin, smax)
if (smin .le. rteps) then
eps = FLMAX
goto 200
return
end if
do k = 1, G
c prok = pro(k)
scalek = scale(k)
const = dble(p)*(pi2log + log(scalek))
do i = 1, n
call dcopy( p, x(i,1), n, w(p1), 1)
call daxpy( p, (-one), mu(1,k), 1, w(p1), 1)
call dgemv( 'N', p, p, one, O(1,1,k), p, w(p1), 1, zero, w, 1)
do j = 1, p
w(j) = w(j) / s(j)
end do
sum = ddot(p,w,1,w,1)/scalek
c z(i,k) = prok*exp(-(const+sum)/two)
z(i,k) = -(const+sum)/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol1 .and. iter .lt. maxi1) goto 100
c smin = sqrt(smin)
c smax = sqrt(smax)
c rcmin = FLMAX
c do k = 1, G
c temp = sqrt(scale(k))
c rcmin = min(rcmin,(temp*smin)/(one+temp*smax))
c end do
c w(1) = rcmin
lwork = 0
eps = hood
200 continue
tol(1) = err
tol(2) = errin
maxi(1) = iter
maxi(2) = inmax
return
end
subroutine msvev ( x, z, n, p, G, w, lwork, maxi, tol,
* mu, scale, shape, O, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G, maxi, lwork
double precision tol
c double precision x(n,p), z(n,G), w(max(4*p,5*p-4,p+G))
double precision x(n,*), z(n,*), w(*)
c double precision scale(G), shape(p), O(p,p,G), mu(p,G), pro(G)
double precision scale(*), shape(*), O(p,p,*), mu(p,*), pro(*)
integer p1, i, j, k, j1, inner, info
double precision err, dummy
double precision temp, sum, smin, smax, cs, sn
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision BIGLOG
parameter (BIGLOG = 709.d0)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
tol = max(tol,zero)
p1 = p + 1
err = FLMAX
inner = 0
call dcopy( p, zero, 0, shape, 1)
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
do j = 1, p
call dcopy( p, zero, 0, O(1,j,k), 1)
end do
sum = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sum
if (sum .ge. one .or. one .lt. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
if (lwork .gt. 0) then
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
end do
call dgesvd( 'N', 'O', p, p, O(1,1,k), p, z(1,k),
* dummy, 1, dummy, 1, w, lwork, info)
if (info .ne. 0) then
inner = info
else
do j = 1, p
temp = z(j,k)
temp = temp*temp
shape(j) = shape(j) + temp
z(j,k) = temp
end do
end if
end if
else
err = zero
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
c inner iteration estimates scale and shape
c pro now contains n*pro
if (inner .ne. 0 .or. err .eq. zero) then
lwork = inner
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
lwork = 0
call sgnrng( p, shape, 1, smin, smax)
if (smin .eq. zero) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
do k = 1, G
scale(k) = temp / (pro(k)*dble(n))
end do
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
call dscal( p, one/temp, shape, 1)
c iteration to estimate scale and shape
c pro now contains n*pro
if (maxi .le. 0) goto 200
100 continue
call dcopy( p, shape, 1, w , 1)
call dcopy( G, scale, 1, w(p1), 1)
call absrng( p, w, 1, smin, smax)
if (smin .le. one .and. one .ge. smin*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
call dcopy( p, zero, 0, shape, 1)
do k = 1, G
sum = zero
do j = 1, p
sum = sum + z(j,k)/w(j)
end do
temp = (sum/pro(k))/dble(p)
scale(k) = temp
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
do j = 1, p
shape(j) = shape(j) + z(j,k)/temp
end do
end do
inner = inner + 1
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
c normalize the shape matrix
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .ge. BIGLOG) then
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
call dscal( p, one/temp, shape, 1)
err = zero
do j = 1, p
err = max(abs(w(j)-shape(j))/(one+shape(j)), err)
end do
do k = 1, G
err = max(abs(scale(k)-w(p+k))/(one+scale(k)), err)
end do
if (err .ge. tol .and. inner .lt. maxi) goto 100
200 continue
call dscal( G, one/dble(n), pro, 1)
tol = err
maxi = inner
return
end
subroutine msvevp( x, z, n, p, G,
* pshrnk, pmu, pscale, pdof,
* w, lwork, maxi, tol,
* mu, scale, shape, O, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G, maxi, lwork
c double precision pshrnk, pmu(p), pscale(p,p), pdof
double precision pshrnk, pmu(*), pscale(p,*), pdof
double precision tol
c double precision x(n,p), z(n,G), w(lwork)
double precision x(n,*), z(n,*), w( * )
c double precision mu(p,G), pro(G)
double precision mu(p,*), pro(*)
c double precision scale(G), shape(p), O(p,p,G)
double precision scale(*), shape(*), O(p,p,*)
integer p1, i, j, k, l, j1, inner, info
double precision sum, term, temp, err, smin, smax
double precision sumz, cs, sn, dummy, const
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (pshrnk .le. zero) pshrnk = zero
pdof = pdof*1.d0
tol = max(tol,zero)
p1 = p + 1
err = FLMAX
inner = 0
l = 0
call dcopy( p, zero, 0, shape, 1)
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
do j = 1, p
call dcopy( p, pscale(1,j), 1, O(1,j,k), 1)
end do
sumz = zero
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sumz / dble(n)
if (sumz .ge. one .or. one .lt. sumz*FLMAX) then
call dscal( p, (one/sumz), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
end do
call dcopy( p, pmu, 1, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
term = sumz+pshrnk
const = (sumz*pshrnk)/term
call dscal( p, sqrt(const), w, 1)
j = 1
do j1 = 2, p
call drotg( O(j,j,k), w(j), cs, sn)
call drot( p-j, O(j,j1,k), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( O(p,p,k), w(p), cs, sn)
call dscal( p, sumz/term, mu(1,k), 1)
call daxpy( p, pshrnk/term, pmu, 1, mu(1,k), 1)
call dgesvd( 'N', 'O', p, p, O(1,1,k), p, z(1,k),
* dummy, 1, dummy, 1, w, lwork, info)
if (info .ne. 0) then
l = info
else
do j = 1, p
temp = z(j,k)
temp = temp*temp
shape(j) = shape(j) + temp
z(j,k) = temp
end do
end if
else
err = zero
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (l .ne. 0 .or. err .eq. zero) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
do k = 1, G
scale(k) = temp / (pro(k)*dble(n))
end do
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
call dscal( p, one/temp, shape, 1)
if (maxi .le. 0) goto 200
100 continue
call dcopy( p, shape, 1, w , 1)
call dcopy( G, scale, 1, w(p1), 1)
call sgnrng( p+G, w, 1, smin, smax)
if (smin .le. zero) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
call dcopy( p, zero, 0, shape, 1)
do k = 1, G
sum = zero
do j = 1, p
if (w(j) .le. z(j,k) .and. z(j,k) .ge. w(j)*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
sum = sum + z(j,k)/w(j)
end do
temp = sum/(pro(k)*dble(n*p))
scale(k) = temp
do j = 1, p
if (temp .le. z(j,k) .and. z(j,k) .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
call dcopy( G, FLMAX, 0, scale, 1)
goto 200
end if
shape(j) = shape(j) + z(j,k)/temp
end do
end do
inner = inner + 1
call sgnrng( p, shape, 1, smin, smax)
if (smin .le. zero) then
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .ge. BIGLOG) then
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
if (temp .ge. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
goto 200
end if
call dscal( p, one/temp, shape, 1)
err = zero
do j = 1, p
err = max(abs(w(j)-shape(j))/(one+shape(j)), err)
end do
do k = 1, G
err = max(abs(scale(k)-w(p+k))/(one+scale(k)), err)
end do
if (err .ge. tol .and. inner .lt. maxi) goto 100
200 continue
lwork = l
tol = err
maxi = inner
return
end
subroutine esvii ( x, mu, sigsq, pro, n, p, G, Vinv, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
double precision hood, Vinv
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), sigsq(G), pro(G[+1])
double precision mu(p,*), sigsq(*), pro( * )
integer i, j, k, nz
double precision sum, temp, const, tmin, tmax
double precision prok, sigsqk, sigmin
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMAX
parameter (RTMAX = 1.340780792994260d154)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
call sgnrng( G, sigsq, 1, sigmin, temp)
if (sigmin .le. zero) then
hood = FLMAX
return
end if
do k = 1, G
c prok = pro(k)
sigsqk = sigsq(k)
const = dble(p)*(pi2log+log(sigsq(k)))
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
if (abs(temp) .ge. RTMAX) then
hood = FLMAX
return
end if
if (abs(temp) .gt. RTMIN) sum = sum + temp*temp
end do
c z(i,k) = prok*exp(-(const+sum/sigsqk)/two)
if (sigsqk .lt. one .and. sum .ge. sigsqk*FLMAX) then
hood = FLMAX
return
end if
z(i,k) = -(const+sum/sigsqk)/two
end do
end do
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c sum = zero
c do k = 1, nz
c sum = sum + z(i,k)
c end do
c hood = hood + log(sum)
c call dscal( nz, (one/sum), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
return
end
subroutine hcvii ( x, n, p, ic, ng, ns, ALPHA, v, nd, d)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, ic(n), ng, ns, nd
c double precision x(n,p), v(p). d(*), ALPHA
double precision x(n,*), v(*), d(*), ALPHA
integer lg, ld, ll, lo, ls, i, j, k, m
integer ni, nj, nij, nopt, niop, njop
integer ij, ici, icj, iopt, jopt, iold
double precision ALFLOG
double precision qi, qj, qij, ri, rj, rij, si, sj
double precision tracei, tracej, trcij, trop
double precision termi, termj, trmij, tmop
double precision dij, dopt, siop, sjop
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision sqrthf
parameter (sqrthf = .70710678118654757274d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision EPSMAX
parameter (EPSMAX = 2.2204460492503131d-16)
double precision ddot
external ddot
c------------------------------------------------------------------------------
iopt = 0
niop = 0
njop = 0
nopt = 0
tmop = 0.d0
trop = 0.d0
lg = ng
ld = (ng*(ng-1))/2
ll = nd-ng
lo = nd
if (ng .eq. 1) return
ALPHA = max(ALPHA,EPSMAX)
ALFLOG = log(ALPHA)
c call intpr( 'ic', -1, ic, n)
c group heads should be first among rows of x
i = 1
j = 2
1 continue
icj = ic(j)
if (icj .ne. j) goto 2
if (j .eq. lg) goto 3
i = j
j = j + 1
goto 1
2 continue
k = i
m = j + 1
do j = m, n
icj = ic(j)
if (icj .gt. k) then
k = k + 1
call dswap( p, x(k,1), n, x(j,1), n)
ic(j) = ic(k)
ic(k) = icj
end if
end do
3 continue
c set up pointers
do j = 1, n
i = ic(j)
if (i .ne. j) then
c update sum of squares
k = ic(i)
if (k .eq. 1) then
ic(i) = j
ic(j) = 2
call dscal( p, sqrthf, x(i,1), n)
call dscal( p, sqrthf, x(j,1), n)
call dcopy( p, x(j,1), n, v, 1)
call daxpy( p, (-one), x(i,1), n, v, 1)
call daxpy( p, one, x(j,1), n, x(i,1), n)
c call dcopy( p, FLMAX, 0, x(j,1), n)
c x(j,1) = ddot( p, v, 1, v, 1) / two
x(j,1) = ddot( p, v, 1, v, 1)
else
ic(j) = 0
ni = ic(k)
ic(k) = ni + 1
ri = dble(ni)
rij = dble(ni+1)
qj = one/rij
qi = ri*qj
si = sqrt(qi)
sj = sqrt(qj)
call dcopy( p, x(j,1), n, v, 1)
call dscal( p, si, v, 1)
call daxpy( p, (-sj), x(i,1), n, v, 1)
c x(k,1) = qi*x(k,1) + qj*ddot(p, v, 1, v, 1)
x(k,1) = x(k,1) + ddot(p, v, 1, v, 1)
call dscal( p, si, x(i,1), n)
call daxpy( p, sj, x(j,1), n, x(i,1), n)
c call dcopy( p, FLMAX, 0, x(j,1), n)
end if
else
ic(j) = 1
end if
end do
c store terms also so as not to recompute them
do k = 1, ng
i = ic(k)
if (i .ne. 1) then
ni = ic(i)
ri = dble(ni)
c x(i,2) = ri*log(x(i,1)+ALPHA)
x(i,2) = ri*log((x(i,1)+ALPHA)/ri)
end if
end do
c call intpr( 'ic', -1, ic, n)
c call dblepr( 'trace', -1, x(1,1), n)
c call dblepr( 'term', -1, x(1,2), n)
c compute change in likelihood and determine minimum
dopt = FLMAX
ij = 0
do j = 2, ng
nj = ic(j)
if (nj .eq. 1) then
tracej = zero
termj = ALFLOG
rj = one
else
tracej = x(nj,1)
termj = x(nj,2)
nj = ic(nj)
rj = dble(nj)
end if
do i = 1, (j-1)
ni = ic(i)
if (ni .eq. 1) then
tracei = zero
termi = ALFLOG
ri = one
else
tracei = x(ni,1)
termi = x(ni,2)
ni = ic(ni)
ri = dble(ni)
end if
nij = ni + nj
rij = dble(nij)
qij = one/rij
qi = ri*qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
call dcopy(p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
c trcij = (qi*tracei + qj*tracej) + qij*ddot(p,v,1,v,1)
trcij = (tracei + tracej) + ddot(p,v,1,v,1)
c trmij = rij*log(trcij+ALPHA)
trmij = rij*log((trcij+ALPHA)/rij)
dij = trmij - (termi + termj)
ij = ij + 1
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
trop = trcij
tmop = trmij
nopt = nij
niop = ni
njop = nj
siop = si
sjop = sj
iopt = i
jopt = j
end if
end do
end do
c call dblepr( 'dij', -1, d, (l*(l-1))/2)
if (ns .eq. 1) then
if (iopt .lt. jopt) then
x(1,1) = dble(iopt)
x(1,2) = dble(jopt)
else
x(1,1) = dble(jopt)
x(1,2) = dble(iopt)
end if
d(1) = dopt
return
end if
if (niop .ne. 1) ic(ic(iopt)) = 0
if (njop .ne. 1) ic(ic(jopt)) = 0
ls = 1
100 continue
c if (.false.) then
c ij = 1
c jj = 1
c do j = 2, n
c nj = ic(j)
c if (nj .ne. 0 .and. abs(nj) .le. n) then
c call dblepr( 'dij', -1, d(ij), jj)
c ij = ij + jj
c jj = jj + 1
c end if
c end do
c end if
call dscal( p, siop, x(iopt,1), n)
call daxpy( p, sjop, x(jopt,1), n, x(iopt,1), n)
if (jopt .ne. lg) then
call wardsw( jopt, lg, d)
call dcopy( p, x(lg,1), n, x(jopt,1), n)
m = ic(jopt)
ic(jopt) = ic(lg)
ic(lg) = m
end if
ic(iopt) = lg
ic(lg) = nopt
x(lg,1) = trop
x(lg,2) = tmop
d(lo) = dopt
lo = lo - 1
d(lo) = dble(iopt)
lo = lo - 1
d(lo) = dble(jopt)
lo = lo - 1
lg = lg - 1
ld = ld - lg
iold = iopt
iopt = -1
jopt = -1
dopt = FLMAX
ni = nopt
ri = dble(ni)
tracei = trop
termi = tmop
ij = ((iold-1)*(iold-2))/2
if (iold .gt. 1) then
do j = 1, (iold - 1)
nj = ic(j)
if (nj .ne. 1) then
tracej = x(nj,1)
termj = x(nj,2)
nj = ic(nj)
rj = dble(nj)
else
tracej = zero
termj = ALFLOG
rj = one
end if
nij = ni + nj
rij = dble(nij)
qij = one/rij
qi = ri*qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
call dcopy( p, x(iold,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
c trcij = (qi*tracei + qj*tracej) + qij*ddot(p,v,1,v,1)
trcij = (tracei + tracej) + ddot(p,v,1,v,1)
c trmij = rij*log(trcij+ALPHA)
trmij = rij*log((trcij+ALPHA)/rij)
dij = trmij - (termi + termj)
ij = ij + 1
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
trop = trcij
tmop = trmij
iopt = j
jopt = iold
nopt = nij
niop = ni
njop = nj
sjop = si
siop = sj
end if
end do
end if
if (iold .lt. lg) then
i = iold
ij = ij + i
do j = (iold + 1), lg
nj = ic(j)
if (nj .ne. 1) then
tracej = x(nj,1)
termj = x(nj,2)
nj = ic(nj)
rj = dble(nj)
else
tracej = zero
termj = ALFLOG
rj = one
end if
nij = ni + nj
rij = dble(nij)
qij = one /rij
qi = ri*qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
call dcopy( p, x(iold,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
c trcij = (qi*tracei + qj*tracej) + qij*ddot(p,v,1,v,1)
trcij = (tracei + tracej) + ddot(p,v,1,v,1)
c trmij = rij*log(trcij+ALPHA)
trmij = rij*log((trcij+ALPHA)/rij)
dij = trmij - (termi + termj)
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
trop = trcij
tmop = trmij
iopt = iold
jopt = j
nopt = nij
niop = ni
njop = nj
siop = si
sjop = sj
end if
ij = ij + i
i = j
end do
end if
c update d and find max
jopt = 2
iopt = 1
dopt = d(1)
if (lg .eq. 2) goto 900
ij = 1
dopt = d(1)
do i = 2, ld
qi = d(i)
if (qi .le. dopt) then
ij = i
dopt = qi
end if
end do
if (ij .gt. 1) then
do i = 2, ij
iopt = iopt + 1
if (iopt .ge. jopt) then
jopt = jopt + 1
iopt = 1
end if
end do
end if
i = ic(iopt)
j = ic(jopt)
if (iopt .ne. iold .and. jopt .ne. iold) then
if (i .ne. 1) then
tracei = x(i,1)
termi = x(i,2)
niop = ic(i)
ri = dble(niop)
else
tracei = zero
termi = ALFLOG
niop = 1
ri = one
end if
if (j .ne. 1) then
tracej = x(j,1)
termj = x(j,2)
njop = ic(j)
rj = dble(njop)
else
tracej = zero
termj = ALFLOG
njop = 1
rj = one
end if
nopt = niop + njop
rij = dble(nopt)
qij = one/rij
qi = ri*qij
qj = rj*qij
siop = sqrt(qi)
sjop = sqrt(qj)
call dcopy( p, x(iopt,1), n, v, 1)
call dscal( p, sjop, v, 1)
call daxpy( p, (-siop), x(jopt,1), n, v, 1)
c trop = (qi*tracei + qj*tracej) + qij*ddot(p,v,1,v,1)
trop = (tracei + tracej) + ddot(p,v,1,v,1)
c tmop = rij*log(trop+ALPHA)
tmop = rij*log((trop+ALPHA)/rij)
end if
ls = ls + 1
if (ls .eq. ns) goto 900
goto 100
900 continue
d(lo) = dopt
lo = lo - 1
d(lo) = dble(iopt)
lo = lo - 1
d(lo) = dble(jopt)
do i = 1, ng
ic(i) = i
end do
lo = nd - 1
ld = lo
si = d(lo)
lo = lo - 1
sj = d(lo)
ic(int(sj)) = ng
if (si .lt. sj) then
x(1,1) = si
x(1,2) = sj
else
x(1,1) = sj
x(1,2) = si
end if
lg = ng + 1
do k = 2, ns
lo = lo - 1
d(ld) = d(lo)
ld = ld - 1
lo = lo - 1
i = int(d(lo))
ici = ic(i)
lo = lo - 1
j = int(d(lo))
icj = ic(j)
if (ici .gt. icj) ic(i) = icj
ic(j) = ic(lg-k)
if (ici .lt. icj) then
x(k,1) = dble(ici)
x(k,2) = dble(icj)
else
x(k,1) = dble(icj)
x(k,2) = dble(ici)
end if
end do
ld = nd
lo = 1
do k = 1, ns
si = d(lo)
d(lo) = d(ld)
d(ld) = si
ld = ld - 1
lo = lo + 1
end do
return
end
subroutine mevii ( EQPRO, x, n, p, G, Vinv, z, maxi, tol, eps,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
double precision Vinv, eps, tol
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), sigsq(G), pro(G[+1])
double precision mu(p,*), sigsq(*), pro( * )
integer nz, iter, i, j, k
double precision sumz, sum, temp, const, term, zsum
double precision sigmin, sigsqk, hold, hood, err
double precision prok, tmin, tmax, ViLog, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
zsum = one
do k = 1, G
sumz = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
if (.not. EQPRO) pro(k) = sumz / dble(n)
zsum = min(sumz,zsum)
if (sumz .gt. rteps) then
call dscal( p, (one/sumz), mu(1,k), 1)
sigsqk = zero
do i = 1, n
sum = zero
do j = 1, p
temp = abs(x(i,j) - mu(j,k))
if (temp .gt. RTMIN) sum = sum + temp*temp
end do
if (sqrt(z(i,k))*sqrt(sum) .gt. RTMIN)
* sigsqk = sigsqk + z(i,k)*sum
z(i,k) = sum
end do
sigsq(k) = (sigsqk/sumz)/dble(p)
else
sigsq(k) = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
call sgnrng( G, sigsq, 1, sigmin, temp)
if (sigmin .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
do k = 1, G
c temp = pro(k)
sigsqk = sigsq(k)
const = dble(p)*(pi2log+log(sigsqk))
do i = 1, n
c z(i,k) = temp*exp(-(const+z(i,k)/sigsqk)/two)
z(i,k) = -(const+z(i,k)/sigsqk)/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
const = zero - tmax
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) + const
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)-const)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine meviip( EQPRO, x, n, p, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
double precision Vinv, eps, tol
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), sigsq(G), pro(G[+1])
double precision mu(p,*), sigsq(*), pro( * )
integer nz, iter, i, j, k
double precision sumz, sum, temp, const, term, zsum
double precision sigmin, sigsqk, hold, hood, err
double precision prok, tmin, tmax, ViLog, rteps
double precision pmupmu, cmu, cgam, rmu, rgam
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision ddot, dlngam
external ddot, dlngam
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
pmupmu = ddot(p,pmu,1,pmu,1)
100 continue
iter = iter + 1
zsum = one
do k = 1, G
sumz = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
if (.not. EQPRO) pro(k) = sumz / dble(n)
zsum = min(sumz,zsum)
if (sumz .gt. rteps) then
call dscal( p, (one/sumz), mu(1,k), 1)
sigsqk = pscale
do i = 1, n
sum = zero
do j = 1, p
temp = abs(x(i,j) - mu(j,k))
if (temp .gt. RTMIN) sum = sum + temp*temp
end do
if (sqrt(z(i,k))*sqrt(sum) .gt. RTMIN)
* sigsqk = sigsqk + z(i,k)*sum
end do
temp = pmupmu + ddot(p, mu(1,k), 1, mu(1,k), 1)
temp = temp - two*ddot(p,mu(1,k),1,pmu,1)
const = sumz+pshrnk
sigsqk = sigsqk + ((sumz*pshrnk)/const) * temp
c sigsq(k) = sigsqk/(pdof+(sumz+one)*dble(p)+two)
temp = pdof+sumz*dble(p)+two
if (pshrnk .gt. zero) temp = temp + dble(p)
sigsq(k) = sigsqk/temp
call dscal( p, sumz/const, mu(1,k), 1)
call daxpy( p, pshrnk/const, pmu, 1, mu(1,k), 1)
else
sigsq(k) = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
call sgnrng( G, sigsq, 1, sigmin, temp)
if (sigmin .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
do k = 1, G
sigsqk = sigsq(k)
const = dble(p)*(pi2log+log(sigsqk))
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + temp*temp
end do
z(i,k) = -(const+sum/sigsqk)/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
const = zero - tmax
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) + const
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)-const)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
if (pshrnk .gt. zero) then
cmu = dble(p)*(log(pshrnk)-pi2log)/two
const = pdof/two
cgam = const*log(pscale/two)-dlngam(const)
rmu = zero
rgam = zero
do k = 1, G
term = log(sigsq(k))
temp = pmupmu + ddot( p, mu(1,k), 1, mu(1,k), 1)
temp = temp - two*ddot( p, mu(1,k), 1, pmu, 1)
rmu = rmu + (pshrnk*temp)/sigsq(k)
rgam = rgam + ((pdof+3.d0)*term - (pscale/sigsq(k)))
end do
rmu = -rmu /two
rgam = -rgam/two
pdof = (dble(G)*cmu+rmu) + (dble(G)*cgam+rgam)
else
pdof = FLMAX
end if
return
end
subroutine msvii ( x, z, n, p, G, mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision x(n,p), z(n,G), mu(p,G), sigsq(G), pro(G)
double precision x(n,*), z(n,*), mu(p,*), sigsq(*), pro(*)
integer i, j, k
double precision sum, sumz, temp, sigsqk
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
c------------------------------------------------------------------------------
do k = 1, G
sumz = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sumz / dble(n)
if (sumz .ge. one .or. one .le. sumz*FLMAX) then
call dscal( p, (one/sumz), mu(1,k), 1)
sigsqk = zero
do i = 1, n
sum = zero
do j = 1, p
temp = abs(x(i,j) - mu(j,k))
if (temp .gt. RTMIN) sum = sum + temp*temp
end do
if (sqrt(z(i,k))*sqrt(sum) .gt. RTMIN)
* sigsqk = sigsqk + z(i,k)*sum
end do
temp = sumz*dble(p)
if (temp .ge. one .or. sigsqk .le. temp*FLMAX) then
sigsq(k) = sigsqk/temp
else
sigsq(k) = FLMAX
end if
else
sigsq(k) = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
return
end
subroutine msviip( x, z, n, p, G,
* pshrnk, pmu, pscale, pdof,
* mu, sigsq, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
c double precision x(n,p), z(n,G)
double precision x(n,*), z(n,*)
c double precision mu(p,G), sigsq(G), pro(G)
double precision mu(p,*), sigsq(*), pro(*)
integer i, j, k
double precision sumz, sum, temp
double precision sigsqk, const, pmupmu
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision ddot
external ddot
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
pmupmu = ddot(p,pmu,1,pmu,1)
do k = 1, G
sumz = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sumz / dble(n)
if (sumz .ge. one .or. one .lt. sumz*FLMAX) then
call dscal( p, (one/sumz), mu(1,k), 1)
sigsqk = pscale
do i = 1, n
sum = zero
do j = 1, p
temp = abs(x(i,j) - mu(j,k))
if (temp .gt. RTMIN) sum = sum + temp*temp
end do
if (sqrt(z(i,k))*sqrt(sum) .gt. RTMIN)
* sigsqk = sigsqk + z(i,k)*sum
end do
temp = pmupmu + ddot(p, mu(1,k), 1, mu(1,k), 1)
temp = temp - two*ddot(p,mu(1,k),1,pmu,1)
const = sumz+pshrnk
sigsqk = sigsqk + ((sumz*pshrnk)/const) * temp
temp = pdof+sumz*dble(p)+two
if (pshrnk .gt. zero) temp = temp + dble(p)
sigsq(k) = sigsqk/temp
call dscal( p, sumz/const, mu(1,k), 1)
call daxpy( p, pshrnk/const, pmu, 1, mu(1,k), 1)
else
sigsq(k) = FLMAX
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
return
end
subroutine esvvi ( x, mu, scale, shape, pro, n, p, G,
* Vinv, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
double precision hood, Vinv
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), scale(G), shape(p,G), pro(G[+1])
double precision mu(p,*), scale(*), shape(p,*), pro( * )
integer i, j, k, nz
double precision sum, temp, const, tmin, tmax
double precision smin, smax, prok, scalek
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMAX
parameter (RTMAX = 1.340780792994260d154)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
c------------------------------------------------------------------------------
call sgnrng( G, scale, 1, smin, smax)
if (smin .le. zero) then
hood = FLMAX
return
end if
do k = 1, G
call sgnrng( p, shape(1,k), 1, smin, smax)
if (smin .le. zero) then
hood = FLMAX
return
end if
temp = sqrt(scale(k))
do j = 1, p
shape(j,k) = temp*sqrt(shape(j,k))
end do
end do
do k = 1, G
c prok = pro(k)
scalek = scale(k)
const = dble(p)*(pi2log+log(scalek))
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
if (shape(j,k) .lt. one .and.
* abs(temp) .ge. shape(j,k)*FLMAX) then
hood = FLMAX
return
end if
temp = temp/shape(j,k)
if (abs(temp) .gt. RTMIN) sum = sum + temp*temp
end do
c z(i,k) = prok*exp(-(const+sum)/two)
z(i,k) = -(const+sum)/two
end do
end do
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c sum = zero
c do k = 1, nz
c sum = sum + z(i,k)
c end do
c hood = hood + log(sum)
c call dscal( nz, (one/sum), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
return
end
subroutine mevvi ( EQPRO, x, n, p, G, Vinv, z, maxi, tol, eps,
* mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
double precision Vinv, eps, tol
double precision x(n,*), z(n, * )
double precision mu(p,*), scale(*), shape(p,*), pro( * )
integer nz, iter, i, j, k
double precision sum, temp, term, scalek, epsmin
double precision hold, hood, err, smin, smax, const
double precision prok, tmin, tmax, ViLog, zsum, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
end if
tol = max(tol,zero)
eps = max(eps,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
zsum = one
do k = 1, G
call dcopy( p, zero, 0, shape(1,k), 1)
call dcopy( p, zero, 0, mu(1,k), 1)
sum = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
z(i,k) = sqrt(temp)
end do
pro(k) = sum
c pro(k) now contains n_k
zsum = min(zsum,sum)
if (sum .gt. rteps) then
call dscal( p, (one/sum), mu(1,k), 1)
do j = 1, p
sum = zero
do i = 1, n
temp = z(i,k)*(x(i,j) - mu(j,k))
sum = sum + temp*temp
end do
shape(j,k) = shape(j,k) + sum
end do
end if
end do
if (zsum .le. rteps) then
call dscal( G, one/dble(n), pro, 1)
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
epsmin = FLMAX
do k = 1, G
call sgnrng(p, shape(1,k), 1, smin, smax)
epsmin = min(smin,epsmin)
if (smin .le. zero) then
scale(k) = zero
else
temp = zero
do j = 1, p
temp = temp + log(shape(j,k))
end do
temp = temp/dble(p)
if (temp .gt. BIGLOG) then
call dscal( G, one/dble(n), pro, 1)
tol = zsum
eps = FLMAX
maxi = iter
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
scale(k) = temp/pro(k)
epsmin = min(temp,epsmin)
if (temp .le. eps) then
call dscal( G, one/dble(n), pro, 1)
tol = zsum
eps = FLMAX
maxi = iter
return
end if
call dscal( p, one/temp, shape(1,k), 1)
end if
end do
if (.not. EQPRO) then
call dscal( G, one/dble(n), pro, 1)
else if (Vinv .le. zero) then
call dscal( G, one/dble(G), pro, 1)
end if
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
if (epsmin .le. eps) then
tol = err
eps = -FLMAX
maxi = iter
return
end if
call sgnrng( G, scale, 1, smin, smax)
if (smin .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
do k = 1, G
call sgnrng( p, shape(1,k), 1, smin, smax)
if (smin .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
end do
do k = 1, G
scalek = scale(k)
const = dble(p)*(pi2log + log(scalek))
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + (temp*temp)/shape(j,k)
end do
c z(i,k) = pro(k)*exp(-(const+(sum/scalek))/two)
z(i,k) = -(const+(sum/scalek))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine mevvip( EQPRO, x, n, p, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps,
* mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
double precision Vinv, eps, tol
c double precision x(n,p), z(n,G[+1])
double precision x(n,*), z(n, * )
c double precision mu(p,G), scale(G), shape(p,G), pro(G[+1])
double precision mu(p,*), scale(*), shape(p,*), pro( * )
integer nz, iter, i, j, k
double precision sumz, sum, temp, term, scalek, epsmin
double precision hold, hood, err, smin, smax, const
double precision prok, tmin, tmax, ViLog, zsum, rteps
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
end if
eps = max(eps,zero)
tol = max(tol,zero)
rteps = sqrt(eps)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
zsum = one
do k = 1, G
call dcopy( p, pscale, 0, shape(1,k), 1)
call dcopy( p, zero, 0, mu(1,k), 1)
sumz = zero
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
z(i,k) = sqrt(temp)
end do
pro(k) = sumz
zsum = min(zsum,sumz)
if (sumz .gt. rteps) then
call dscal( p, (one/sumz), mu(1,k), 1)
term = pshrnk+sumz
const = (pshrnk*sumz)/term
do j = 1, p
sum = zero
do i = 1, n
temp = z(i,k)*(x(i,j) - mu(j,k))
sum = sum + temp*temp
end do
shape(j,k) = shape(j,k) + sum
temp = pmu(j) - mu(j,k)
shape(j,k) = shape(j,k) + const*(temp*temp)
end do
call dscal( p, sumz/term, mu(1,k), 1)
call daxpy( p, pshrnk/term, pmu, 1, mu(1,k), 1)
end if
end do
if (zsum .le. rteps) then
call dscal( G, one/dble(n), pro, 1)
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
c pro(k) now contains n_k
epsmin = FLMAX
term = pdof+two
if (pshrnk .gt. zero) term = term + one
do k = 1, G
call sgnrng(p, shape(1,k), 1, smin, smax)
epsmin = min(smin,epsmin)
if (smin .eq. zero) then
scale(k) = zero
else
sum = zero
do j = 1, p
sum = sum + log(shape(j,k))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
call dscal( G, one/dble(n), pro, 1)
tol = zsum
eps = FLMAX
maxi = iter
return
end if
if (temp .gt. SMALOG) then
temp = exp(temp)
else
temp = zero
end if
c pro(k) contains n_k
scale(k) = temp/(pro(k)+term)
epsmin = min(temp,epsmin)
if (temp .le. eps) then
call dscal( G, one/dble(n), pro, 1)
tol = zsum
eps = FLMAX
maxi = iter
return
end if
call dscal( p, one/temp, shape(1,k), 1)
end if
end do
if (.not. EQPRO) then
call dscal( G, one/dble(n), pro, 1)
else if (Vinv .le. zero) then
call dcopy( G, one/dble(G), 0, pro, 1)
end if
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
if (epsmin .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
call sgnrng( G, scale, 1, smin, smax)
if (smin .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
do k = 1, G
call sgnrng( p, shape(1,k), 1, smin, smax)
if (smin .le. eps) then
tol = err
eps = FLMAX
maxi = iter
return
end if
end do
do k = 1, G
scalek = scale(k)
const = dble(p)*(pi2log + log(scalek))
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j,k)
sum = sum + (temp*temp)/shape(j,k)
end do
c z(i,k) = pro(k)*exp(-(const+(sum/scalek))/two)
z(i,k) = -(const+(sum/scalek))/two
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
tol = err
eps = hood
maxi = iter
return
end
subroutine msvvi ( x, z, n, p, G, mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision x(n,p), z(n,G)
double precision x(n,*), z(n,*)
c double precision mu(p,G), scale(G), shape(p,G), pro(G)
double precision mu(p,*), scale(*), shape(p,*), pro(*)
integer i, j, k
double precision sum, temp, smin, smax
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
do k = 1, G
call dcopy( p, zero, 0, shape(1,k), 1)
sum = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
z(i,k) = sqrt(temp)
end do
pro(k) = sum
if (sum .ge. one .or. one .lt. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
else
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
end do
c pro(k) now contains n_k
do k = 1, G
if (mu(1,k) .ne. FLMAX) then
do j = 1, p
sum = zero
do i = 1, n
temp = z(i,k)*(x(i,j) - mu(j,k))
sum = sum + temp*temp
end do
shape(j,k) = shape(j,k) + sum
end do
else
call dcopy( p, FLMAX, 0, shape(1,k), 1)
end if
end do
do k = 1, G
call sgnrng(p, shape(1,k), 1, smin, smax)
if (smin .le. zero) then
scale(k) = zero
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
if (smax .eq. FLMAX) then
scale(k) = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j,k))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
scale(k) = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
if (temp .lt. SMALOG) then
temp = zero
scale(k) = zero
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
temp = exp(temp)
if (pro(k) .lt. one .and. temp .ge. pro(k)*FLMAX) then
scale(k) = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
scale(k) = temp/pro(k)
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape(1,k), 1)
goto 100
end if
call dscal( p, one/temp, shape(1,k), 1)
100 continue
end do
call dscal( G, one/dble(n), pro, 1)
return
end
subroutine msvvip( x, z, n, p, G,
* pshrnk, pmu, pscale, pdof,
* mu, scale, shape, pro)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
c double precision x(n,p), z(n,G)
double precision x(n,*), z(n,*)
c double precision mu(p,G), scale(G), shape(p,G), pro(G)
double precision mu(p,*), scale(*), shape(p,*), pro(*)
integer i, j, k
double precision sumz, sum, temp, term
double precision smin, smax, const
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
do k = 1, G
call dcopy( p, pscale, 0, shape(1,k), 1)
sumz = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
z(i,k) = sqrt(temp)
end do
pro(k) = sumz
if (sumz .ge. one .or. one .le. sumz*FLMAX) then
call dscal( p, (one/sumz), mu(1,k), 1)
term = pshrnk+sumz
const = (pshrnk*sumz)/term
do j = 1, p
sum = zero
do i = 1, n
temp = z(i,k)*(x(i,j) - mu(j,k))
sum = sum + temp*temp
end do
shape(j,k) = shape(j,k) + sum
temp = pmu(j) - mu(j,k)
shape(j,k) = shape(j,k) + const*(temp*temp)
end do
call dscal( p, sumz/term, mu(1,k), 1)
call daxpy( p, pshrnk/term, pmu, 1, mu(1,k), 1)
else
call dcopy( p, FLMAX, 0, mu(1,k), 1)
call dcopy( p, FLMAX, 0, shape(1,k), 1)
end if
end do
c pro(k) now contains n_k
do k = 1, G
call sgnrng(p, shape(1,k), 1, smin, smax)
if (smin .le. zero) then
scale(k) = zero
call dcopy( p, FLMAX, 0, shape(1,k), 1)
else if (smax .eq. FLMAX) then
scale(k) = FLMAX
else
sum = zero
do j = 1, p
sum = sum + log(shape(j,k))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
scale(k) = FLMAX
call dcopy( p, FLMAX, 0, shape(1,k), 1)
else if (temp .lt. SMALOG) then
temp = zero
scale(k) = zero
call dcopy( p, FLMAX, 0, shape(1,k), 1)
else
temp = exp(temp)
c pro(k) contains n_k
term = pro(k) + pdof + two
if (pshrnk .gt. zero) term = term + one
scale(k) = temp/term
if (temp .ge. one .or. one .le. temp*FLMAX) then
call dscal( p, one/temp, shape(1,k), 1)
else
call dcopy( p, FLMAX, 0, shape(1,k), 1)
end if
end if
end if
end do
call dscal( G, one/dble(n), pro, 1)
return
end
subroutine esvvv ( CHOL, x, mu, Sigma, pro, n, p, G, Vinv,
* w, hood, z)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c character CHOL
logical CHOL
c integer n, p, G
integer n, p, G
double precision hood, Vinv
c double precision x(n,p), w(p), z(n,G[+1])
double precision x(n,*), w(*), z(n, * )
c double precision mu(p,G), Sigma(p,p,G), pro(G[+1])
double precision mu(p,*), Sigma(p,p,*), pro( * )
integer nz, p1, info, i, j, k
double precision const, detlog, temp, prok, tmin, tmax
double precision umin, umax, sum
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision RTMAX
parameter (RTMAX = 1.340780792994260d154)
double precision RTMIN
parameter (RTMIN = 1.49166814624d-154)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
p1 = p + 1
c if (CHOL .eq. 'N') then
if (.not. CHOL) then
do k = 1, G
call dpotrf( 'U', p, Sigma(1,1,k), p, info)
w(1) = dble(info)
if (info .ne. 0) then
hood = FLMAX
return
end if
end do
end if
do k = 1, G
call absrng( p, Sigma(1,1,k), p1, umin, umax)
if (umax .le. one .and. umax .ge. umin*RTMAX) then
w(1) = zero
hood = FLMAX
return
end if
if (umax .ge. one .and. umin .le. umax*RTMIN) then
w(1) = zero
hood = FLMAX
return
end if
end do
do k = 1, G
detlog = zero
do j = 1, p
detlog = detlog + log(abs(Sigma(j,j,k)))
end do
const = dble(p)*pi2log/two + detlog
c prok = pro(k)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dtrsv( 'U', 'T', 'N', p, Sigma(1,1,k), p, w, 1)
temp = ddot( p, w, 1, w, 1)/two
c z(i,k) = prok*exp(-(const+temp))
z(i,k) = -(const+temp)
end do
end do
w(1) = zero
if (pro(1) .lt. zero) return
nz = G
if (Vinv .gt. zero) then
nz = nz + 1
c call dcopy( n, pro(nz)*Vinv, 0, z(1,nz), 1)
call dcopy( n, log(Vinv), 0, z(1,nz), 1)
end if
c hood = zero
c do i = 1, n
c sum = zero
c do k = 1, nz
c sum = sum + z(i,k)
c end do
c hood = hood + log(sum)
c call dscal( nz, (one/sum), z(i,1), n)
c end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
if (sum .lt. one .and. one .ge. sum*FLMAX) then
w(1) = zero
hood = FLMAX
return
end if
call dscal( nz, (one/sum), z(i,1), n)
end do
w(1) = zero
return
end
subroutine hcvvv ( x, n, p, ic, ng, ns, ALPHA, BETA,
* v, u, s, r, nd, d)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, ic(n), ng, ns, nd
double precision ALPHA, BETA
c double precision x(n,p+1), v(p), u(p,p), s(p,p)
c double precision r(p,p), d(ng*(ng-1)/2)
double precision x(n,*), v(*), u(p,*), s(p,*)
double precision r(p,*), d(*)
integer psq, pm1, pp1
integer i, j, k, l, m, ij, iold
integer lg, ld, ll, lo, ls
integer ici, icj, ni, nj, nij
integer nopt, niop, njop, iopt, jopt
double precision trcij, trmij, trop, tmop
double precision traci, tracj, termi, termj
double precision qi, qj, qij, si, sj, sij, ri, rj, rij
double precision dij, dopt, siop, sjop
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision rthalf
parameter (rthalf = .7071067811865476d0)
double precision ddot, vvvtij
external ddot, vvvtij
double precision BETA0, ALPHA0, ABLOG
common /VVVMCL/ BETA0, ALPHA0, ABLOG
save /VVVMCL/
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision EPSMAX
parameter (EPSMAX = 2.2204460492503131d-16)
c------------------------------------------------------------------------------
iopt = 0
niop = 0
nopt = 0
tmop = 0.d0
trop = 0.d0
lg = ng
ld = (ng*(ng-1))/2
ll = nd-ng
lo = nd
psq = p*p
pm1 = p-1
pp1 = p+1
if (ng .eq. 1) return
ALPHA = max(ALPHA,EPSMAX)
BETA0 = BETA
ALPHA0 = ALPHA
ABLOG = log(BETA*ALPHA)
c call intpr( 'ic', -1, ic, n)
c group heads should be first among rows of x
i = 1
j = 2
1 continue
icj = ic(j)
if (icj .ne. j) goto 2
if (j .eq. ng) goto 3
i = j
j = j + 1
goto 1
2 continue
k = i
m = j + 1
do j = m, n
icj = ic(j)
if (icj .gt. k) then
k = k + 1
call dswap( p, x(k,1), n, x(j,1), n)
ic(j) = ic(k)
ic(k) = icj
end if
end do
3 continue
c set up pointers
if (ng .eq. n) goto 4
do j = n, ng+1, -1
icj = ic(j)
i = ic(icj)
ic(icj) = j
if (i .ne. icj) then
ic(j) = i
else
ic(j) = j
end if
end do
4 continue
c call intpr( 'ic', -1, ic, n)
c initialize by simulating merges
do k = 1, ng
j = ic(k)
if (j .ne. k) then
c non-singleton
call dcopy( psq, zero, 0, r, 1)
trcij = zero
l = 1
10 continue
m = l + 1
qj = one/dble(m)
qi = dble(l)*qj
si = sqrt(qi)
sj = sqrt(qj)
call dcopy( p, x(j,1), n, v, 1)
call dscal( p, si, v, 1)
call daxpy( p, (-sj), x(k,1), n, v, 1)
trcij = trcij + ddot( p, v, 1, v, 1)
call dscal( p, si, x(k,1), n)
call daxpy( p, sj, x(j,1), n, x(k,1), n)
call mclrup( m, p, v, r, p)
l = m
i = ic(j)
if (i .eq. j) goto 20
j = i
goto 10
20 continue
c d(ll+k) = trcij
c copy triangular factor into the rows of x
j = k
m = p
do i = 1, min(l-1,p)
j = ic(j)
call dcopy( m, r(i,i), p, x(j,i), n)
m = m - 1
end do
ij = j
if (l .ge. p) then
do m = p, l
icj = ic(j)
ic(j) = -k
j = icj
end do
end if
ic(ij) = n+l
x(k, pp1) = zero
if (l .ge. 2) then
x( k, pp1) = trcij
trmij = vvvtij( l, p, r, sj, trcij)
x(ic(k),pp1) = trmij
end if
else
ic(k) = 1
c d(ll+k) = zero
end if
end do
c call intpr( 'ic', -1, ic, n)
c call dblepr( '', -1, x(1,pp1), n)
c call dblepr( 'trac', -1, d(ll+1), ng)
c call dblepr( 'term', -1, term, n)
c compute change in likelihood and determine minimum
dopt = FLMAX
ij = 0
do j = 2, ng
icj = ic(j)
nj = 1
if (icj .eq. 1) then
tracj = zero
termj = ABLOG
do i = 1, (j-1)
ni = 1
ici = ic(i)
if (ici .eq. 1) then
nij = 2
rij = two
si = rthalf
sj = rthalf
sij = rthalf
call dcopy( p, x(i,1), n, v, 1)
call daxpy( p, (-one), x(j,1), n, v, 1)
call dscal( p, rthalf, v, 1)
c trcij = half*ddot( p, v, 1, v, 1)
trcij = ddot( p, v, 1, v, 1)
call dcopy( p, v, 1, u, p)
c trmij = rij*log(BETA*trcij+ALPHA)
trmij = two*log(BETA*(trcij+ALPHA)/two)
termi = ABLOG
else
m = p
l = ici
110 continue
call dcopy( m, x(l,ni), n, u(ni,ni), p)
ni = ni + 1
m = m - 1
l = ic(l)
if (l .le. n) goto 110
ni = l - n
c traci = d(ll+i)
c traci = trac(i)
c termi = vvvtrm(i,ni,n,p,ic,x,traci)
c termi = term(i)
traci = x( i , pp1)
termi = x(ic(i), pp1)
ri = dble(ni)
nij = ni + 1
rij = dble(nij)
qij = one/rij
qi = ri*qij
si = sqrt(qi)
sj = sqrt(qij)
sij = sj
call dcopy(p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
trcij = traci + ddot(p,v,1,v,1)
call mclrup( nij, p, v, u, p)
trmij = vvvtij( nij, p, u, sij, trcij)
end if
dij = trmij - (termi + termj)
ij = ij + 1
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
trop = trcij
tmop = trmij
nopt = nij
niop = ni
njop = nj
siop = si
sjop = sj
iopt = i
jopt = j
m = p
do k = 1, min(nij-1,p)
call dcopy( m, u(k,k), p, r(k,k), p)
m = m - 1
end do
end if
end do
else
m = p
l = icj
120 continue
call dcopy( m, x(l,nj), n, s(nj,nj), p)
nj = nj + 1
m = m - 1
l = ic(l)
if (l .le. n) goto 120
nj = l - n
c tracj = d(ll+j)
c termj = vvvtrm(j,nj,n,p,ic,x,tracj)
tracj = x( j , pp1)
termj = x( ic(j), pp1)
rj = dble(nj)
do i = 1, (j-1)
m = p
do k = 1, min(nj-1,p)
call dcopy( m, s(k,k), p, u(k,k), p)
m = m - 1
end do
ni = 1
ici = ic(i)
if (ici .eq. 1) then
nij = nj + 1
rij = dble(nij)
qij = one/rij
qi = qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
sij = sqrt(qij)
call dcopy(p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
trcij = tracj + ddot(p,v,1,v,1)
termi = ABLOG
else
m = p
l = ici
k = nj + 1
130 continue
call dcopy( m, x(l,ni), n, v, 1)
call mclrup( k, m, v, u(ni,ni), p)
ni = ni + 1
m = m - 1
l = ic(l)
if (l .le. n) goto 130
ni = l - n
c traci = d(ll+i)
c termi = vvvtrm(i,ni,n,p,ic,x,traci)
traci = x( i , pp1)
termi = x(ic(i), pp1)
ri = dble(ni)
nij = ni + nj
rij = dble(nij)
qij = one/rij
qi = ri*qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
sij = sqrt(qij)
call dcopy(p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
trcij = ( traci + tracj) + ddot(p,v,1,v,1)
end if
call mclrup( nij, p, v, u, p)
trmij = vvvtij( nij, p, u, sij, trcij)
dij = trmij - (termi + termj)
ij = ij + 1
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
trop = trcij
tmop = trmij
nopt = nij
niop = ni
njop = nj
siop = si
sjop = sj
iopt = i
jopt = j
m = p
do k = 1, min(nij-1,p)
call dcopy( m, u(k,k), p, r(k,k), p)
m = m - 1
end do
end if
end do
end if
end do
c if (.false.) then
c i = 1
c ij = 1
c do j = 2, ng
c call dblepr( 'dij', -1, d(ij), i)
c ij = ij + i
c i = j
c end do
c end if
if (ns .eq. 1) then
if (iopt .lt. jopt) then
x(1,1) = iopt
x(1,2) = jopt
else
x(1,1) = jopt
x(1,2) = iopt
end if
d(1) = dopt
return
end if
ls = 1
200 continue
call dcopy( p, x(iopt,1), n, v, 1)
call dscal( p, siop, v, 1)
call daxpy( p, sjop, x(jopt,1), n, v, 1)
if (jopt .ne. lg) then
call wardsw( jopt, lg, d)
call dcopy( p, x(lg,1), n, x(jopt,1), n)
m = ic(jopt)
icj = ic(lg)
if (icj .ne. 1) x( jopt, pp1) = x( lg, pp1)
ic(jopt) = icj
ic(lg) = m
end if
if (niop .eq. 1) then
ic(iopt) = lg
else
l = ic(iopt)
do k = 1, min(niop-1,p)
m = l
l = ic(l)
end do
if (l .lt. n) call intpr("l .lt. n", 8, l, 1)
ic(m) = lg
end if
l = ic(iopt)
do k = 1, min(nopt-1,p)
call dcopy( p, r(1,1), p, x(l,1), n)
m = l
l = ic(l)
end do
ic(m) = nopt + n
c call intpr('ic', 2, ic, n)
c term(iopt) = tmop
c trac(iopt) = trop
x(iopt, pp1) = zero
if (nopt .ge. 2) then
x(iopt,pp1) = trop
x(ic(iopt),pp1) = tmop
endif
call dcopy( p, v, 1, x(iopt,1), n)
d(lo) = dopt
lo = lo - 1
d(lo) = dble(iopt)
lo = lo - 1
d(lo) = dble(jopt)
lo = lo - 1
lg = lg - 1
ld = ld - lg
iold = iopt
dopt = FLMAX
ni = nopt
ri = dble(ni)
termi = tmop
traci = trop
ij = ((iold-1)*(iold-2))/2
if (iold .gt. 1) then
do j = 1, (iold-1)
call dcopy(psq, zero, 0, u, 1)
m = p
do k = 1, min(ni-1,p)
call dcopy(m, r(k,k), p, u(k,k), p)
m = m - 1
end do
nj = 1
icj = ic(j)
if (icj .eq. 1) then
nij = ni + 1
rij = dble(nij)
qij = one/rij
qi = ri*qij
si = sqrt(qi)
sj = sqrt(qij)
sij = sj
call dcopy(p, x(j,1), n, v, 1)
call dscal( p, si, v, 1)
call daxpy( p, (-sj), x(iold,1), n, v, 1)
trcij = traci + ddot(p,v,1,v,1)
tracj = zero
termj = ABLOG
else
m = p
l = icj
k = ni + 1
310 continue
call dcopy( m, x(l,nj), n, v, 1)
call mclrup( k, m, v, u(nj,nj), p)
k = k + 1
nj = nj + 1
m = m - 1
l = ic(l)
if (l .le. n) goto 310
nj = l - n
c call vvvget(j,nj,n,p,ic,x,tracj,termj)
tracj = x( j ,pp1)
termj = x(ic(j),pp1)
rj = dble(nj)
nij = ni + nj
rij = dble(nij)
qij = one/rij
qi = ri*qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
sij = sqrt(qij)
call dcopy(p, x(j,1), n, v, 1)
call dscal( p, si, v, 1)
call daxpy( p, (-sj), x(iold,1), n, v, 1)
trcij = ( traci + tracj) + ddot(p,v,1,v,1)
end if
call mclrup( nij, p, v, u, p)
trmij = vvvtij( nij, p, u, sij, trcij)
dij = trmij - (termi + termj)
ij = ij + 1
d(ij) = dij
if (dij .le. dopt) then
dopt = dij
trop = trcij
tmop = trmij
nopt = nij
niop = nj
njop = ni
siop = sj
sjop = si
iopt = j
jopt = iold
m = p
do k = 1, min(nij-1,p)
call dcopy(m, u(k,k), p, s(k,k), p)
m = m - 1
end do
end if
end do
end if
if (iold .lt. lg) then
i = iold
ij = ij + i
do j = (iold+1), lg
call dcopy(psq, zero, 0, u, 1)
m = p
do k = 1, min(ni-1,p)
call dcopy(m, r(k,k), p, u(k,k), p)
m = m - 1
end do
nj = 1
icj = ic(j)
if (icj .eq. 1) then
nij = ni + 1
rij = dble(nij)
qij = one/rij
qi = ri*qij
si = sqrt(qi)
sj = sqrt(qij)
sij = sj
call dcopy(p, x(j,1), n, v, 1)
call dscal( p, si, v, 1)
call daxpy( p, (-sj), x(iold,1), n, v, 1)
trcij = traci + ddot(p,v,1,v,1)
termj = ABLOG
else
m = p
l = icj
k = ni + 1
410 continue
call dcopy( m, x(l,nj), n, v, 1)
call mclrup( k, m, v, u(nj,nj), p)
k = k + 1
nj = nj + 1
m = m - 1
l = ic(l)
if (l .le. n) goto 410
nj = l - n
c call vvvget(j,nj,n,p,ic,x,tracj,termj)
tracj = x( j ,pp1)
termj = x(ic(j),pp1)
rj = dble(nj)
nij = ni + nj
rij = dble(nij)
qij = one/rij
qi = ri*qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
sij = sqrt(qij)
call dcopy(p, x(j,1), n, v, 1)
call dscal( p, si, v, 1)
call daxpy( p, (-sj), x(iold,1), n, v, 1)
trcij = ( traci + tracj) + ddot(p,v,1,v,1)
end if
call mclrup( nij, p, v, u, p)
trmij = vvvtij( nij, p, u, sij, trcij)
dij = trmij - (termi + termj)
d(ij) = dij
ij = ij + i
i = j
if (dij .le. dopt) then
dopt = dij
trop = trcij
tmop = trmij
nopt = nij
niop = ni
njop = nj
siop = si
sjop = sj
iopt = iold
jopt = j
m = p
do k = 1, min(nij-1,p)
call dcopy(m, u(k,k), p, s(k,k), p)
m = m - 1
end do
end if
end do
end if
c update d and find max
jopt = 2
iopt = 1
dopt = d(1)
if (lg .eq. 2) goto 900
ij = 1
do i = 2, ld
qi = d(i)
if (qi .le. dopt) then
ij = i
dopt = qi
end if
end do
c call dblepr("d", 1, d, nd)
c call dblepr("d", 1, d, ld)
if (ij .gt. 1) then
do i = 2, ij
iopt = iopt + 1
if (iopt .ge. jopt) then
jopt = jopt + 1
iopt = 1
end if
end do
end if
do k = 1, p
call dcopy( p, zero, 0, r(1,k), 1)
end do
if (iopt .ne. iold .and. jopt .ne. iold) then
i = iopt
j = jopt
nj = 1
icj = ic(j)
ni = 1
ici = ic(i)
if (icj .eq. 1) then
termj = ABLOG
if (ici .eq. 1) then
nij = 2
rij = two
si = rthalf
sj = rthalf
call dcopy(p, x(i,1), n, v, 1)
call daxpy( p, (-one), x(j,1), n, v, 1)
call dscal( p, rthalf, v, 1)
trcij = ddot( p, v, 1, v, 1)
call dcopy( p, v, 1, r, p)
termi = ABLOG
else
m = p
l = ici
610 continue
call dcopy( m, x(l,ni), n, r(ni,ni), p)
ni = ni + 1
m = m - 1
l = ic(l)
if (l .le. n) goto 610
ni = l - n
c call vvvget(i,ni,n,p,ic,x,traci,termi)
traci = x( i , pp1)
termi = x(ic(i), pp1)
ri = dble(ni)
nij = ni + 1
rij = dble(nij)
qij = one/rij
qi = ri*qij
si = sqrt(qi)
sj = sqrt(qij)
call dcopy(p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
trcij = traci + ddot( p, v, 1, v, 1)
call mclrup( nij, p, v, r, p)
end if
else
m = p
l = icj
620 continue
call dcopy( m, x(l,nj), n, r(nj,nj), p)
nj = nj + 1
m = m - 1
l = ic(l)
if (l .le. n) goto 620
nj = l - n
c call vvvget(j,nj,n,p,ic,x,tracj,termj)
tracj = x( j , pp1)
termj = x(ic(j), pp1)
rj = dble(nj)
if (ici .eq. 1) then
nij = nj + 1
rij = dble(nij)
qij = one/rij
qj = rj*qij
si = sqrt(qij)
sj = sqrt(qj)
call dcopy(p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
trcij = tracj + ddot( p, v, 1, v, 1)
termi = ABLOG
else
m = p
l = ici
k = nj + 1
630 continue
call dcopy( m, x(l,ni), n, v, 1)
call mclrup( k, m, v, r(ni,ni), p)
ni = ni + 1
m = m - 1
l = ic(l)
if (l .le. n) goto 630
ni = l - n
c call vvvget(i,ni,n,p,ic,x,traci,termi)
traci = x( i , pp1)
termi = x(ic(i), pp1)
ri = dble(ni)
nij = ni + nj
rij = dble(nij)
qij = one/rij
qi = ri*qij
qj = rj*qij
si = sqrt(qi)
sj = sqrt(qj)
call dcopy(p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
trcij = ( traci + tracj) + ddot( p,v,1,v,1)
end if
call mclrup( nij, p, v, r, p)
end if
trop = trcij
tmop = dopt + (termi + termj)
nopt = nij
niop = ni
njop = nj
siop = si
sjop = sj
else
m = p
do k = 1, min(nopt-1,p)
call dcopy(m, s(k,k), p, r(k,k), p)
m = m - 1
end do
l = ic(iopt)
if (l .ne. 1) then
710 continue
if (l .le. n) then
l = ic(l)
goto 710
end if
niop = l-n
else
niop = 1
end if
l = ic(jopt)
if (l .ne. 1) then
720 continue
if (l .le. n) then
l = ic(l)
goto 720
end if
njop = l-n
else
njop = 1
end if
nopt = niop + njop
end if
ls = ls + 1
if (ls .eq. ns) goto 900
goto 200
900 continue
d(lo) = dopt
lo = lo - 1
d(lo) = dble(iopt)
lo = lo - 1
d(lo) = dble(jopt)
do i = 1, ng
ic(i) = i
end do
lo = nd - 1
ld = lo
si = d(lo)
lo = lo - 1
sj = d(lo)
ic(int(sj)) = ng
if (si .lt. sj) then
x(1,1) = si
x(1,2) = sj
else
x(1,1) = sj
x(1,2) = si
end if
lg = ng + 1
do k = 2, ns
lo = lo - 1
d(ld) = d(lo)
ld = ld - 1
lo = lo - 1
i = int(d(lo))
ici = ic(i)
lo = lo - 1
j = int(d(lo))
icj = ic(j)
if (ici .gt. icj) ic(i) = icj
ic(j) = ic(lg-k)
if (ici .lt. icj) then
x(k,1) = dble(ici)
x(k,2) = dble(icj)
else
x(k,1) = dble(icj)
x(k,2) = dble(ici)
end if
end do
ld = nd
lo = 1
do k = 1, ns
si = d(lo)
d(lo) = d(ld)
d(ld) = si
ld = ld - 1
lo = lo + 1
end do
return
end
double precision function vvvtij( l, p, r, s, trac)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer l, p
double precision r(p,*), s, trac
double precision detlog
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision det2mc
external det2mc
double precision BETA, ALPHA, ABLOG
common /VVVMCL/ BETA, ALPHA, ABLOG
save /VVVMCL/
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
if (l .le. p) then
vvvtij = log(BETA*(trac+ALPHA)/dble(l))
else
if (trac .eq. zero) then
vvvtij = log((ALPHA*BETA)/dble(l))
else
detlog = det2mc( p, r, s)
if (detlog .eq. -FLMAX) then
vvvtij = log(BETA*(trac+ALPHA)/dble(l))
else if (detlog .le. zero) then
vvvtij = log(exp(detlog)+BETA*(trac+ALPHA)/dble(l))
else
vvvtij = log(one+exp(-detlog)*(BETA*(trac+ALPHA)/dble(l)))
* + detlog
end if
end if
end if
vvvtij = dble(l)*vvvtij
return
end
double precision function det2mc( n, u, s)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer k, n
double precision q, s
double precision u(n,*)
double precision zero, two
parameter (zero = 0.d0, two = 2.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
det2mc = zero
do k = 1, n
q = u(k,k)*s
if (abs(q) .le. zero) then
det2mc = -FLMAX
return
end if
det2mc = det2mc + log(abs(q))
end do
det2mc = two*det2mc
return
end
subroutine mevvv ( EQPRO, x, n, p, G, Vinv, z, maxi, tol, eps,
* mu, U, pro, w, S)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
double precision Vinv, eps, tol
c double precision x(n,p), z(n,G), w(p)
double precision x(n,*), z(n,*), w(*)
c double precision mu(p,G), U(p,p,G), pro(G), S(p,p)
double precision mu(p,*), U(p,p,*), pro(*), S(p,*)
integer nz, p1, iter, i, j, k, l, j1
double precision piterm, hold, rcmin, rteps
double precision temp, term, cs, sn, umin, umax
double precision sumz, sum, detlog, const, hood, err
double precision prok, tmin, tmax, ViLog, zsum
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
piterm = dble(p)*pi2log/two
p1 = p + 1
eps = max(eps,zero)
rteps = sqrt(eps)
tol = max(tol,zero)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
c zero out the lower triangle
do k = 1, G
do j = 1, p
do l = 1, p
S(l,j) = U(l,j,k)
end do
end do
i = 1
do j = 2, p
call dcopy( p-i, zero, 0, S(j,i), 1)
i = j
end do
do j = 1, p
do l = 1, p
U(l,j,k) = S(l,j)
end do
end do
end do
iter = 0
100 continue
iter = iter + 1
zsum = one
do k = 1, G
do j = 1, p
do l = 1, p
S(l,j) = U(l,j,k)
end do
end do
do j = 1, p
call dcopy( j, zero, 0, S(1,j), 1)
end do
call dcopy( p, zero, 0, mu(1,k), 1)
sumz = zero
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
if (.not. EQPRO) pro(k) = sumz / dble(n)
zsum = min(sumz,zsum)
if (sumz .gt. rteps) then
call dscal( p, (one/sumz), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( S(j,j), w(j), cs, sn)
call drot( p-j, S(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( S(p,p), w(p), cs, sn)
end do
do j = 1, p
call dscal( j, one/sqrt(sumz), S(1,j), 1)
end do
else
call dcopy( p, FLMAX, 0, z(1,k), 1)
end if
do j = 1, p
do l = 1, p
U(l,j,k) = S(l,j)
end do
end do
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
if (Vinv .gt. zero) then
term = zero
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
rcmin = FLMAX
do k = 1, G
do j = 1, p
do l = 1, p
S(l,j) = U(l,j,K)
end do
end do
call absrng( p, S, p1, umin, umax)
rcmin = min(umin/(one+umax),rcmin)
end do
if (rcmin .le. rteps) then
tol = rcmin
eps = FLMAX
maxi = iter
return
end if
do k = 1, G
do j = 1, p
do l = 1, p
S(l,j) = U(l,j,K)
end do
end do
c temp = pro(k)
detlog = zero
do j = 1, p
detlog = detlog + log(abs(S(j,j)))
end do
const = piterm+detlog
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dtrsv( 'U', 'T', 'N', p, S, p, w, 1)
sum = ddot( p, w, 1, w, 1)/two
c z(i,k) = temp*exp(-(const+sum))
z(i,k) = -(const+sum)
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
c w(1) = rcmin
tol = err
eps = hood
maxi = iter
return
end
subroutine mevvvp( EQPRO, x, n, p, G, Vinv,
* pshrnk, pmu, pscale, pdof,
* z, maxi, tol, eps, mu, U, pro, w, S)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
logical EQPRO
integer n, p, G, maxi
c double precision pshrnk, pmu(p), pscale(p,p), pdof
double precision pshrnk, pmu(*), pscale(p,*), pdof
double precision Vinv, eps, tol
c double precision x(n,p), z(n,G), w(p)
double precision x(n,*), z(n,*), w(*)
c double precision mu(p,G), U(p,p,G), pro(G), S(p,p)
double precision mu(p,*), U(p,p,*), pro(*), S(p,*)
integer nz, p1, iter, i, j, k, l, j1
double precision piterm, hold, rcmin, rteps
double precision temp, term, cs, sn, umin, umax
double precision sum, sumz, detlog, const, hood, err
double precision prok, tmin, tmax, ViLog
double precision cmu, cgam, rmu, rgam, zsum
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision twolog
parameter (twolog = 0.6931471805599453d0)
double precision pilog
parameter (pilog = 1.144729885849400d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG
parameter (SMALOG = -708.d0)
double precision ddot, dlngam
external ddot, dlngam
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
if (maxi .le. 0) return
if (Vinv .gt. zero) then
nz = G + 1
ViLog = log(Vinv)
else
nz = G
if (EQPRO) call dcopy( G, one/dble(G), 0, pro, 1)
end if
piterm = dble(p)*pi2log/two
p1 = p + 1
eps = max(eps,zero)
rteps = sqrt(eps)
tol = max(tol,zero)
c FLMAX = d1mach(2)
hold = FLMAX/two
hood = FLMAX
err = FLMAX
iter = 0
100 continue
iter = iter + 1
zsum = one
do k = 1, G
do j = 1, p
do l = 1, p
S(l,j) = U(l,j,k)
end do
end do
do j = 1, p
call dcopy( p, pscale(1,j), 1, S(1,j), 1)
end do
sumz = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
if (.not. EQPRO) pro(k) = sumz / dble(n)
zsum = min(sumz,zsum)
if (sumz .gt. rteps) then
call dscal( p, (one/sumz), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( S(j,j), w(j), cs, sn)
call drot( p-j, S(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( S(p,p), w(p), cs, sn)
end do
call dcopy( p, pmu, 1, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
const = sumz+pshrnk
temp = (sumz*pshrnk)/const
call dscal( p, sqrt(temp), w, 1)
j = 1
do j1 = 2, p
call drotg( S(j,j), w(j), cs, sn)
call drot( p-j, S(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( S(p,p), w(p), cs, sn)
do j = 1, p
temp = pdof+sumz+dble(p)+two
call dscal( j, one/sqrt(temp), S(1,j), 1)
end do
call dscal( p, sumz/const, mu(1,k), 1)
call daxpy( p, pshrnk/const, pmu, 1, mu(1,k), 1)
else
call dcopy( p, FLMAX, 0, z(1,k), 1)
end if
do j = 1, p
do l = 1, p
U(l,j,k) = S(l,j)
end do
end do
end do
if (zsum .le. rteps) then
tol = zsum
eps = -FLMAX
maxi = iter
return
end if
term = zero
if (Vinv .gt. zero) then
do i = 1, n
term = term + z(i,nz)
end do
temp = term / dble(n)
pro(nz) = temp
call dcopy( n, ViLog, 0, z(1,nz), 1)
if (EQPRO) then
temp = (one - pro(nz))/dble(G)
call dcopy( G, temp, 0, pro, 1)
end if
end if
rcmin = FLMAX
do k = 1, G
do j = 1, p
do l = 1, p
S(l,j) = U(l,j,K)
end do
end do
call absrng( p, S, p1, umin, umax)
rcmin = min(umin/(one+umax),rcmin)
end do
if (rcmin .le. rteps) then
tol = rcmin
eps = FLMAX
maxi = iter
return
end if
rmu = zero
rgam = zero
do k = 1, G
c temp = pro(k)
do j = 1, p
do l = 1, p
S(l,j) = U(l,j,k)
end do
end do
detlog = zero
do j = 1, p
detlog = detlog + log(abs(S(j,j)))
end do
rmu = rmu - detlog
rgam = rgam - (pdof+dble(p)+one)*detlog
const = piterm+detlog
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dtrsv( 'U', 'T', 'N', p, S, p, w, 1)
sum = ddot( p, w, 1, w, 1)/two
c z(i,k) = temp*exp(-(const+sum))
z(i,k) = -(const+sum)
end do
end do
hood = zero
do i = 1, n
tmin = FLMAX
tmax = -FLMAX
do k = 1, nz
prok = pro(k)
if (prok .eq. zero) then
z(i,k) = zero
else
temp = log(prok) + z(i,k)
tmin = min(tmin,temp)
tmax = max(tmax,temp)
z(i,k) = temp
end if
end do
sum = zero
do k = 1, nz
if (pro(k) .ne. zero) then
temp = z(i,k) - tmax
if (temp .ge. SMALOG) then
z(i,k) = exp(temp)
sum = sum + z(i,k)
else
z(i,k) = zero
end if
end if
end do
hood = hood + (log(sum)+tmax)
call dscal( nz, (one/sum), z(i,1), n)
end do
err = abs(hold-hood)/(one+abs(hood))
hold = hood
if (err .gt. tol .and. iter .lt. maxi) goto 100
c w(1) = rcmin
tol = err
eps = hood
maxi = iter
cmu = dble(p)*(log(pshrnk) - pi2log)/two
sum = zero
do k = 1, G
do j = 1, p
do l = 1, p
S(l,j) = U(l,j,k)
end do
end do
call daxpy( p, (-one), mu(1,k), 1, pmu, 1)
call dtrsv('U','T','N',p, S, p, pmu, 1)
sum = sum + ddot( p, pmu, 1, pmu, 1)
end do
rmu = rmu - pshrnk*sum/two
sum = zero
term = zero
temp = zero
do j = 1, p
call dcopy( p, pscale(j,1), p, pmu, 1)
c call dtrsv('U','T','N', p, U, p, pmu, 1)
i = p-j+1
c call dtrsv('U','T','N', i, U(j,j,k),i,pmu(j),1)
call dtrsv('U','T','N', i, S(j,j), p, pmu(j), 1)
sum = sum + ddot(i, pmu(j), 1, pmu(j), 1)
temp = temp + log(abs(pscale(j,j)))
term = term + dlngam((pdof+one-dble(j))/two)
end do
rgam = rgam - sum/two
const = -dble(p)*(pdof*twolog+(dble(p)-one)*pilog/two)
cgam = (const-pdof*temp)/two-term
pdof = (dble(G)*cmu+rmu) + (dble(G)*cgam+rgam)
return
end
subroutine msvvv ( x, z, n, p, G, w, mu, U, pro, S)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision x(n,p), z(n,G), w(p)
double precision x(n,*), z(n,*), w(*)
c double precision mu(p,G), U(p,p,G), pro(G), S(p,p)
double precision mu(p,*), U(p,p,*), pro(*), S(p,*)
integer i, j, k, l, j1
double precision sum, temp, cs, sn
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
c------------------------------------------------------------------------------
do k = 1, G
call dcopy( p, zero, 0, mu(1,k), 1)
do j = 1, p
c call dcopy( j, zero, 0, U(1,j,k), 1)
call dcopy( j, zero, 0, S(1,j), 1)
end do
sum = zero
do i = 1, n
temp = z(i,k)
sum = sum + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sum / dble(n)
if (sum .ge. one .or. one .lt. sum*FLMAX) then
call dscal( p, (one/sum), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( S(j,j), w(j), cs, sn)
call drot( p-j, S(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( S(p,p), w(p), cs, sn)
end do
temp = sqrt(sum)
if (temp .ge. one .or. one .lt. temp*FLMAX) then
do j = 1, p
call dscal( j, one/temp, S(1,j), 1)
end do
else
do j = 1, p
call dcopy( j, FLMAX, 0, S(1,j), 1)
end do
end if
else
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
do j = 1, p
do l = 1, p
U(l,j,k) = S(l,j)
end do
end do
end do
return
end
subroutine msvvvp( x, z, n, p, G,
* pshrnk, pmu, pscale, pdof,
* w, mu, U, pro, S)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n, p, G
c double precision pshrnk, pmu(p), pscale(p,p), pdof
double precision pshrnk, pmu(*), pscale(p,*), pdof
c double precision x(n,p), z(n,G), w(p)
double precision x(n,*), z(n,*), w(*)
c double precision mu(p,G), U(p,p,G), pro(G), S(p,p)
double precision mu(p,*), U(p,p,*), pro(*), S(p,*)
c------------------------------------------------------------------------------
c
c x double (input) (n,p) matrix of observations.
c z double (input/output) (n,G[+1]) conditional probabilities.
c n integer (input) number of observations.
c p integer (input) dimension of the data.
c G integer (input) number of Gaussian clusters in the mixture.
c mu double (output) (p,G) mean for each group.
c U double (output) (p,p,G)
c pro double (output) (G) mixing proportions (used even if equal).
c w double (scratch) (max(p,G))
integer i, j, k, l, j1
double precision sumz, temp, cs, sn, const
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
c------------------------------------------------------------------------------
do k = 1, G
do j = 1, p
do l = 1, p
S(l,j) = U(l,j,k)
end do
end do
do j = 1, p
call dcopy( p, pscale(1,j), 1, S(1,j), 1 )
end do
sumz = zero
call dcopy( p, zero, 0, mu(1,k), 1)
do i = 1, n
temp = z(i,k)
sumz = sumz + temp
call daxpy( p, temp, x(i,1), n, mu(1,k), 1)
end do
pro(k) = sumz / dble(n)
if (sumz .ge. one .or. one .lt. sumz*FLMAX) then
call dscal( p, (one/sumz), mu(1,k), 1)
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
call dscal( p, sqrt(z(i,k)), w, 1)
j = 1
do j1 = 2, p
call drotg( S(j,j), w(j), cs, sn)
call drot( p-j, S(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( S(p,p), w(p), cs, sn)
end do
call dcopy( p, pmu, 1, w, 1)
call daxpy( p, (-one), mu(1,k), 1, w, 1)
const = sumz+pshrnk
temp = (sumz*pshrnk)/const
call dscal( p, sqrt(temp), w, 1)
j = 1
do j1 = 2, p
call drotg( S(j,j), w(j), cs, sn)
call drot( p-j, S(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( S(p,p), w(p), cs, sn)
temp = pdof+sumz+dble(p)+one
if (pshrnk .gt. zero) temp = temp + one
do j = 1, p
call dscal( j, one/sqrt(temp), S(1,j), 1)
end do
call dscal( p, sumz/const, mu(1,k), 1)
call daxpy( p, pshrnk/const, pmu, 1, mu(1,k), 1)
else
call dcopy( p, FLMAX, 0, mu(1,k), 1)
end if
do j = 1, p
do l = 1, p
U(l,j,k) = S(l,j)
end do
end do
end do
return
end
subroutine mvn1d ( x, n, mu, sigsq, hood)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n
integer n
double precision mu, sigsq, hood
c double precision x(n)
double precision x(*)
c------------------------------------------------------------------------------
c
c x double (input) (n) matrix of observations (destroyed).
c n integer (input) number of observations.
c mu double (output) mean.
c sigsq double (output) variance.
c hood double (output) loglikelihood.
double precision dn
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision ddot
external ddot
c------------------------------------------------------------------------------
dn = dble(n)
mu = ddot( n, one/dn, 0, x, 1)
sigsq = zero
call daxpy( n, (-one), mu, 0, x, 1)
sigsq = ddot( n, x, 1, x, 1)/dn
if (sigsq .eq. zero) then
hood = FLMAX
else
hood = -dn*(pi2log + (one + log(sigsq)))/two
end if
return
end
subroutine mvn1p ( x, n, pshrnk, pmu, pscale, pdof,
* mu, sigsq, hood)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
integer n
double precision pshrnk, pmu, pscale, pdof
double precision mu, sigsq, hood
c double precision x(n)
double precision x(*)
integer i
double precision dn, const, term, temp, xbar
double precision cmu, cgam, rmu, rgam
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision ddot, dlngam
external ddot, dlngam
c------------------------------------------------------------------------------
if (pshrnk .lt. zero) pshrnk = zero
dn = dble(n)
xbar = ddot( n, one/dn, 0, x, 1)
const = pshrnk + dn
mu = (dn/const)*xbar + (pshrnk/const)*pmu
sigsq = zero
do i = 1, n
temp = xbar - x(i)
sigsq = sigsq + temp*temp
end do
temp = xbar - pmu
sigsq = sigsq + pscale + dn*(pshrnk/const)*(temp*temp)
temp = pdof + dn + two
if (pshrnk .gt. zero) temp = temp + one
sigsq = sigsq / temp
if (sigsq .eq. zero) then
hood = FLMAX
else
call daxpy( n, (-one), mu, 0, x, 1)
temp = ddot( n, x, 1, x, 1)
if (sigsq .lt. one .and. temp .ge. sigsq*FLMAX) then
hood = FLMAX
return
end if
temp = temp/sigsq
hood = -(dn*(pi2log + log(sigsq)) + temp)/two
end if
if (pshrnk .gt. zero) then
cmu = (pi2log-log(pshrnk))/two
term = pdof/two
cgam = term*log(pscale/two) - dlngam(term)
temp = pmu - mu
const = log(sigsq)
rmu = -(const - (pshrnk/sigsq)*(temp*temp))/two
rgam = -(term+one)*const - (pscale/sigsq)/two
pdof = (cmu+rmu) + (cgam+rgam)
else
pdof = FLMAX
end if
return
end
subroutine mnxiip( x, n, p, pshrnk, pmu, pscale, pdof,
* mu, sigsq, hood)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n, p
integer n, p
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
double precision sigsq, hood
c double precision x(n,p), mu(p)
double precision x(n,*), mu(*)
integer i, j
double precision dnp, scl, temp, term, sum
double precision dmudmu, pmupmu, cmu, cgam, rmu, rgam
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision ddot, dlngam
external ddot, dlngam
c------------------------------------------------------------------------------
dnp = dble(n*p)
scl = one/dble(n)
do j = 1, p
mu(j) = ddot( n, scl, 0, x(1,j), 1)
end do
sum = zero
do i = 1, n
do j = 1, p
temp = x(i,j) - mu(j)
sum = sum + temp*temp
end do
end do
pmupmu = ddot(p,pmu,1,pmu,1)
dmudmu = ddot(p,mu,1,mu,1)
temp = dmudmu + pmupmu
temp = temp - two*ddot(p,mu,1,pmu,1)
term = pshrnk + dble(n)
scl = (pshrnk*dble(n))/term
sigsq = pscale + scl*temp + sum
temp = pdof + dble(n*p) + two
if (pshrnk .gt. zero) temp = temp + dble(p)
sigsq = sigsq/temp
call dscal( p, dble(n)/term, mu, 1)
call daxpy( p, pshrnk/term, pmu, 1, mu, 1)
if (sigsq .eq. zero) then
hood = FLMAX
else
sum = zero
do i = 1, n
do j = 1, p
temp = x(i,j) - mu(j)
sum = sum + temp*temp
end do
end do
hood = -(sum/sigsq + dnp*(pi2log + log(sigsq)))/two
end if
if (pshrnk .gt. zero) then
dmudmu = ddot(p,mu,1,mu,1)
cmu = dble(p)*(log(pshrnk)-pi2log)/two
temp = (dmudmu+pmupmu) - two*ddot(p,pmu,1,mu,1)
term = log(sigsq)
rmu = -(dble(p)*term + (pshrnk*temp)/sigsq)/two
temp = pdof/two
cgam = temp*log(pscale/two) - dlngam(temp)
rgam = -(temp+one)*term - pscale/(two*sigsq)
pdof = (cmu+rmu) + (cgam+rgam)
else
pdof = FLMAX
end if
return
end
subroutine mvnxii( x, n, p, mu, sigsq, hood)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n, p
integer n, p
double precision sigsq, hood
c double precision x(n,p), mu(p)
double precision x(n,*), mu(*)
integer j
double precision dnp, scl
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision ddot
external ddot
c------------------------------------------------------------------------------
dnp = dble(n*p)
scl = one/dble(n)
do j = 1, p
mu(j) = ddot( n, scl, 0, x(1,j), 1)
end do
sigsq = zero
do j = 1, p
call daxpy( n, (-one), mu(j), 0, x(1,j), 1)
sigsq = sigsq + ddot( n, x(1,j), 1, x(1,j), 1)
end do
sigsq = sigsq/dnp
if (sigsq .eq. zero) then
hood = FLMAX
else
hood = -dnp*(pi2log + (one + log(sigsq)))/two
end if
return
end
subroutine mnxxip( x, n, p, pshrnk, pmu, pscale, pdof,
* mu, scale, shape, hood)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n, p
integer n, p
c double precision pshrnk, pmu(p), pscale, pdof
double precision pshrnk, pmu(*), pscale, pdof
double precision scale, hood
c double precision x(n,p), mu(p), shape(p)
double precision x(n,*), mu(*), shape(*)
integer i, j
double precision sum, temp, smin, smax
double precision term, const, scl
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
temp = one/dble(n)
do j = 1, p
mu(j) = ddot( n, temp, 0, x(1,j), 1)
shape(j) = zero
end do
do j = 1, p
sum = zero
do i = 1, n
temp = x(i,j) - mu(j)
sum = sum + temp*temp
end do
shape(j) = shape(j) + sum
end do
term = pshrnk + dble(n)
scl = (pshrnk*dble(n))/term
do j = 1, p
temp = pmu(j) - mu(j)
shape(j) = shape(j) + scl*(temp*temp) + pscale
end do
call dscal( p, dble(n)/term, mu, 1)
call daxpy( p, pshrnk/term, pmu, 1, mu, 1)
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. zero) then
call dcopy( p, FLMAX, 0, shape, 1)
scale = zero
hood = FLMAX
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .ge. BIGLOG) then
call dcopy( p, FLMAX, 0, shape, 1)
scale = FLMAX
hood = FLMAX
return
end if
if (temp .le. SMALOG) then
call dcopy( p, FLMAX, 0, shape, 1)
scale = zero
hood = FLMAX
return
end if
temp = exp(temp)
term = pdof + dble(n) + two
if (pshrnk .gt. zero) term = term + one
scale = temp/term
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
hood = FLMAX
return
end if
call dscal( p, one/temp, shape, 1)
const = dble(p)*(pi2log+log(scale))
hood = zero
do i = 1, n
sum = zero
do j = 1, p
temp = x(i,j) - mu(j)
sum = sum + (temp*temp)/shape(j)
end do
hood = hood - (const+(sum/scale))/two
end do
c log posterior computation not yet available
pdof = FLMAX
return
end
subroutine mvnxxi( x, n, p, mu, scale, shape, hood)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n, p
integer n, p
double precision scale, hood
c double precision x(n,p), mu(p), shape(p)
double precision x(n,*), mu(*), shape(*)
integer i, j
double precision dn, scl, sum, temp, smin, smax
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision SMALOG, BIGLOG
parameter (SMALOG = -708.d0, BIGLOG = 709.d0)
double precision ddot
external ddot
c------------------------------------------------------------------------------
dn = dble(n)
scl = one/dn
do j = 1, p
mu(j) = ddot( n, scl, 0, x(1,j), 1)
shape(j) = zero
end do
do j = 1, p
sum = zero
do i = 1, n
temp = x(i,j) - mu(j)
sum = sum + temp*temp
end do
shape(j) = shape(j) + sum
end do
call sgnrng(p, shape, 1, smin, smax)
if (smin .le. zero) then
call dcopy( p, FLMAX, 0, shape, 1)
scale = zero
hood = FLMAX
return
end if
sum = zero
do j = 1, p
sum = sum + log(shape(j))
end do
temp = sum/dble(p)
if (temp .gt. BIGLOG) then
call dcopy( p, FLMAX, 0, shape, 1)
scale = FLMAX
hood = FLMAX
return
end if
if (temp .lt. SMALOG) then
call dcopy( p, FLMAX, 0, shape, 1)
scale = zero
hood = FLMAX
return
end if
temp = exp(temp)
scale = temp/dn
if (temp .lt. one .and. one .ge. temp*FLMAX) then
call dcopy( p, FLMAX, 0, shape, 1)
hood = FLMAX
return
end if
call dscal( p, one/temp, shape, 1)
hood = -dble(n*p)*(one + pi2log + log(scale))/two
return
end
subroutine mnxxxp( x, n, p, w,
* pshrnk, pmu, pscale, pdof,
* mu, U, hood)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n, p
integer n, p
c double precision pshrnk, pmu(p), pscale(p,p), pdof
double precision pshrnk, pmu(*), pscale(p,*), pdof
double precision hood
c double precision x(n,p), w(p), mu(p), U(p,p)
double precision x(n,*), w(*), mu(*), U(p,*)
integer i, j, j1
double precision dnp, scl, detlog, sum, term, temp
double precision umin, umax, cs, sn, const
double precision cmu, cgam, rmu, rgam
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision twolog
parameter (twolog = 0.6931471805599453d0)
double precision pilog
parameter (pilog = 1.144729885849400d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision ddot, dlngam
external ddot, dlngam
c------------------------------------------------------------------------------
dnp = dble(n*p)
scl = one/dble(n)
do j = 1, p
mu(j) = ddot( n, scl, 0, x(1,j), 1)
call dcopy( p, pscale(1,j), 1, U(1,j), 1)
end do
c mu contains ybar; U contains Cholesky factor of inverse Wishart scale
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu, 1, w, 1)
j = 1
do j1 = 2, p
call drotg( U(j,j), w(j), cs, sn)
call drot( p-j, U(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( U(p,p), w(p), cs, sn)
end do
call dcopy( p, pmu, 1, w, 1)
call daxpy( p, (-one), mu, 1, w, 1)
term = (pshrnk*dble(n))/(pshrnk+dble(n))
call dscal( p, sqrt(term), w, 1)
j = 1
do j1 = 2, p
call drotg( U(j,j), w(j), cs, sn)
call drot( p-j, U(j,j1), p, w(j1), 1, cs, sn)
j = j1
end do
call drotg( U(p,p), w(p), cs, sn)
scl = pdof + dble(n+p+1)
if (pshrnk .gt. zero) scl = scl + one
scl = one/sqrt(scl)
do j = 1, p
call dscal( j, scl, U(1,j), 1)
end do
term = pshrnk + dble(n)
call dscal( p, dble(n)/term, mu, 1)
call daxpy( p, pshrnk/term, pmu, 1, mu, 1)
call absrng( p, U, p+1, umin, umax)
c rcond = umin / (one + umax)
if (umin .eq. zero) then
hood = FLMAX
return
end if
detlog = zero
do j = 1, p
detlog = detlog + log(abs(U(j,j)))
end do
const = dble(n)*(detlog + dble(p)*pi2log/two)
sum = zero
do i = 1, n
call dcopy( p, x(i,1), n, w, 1)
call daxpy( p, (-one), mu, 1, w, 1)
call dtrsv( 'U', 'T', 'N', p, U, p, w, 1)
sum = sum + ddot(p, w, 1, w, 1)
end do
hood = -(const+sum/two)
cmu = dble(p)*(log(pshrnk) - pi2log)/two
call dcopy( p, pmu, 1, w, 1)
call daxpy( p, (-one), mu, 1, w, 1)
call dtrsv( 'U', 'T', 'N', p, U, p, w, 1)
temp = ddot( p, w, 1, w, 1)
sum = zero
term = zero
do j = 1, p
term = term + dlngam((pdof+dble(1-j))/two)
call dcopy( p, pscale(j,1), p, pmu, 1)
c call dtrsv('U','T','N', p, U, p, pmu, 1)
i = p-j+1
c call dtrsv('U','T','N', i, U(j,j),i,pmu(j),1)
call dtrsv('U','T','N', i, U(j,j),p,pmu(j),1)
sum = sum + ddot(i, pmu(j), 1, pmu(j), 1)
end do
if (pshrnk .gt. zero) then
rmu = -(detlog+pshrnk*temp/two)
const = -dble(p)*(pdof*twolog+(dble(p)-one)*pilog/two)
cgam = (const/two-pdof*detlog) - term
rgam = -((pdof+dble(p)+one)*detlog + sum/two)
pdof = (cmu+cgam) + (rmu+rgam)
else
pdof = FLMAX
end if
return
end
subroutine mvnxxx( x, n, p, mu, U, hood)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
implicit NONE
c integer n, p
integer n, p
double precision hood
c double precision x(n,p), mu(p), U(p,p)
double precision x(n,*), mu(*), U(p,*)
integer i, j, j1
double precision dn, dnp, scl
double precision umin, umax, cs, sn
double precision zero, one, two
parameter (zero = 0.d0, one = 1.d0, two = 2.d0)
double precision pi2log
parameter (pi2log = 1.837877066409345d0)
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision ddot
external ddot
c------------------------------------------------------------------------------
dn = dble(n)
dnp = dble(n*p)
scl = one/dn
do j = 1, p
mu(j) = ddot( n, scl, 0, x(1,j), 1)
call dcopy( p, zero, 0, U(1,j), 1)
end do
do i = 1, n
call daxpy( p, (-one), mu, 1, x(i,1), n)
j = 1
do j1 = 2, p
call drotg( U(j,j), x(i,j), cs, sn)
call drot( p-j, U(j,j1), p, x(i,j1), n, cs, sn)
j = j1
end do
call drotg( U(p,p), x(i,p), cs, sn)
end do
scl = sqrt(scl)
do j = 1, p
call dscal( j, scl, U(1,j), 1)
end do
call absrng( p, U, p+1, umin, umax)
c rcond = umin / (one + umax)
if (umin .eq. zero) then
hood = FLMAX
else
hood = zero
do j = 1, p
hood = hood + log(abs(U(j,j)))
end do
hood = -dn*(hood + dble(p)*(pi2log + one)/two)
end if
c
c do j = 1, p
c do i = 1, j
c x(i,j) = ddot(i,U(1,i),1,U(1,j),1)
c if (i .ne. j) x(j,i) = x(i,j)
c end do
c end do
c do j = 1, p
c call dcopy( p, x(1,j), 1, U(1,j), 1)
c end do
return
end
c Luca: add to check if compile ok
subroutine hceee ( x, n, p, ic, ng, ns, io, jo, v, s, u, r)
c This function is part of the MCLUST software described at
c http://www.stat.washington.edu/mclust
c Copyright information and conditions for use of MCLUST are given at
c http://www.stat.washington.edu/mclust/license.txt
c Gaussian model-based clustering algorithm in clusters share a common
c variance (shape, volume, and orientation are the same for all clusters).
implicit NONE
integer n, p, ic(n), ng, ns, io(*), jo(*)
c double precision x(n,p), v(p), s(p,p), u(p,p), r(p,p)
double precision x(n,*), v(*), s(*), u(*), r(*)
c------------------------------------------------------------------------------
c
c x double (input/output) On input, the (n by p) matrix containing
c the observations. On output, the first two columns
c and ns rows contain the determinant and trace of the
c sum of the sample cross product matrices. Columns 3 and 4
c contain the merge indices if p .ge. 4
c n integer (input) number of observations
c p integer (input) dimension of the data
c ic integer (input) (n) Initial partitioning of the data; groups must
c be numbered consecutively.
c ng integer (input) Number of groups in initial partition.
c ns integer (input) Desired number of stages of clustering.
c io,jo integer (output [p .le. 3]) If p .lt. 3, both io and jo must be of
c length ns and contain the indices of the merged pairs on
c output. If p .eq. 3, jo must be of length ns and contains
c an index of each merged on output pair. Otherwise io and
c jo are not used and can be of length 1.
c v double (scratch/output) (p) On output, algorithm breakpoints;
c tells where the algorithm switches from using trace
c to trace + det, and from trace + det to det as criterion.
c s double (scratch/output) (p,p) On output the first column contains
c the initial trace and determinant of the sum of sample
c cross product matrices.
c u,r double (scratch) (p,p)
integer q, i, j, k, l, m, i1, i2, l1, l2
integer ni, nj, nij, lw, ls, lg, ici, icj
integer nopt, iopt, jopt, idet, jdet, ndet
double precision DELOG
double precision ri, rj, rij, dij, tij, zij
double precision trc0, trc1, trcw, det0, det1, detw
double precision si, sj, siop, sjop, sidt, sjdt
double precision dopt, zopt, dijo, tijo, tdet
double precision zero, one
parameter (zero = 0.d0, one = 1.d0)
double precision ddot, detmc2
external ddot, detmc2
double precision FLMAX
parameter (FLMAX = 1.7976931348623157d308)
double precision EPSMIN
parameter (EPSMIN = 1.1102230246251565d-16)
c------------------------------------------------------------------------------
i1 = 0
i2 = 0
trcw = 0.d0
tijo = 0.d0
tdet = 0.d0
sjdt = 0.d0
sidt = 0.d0
dijo = 0.d0
ndet = 0
jdet = 0
idet = 0
iopt = 0
nopt = 0
jopt = 0
lw = p*p
c call intpr('ic', -1, ic, n)
c form scaled column sums
call dscal( n*p, one/sqrt(dble(n)), x, 1)
si = one/sqrt(dble(p))
sj = si / dble(n)
call dcopy( p, zero, 0, v, 1)
do k = 1, n
call daxpy( p, sj, x(k,1), n, v, 1)
end do
trc0 = zero
call dcopy( lw, zero, 0, r, 1)
do k = 1, n
call dcopy( p, v, 1, s, 1)
call daxpy( p, (-si), x(k,1), n, s, 1)
trc0 = trc0 + ddot( p, s, 1, s, 1)
call mclrup( (k+1), p, s, r, p)
end do
det0 = detmc2( p, r)
DELOG = log(trc0+EPSMIN)
c group heads should be first among rows of x
i = 1
j = 2
1 continue
icj = ic(j)
if (icj .ne. j) goto 2
if (j .eq. ng) goto 3
i = j
j = j + 1
goto 1
2 continue
k = i
m = j + 1
do j = m, n
icj = ic(j)
if (icj .gt. k) then
k = k + 1
call dswap( p, x(k,1), n, x(j,1), n)
ic(j) = ic(k)
ic(k) = icj
end if
end do
3 continue
c call intpr( 'ic', -1, ic, n)
call dcopy( lw, zero, 0, r, 1)
q = 1
do j = 1, n
i = ic(j)
if (i .ne. j) then
c update trace and Cholesky factor as if a merge
q = q + 2
ni = ic(i)
ri = dble(ni)
rij = dble(ni+1)
sj = sqrt(one/rij)
si = sqrt(ri)*sj
call dcopy( p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
trcw = trcw + ddot(p, v, 1, v, 1)
call mclrup( q, p, v, r, p)
ic(j) = 0
ic(i) = ic(i) + 1
call dscal( p, si, x(i,1), n)
call daxpy( p, sj, x(j,1), n, x(i,1), n)
c call dcopy( p, FLMAX, 0, x(j,1), n)
c update column sum in jth row
else
ic(j) = 1
end if
end do
c call intpr('ic', -1, ic, n)
trc1 = trcw
if (q .lt. p) then
detw = -FLMAX
else
detw = detmc2( p, r)
end if
det1 = detw
ls = 1
lg = ng
l1 = 0
l2 = 0
100 continue
if (q .ge. p) then
c if (.false.)
c * call intpr('PART 2 --------------------------', -1, ls, 0)
if (detw .lt. DELOG) then
goto 200
else
goto 300
end if
end if
dopt = FLMAX
do j = 2, lg
nj = ic(j)
rj = dble(nj)
do i = 1, (j-1)
ni = ic(i)
ri = dble(ni)
nij = ni + nj
rij = dble(nij)
si = sqrt(ri/rij)
sj = sqrt(rj/rij)
call dcopy( p, x(i,1), n, s, 1)
call dscal( p, sj, s, 1)
call daxpy( p, (-si), x(j,1), n, s, 1)
tij = trcw + ddot(p, s, 1, s, 1)
zij = max(tij,EPSMIN)
if (zij .le. dopt) then
dopt = zij
nopt = nij
siop = si
sjop = sj
iopt = i
jopt = j
call dcopy( p, s, 1, v, 1)
end if
end do
end do
trcw = dopt
if (ls .eq. ns) goto 900
call dscal( p, siop, x(iopt,1), n)
call daxpy( p, sjop, x(jopt,1), n, x(iopt,1), n)
if (jopt .ne. lg) then
call dcopy( p, x(lg,1), n, x(jopt,1), n)
ic(jopt) = ic(lg)
end if
ic(iopt) = nopt
x(lg,1) = detw
x(lg,2) = trcw
if (p .ge. 4) then
x(lg,3) = dble(iopt)
x(lg,4) = dble(jopt)
else if (p .eq. 3) then
x(lg,3) = dble(iopt)
jo(ls) = jopt
else
io(ls) = iopt
jo(ls) = jopt
end if
c update the Cholesky factor
q = q + 1
call mclrup( q, p, v, r, p)
ls = ls + 1
lg = lg - 1
goto 100
200 continue
q = q + 1
c call intpr('ic', -1, ic, n)
dopt = FLMAX
zopt = FLMAX
do j = 2, lg
nj = ic(j)
rj = dble(nj)
do i = 1, (j-1)
ni = ic(i)
ri = dble(ni)
nij = ni + nj
rij = dble(nij)
si = sqrt(ri/rij)
sj = sqrt(rj/rij)
call dcopy( p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
tij = trcw + ddot(p, v, 1, v, 1)
call dcopy( lw, r, 1, u, 1)
call mclrup( q, p, v, u, p)
dij = detmc2( p, u)
if (dij .le. dopt) then
dopt = dij
tdet = tij
ndet = nij
sidt = si
sjdt = sj
idet = i
jdet = j
end if
if (tij .eq. zero) then
zij = -FLMAX
else
zij = max(tij,EPSMIN)
if (dij .eq. (-FLMAX)) then
zij = log(zij)
else if (dij .le. zero) then
zij = log(exp(dij) + zij)
else
zij = log(one + zij*exp(-dij)) + dij
end if
end if
if (zij .le. zopt) then
zopt = zij
dijo = dij
tijo = tij
nopt = nij
siop = si
sjop = sj
iopt = i
jopt = j
call dcopy( lw, u, 1, s, 1)
end if
end do
end do
if (dopt .lt. DELOG) then
if (l1 .eq. 0) l1 = ls
trcw = tijo
detw = dijo
call dcopy( lw, s, 1, r, 1)
else
l2 = ls
trcw = tdet
detw = dopt
siop = sidt
sjop = sjdt
nopt = ndet
iopt = idet
jopt = jdet
call dcopy( p, x(iopt,1), n, v, 1)
call dscal( p, sjop, v, 1)
call daxpy( p, (-siop), x(jopt,1), n, v, 1)
call mclrup( q, p, v, r, p)
end if
if (ls .eq. ns) goto 900
call dscal( p, siop, x(iopt,1), n)
call daxpy( p, sjop, x(jopt,1), n, x(iopt,1), n)
if (jopt .ne. lg) then
call dcopy( p, x(lg,1), n, x(jopt,1), n)
ic(jopt) = ic(lg)
end if
ic(iopt) = nopt
x(lg,1) = detw
x(lg,2) = trcw
if (p .ge. 4) then
x(lg,3) = dble(iopt)
x(lg,4) = dble(jopt)
else if (p .eq. 3) then
x(lg,3) = dble(iopt)
jo(ls) = jopt
else
io(ls) = iopt
jo(ls) = jopt
end if
ls = ls + 1
lg = lg - 1
if (detw .ge. DELOG) then
c if (.false.)
c * call intpr('PART 3 --------------------------', -1, ls, 0)
goto 300
end if
goto 200
300 continue
q = q + 1
detw = FLMAX
do j = 2, lg
nj = ic(j)
rj = dble(nj)
do i = 1, (j-1)
ni = ic(i)
ri = dble(ni)
nij = ni + nj
rij = dble(nij)
si = sqrt(ri/rij)
sj = sqrt(rj/rij)
call dcopy( p, x(i,1), n, v, 1)
call dscal( p, sj, v, 1)
call daxpy( p, (-si), x(j,1), n, v, 1)
call dcopy( lw, r, 1, u, 1)
call mclrup( q, p, v, u, p)
dij = detmc2( p, u)
if (dij .le. detw) then
detw = dij
nopt = nij
siop = si
sjop = sj
iopt = i
jopt = j
call dcopy( lw, u, 1, s, 1)
end if
end do
end do
c update the trace
call dcopy( p, x(iopt,1), n, v, 1)
call dscal( p, sjop, v, 1)
call daxpy( p, (-siop), x(jopt,1), n, v, 1)
trcw = trcw + ddot( p, v, 1, v, 1)
if (ls .eq. ns) goto 900
call dcopy( lw, s, 1, r, 1)
call dscal( p, siop, x(iopt,1), n)
call daxpy( p, sjop, x(jopt,1), n, x(iopt,1), n)
if (jopt .ne. lg) then
call dcopy( p, x(lg,1), n, x(jopt,1), n)
ic(jopt) = ic(lg)
end if
ic(iopt) = nopt
x(lg,1) = detw
x(lg,2) = trcw
if (p .ge. 4) then
x(lg,3) = dble(iopt)
x(lg,4) = dble(jopt)
else if (p .eq. 3) then
x(lg,3) = dble(iopt)
jo(ls) = jopt
else
io(ls) = iopt
jo(ls) = jopt
end if
ls = ls + 1
lg = lg - 1
goto 300
900 continue
x(lg,1) = detw
x(lg,2) = trcw
if (p .ge. 4) then
if (iopt .lt. jopt) then
x(lg,3) = dble(iopt)
x(lg,4) = dble(jopt)
else
x(lg,3) = dble(jopt)
x(lg,4) = dble(iopt)
end if
else if (p .eq. 3) then
if (iopt .lt. jopt) then
x(lg,3) = dble(iopt)
jo(ls) = jopt
else
x(lg,3) = dble(jopt)
jo(ls) = iopt
end if
else
if (iopt .lt. jopt) then
io(ls) = iopt
jo(ls) = jopt
else
io(ls) = jopt
jo(ls) = iopt
end if
end if
c decode
do k = 1, ng
ic(k) = k
end do
m = ng + 1
if (p .ge. 4) then
l = m
do k = 1, ns
l = l - 1
i = int(x(l,3))
ici = ic(i)
j = int(x(l,4))
icj = ic(j)
if (ici .gt. icj) ic(i) = icj
ic(j) = ic(m - k)
if (ici .lt. icj) then
x(l,3) = dble(ici)
x(l,4) = dble(icj)
else
x(l,3) = dble(icj)
x(l,4) = dble(ici)
end if
end do
else if (p .eq. 3) then
l = m
do k = 1, ns
l = l - 1
i = int(x(l,3))
ici = ic(i)
j = jo(k)
icj = ic(j)
if (ici .gt. icj) ic(i) = icj
ic(j) = ic(m - k)
if (ici .lt. icj) then
x(l,3) = dble(ici)
jo(k) = icj
else
x(l,3) = dble(icj)
jo(k) = ici
end if
end do
else
do k = 1, ns
i = io(k)
ici = ic(i)
j = jo(k)
icj = ic(j)
if (ici .gt. icj) ic(i) = icj
ic(j) = ic(m - k)
if (ici .lt. icj) then
io(k) = ici
jo(k) = icj
else
io(k) = icj
jo(k) = ici
end if
end do
end if
l = 2
m = min(p,4)
do k = ng, lg, -1
if (k .le. l) goto 950
call dswap( m, x(k,1), n, x(l,1), n)
l = l + 1
end do
950 continue
x(1,1) = det1
x(1,2) = trc1
v(1) = dble(l1)
v(2) = dble(l2)
s(1) = det0
s(2) = trc0
return
end
mclust/NAMESPACE 0000644 0001762 0000144 00000013417 13474424342 013015 0 ustar ligges users useDynLib(mclust)
# useDynLib(mclust, .registration = TRUE)
# Export all names
# exportPattern(".")
# Import all packages listed as Imports or Depends
import("stats", "utils", "graphics", "grDevices")
# export(.mclust)
export(mclust.options, emControl)
export(em, emE, emEEE, emEEI, emEEV, emEII, emEVI,
emV, emVEI, emVEV, emVII, emVVI, emVVV,
emEVV, emVEE, emEVE, emVVE,
emX, emXII, emXXI, emXXX)
export(me, meE, meEEE, meEEI, meEEV, meEII, meEVI,
meV, meVEI, meVEV, meVII, meVVI, meVVV,
meEVV, meVEE, meEVE, meVVE,
meX, meXII, meXXI, meXXX)
export(sim, simE, simEEE, simEEI, simEEV, simEII, simEVI,
simV, simVEI, simVEV, simVII, simVVI, simVVV,
simEVV, simVEE, simEVE, simVVE)
export(estep, estepE, estepEEE, estepEEI, estepEEV, estepEII, estepEVI,
estepV, estepVEI, estepVEV, estepVII, estepVVI, estepVVV,
estepEVV, estepVEE, estepEVE, estepVVE)
export(mstep, mstepE, mstepEEE, mstepEEI, mstepEEV, mstepEII, mstepEVI,
mstepV, mstepVEI, mstepVEV, mstepVII, mstepVVI, mstepVVV,
mstepEVV, mstepVEE, mstepEVE, mstepVVE)
export(mvn, mvnX, mvnXII, mvnXXI, mvnXXX)
export(cdens, cdensE, cdensEEE, cdensEEI, cdensEEV, cdensEII, cdensEVI,
cdensV, cdensVEI, cdensVEV, cdensVII, cdensVVI, cdensVVV,
cdensEVV, cdensVEE, cdensEVE, cdensVVE,
cdensX, cdensXII, cdensXXI, cdensXXX)
export(bic, pickBIC, mclustBICupdate)
export(mclustLoglik, print.mclustLoglik)
S3method("print", "mclustLoglik")
export(nVarParams, nMclustParams)
export(map, unmap, partconv, partuniq, errorBars)
export(mclustModel, mclustModelNames, checkModelName, mclustVariance)
export(decomp2sigma, sigma2decomp)
export(imputeData, imputePairs, matchCluster, majorityVote)
export(mapClass, classError, adjustedRandIndex, BrierScore)
export(mclust1Dplot, mclust2Dplot, mvn2plot, surfacePlot, uncerPlot)
export(clPairs, clPairsLegend, coordProj, randProj,
randomOrthogonalMatrix)
export(priorControl, defaultPrior, hypvol)
export(hc, print.hc, plot.hc, as.hclust.hc, as.dendrogram.hc)
S3method("print", "hc")
S3method("plot", "hc")
S3method("as.hclust", "hc")
S3method("as.dendrogram", "hc")
export(hcE, hcEEE, hcEII, hcV, hcVII, hcVVV)
export(hclass, randomPairs)
export(mclustBIC, print.mclustBIC, summary.mclustBIC,
print.summary.Mclust, plot.mclustBIC,
summaryMclustBIC, summaryMclustBICn)
S3method("print", "mclustBIC")
S3method("summary", "mclustBIC")
S3method("print", "summary.mclustBIC")
S3method("plot", "mclustBIC")
export(Mclust, print.Mclust, summary.Mclust, print.summary.Mclust, plot.Mclust,
predict.Mclust, logLik.Mclust)
S3method("print", "Mclust")
S3method("summary", "Mclust")
S3method("print", "summary.Mclust")
S3method("plot", "Mclust")
S3method("predict", "Mclust")
S3method("logLik", "Mclust")
export(densityMclust, plot.densityMclust, dens, predict.densityMclust,
cdfMclust, quantileMclust, densityMclust.diagnostic,
plotDensityMclust1, plotDensityMclust2, plotDensityMclustd)
S3method("plot", "densityMclust")
S3method("predict", "densityMclust")
export(MclustDA, print.MclustDA, summary.MclustDA, print.summary.MclustDA,
plot.MclustDA, predict.MclustDA, cvMclustDA, getParameters.MclustDA,
logLik.MclustDA, classPriorProbs)
S3method("print", "MclustDA")
S3method("summary", "MclustDA")
S3method("print", "summary.MclustDA")
S3method("plot", "MclustDA")
S3method("predict", "MclustDA")
S3method("logLik", "MclustDA")
export(MclustDR, print.MclustDR, summary.MclustDR, print.summary.MclustDR,
plot.MclustDR, plotEvalues.MclustDR, projpar.MclustDR,
predict.MclustDR, predict2D.MclustDR)
S3method("print", "MclustDR")
S3method("summary", "MclustDR")
S3method("print", "summary.MclustDR")
S3method("plot", "MclustDR")
S3method("predict", "MclustDR")
export(MclustDRsubsel,
MclustDRsubsel_cluster, MclustDRsubsel_classif,
MclustDRsubsel1cycle, MclustDRrecoverdir,
print.MclustDRsubsel, summary.MclustDRsubsel)
S3method("print", "MclustDRsubsel")
S3method("summary", "MclustDRsubsel")
export(me.weighted, covw, hdrlevels, dmvnorm)
export(icl, mclustICL, print.mclustICL,
summary.mclustICL, print.summary.mclustICL,
plot.mclustICL)
S3method("icl", "Mclust")
S3method("icl", "MclustDA")
S3method("print", "mclustICL")
S3method("summary", "mclustICL")
S3method("print", "summary.mclustICL")
S3method("plot", "mclustICL")
export(mclustBootstrapLRT, print.mclustBootstrapLRT, plot.mclustBootstrapLRT)
S3method("print", "mclustBootstrapLRT")
S3method("plot", "mclustBootstrapLRT")
export(MclustBootstrap, print.MclustBootstrap,
summary.MclustBootstrap, print.summary.MclustBootstrap,
plot.MclustBootstrap)
S3method("print", "MclustBootstrap")
S3method("summary", "MclustBootstrap")
S3method("print", "summary.MclustBootstrap")
S3method("plot", "MclustBootstrap")
export(as.Mclust, as.Mclust.default, as.Mclust.densityMclust)
S3method("as.Mclust", "default")
S3method("as.Mclust", "densityMclust")
export(as.densityMclust, as.densityMclust.default, as.densityMclust.Mclust)
S3method("as.densityMclust", "default")
S3method("as.densityMclust", "Mclust")
export(clustCombi, print.clustCombi,
summary.clustCombi, print.summary.clustCombi,
plot.clustCombi, combiPlot, entPlot, combiTree,
combMat, clustCombiOptim)
S3method("plot", "clustCombi")
S3method("print", "clustCombi")
S3method("summary", "clustCombi")
S3method("print", "summary.clustCombi")
export(gmmhd, print.gmmhd,
summary.gmmhd, print.summary.gmmhd,
plot.gmmhd,
gmmhdClusterCores, gmmhdClassify)
S3method("print", "gmmhd")
S3method("summary", "gmmhd")
S3method("print", "summary.gmmhd")
S3method("plot", "gmmhd")
# deprecated functions
export(cv.MclustDA, cv1EMtrain, bicEMtrain)
mclust/NEWS.md 0000644 0001762 0000144 00000036223 13510361761 012670 0 ustar ligges users # mclust 5.4.5
* Fixed warnings in Fortran calls raised by CRAN.
# mclust 5.4.4
- Added `classPriorProbs()` to estimate prior class probabilities.
- Added `BrierScore()` to compute the Brier score for assessing the accuracy of probabilistic predictions.
- Added `randomOrthogonalMatrix()` to generate random orthogonal basis matrices.
- Partial rewriting of `summary.MclustDA()` internals to provide both the classification error and the Brier score for training and/or test data.
- Partial rewriting of `plot.MclustDA()` internals.
- Added `dmvnorm()` for computing the density of a general multivariate Gaussian distribution via efficient Fortran code.
- Added Wisconsin diagnostic breast cancer (WDBC) data.
- Added EuroUnemployment data.
- Fixed mismatches in Fortran calls.
- Bugs fix.
# mclust 5.4.3
- Added website site and update DESCRIPTION with URL.
- Fixed a bug when checking for univariate data with a single observation in several instances. Using `NCOL()` works both for n-values vector or nx1 matrix.
- Fixed a bug when `hcPairs` are provided in the `initialization` argument of `mclustBIC()` (and relatives) and the number of observations exceed the threshold for subsetting.
- Fixed bugs on axes for some manual pairs plots.
- Renamed `type = "level"` to `type = "hdr"`, and `level.prob` to `prob`, in `surfacePlot()` for getting HDRs graphs
- Fixed a bug in `type = "hdr"` plot on `surfacePlot()`.
- Fixed a bug in `as.Mclust()`.
- Small changes to `summary.MclustDA()` when `modelType = "EDDA"` and in general for a more compact output.
# mclust 5.4.2
- Added `mclustBICupdate()` to merge the best values from two BIC results as returned by `mclustBIC()`.
- Added `mclustLoglik()` to compute the maximal log-likelihood values from BIC results as returned by `mclustBIC()`.
- Added option `type = "level"` to `plot.densityMclust()` and `surfacePlot()` to draw highest density regions.
- Added `meXXI()` and `meXXX()` to exported functions.
- Updated vignette.
# mclust 5.4.1
- Added parametric bootstrap option (`type = "pb"`) in `MclustBootstrap()`.
- Added the options to get averages of resampling distributions in `summary.MclustBootstrap()` and to plot resampling-based confidence intervals in `plot.MclustBootstrap()`.
- Added function `catwrap()` for wrapping printed lines at `getOption("width")` when using `cat()`.
- `mclust.options()` now modify the variable `.mclust` in the namespace of the package, so it should work even inside an mclust-function call.
- Fixed a bug in `covw()` when `normalize = TRUE`.
- Fixed a bug in `estepVEV()` and `estepVEE()` when parameters contains `Vinv`.
- Fixed a bug in `plotDensityMclustd()` when drawing marginal axes.
- Fixed a bug in `summary.MclustDA()` when computing classification error in the extreme case of a minor class of assignment.
- Fixed a bug in the initialisation of `mclustBIC()` when a noise component is present for 1-dimensional data.
- Fixed bugs in some examples documenting `clustCombi()` and related functions.
# mclust 5.4
- Model-based hierarchical clustering used to start the EM-algorithm is now based on the scaled SVD transformation proposed by Scrucca and Raftery (2016). This change is not backward compatible. However, previous results can be easily obtained by issuing the command: `mclust.options(hcUse = "VARS") For more details see help("mclust.options")`.
- Added `subset` parameter in `mclust.options()` to control the maximal sample size to be used in the initial model-based hierarchical phase.
- `predict.densityMclust()` can optionally returns the density on a logarithm scale.
- Removed normalization of mixing proportions for new models in single mstep.
- Internal rewrite of code used by `packageStartupMessage()`.
- Fixed a small bug in `MclustBootstrap()` in the univariate data case.
- Fixed bugs when both the noise and subset are provided for initialization.
- Vignette updated to include references, startup message, css style, etc.
- Various bug fixes in plotting methods when noise is present.
- Updated references in `citation()` and man pages.
# mclust 5.3 (2017-05)
- Added `gmmhd()` function and relative methods.
- Added `MclustDRsubsel()` function and relative methods.
- Added option to use subset in the hierarchical initialization step when a noise component is present.
- `plot.clustCombi()` presents a menu in interactive sessions, no more need of data for classification plots but extract the data from the `clustCombi` object.
- Added `combiTree()` plot for `clustCombi` objects.
- `clPairs()` now produces a single scatterplot in the bivariate case.
- Fixed a bug in `imputeData()` when seed is provided. Now if a seed is provided the data matrix is reproducible.
- in `imputeData()` and `imputePairs()` some name of arguments have been modified to be coherent with the rest of the package.
- Added functions `matchCluster()` and `majorityVote()`.
- Rewrite of print and summary methods for `clustCombi` class objects.
- Added `clustCombiOptim()`.
- Fixed a bug in `randomPairs()` when nrow of input data is odd.
- Fixed a bug in `plotDensityMclust2()`, `plotDensityMclustd()` and `surfacePlot()` when a noise component is present.
# mclust 5.2.3 (2017-03)
- Added native routine registration for Fortran code.
- Fixed lowercase argument PACKAGE in `.Fortran()` calls.
# mclust 5.2.2 (2017-01)
- Fixed a bug in rare case when performing an extra M step at the end of EM algorithm.
# mclust 5.2.1 (2017-01)
- Replaced `structure(NULL, *)` with `structure(list(), *)`
# mclust 5.2 (2016-03)
- Added argument `x` to `Mclust()` to use BIC values from previous computations to avoid recomputing for the same models. The same argument and functionality was already available in `mclustBIC()`.
- Added argument `x` to `mclustICL()` to use ICL values from previous computations to avoid recomputing for the same models.
- Fixed a bug on `plot.MclustBootstrap()` for the `"mean"` and `"var"` in the univariate case.
- Fixed uncertainty plots.
- Added functions `as.Mclust()` and `as.densityMclust()` to convert object to specific mclust classes.
- Solved a numerical accuracy problem in `qclass()` when the scale of `x` is (very) large by making the tolerance eps scale dependent.
- Use transpose subroutine instead of non-Fortran 77 TRANSPOSE function in `mclustaddson.f`.
- Fixed `predict.Mclust()` and `predict.MclustDR()` by implementing a more efficient and accurate algorithm for computing the densities.
# mclust 5.1 (2015-10)
- Fixed slow convergence for VVE and EVE models.
- Fixed a bug in orientation for model VEE.
- Added an extra M-step and parameters update in `Mclust()` call via `summaryMclustBIC()`.
# mclust 5.0.2 (2015-07)
- Added option to `MclustBootstrap()` for using weighted likelihood bootstrap.
- Added a plot method for `MclustBootstrap` objects.
- Added `errorBars()` function.
- Added `clPairsLegend()` function.
- Added `covw()` function.
- Fixed rescaling of mixing probabilities in new models.
- bug fixes.
# mclust 5.0.1 (2015-04)
- Fixed bugs.
- Added print method for `hc` objects.
# mclust 5.0.0 (2015-03)
- Added the four missing models (EVV, VEE, EVE, VVE) to the mclust family. A noise component is allowed, but no prior is available.
- Added `mclustBootstrapLRT()` function (and corresponding print and plot methods) for selecting the number of mixture components based on the sequential bootstrap likelihood ratio test.
- Added `MclustBootstrap()` function (and corresponding print and summary methods) for performing bootstrap inference. This provides standard errors for parameters and confidence intervals.
- Added `"A quick tour of mclust"` vignette as html generated using rmarkdown and knitr. Older vignettes are included as other documentation for the package.
- Modified arguments to `mvn2plot()` to control colour, lty, lwd, and pch of ellipses and mean point.
- Added functions `emX()`, `emXII()`, `emXXI()`, `emXXX()`, `cdensX()`, `cdensXII()`, `cdensXXI()`, and `cdensXXX()`, to deal with single-component cases, so calling the em function works even if `G = 1`.
- Small changes to `icl()`, now it is a generic method, with specialized methods for `Mclust` and `MclustDA` objects.
- Fixed bug for transformations in the initialization step when some variables are constant (i.e. the variance is zero) or a one-dimensional data is provided.
- Changed the order of arguments in `hc()` (and all the functions calling it).
- Small modification to `CITATION` file upon request of CRAN maintainers.
- Various bug fixes.
# mclust 4.4 (2014-09)
- Added option for using transformation of variables in the hierarchical initialization step.
- Added `quantileMclust()` for computing the quantiles from a univariate Gaussian mixture distribution.
- Fixed bugs on `summaryMclustBIC()`, `summaryMclustBICn()`, `Mclust()` to return a matrix of 1s on a single column for `z` even in the case of `G = 1`. This is to avoid error on some plots.
- Moved pdf files (previously included as vignettes) to `inst/doc` with corresponding `index.html`.
# mclust 4.3 (2014-03)
- Fixed bug for `logLik.MclustDA()` in the univariate case.
- Added argument `"what"` to `predict.densityMclust()` function for choosing what to retrieve, the mixture density or component density.
- `hc()` function has an additional parameter to control if the original variables or a transformation of them should be used for hierarchical clustering.
- Added `"hcUse"` argument in `mclust.options()` to be passed as default to `hc()`.
- Added the storing of original data (and class for classification models) in the object returned by the main functions.
- Added component `hypvol` to `Mclust` object which provide the hypervolume of the noise component when required, otherwise is set to NA.
- Added a warning when prior is used and BIC returns NAs.
- Fixed bugs in `summary.Mclust()`, `print.summary.Mclust()`, `plot.Mclust()` and `icl()` in the case of presence of a noise component.
- Fixed bug on some plots in `plot.MclustDR()` which requires `plot.new()` before calling `plot.window()`.
- Fixed a bug in `MclustDR()` for the one-dimensional case.
- Corrections to `Mclust` man page.
- Various small bug fixes.
# mclust 4.2 (2013-07)
- Fixed bug in `sim*()` functions when no obs are assigned to a component.
- `MclustDA()` allows to fit a single class model.
- Fixex bug in `summary.Mclust()` when a subset is used for initialization.
- Fixed a bug in the function `qclass()` when ties are present in quantiles, so it always return the required number of classes.
- Various small bug fixes.
# mclust 4.1 (2013-04)
- Added `icl()` function for computing the integrated complete-data likelihood.
- Added `mclustICL()` function with associated print and plot methods.
- `print.mclustBIC()` shows also the top models based on BIC.
- Modified `summary.Mclust()` to return also the icl.
- Rewrite of `adjustedRandIndex()` function. This version is more efficient for large vectors.
- Updated help for `adjustedRandIndex()`.
- Modifications to `MclustDR()` and its summary method.
- Changed behavior of `plot.MclustDR(..., what = "contour")`.
- Improved plot of uncertainty for `plot.MclustDR(..., what = "boundaries")`.
- Corrected a bug for malformed GvHD data.
- Corrected version of qclass for selecting initial values in case of 1D data when successive quantiles coincide.
- Corrected version of plot BIC values when only a single G component models are fitted.
- Various bug fixes.
# mclust 4.0 (2012-08)
- Added new summary and print methods for `Mclust()`.
- Added new summary and print methods for `densityMclust()`.
- Included `MclustDA()` function and methods.
- Included `MclustDR()` function and methods.
- Included `me.weighted()` function.
- Restored hierarchical clustering capability for the EEE model (hcEEE).
- Included vignettes for mclust version 4 from Technical Report No. 597 and for using weights in mclust.
- Adoption of GPL (>= 2) license.
# mclust 3.5 (2012-07)
- Added `summary.Mclust()`.
- New functions for plotting and summarizing density estimation.
- Various bug fixes.
- Added `clustCombi()` and related functions (code and doc provided by Jean-Patrick Baudry).
- Bug fix: variable names lost when G = 1.
# mclust 3.4.11 (2012-01)
- Added `NAMESPACE`.
# mclust 3.4.10 (2011-05)
- Removed intrinsic gamma-
# mclust 3.4.9 (2011-05)
- Fixed `hypvol()` function to avoid overflow.
- Fixed `hypvol()` help file value description.
- Removed unused variables and tabs from source code.
- Switched to intrinsic gamma in source code.
- Fixed default warning in estepVEV and mstepVEV.
# mclust 3.4.8 (2010-12)
- Fixed output when G = 1 (it had NA for the missing `z` component).
# mclust 3.4.7 (2010-10)
- Removed hierarchical clustering capability for the `EEE` model (hcEEE).
- The R 2.12.0 build failed due to a 32-bit Windows compiler error, forcing removal of the underlying Fortran code for hcEEE from the package, which does not contain errors and compiles on other platforms.
# mclust 3.4.6 (2010-08)
- Added description of parameters output component to `Mclust` and `summary.mclustBIC` help files.
# mclust 3.4.5 (2010-07)
- Added `densityMclust()` function.
# mclust 3.4.4 (2010-04)
- Fixed bug in covariance matrix output for EEV and VEV models.
# mclust 3.4.3 (2010-02)
- Bug fixes.
# mclust 3.4.2 (2010-02)
- Moved CITATION to inst and used standard format
- BibTex entries are in inst/cite.
- Fixed bug in handling missing classes in `mclustBIC()`.
- Clarified license wording.
# mclust 3.4.1 (2010-01)
- Corrected output description in `mclustModel` help file.
- Updated mclust manual reference to show revision.
# mclust 3.4 (2009-12)
- Updated `defaultPrior` help file.
- Added utility functions for imputing missing data with the mix package.
- Changed default max to number of mixture components in each class from 9 to 3.
# mclust 3.3.2 (2009-10)
- Fixed problems with \cr in `mclustOptions` help file
# mclust 3.3.1 (2009-06)
- Fixed `plot.mclustBIC()` and `plot.Mclust()` to handle `modelNames`.
- Changed "orientation" for VEV, VVV models to be consistent with R `eigen()` and the literature
- Fixed some problems including doc for the noise option.
- Updated the `unmap()` function to optionally include missing groups.
# mclust 3.3 (2009-06)
- Fixed bug in the `"errors"` option for `randProj()`.
- Fixed boundary cases for the `"noise"` option.
# mclust 3.2 (2009-04)
- Added permission for CRAN distribution to LICENSE.
- Fixed problems with help files found by new parser.
- Changed PKG_LIBS order in src/Makevars.
- Fixed `Mclust()` to handle sampling in data expression in call.
# mclust 3.1.10 (2008-11)
- Added `EXPR = to` all switch functions that didn't already have it.
# mclust 3.1.9 (2008-10)
- Added `pro` component to parameters in `dens()` help file.
- Fixed some problems with the noise option.
# mclust 3.1.1 (2007-03)
- Default seed changed in `sim*()` functions.
- Added model name check to various functions.
- Otherwise backward compatible with version 3.0
# mclust 3.1 (2007-01)
- Most plotting functions changed to use color.
- `Mclust()` and `mclustBIC()` fixed to work with G=1
- Otherwise backward compatible with version 3.0.
# mclust 3.0 (2006-10)
- New functionality added, including conjugate priors for Bayesian regularization.
- Backward compatibility is not guaranteed since the implementation of some functions has changed to make them easier to use or maintain.
mclust/data/ 0000755 0001762 0000144 00000000000 13510412702 012465 5 ustar ligges users mclust/data/Baudry_etal_2010_JCGS_examples.rda 0000644 0001762 0000144 00000122361 13510412701 020562 0 ustar ligges users ‹ ´ýy8ÕÑ÷?›çñæá˜Ëi¯$sEBD“”•F¥($¡©LíC©Ìcæyžçé>õù~~÷õ|ŸûºîçŸçŸs8×9ï÷9{¯õZ¯×Þkmit`3Ç::::FÚ##íO&Ú=;í™ÙÍGSUŽŽ‘øïMtt<´§ 9pj½5ÆÄ2‚üO¹€ÅßáìDš÷y}Ç 'MöÃÈAÜþšåÁ±“ˆªÛÛ̳þMÜ÷Ó¿OdžT9KZã®äwìü1‚¤Õ¾3¿c2€¢é>j.c
R¼ ž¾ê’hYþÛXCvPŽÏ'¼)Ñê2‹1öÃhþëÃIÕw½ )³+à4q#êêåʈ6Ç%Û3b’… ìÐ >¢??î{)w¿ŒŠôþçW˜qu¬ƒ»Ž7®Q6cÞqø4P>l 'Ù£ÅݵäürÑo;‰=£ì¨•‡u¶0Ç
Ø·77$.Ùz<ÉÄ2¬ÕÐÈîÀã[Ô@r¯û§'ÔdQ&¤½±r³Gsrиm‹ø´==úJ49œpMϾÕK6iùëÏ>YþÂÍ7¼§¨«Ú ¹ëÁ oF#Üè6ýd)sÝöÛîJÅ·Þf[<F”"Y£V€bðæ‘–êÖÈ×NÉqÛ‰¤X4%è×ß0̃~UZÖd]z
”QÊ}2½0jî¾¹Ïãt
š6×XïüÉ‹º×E¯
1à–q²”¬û *ýrÚÈ‚Pˆ›žÙ\åEƒ–Ì!_AêÖí%ÛÂP—ytÌ.aœÑpõa£ücÔ߯›PŽæVß=|‹L;’WŽ‚”ÁØ÷2»ŸˆZðVØó!P¢RF5.ЮSÕ˜¸[Ï~xËò[A$ŸÜ|â\Ÿ Reá„bÑ’]žêxCšXßò¥fò:Pj†ùíÏ ¢iîà}K[qÏÖĨ«Ç§Q—ùÅåÛ‹á´ûBP¥¹þY^1z$ïÍâÞ
_-wj“/Züpì°²š8·ð8ÙÛ7&ŠP=KÉ¥PQrîH¥{¿¼”e9úÝuGmH óôXˆÆVg‰p…u·„aHƼ®D Ez~ißðH<Á§.>B³“ùÊ;›6 +Û™&{ ãŸå휵B‹ íµ|¡£¸ûVL\“L)Z_¨Úò8M¥V–ß2G³ï.Rú£¹ë»òÉñ¸ÎæFãÔùU
n½Ÿ;Á”6ç“ÖÝ@‘þpX1 ï5
ê[FU’~}W-) Õªlpec5P‚Óƒ}†_ƒ=¥øœ›ÂÃÂÇYßy¡ºÑІ¢K¨—Þ]F¶T¤Œ±ü '‚$)”Y;þ5þ]Õ¹e ÍœµJ{ óg²vÓí¥Ù)Ç‹Iu54Üþð‡ç:p%P}¼½ èÔTƒÄ~pÛ©¯iɯ^¡—ŠÙº#4®†,«4Ð8ïY‡ìg4á{ÿžäápÔQ2ÀOéEÓ£–„).´~Íá¢ô3.<¤g¶Á¢1$ûýxÚ†Šø²Äºt&@²[¼®æÏ=´œsóÆÓvP”nyŒ§¾ ]¹´Y4kü-b{?šŒ´3?§*Šf·UqÎ½ßæœMŠ–¼Î£¹×ëQUÓ %P£›(è¦ZÖ[ ';ö\<‰¦U‡ëú×Qç'EÕê×¶höR°kÙ{|üÍbñ{#0F׈ïî“îØ3Ö&Ó@ÒÒZÖ(¸¤W´/ëT1 ¡%&ñµh4‘ô–.ÿ1Ð7>}"ÔfÏÓÕ¸>¹†ºÃ»MAÕÂì7›pË×ö¢‹ÛÄ@"Ìa¨¸7%Uìý¼Â~fxï1[4ÜñIª2S×ÇÜÐî$¼ÊsQfÄ$
ÒÅÇ~ï˜"‚T”6«ûªÉyÛ‰âÑ빎ØÚh>•‘a›¢™æJ²í›C ѹ£àä™\šK.|«@ÓåwÛŸ¥+‚”‹¤‰D—!êöº¼g´½¤ö\Ûµ+_¤ø°ß»sìhôò'
¡M\÷6Xó¥dêK1±