未来趋势预测,系统特性分析,噪点处理, 优化曲线等业务需求

262 阅读1分钟

1.java进行实现需要导入

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-math3</artifactId>
    <version>3.6.1</version>
</dependency>

2.模拟数据进行曲线生成,进行四次曲线拟合,然后进行二分递归获取最优数据

public Map fitting(@RequestParam(value = "sum") Integer sum) {
    List<Map<String,Double>> params = new ArrayList<>();
    for (int i = 0; i <= sum; i++) {
        Map<String,Double> xy = new HashMap<>();
        xy.put("x",Double.valueOf(i) * 10);
        xy.put("y",Math.random() * 100);
        params.add(xy);
    }
    List<Map> stringObjectMap = modifyMonitorDataService.fittingRecursion(params);
    Map<String,Object> resultList = new HashMap<>();
    resultList.put("stringObjectMap",stringObjectMap);
    resultList.put("params",params);
    return resultList;
}
/**
 * 获取最优拟合结果
 *
 * @param params
 * @return
 */
public List<Map> fittingRecursion(List<Map<String, Double>> params) {
    double[] fittingValue = getFittingValue(params);
    double fittingDifference = getFittingDifference(params, fittingValue);

    int numberOfCycles = 0;
    List<Map> resultList = new ArrayList<>();
    dichotomousRecursion(params, fittingDifference, fittingValue, numberOfCycles, resultList);

    List<Map> doubles = new ArrayList<>();
    if (resultList.size() > 0) {
        log.info("\r\n拟合结果集:{}", JSONUtil.toJsonStr(resultList));
        Map<String, Object> map = resultList.get(0);

        int half = Integer.parseInt(map.get("half").toString());
        double floor = Math.floor(params.size() / half);

        int start = 0;
        int end = half;
        for (int i = 0; i < floor; i++) {
            List<Map<String, Double>> maps = params.subList(start, end);
            double[] fittingDouble = getFittingValue(maps);
            Map<String,Object> obj = new HashMap<>();
            obj.put("fittingDouble",fittingDouble);
            obj.put("sum",half);
            doubles.add(obj);
            start = end;
            end = start + half;
        }

        return doubles;
    }
    Map<String,Object> obj = new HashMap<>();
    obj.put("fittingDouble",fittingValue);
    obj.put("sum",params.size());
    doubles.add(obj);
    return doubles;
}
/**
 * 获取参数拟合
 *
 * @param params
 * @return
 */
private double[] getFittingValue(List<Map<String, Double>> params) {
    WeightedObservedPoints points = new WeightedObservedPoints();
    for (int i = 0; i < params.size(); i++) {
        points.add(params.get(i).get("x"), params.get(i).get("y"));
    }
    PolynomialCurveFitter fitter = PolynomialCurveFitter.create(3);
    return fitter.fit(points.toList());
}
/**
 * 获取拟合误差值
 *
 * @param params
 * @param result
 * @return
 */
private double getFittingDifference(List<Map<String, Double>> params, double[] result) {
    double difference = 0.0;
    for (int i = 0; i < params.size(); i++) {
        double yv = (result[3] * Math.pow(params.get(i).get("x"), 3)) + ((result[2] * Math.pow(params.get(i).get("x"), 2))) + (result[1] * params.get(i).get("x")) + result[0];
        difference += Math.abs(yv - params.get(i).get("y"));
    }
    return difference;
}
/**
 * 递归二分拟合
 *
 * @param params
 * @param fittingDifference
 * @param fittingValue
 * @param numberOfCycles
 * @param resultList
 */
private void dichotomousRecursion(List<Map<String, Double>> params, double fittingDifference, double[] fittingValue, int numberOfCycles, List<Map> resultList) {
    Map<String, Object> resultParams = new HashMap<>();
    if (params.size() >= 20) {
        numberOfCycles += 1;
        int half = (int) Math.floor(params.size() / 2);
        List<Map<String, Double>> anterior = params.subList(0, half);
        List<Map<String, Double>> rearSection = params.subList(half, params.size());

        double[] resultHalf = getFittingValue(anterior);
        double differenceHalf = getFittingDifference(anterior, resultHalf);

        double[] resultSection = getFittingValue(rearSection);
        double differenceSection = getFittingDifference(rearSection, resultSection);

        if (differenceHalf < fittingDifference || differenceSection < fittingDifference) {
            if (differenceHalf <= differenceSection) {
                dichotomousRecursion(anterior, differenceHalf, resultHalf, numberOfCycles, resultList);
            }
            if (differenceSection <= differenceHalf) {
                dichotomousRecursion(rearSection, differenceSection, resultSection, numberOfCycles, resultList);
            }
        }
        resultParams.put("numberOfCycles", numberOfCycles);
        resultParams.put("fittingValue", fittingValue);
        resultParams.put("fittingDifference", fittingDifference);
        resultParams.put("half", half);
        resultList.add(resultParams);
    }
}