Skip to content

Commit 1c1574f

Browse files
authored
[AINode] Add Holt-Winters algorithm and fix related bugs
1 parent 43678a1 commit 1c1574f

6 files changed

Lines changed: 37 additions & 8 deletions

File tree

integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeBasicIT.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,26 @@ public void ModelOperationTest() {
176176
}
177177
}
178178

179+
@Test
180+
public void callInferenceTest2() {
181+
String sql =
182+
"CALL INFERENCE(_holtwinters, \"select s0 from root.AI.data\", predict_length=6, generateTime=true)";
183+
try (Connection connection = EnvFactory.getEnv().getConnection();
184+
Statement statement = connection.createStatement()) {
185+
try (ResultSet resultSet = statement.executeQuery(sql)) {
186+
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
187+
checkHeader(resultSetMetaData, "Time,output0");
188+
int count = 0;
189+
while (resultSet.next()) {
190+
count++;
191+
}
192+
assertEquals(6, count);
193+
}
194+
} catch (SQLException e) {
195+
fail(e.getMessage());
196+
}
197+
}
198+
179199
@Test
180200
public void callInferenceTest() {
181201
String sql =

integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -537,11 +537,12 @@ public void testInformationSchema() throws SQLException {
537537
"model_id,",
538538
new HashSet<>(
539539
Arrays.asList(
540-
"_timerxl,",
541540
"_STLForecaster,",
542541
"_NaiveForecaster,",
543-
"_ARIMA,",
544-
"_ExponentialSmoothing,")));
542+
"_HoltWinters,",
543+
"_TimerXL,",
544+
"_ExponentialSmoothing,",
545+
"_ARIMA,")));
545546

546547
TestUtils.assertResultSetEqual(
547548
statement.executeQuery(
@@ -658,9 +659,10 @@ public void testInformationSchema() throws SQLException {
658659
"model_id,",
659660
new HashSet<>(
660661
Arrays.asList(
661-
"_timerxl,",
662+
"_TimerXL,",
662663
"_STLForecaster,",
663664
"_NaiveForecaster,",
665+
"_HoltWinters,",
664666
"_ARIMA,",
665667
"_ExponentialSmoothing,")));
666668

iotdb-core/ainode/ainode/core/constant.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ class ModelInputName(Enum):
139139
class BuiltInModelType(Enum):
140140
# forecast models
141141
ARIMA = "_arima"
142+
HOLTWINTERS = "_holtwinters"
142143
EXPONENTIAL_SMOOTHING = "_exponentialsmoothing"
143144
NAIVE_FORECASTER = "_naiveforecaster"
144145
STL_FORECASTER = "_stlforecaster"

iotdb-core/ainode/ainode/core/model/built_in_model_factory.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def get_model_attributes(model_id: str):
4545
attribute_map = arima_attribute_map
4646
elif model_id == BuiltInModelType.NAIVE_FORECASTER.value:
4747
attribute_map = naive_forecaster_attribute_map
48-
elif model_id == BuiltInModelType.EXPONENTIAL_SMOOTHING.value:
48+
elif model_id == BuiltInModelType.EXPONENTIAL_SMOOTHING.value or model_id == BuiltInModelType.HOLTWINTERS.value:
4949
attribute_map = exponential_smoothing_attribute_map
5050
elif model_id == BuiltInModelType.STL_FORECASTER.value:
5151
attribute_map = stl_forecaster_attribute_map
@@ -85,7 +85,7 @@ def fetch_built_in_model(model_id, inference_attributes):
8585
# build the built-in model
8686
if model_id == BuiltInModelType.ARIMA.value:
8787
model = ArimaModel(attributes)
88-
elif model_id == BuiltInModelType.EXPONENTIAL_SMOOTHING.value:
88+
elif model_id == BuiltInModelType.EXPONENTIAL_SMOOTHING.value or model_id == BuiltInModelType.HOLTWINTERS.value:
8989
model = ExponentialSmoothingModel(attributes)
9090
elif model_id == BuiltInModelType.NAIVE_FORECASTER.value:
9191
model = NaiveForecasterModel(attributes)

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/ModelInfo.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,14 @@ public class ModelInfo implements SnapshotProcessor {
7474

7575
private static final Set<String> builtInAnomalyDetectionModel = new HashSet<>();
7676

77+
private static final int timerXLInputLength = 2880;
78+
7779
static {
78-
builtInForecastModel.add("_timerxl");
80+
builtInForecastModel.add("_TimerXL");
7981
builtInForecastModel.add("_ARIMA");
8082
builtInForecastModel.add("_NaiveForecaster");
8183
builtInForecastModel.add("_STLForecaster");
84+
builtInForecastModel.add("_HoltWinters");
8285
builtInForecastModel.add("_ExponentialSmoothing");
8386
builtInAnomalyDetectionModel.add("_GaussianHMM");
8487
builtInAnomalyDetectionModel.add("_GMMHMM");
@@ -269,6 +272,9 @@ public GetModelInfoResp getModelInfo(GetModelInfoPlan plan) {
269272
// check if it's a built-in model
270273
if ((modelType = checkModelType(modelName)) != ModelType.USER_DEFINED) {
271274
modelInformation = new ModelInformation(modelType, modelName);
275+
if (modelName.equalsIgnoreCase("_timerxl")) {
276+
modelInformation.setInputLength(timerXLInputLength);
277+
}
272278
} else {
273279
modelInformation = modelTable.getModelInformationById(modelName);
274280
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/tvf/ForecastTableFunction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ public TableFunctionAnalysis analyze(Map<String, Argument> arguments) {
333333
}
334334
}
335335
} else {
336-
String[] predictedColumnsArray = predicatedColumns.split(",");
336+
String[] predictedColumnsArray = predicatedColumns.split(";");
337337
Map<String, Integer> inputColumnIndexMap = new HashMap<>();
338338
for (int i = 0, size = allInputColumnsName.size(); i < size; i++) {
339339
Optional<String> fieldName = allInputColumnsName.get(i);

0 commit comments

Comments
 (0)