public RandomForest merge(RandomForest other) {
        if (!formula.equals(other.formula)) {
            throw new IllegalArgumentException("RandomForest have different model formula");
        }

        Model[] forest = new Model[models.length + other.models.length];
        System.arraycopy(models, 0, forest, 0, models.length);
        System.arraycopy(other.models, 0, forest, models.length, other.models.length);

        // rough estimation
        RegressionMetrics mergedMetrics = new RegressionMetrics(
                metrics.fitTime * other.metrics.fitTime,
                metrics.scoreTime * other.metrics.scoreTime,
                metrics.size,
                (metrics.rss * other.metrics.rss) / 2,
                (metrics.mse * other.metrics.mse) / 2,
                (metrics.rmse * other.metrics.rmse) / 2,
                (metrics.mad * other.metrics.mad) / 2,
                (metrics.r2 * other.metrics.r2) / 2
        );

        double[] mergedImportance = importance.clone();
        for (int i = 0; i < importance.length; i++) {
            mergedImportance[i] += other.importance[i];
        }

        return new RandomForest(formula, forest, mergedMetrics, mergedImportance);
    }
@Test
    public void testMerge() {
        System.out.println("merge");

        RandomForest forest1 = RandomForest.fit(Abalone.formula, Abalone.train, 50, 3, 20, 100, 5, 1.0, Arrays.stream(seeds));
        RandomForest forest2 = RandomForest.fit(Abalone.formula, Abalone.train, 50, 3, 20, 100, 5, 1.0, Arrays.stream(seeds).skip(50));
        RandomForest forest = forest1.merge(forest2);
        double rmse1 = RMSE.of(Abalone.testy, forest1.predict(Abalone.test));
        double rmse2 = RMSE.of(Abalone.testy, forest2.predict(Abalone.test));
        double rmse  = RMSE.of(Abalone.testy, forest.predict(Abalone.test));
        System.out.format("Forest 1 RMSE = %.4f%n", rmse1);
        System.out.format("Forest 2 RMSE = %.4f%n", rmse2);
        System.out.format("Merged   RMSE = %.4f%n", rmse);
        assertEquals(2.0858, rmse1, 1E-4);
        assertEquals(2.0633, rmse2, 1E-4);
        assertEquals(2.0693, rmse,  1E-4);
    }