All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mitre.caasd.commons.math.XyDataset Maven / Gradle / Ivy

/*
 *    Copyright 2022 The MITRE Corporation
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.mitre.caasd.commons.math;

import static com.google.common.collect.Lists.newArrayList;
import static org.mitre.caasd.commons.math.DataSplitter.checkInputData;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/** A XyDataset is a convenience class that make DataSplitters easier to use. */
public class XyDataset {

    private final List xData;
    private final List yData;

    private FastLinearApproximation approx;

    /**
     * Create an XyDataset assuming: (1) inputs are not null, (2) inputs have same size, (3) the x
     * data is strictly increasing.
     *
     * @param xData A strictly increasing sequence of x values
     * @param yData A y value for each x value
     */
    public XyDataset(List xData, List yData) {
        checkInputData(xData, yData);
        this.xData = xData;
        this.yData = yData;
    }

    public List xData() {
        return xData;
    }

    public List yData() {
        return yData;
    }

    public int size() {
        return xData.size();
    }

    public FastLinearApproximation approximateFit() {
        if (approx == null) {
            this.approx = new FastLinearApproximation(xData, yData);
        }
        return approx;
    }

    public double slopeEstimate() {
        return approximateFit().slope();
    }

    public double avgSquaredErrorEstimate() {
        return approximateFit().avgSquaredError();
    }

    public double length() {
        return xData.get(xData.size() - 1) - xData.get(0);
    }

    /**
     * This is a convenience function that applies a DataSplitter to this data AND repackages the
     * "array of split index" results into a more useful array of new Datasets (which should
     * partition this dataset).
     *
     * @param splitter
     *
     * @return An array of new XyDatasets that partition this data.
     */
    public XyDataset[] split(DataSplitter splitter) {

        int[] splitIndices = splitter.computeSplitsFor(xData, yData);

        XyDataset[] splits = new XyDataset[splitIndices.length - 1];

        for (int i = 0; i < splitIndices.length - 1; i++) {
            splits[i] = new XyDataset(
                    xData.subList(splitIndices[i], splitIndices[i + 1]),
                    yData.subList(splitIndices[i], splitIndices[i + 1]));
        }
        return splits;
    }

    public ArrayList asXyPointList() {
        ArrayList list = new ArrayList(xData.size());

        Iterator xIter = xData.iterator();
        Iterator yIter = yData.iterator();

        while (xIter.hasNext()) {
            list.add(new XyPoint(xIter.next(), yIter.next()));
        }
        return list;
    }

    public XyDataset takeDerivative() {
        ArrayList xCopy = newArrayList(xData);
        ArrayList yCopy = newArrayList();
        int n = xCopy.size();

        for (int i = 0; i < n; i++) {
            if (i == 0) {
                double slopeToNext = (yData.get(i + 1) - yData.get(i)) / (xData.get(i + 1) - xData.get(i));
                yCopy.add(slopeToNext);
            } else if (i == n - 1) {
                double slopeToPrior = (yData.get(i) - yData.get(i - 1)) / (xData.get(i) - xData.get(i - 1));
                yCopy.add(slopeToPrior);
            } else {
                double slopeToPrior = (yData.get(i) - yData.get(i - 1)) / (xData.get(i) - xData.get(i - 1));
                double slopeToNext = (yData.get(i + 1) - yData.get(i)) / (xData.get(i + 1) - xData.get(i));
                double slopeBetween = (yData.get(i + 1) - yData.get(i - 1)) / (xData.get(i + 1) - xData.get(i - 1));
                double avgSlope = (slopeToPrior + slopeToNext + slopeBetween) / 3.0;
                yCopy.add(avgSlope);
            }
        }
        return new XyDataset(xCopy, yCopy);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy