helochen - Overview

public void generateRangeWater() throws IOException {
        // 从4.2 - 3.8 - 2.0 雨量范围可以推测历史数据
        File file = new File("E:\\2025 水务局\\20250614\\" + System.currentTimeMillis() / 1000 + ".csv");
        if (!file.exists()) {
            file.createNewFile();
        }
        double[] waterHeight = new double[]{4.2, 3.8, 3.4, 3.0, 2.6, 2.2};
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String[] header = {"code", "source", "target", "rangeStart", "rangeEnd", "time"};
        // 数据组
        List<Double[]> trainingData = new ArrayList<>();

        try (FileWriter writer = new FileWriter(file)) {
            // 写入文件头
            writer.write(String.join(",", header) + "\n");

            for (int i = 1; i < waterHeight.length; i++) {
                String where = " Z >= " + waterHeight[i] + " and Z <=" + waterHeight[i - 1];
                log.info("{}", where);
                List<Map<String, Object>> maps = remoteService.queryRangeData("hdz", "81212478", where);

                for (Map<String, Object> map : maps) {
                    log.error("输出结束start......");
                    // 每个去找他历史得消息
                    PredictionDeviceDataVo objData = PredictionDeviceDataVo.createFromMap(map);

                    if (null != objData) {
                        if (objData.getUpdateTime() != null) {
                            Date startDate = DateUtils.addHours(objData.getUpdateTime(), -1);
                            Date endDate = DateUtils.addHours(objData.getUpdateTime(), 0);
                            log.info("河道站 峡口 输出情况:{}", objData);
                            // 大圳埔排站(外)
                            List<Map<String, Object>> keyPointOne = remoteService.queryData(df.format(startDate), df.format(endDate), "hdz", "81212375");
                            String oneRecord = this.outCsv("81212375", keyPointOne, objData.getData(), waterHeight[i], waterHeight[i - 1]);
                            writer.write(oneRecord);
                            PredictionDeviceDataVo avgOne = this.avg(keyPointOne);
                            String oneRecordAvg = this.outCsv("--81212375--", avgOne, objData.getData(), waterHeight[i], waterHeight[i - 1]);
                            writer.write(oneRecordAvg);

                            // 同沙村
                            List<Map<String, Object>> keyPointTwo = remoteService.queryData(df.format(startDate), df.format(endDate), "hdz", "81212448");
                            String twoRecord = this.outCsv("81212448", keyPointTwo, objData.getData(), waterHeight[i], waterHeight[i - 1]);
                            writer.write(twoRecord);
                            PredictionDeviceDataVo avgTwo = this.avg(keyPointTwo);
                            String twoRecordAvg = this.outCsv("--81212448--", avgTwo, objData.getData(), waterHeight[i], waterHeight[i - 1]);
                            writer.write(twoRecordAvg);
                            // 横沥
                            Date startDate2 = DateUtils.addHours(objData.getUpdateTime(), -2);
                            Date endDate2 = DateUtils.addHours(objData.getUpdateTime(), -1);
                            List<Map<String, Object>> keyPointThree = remoteService.queryData(df.format(startDate2), df.format(endDate2), "hdz", "81212356");
                            String threeRecord = this.outCsv("81212356", keyPointThree, objData.getData(), waterHeight[i], waterHeight[i - 1]);
                            writer.write(threeRecord);
                            PredictionDeviceDataVo avgThree = this.avg(keyPointTwo);
                            String threeRecordAvg = this.outCsv("--81212356--", avgThree, objData.getData(), waterHeight[i], waterHeight[i - 1]);
                            writer.write(threeRecordAvg);
                            // 数据处理
                            if (CollectionUtil.isNotEmpty(keyPointOne) && CollectionUtil.isNotEmpty(keyPointTwo) && CollectionUtil.isNotEmpty(keyPointThree)) {
                                int minIndex = Math.min(Math.min(keyPointOne.size(), keyPointTwo.size()), keyPointThree.size());
                                for (int j = 0; j < minIndex; j++) {
                                    PredictionDeviceDataVo one = PredictionDeviceDataVo.createFromMap(keyPointOne.get(j));
                                    PredictionDeviceDataVo two = PredictionDeviceDataVo.createFromMap(keyPointTwo.get(j));
                                    PredictionDeviceDataVo three = PredictionDeviceDataVo.createFromMap(keyPointThree.get(j));
                                    trainingData.add(new Double[]{one.getData(), two.getData(), three.getData(), objData.getData()});
                                }
                            }

                        }
                    }
                    log.error("输出结束over......");
                }
            }
            this.generate(trainingData);
        } catch (IOException e) {
            System.err.println("生成CSV文件时出错: " + e.getMessage());
        }
    }
	
	
	// 4参数
    private void generate(List<Double[]> trainingData) {
        int n = trainingData.size();
        // 对于 4 个自变量 (a,b,c,d),采用二次多项式展开后共有 15 列特征
        double[][] X = new double[n][15];
        double[] Y = new double[n];
        for (int j = 0; j < n; j++) {
            Double[] data = trainingData.get(j);
            double a = data[0], b = data[1], c = data[2], d = data[3];
            // 填充二次项和交叉项
            X[j][0]  = a * a;
            X[j][1]  = b * b;
            X[j][2]  = c * c;
            X[j][3]  = d * d;
            X[j][4]  = a * b;
            X[j][5]  = a * c;
            X[j][6]  = a * d;
            X[j][7]  = b * c;
            X[j][8]  = b * d;
            X[j][9]  = c * d;
            // 填充一次项
            X[j][10] = a;
            X[j][11] = b;
            X[j][12] = c;
            X[j][13] = d;
            // 常数项(截距)
            X[j][14] = 1;
            // 目标值 e
            Y[j] = data[4];
        }
        this.minMartix(X, Y);
    }	
	
	
    private void generate(List<Double[]> trainingData) {
        double[][] X = new double[trainingData.size()][10];
        double[] Y = new double[trainingData.size()];
        for (int j = 0; j < trainingData.size(); j++) {
            Double[] data = trainingData.get(j);
            for (int i = 0; i < data.length; i++) {
                double a = data[i], b = data[i], c = data[i];
                double d = data[i];
                X[j][0] = a * a;
                X[j][1] = b * b;
                X[j][2] = c * c;
                X[j][3] = a * b;
                X[j][4] = a * c;
                X[j][5] = b * c;
                X[j][6] = a;
                X[j][7] = b;
                X[j][8] = c;
                X[j][9] = 1;
                Y[j] = d;
            }
        }
        this.minMartix(X, Y);
    }
	
	
	
    private void minMartix(double[][] features, double[] targets) {
        RealMatrix X = MatrixUtils.createRealMatrix(features);
        RealVector Y = new ArrayRealVector(targets);

        // 正则化项 λ * I,避免 X^T * X 奇异
        RealMatrix XT = X.transpose();
        RealMatrix XT_X = XT.multiply(X);

        // 添加正则项 λ * I
        double lambda = 1e-6;
        RealMatrix identity = MatrixUtils.createRealIdentityMatrix(XT_X.getRowDimension());
        RealMatrix XT_X_reg = XT_X.add(identity.scalarMultiply(lambda));

        RealVector XT_Y = XT.operate(Y);
        DecompositionSolver solver = new LUDecomposition(XT_X_reg).getSolver();
        RealVector solution = solver.solve(XT_Y);

        log.info("系统矩阵参数结果:{}", solution.toArray());

        List<Double> args = Arrays.stream(solution.toArray())
            .boxed()
            .collect(Collectors.toList());

        BaseParamsArgs vo = new BaseParamsArgs();
        vo.setArgId(IdGeneratorHelper.next());
        vo.setArgJson(JsonUtils.toJsonString(args));

        baseParamsArgsMapper.insert(vo);
    }

    private double predict(double a, double b, double c, Double[] coefficients) {
        return coefficients[0] * a * a +
            coefficients[1] * b * b +
            coefficients[2] * c * c +
            coefficients[3] * a * b +
            coefficients[4] * a * c +
            coefficients[5] * b * c +
            coefficients[6] * a +
            coefficients[7] * b +
            coefficients[8] * c +
            coefficients[9]
            // migic number
            - 0.5d
            ;
    }



    private String outCsv(String code, List<Map<String, Object>> keyPointOne, double data, double start, double end) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        StringBuilder sb = new StringBuilder();
        for (Map<String, Object> keyTwo : keyPointOne) {
            PredictionDeviceDataVo two = PredictionDeviceDataVo.createFromMap(keyTwo);
            if (null != two) {
                sb.append(code);
                sb.append(",");
                sb.append(two.getData());
                sb.append(",");
                sb.append(data);
                sb.append(",");
                sb.append(start);
                sb.append(",");
                sb.append(end);
                sb.append(",");
                sb.append(df.format(two.getUpdateTime()));
                sb.append("\n");
            }
        }
        return sb.toString();
    }

    private String outCsv(String code, PredictionDeviceDataVo two, double data, double start, double end) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        StringBuilder sb = new StringBuilder();
        if (null != two) {
            sb.append(code);
            sb.append(",");
            sb.append(two.getData());
            sb.append(",");
            sb.append(data);
            sb.append(",");
            sb.append(start);
            sb.append(",");
            sb.append(end);
            sb.append(",");
            sb.append(df.format(two.getUpdateTime()));
            sb.append("\n");

        }
        return sb.toString();
    }