From ddcfe631b30a65f428c2ecd0d59fda9f8149ed14 Mon Sep 17 00:00:00 2001
From: Gabriel Selzer
Date: Thu, 8 Aug 2024 17:02:31 -0500
Subject: [PATCH 1/4] package-info.java: relax reproducibility
---
.../java/org/scijava/ops/api/package-info.java | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/scijava-ops-api/src/main/java/org/scijava/ops/api/package-info.java b/scijava-ops-api/src/main/java/org/scijava/ops/api/package-info.java
index 1948c5d66..29cce5d5e 100644
--- a/scijava-ops-api/src/main/java/org/scijava/ops/api/package-info.java
+++ b/scijava-ops-api/src/main/java/org/scijava/ops/api/package-info.java
@@ -64,10 +64,12 @@
* An Op is an algorithm adhering to the following traits:
*
*
- * - Ops are stateless and deterministic - with no internal state, calling an
- * Op two times on the same inputs will produce the same output.
* - Ops are named - this name conveys an Op's purpose, and allows us to find
* all Ops implementing a particular operation
+ * - Ops have a number of input and output parameters, each defined by a
+ * type
+ * - Ops adhere to a {@link java.lang.FunctionalInterface}, defining how it
+ * operates
*
*
* Using the name and the combination of input and output parameters, we can
@@ -151,10 +153,11 @@
* and SciJava Ops will take care to call the correct Op based on the concrete
* inputs provided.
*
Result-equivalence, and therefore reproducibility, in Ops, is guaranteed
- * within an OpEnvironment and a set of input objects, but not just for Op
- * calls. This allows us to ensure reproducible pipelines, but also allows us to
- * introduce new Ops into the pipeline or to run pipelines on different inputs
- * without changing the pipeline itself.
+ * within an OpEnvironment and a set of input objects, when deterministic
+ * algorithms are used. Cognizance of algorithm determinism allows users to
+ * create reproducible pipelines, however determinism is not a
+ * requirement for Ops, as it would preclude many valuable algorithms from
+ * becoming an Op.
*
*/
From 36fd044c2bdef628c434d5aa98ac60b45e078e6f Mon Sep 17 00:00:00 2001
From: Gabriel Selzer
Date: Thu, 8 Aug 2024 17:40:48 -0500
Subject: [PATCH 2/4] Add Op determinism as a best practice
---
docs/ops/doc/WritingYourOwnOpPackage.md | 43 +++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/docs/ops/doc/WritingYourOwnOpPackage.md b/docs/ops/doc/WritingYourOwnOpPackage.md
index 9454a8054..3556cd51c 100644
--- a/docs/ops/doc/WritingYourOwnOpPackage.md
+++ b/docs/ops/doc/WritingYourOwnOpPackage.md
@@ -8,6 +8,49 @@ You'll find this page organized into two broad sections. The first section descr
SciJava Ops is designed for modularity, extensibility, and granularity - you can exploit these aspects by adhering to the following guidelines when writing Ops:
+### Fostering reproduciblity
+
+[Determinism](https://en.wikipedia.org/wiki/Deterministic_algorithm) is a valuable aspect of scientific computing, as it is necessary for reproducible science. As many powerful algorithms, due to internal state or parallel processing, behave non-deterministically SciJava Ops does not require Ops be deterministic, however if your Op can be deterministic, we highly recommend you make it so. Consider the following algorithm:
+
+```java
+/**
+ * A simple noise adder
+ * @param input the input data
+ * @implNote op name="filter.addNoise" type=Inplace
+ */
+public static void addNoise(double[] data) {
+ Random r = new Random();
+ for(int i = 0; i < data.length; i++) {
+ // Add a number in [-0.5, 0.5)
+ data[i] += (r.nextDouble() - 0.5);
+ }
+}
+```
+
+We can make it deterministic by adding an `@Nullable` `seed` parameter, with a default value if the user does not pass one:
+
+```java
+/**
+ * A simple noise adder
+ * @param input the input data
+ * @param seed the seed to the {@link java.util.Random}
+ * @implNote op name="filter.addNoise" type=Inplace
+ */
+public static void addNoise(double[] data, @Nullable Long seed) {
+ // use default seed if not provided
+ if (seed == null) {
+ seed = 0xdeadbeef;
+ }
+ Random r = new Random(seed);
+ for(int i = 0; i < data.length; i++) {
+ // Add a number in [-0.5, 0.5)
+ data[i] += (r.nextDouble() - 0.5);
+ }
+}
+```
+
+These small steps ensure that user workflows return the same result every time, even years later!
+
### Using Dependencies
If you are writing an Op that performs many intermediate operations, there's a good chance someone else has written (and even optimized) some or all of them.
From c58a8110e7f6961bf18e85ae11cfaaafed0c9d52 Mon Sep 17 00:00:00 2001
From: hinerm
Date: Mon, 12 Aug 2024 16:37:04 -0500
Subject: [PATCH 3/4] package-info: remove trailing space
---
.../src/main/java/org/scijava/ops/api/package-info.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scijava-ops-api/src/main/java/org/scijava/ops/api/package-info.java b/scijava-ops-api/src/main/java/org/scijava/ops/api/package-info.java
index 29cce5d5e..fbdb6317e 100644
--- a/scijava-ops-api/src/main/java/org/scijava/ops/api/package-info.java
+++ b/scijava-ops-api/src/main/java/org/scijava/ops/api/package-info.java
@@ -157,7 +157,7 @@
* algorithms are used. Cognizance of algorithm determinism allows users to
* create reproducible pipelines, however determinism is not a
* requirement for Ops, as it would preclude many valuable algorithms from
- * becoming an Op.
+ * becoming an Op.
*
*/
From 4db2dab303bb56e5bff1614662073e5f486f67a6 Mon Sep 17 00:00:00 2001
From: hinerm
Date: Mon, 12 Aug 2024 16:37:18 -0500
Subject: [PATCH 4/4] Determinism: reframe slightly for emphasis
---
docs/ops/doc/WritingYourOwnOpPackage.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/ops/doc/WritingYourOwnOpPackage.md b/docs/ops/doc/WritingYourOwnOpPackage.md
index 3556cd51c..757fc6432 100644
--- a/docs/ops/doc/WritingYourOwnOpPackage.md
+++ b/docs/ops/doc/WritingYourOwnOpPackage.md
@@ -10,7 +10,7 @@ SciJava Ops is designed for modularity, extensibility, and granularity - you can
### Fostering reproduciblity
-[Determinism](https://en.wikipedia.org/wiki/Deterministic_algorithm) is a valuable aspect of scientific computing, as it is necessary for reproducible science. As many powerful algorithms, due to internal state or parallel processing, behave non-deterministically SciJava Ops does not require Ops be deterministic, however if your Op can be deterministic, we highly recommend you make it so. Consider the following algorithm:
+[Determinism](https://en.wikipedia.org/wiki/Deterministic_algorithm) is a valuable aspect of scientific computing, as our goal is to facilitate reproducible science. As many powerful algorithms behave non-deterministically, due to factors such as internal state or parallel processing, SciJava Ops does not *require* Ops be deterministic. However, if your Op *can be* deterministic, we highly recommend you make it so. Consider the following algorithm:
```java
/**
@@ -49,7 +49,7 @@ public static void addNoise(double[] data, @Nullable Long seed) {
}
```
-These small steps ensure that user workflows return the same result every time, even years later!
+These small steps give workflows the best chance to return consistent results every time, even years later!
### Using Dependencies