Skip to content

Commit

Permalink
Merge pull request #145 from palatej/develop
Browse files Browse the repository at this point in the history
Improvements of high-frequency
  • Loading branch information
palatej authored Jun 18, 2024
2 parents 5e64f54 + 98087c4 commit 6f2305c
Show file tree
Hide file tree
Showing 20 changed files with 1,122 additions and 414 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>eu.europa.ec.joinup.sat</groupId>
<artifactId>jdplus-sts-base-core</artifactId>
<version>2.1.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>eu.europa.ec.joinup.sat</groupId>
<artifactId>jdplus-tramoseats-base-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,8 @@
import jdplus.toolkit.base.core.regarima.RegArimaModel;
import jdplus.toolkit.base.core.regarima.ami.GenericOutliersDetection;
import jdplus.toolkit.base.core.regarima.ami.OutliersDetectionModule;
import jdplus.toolkit.base.core.ssf.arima.FastArimaForecasts;
import jdplus.toolkit.base.core.ssf.arima.ExactArimaForecasts;
import jdplus.toolkit.base.core.ssf.arima.SsfUcarima;
import jdplus.toolkit.base.core.ssf.composite.CompositeSsf;
import jdplus.toolkit.base.core.stats.likelihood.LogLikelihoodFunction;
import jdplus.toolkit.base.core.timeseries.simplets.Transformations;
import org.checkerframework.checker.nullness.qual.NonNull;

