Skip to content

Fixing double and triple exponential smoothing algorithms, and adding an accompanying test suite - #2629

Open
john-on-line27 wants to merge 5 commits into
apache:mainfrom
john-on-line27:main
Open

john-on-line27 wants to merge 5 commits into
apache:mainfrom
john-on-line27:main

Conversation

@john-on-line27

Copy link
Copy Markdown

The main task of this pull request was to prove the correctness of this code, and this entailed building out a test suite. Since there is no inbuilt function for double and triple exponential smoothing (DES and TES), the best way to validate the algorithm was to create a reference output from the built R functions.

However in doing this, two issues were found. For the double exponential smoothing, the there was an issue with the offset of the function, creating more predictions than the R function with the same amount of data, so this issue was remedied by changing the amount of data being added to the predictions array. The second issue was that the TES function would not run if the frequency was set to an odd number. This was causing an indexing exception in one of the if statements, so the range within the if function was updated to fix this issue.

Additionally, other things have been added to the EMAUtils.java file, more specifically, exception/error handling, as well as comments. This should lead to an easier time for future maintainers of this code.

The shortcomings to this code include the small sample size for the testing data. This was done so that the program does not run too slowly, but if more data is required to assure quality of the code, that is also something that I am willing to include.

Assisted by: AI
AI contributions include the generation of test data, as well as debugging the connection between the JUnit tests and the R tests. The specific AI used was ChatGPT, by OpenAI, and the specific model was GPT-6.1 Sol.

Owen Braun and others added 5 commits September 29, 2026 16:03
Previously, the variables which created the exponential smoothing had no validation, so a mistake or malicious actor could easily break the algorithm by using an invalid alpha, beta or gamma. In order to fix this issue, I created a helper function to validate the range of the smoothing  variables. This function is optimal, because it lends itself to reuse amongst simple, double and exponential smoothing.
Firstly, the exception handling, which was previously in the main function, was moved into the helper functions. This was done to fit with best practices in exception handling.

Secondly, a new helper function was implemented, so that the frequencies being put into the triple exponential are not zero or smaller, as a lower bound, or larger than half of the size of the incoming data array (as the algorithm uses double the size of the frequency to initialize the variables). The first aspect of this test is trivially beneficial, as it makes sure that no invalid values can be input into the algorithm. The second one is also best practice for this specific instance of the algorithm, as it currently fits to the initialization process of the TES algorithm, but is not applicable to all instances of TES.

Thirdly, an error was found in the triple exponential smoothing algorithm, where the application of the centered moving average filter would result in an indexOutOfBoundsException for frequencies with an odd number, as the for loop was incorrectly declared. The downside to this is the assumption that the current workflow for the initialization of the starting variables is either valid or optimal.

Finally, I have added comments to the exponential smoothing algorithms, so that future contributors have a better understanding of what is happening in underneath the hood.
In order to ensure the full correctness of the Java double and triple exponential smoothing algorithms, the current Java file is being tested by a new EMAUtils.java file, which then proceeds to get reference results from R. The reason why this was the option taken, was that there had been many issues when running the original code, so testing was needed. This includes three main cases, the regular double exponential smoothing algorithm, as well as the odd and even frequency cases for triple exponential smoothing. The reason why I split the last two, is due to the centered moving average used for the initialization, there is two different workflows for the even and odd cases, and in previous iterations of the program, the odd case would crash due to an exception. The reasoning behind the JUnit/R set up comes from the fact that R has prebuilt DES/TES functions, so the correctness of the R reference results can be assumed.

The downsides to this approach are two-fold. Firstly, the sample of test data is very small. This is so that the testing does not last a long amount of time, however some may say the length is insufficient. Secondly, the inbuilt reference functions seek to find the optimal alpha, beta and gamma to minimize the RMSE, but since this is irrelevant to what is being tested, it slows down the actual testing.

Assisted by: AI
AI contributions include the generation of test data, as well as debugging the connection between the JUnit tests and the R tests. The specific AI used was ChatGPT, by OpenAI, and the specific model was GPT-6.1 Sol.
Initially the default had been set to search for the optimal alpha, beta and gamma values, the testing was much slower than needed, now I have just added a fixed value for all values across the JUnit and R tests.
@codecov

codecov Bot commented Nov 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.56%. Comparing base (b82911b) to head (77b517f).
⚠️ Report is 19 commits behind head on main.

Additional details and impacted files
@@              Coverage Diff              @@
##               main    #2629       +/-   ##
=============================================
+ Coverage     71.80%   75.56%    +3.75%     
=============================================
  Files          2078      454     -1624     
  Lines        222401    29799   -192602     
  Branches      38306        0    -38306     
=============================================
- Hits         159698    22518   -137180     
+ Misses        51616     7281    -44335     
+ Partials      11087        0    -11087     
Flag Coverage Δ
java ?
python 75.56% <ø> (+0.61%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ywcb00 ywcb00 self-assigned this Nov 2, 2026

@ywcb00 ywcb00 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for addressing this issue @john-on-line27. :)
I added some comments in-line. Could you please have a look at them?

All the best,
David

}


Container javaFittedValues = double_exponential_smoothing(TS_DATA, 0.3, 0.1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we change this test to perform exponential smoothing by calling a DML script rather than calling the Java method directly. Examples for such tests can be found in BuiltinPowerTransformTest.java and BuiltinEMATest.java.

Also, what is the difference between this test class and the BuiltinEMATest.java. Can we merge these two test classes?

Comment on lines +31 to +37
ts_data <- c(
112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118,
115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140,
145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166,
171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194,
196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to pass these data from the java test class instead of hard-coding it inside the R script.

@github-project-automation github-project-automation Bot moved this from In Progress to In Review in SystemDS PR Queue Nov 2, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

2 participants