/**
Expand Down Expand Up @@ -270,7 +266,7 @@ public static ExtendedAirlineEstimation fastProcess(DoubleSeq y, Matrix X, boole

DataInterpolator interpolator = AverageInterpolator.interpolator();
double[] interpolatedData;
int[] missing = IntList.EMPTY;
int[] missing;

if (y.anyMatch(z -> Double.isNaN(z))) {
IntList lmissing = new IntList();
Expand All @@ -283,7 +279,6 @@ public static ExtendedAirlineEstimation fastProcess(DoubleSeq y, Matrix X, boole
Arrays.sort(missing);
}
} else {
interpolatedData = null;
missing = IntList.EMPTY;
}

Expand All @@ -309,10 +304,10 @@ public static ExtendedAirlineEstimation fastProcess(DoubleSeq y, Matrix X, boole
.y(y)
.addX(FastMatrix.of(X_withoutFcast))
.arima(mapping.getDefault())
.meanCorrection(mean);
OutlierDescriptor[] o = null;
if (outliers != null && outliers.length
> 0) {
.meanCorrection(mean)
.missing(missing);
OutlierDescriptor[] o;
if (outliers != null && outliers.length > 0) {
GlsArimaProcessor<ArimaModel> processor = GlsArimaProcessor.builder(ArimaModel.class)
.precision(1e-5)
.build();
Expand Down Expand Up @@ -358,7 +353,7 @@ public static ExtendedAirlineEstimation fastProcess(DoubleSeq y, Matrix X, boole
//Ausgabe anpassen
RegArimaModel model = rslt.getModel();

DoubleSeq y_fcasts = DoubleSeq.empty();
DoubleSeq y_fcasts;

if (nfcasts > 0) {
ExactArimaForecasts fcasts = new ExactArimaForecasts();
Expand Down Expand Up @@ -390,8 +385,8 @@ public static ExtendedAirlineEstimation fastProcess(DoubleSeq y, Matrix X, boole
if (X != null && X.getColumnsCount() != 0) {
for (int j = 0; j < X.getColumnsCount(); ++j) {
double c = coeff.getAndNext();
if (c != 0) {
for (int k = y.length(); k < y.length() + nfcasts; ++k) {
if (c != 0) {
for (int k = y.length(); k < y.length() + nfcasts; ++k) {
y_fcast_a[k - y.length()] += c * X.column(j).get(k);
}
}
Expand Down Expand Up @@ -470,7 +465,14 @@ private void execTransform(ExtendedRegAirlineModelling modelling, ProcessingLog
log.push("log/level");
switch (spec.getTransform().getFunction()) {
case Auto:
log.warning("not implemented yet. log used");
LogLevelModule ll = LogLevelModule.builder()
.aiccLogCorrection(spec.getTransform().getAicDiff())
.estimationPrecision(1e-5)
.build();

ll.process(modelling);
// log.warning("not implemented yet. log used");
break;
case Log:
if (modelling.getDescription().getSeries().getValues().allMatch(x -> x > 0)) {
modelling.getDescription().setLogTransformation(true);
Expand Down Expand Up @@ -537,7 +539,7 @@ private void execOutliers(ExtendedRegAirlineModelling modelling, ProcessingLog l
log.pop();
}

private static int outlierType(String[] all, String cur) {
public static int outlierType(String[] all, String cur) {
for (int i = 0; i < all.length; ++i) {
if (cur.equals(all[i])) {
return i;
Expand All @@ -546,7 +548,7 @@ private static int outlierType(String[] all, String cur) {
return -1;
}

private static IOutlierFactory[] factories(String[] code) {
public static IOutlierFactory[] factories(String[] code) {
List<IOutlierFactory> fac = new ArrayList<>();
for (int i = 0; i < code.length; ++i) {
switch (code[i]) {
Expand All @@ -562,7 +564,7 @@ private static IOutlierFactory[] factories(String[] code) {
return fac.toArray(IOutlierFactory[]::new);
}

private static IOutlier outlier(String code, TsPeriod p) {
public static IOutlier outlier(String code, TsPeriod p) {
LocalDateTime pos = p.start();
return switch (code) {
case "ao", "AO" ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/*
* Copyright 2024 JDemetra+.
* Licensed under the EUPL, Version 1.2 or – as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* https://joinup.ec.europa.eu/software/page/eupl
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
package jdplus.highfreq.base.core.extendedairline;

import java.util.List;
import jdplus.highfreq.base.api.ExtendedAirline;
import jdplus.highfreq.base.api.ExtendedAirlineSpec;
import jdplus.toolkit.base.api.data.DoubleSeq;
import jdplus.toolkit.base.api.data.DoubleSeqCursor;
import jdplus.toolkit.base.api.data.ParametersEstimation;
import jdplus.toolkit.base.api.information.GenericExplorable;
import jdplus.toolkit.base.api.math.matrices.Matrix;
import jdplus.toolkit.base.api.processing.ProcessingLog;
import jdplus.toolkit.base.api.timeseries.regression.MissingValueEstimation;
import jdplus.toolkit.base.core.arima.ArimaModel;
import jdplus.toolkit.base.core.data.DataBlock;
import jdplus.toolkit.base.core.regarima.RegArimaEstimation;
import jdplus.toolkit.base.core.regarima.RegArimaModel;
import jdplus.toolkit.base.core.regarima.RegArimaUtility;
import jdplus.toolkit.base.core.stats.likelihood.ConcentratedLikelihoodWithMissing;
import jdplus.toolkit.base.core.stats.likelihood.LikelihoodStatistics;
import jdplus.toolkit.base.core.stats.likelihood.LogLikelihoodFunction;

/**
*
* @author Jean Palate
*/
@lombok.Value
@lombok.Builder(toBuilder = true, builderClassName = "Builder")
public class LightExtendedAirlineEstimation implements GenericExplorable {

@lombok.NonNull
private DoubleSeq y;
@lombok.NonNull
private Matrix X;
private boolean mean;

@lombok.NonNull
private ExtendedAirline model;

/**
* Regression estimation. The order correspond to the order of the variables
* Fixed coefficients are not included
*/
@lombok.NonNull
private DoubleSeq coefficients;
@lombok.NonNull
private Matrix coefficientsCovariance;

/**
* Positions corresponding to the estimation domain
*/
@lombok.NonNull
private MissingValueEstimation[] missing;
/**
* Parameters of the stochastic component. Fixed parameters are not included
*/
@lombok.NonNull
private ParametersEstimation parameters;

private LikelihoodStatistics statistics;

private DoubleSeq fullResiduals;

@lombok.Singular
private List<ProcessingLog.Information> logs;

public static Builder builder() {
Builder builder = new Builder();
builder.y = DoubleSeq.empty();
builder.X = Matrix.empty();
builder.coefficients = DoubleSeq.empty();
builder.coefficientsCovariance = Matrix.empty();
builder.missing = NOMISSING;
builder.parameters = ParametersEstimation.empty();
builder.fullResiduals = DoubleSeq.empty();
return builder;
}

private static final MissingValueEstimation[] NOMISSING = new MissingValueEstimation[0];

public static LightExtendedAirlineEstimation of(RegArimaEstimation<ArimaModel> estimation, ExtendedAirlineSpec spec) {
Builder builder = builder();
RegArimaModel<ArimaModel> regarima = estimation.getModel();
ConcentratedLikelihoodWithMissing ll = estimation.getConcentratedLikelihood();
LogLikelihoodFunction.Point<RegArimaModel<ArimaModel>, ConcentratedLikelihoodWithMissing> max = estimation.getMax();
int free = spec.freeParametersCount();
int df = ll.degreesOfFreedom() - free;
double vscale = ll.ssq() / df;
builder.y(regarima.getY())
.X(regarima.variables())
.mean(regarima.isMean())
.model(ExtendedAirline.of(spec.withFreeParameters(max.getParameters())))
.coefficients(ll.coefficients())
.coefficientsCovariance(ll.covariance(free, true));
ParametersEstimation pestim = new ParametersEstimation(max.getParameters(), max.asymptoticCovariance(), max.getScore(), "Extended airline");
builder.parameters(pestim)
.statistics(estimation.statistics());
DoubleSeq fullRes = RegArimaUtility.fullResiduals(regarima, ll);
builder.fullResiduals(fullRes);
// complete for missings
int nmissing = ll.nmissing();
if (nmissing > 0) {
DoubleSeq y = regarima.getY();
MissingValueEstimation[] missing = new MissingValueEstimation[nmissing];
DoubleSeqCursor cur = ll.missingCorrections().cursor();
DoubleSeqCursor vcur = ll.missingUnscaledVariances().cursor();
int[] pmissing = regarima.missing();
for (int i = 0; i < nmissing; ++i) {
double m = cur.getAndNext();
double v = vcur.getAndNext();
missing[i] = new MissingValueEstimation(pmissing[i], y.get(pmissing[i]) - m, Math.sqrt(v * vscale));
}
builder.missing(missing);
}
return builder.build();
}

public DoubleSeq originalY() {
if (y.anyMatch(z -> Double.isNaN(z))) {
// already contains the missing values
return y;
}
if (missing.length == 0) {
return y;
}
double[] z = y.toArray();
for (int i = 0; i < missing.length; ++i) {
z[missing[i].getPosition()] = Double.NaN;
}
return DoubleSeq.of(z);
}

public DoubleSeq linearizedData() {
double[] res = y.toArray();

// handle missing values
if (missing.length > 0) {
for (int i = 0; i < missing.length; ++i) {
res[missing[i].getPosition()] = missing[i].getValue();
}
}
DataBlock e = DataBlock.of(res);
if (!X.isEmpty()) {
DoubleSeq regs = regressionEffect();
e.sub(regs);
}
return e;
}

public DoubleSeq regressionEffect() {

if (coefficients.isEmpty()) {
return DoubleSeq.empty();
}

DataBlock d = DataBlock.make(y.length());
d.setAY(coefficients.get(0), X.column(0));
for (int i = 1; i < coefficients.length(); ++i) {
d.addAY(coefficients.get(i), X.column(i));
}
return d;
}

}
Loading

0 comments on commit 6f2305c

Please sign in to comment.