Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RandomRegistry not compatible with JRE 17 #866

Closed
kellox opened this issue Jun 27, 2023 · 7 comments
Closed

RandomRegistry not compatible with JRE 17 #866

kellox opened this issue Jun 27, 2023 · 7 comments
Assignees
Milestone

Comments

@kellox
Copy link

kellox commented Jun 27, 2023

According to the documentation Jenetics 7.1.3 requires "at least Java 17". However, it's not clear from the documentation if a JRE 17+ is sufficient.

We use the bundled Jetbrains JRE in IntelliJ during execution in our project. If RandomRegistry is initialized, an ExceptionInInitializerError is thrown because the static member variable is initialized as

	private static final TLR<RandomGenerator> DEFAULT_RANDOM_FACTORY =
		new TLR<>(RandomGeneratorFactory.of("L64X256MixRandom")::create);

However, the PRNG L64X256MixRandom as part of JDK 17 and not known in JRE 17, which leads to a ExceptionInInitializerError.

@jenetics
Copy link
Owner

Java 17 is sufficient for running Jenetics. But I would recommend an official full Java installation, since it is not defined whats in a JRE. There is no longer an official JRE from Oracle, and I don't know what this builds left out.

https://stackoverflow.com/questions/55868821/when-jre-was-completely-discontinued-as-a-separate-offering

@kellox
Copy link
Author

kellox commented Jun 27, 2023

I just tried out the latest JRE 17 (Build 17.0.7+7) from https://adoptium.net/temurin/archive/ and it doesn't work either.
The problem has to do with the default L64X256MixRandom random number generator. All random generators from the LXM group are only contained in JDK (but not in JRE).

In my opinion DEFAULT_RANDOM_FACTORY in RandomRegistry should use PRNG which is also known to JRE 17.

@jenetics
Copy link
Owner

From the Java documentation

Random Number Generator Algorithms Available
These algorithms [in the table below] must be found with the current version of Java SE. A particular JDK implementation may recognize additional algorithms; check the JDK's documentation for details. The set of algorithms required by Java SE may be updated by changes to the Java SE specification. Over time, new algorithms may be added and old algorithms may be removed.

Algorithm Group Period StateBits Equidistribution
L128X1024MixRandom LXM BigInteger.ONE.shiftLeft(1024).subtract(BigInteger.ONE).shiftLeft(128) 1152 1
L128X128MixRandom LXM BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE).shiftLeft(128) 256 1
L128X256MixRandom LXM BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftLeft(128) 384 1
L32X64MixRandom LXM BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE).shiftLeft(32) 96 1
L64X1024MixRandom LXM BigInteger.ONE.shiftLeft(1024).subtract(BigInteger.ONE).shiftLeft(64) 1088 16
L64X128MixRandom LXM BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE).shiftLeft(64) 192 2
L64X128StarStarRandom LXM BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE).shiftLeft(64) 192 2
L64X256MixRandom LXM BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftLeft(64) 320 4
Random Legacy BigInteger.ONE.shiftLeft(48) 48 0
SplittableRandom Legacy BigInteger.ONE.shiftLeft(64) 64 1
ThreadLocalRandom * Legacy BigInteger.ONE.shiftLeft(64) 64 1
Xoroshiro128PlusPlus Xoroshiro BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE) 128 1
Xoshiro256PlusPlus Xoshiro BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE) 256 3

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/random/package-summary.html

@kellox
Copy link
Author

kellox commented Jun 28, 2023

Yes, Java SE contains the JDK. Therefore, a Java SE installation will work because all LXM Group PRNG are known (because they are part of the JDK).
So a "full Java installation" is not only recommended but "a must have" to be able to run Jenetics with all features.

jenetics added a commit that referenced this issue Aug 4, 2023
Signed-off-by: Franz Wilhelmstötter <franz.wilhelmstoetter@gmail.com>
jenetics added a commit that referenced this issue Aug 4, 2023
…e_random_generator

#866: Make default random generator configurable.
@jenetics
Copy link
Owner

jenetics commented Aug 4, 2023

The default random generator can be changed via system property of the command line.

java -Dio.jenetics.util.defaultRandomGenerator=L64X1024MixRandom\
     -cp jenetics-@__version__@.jar:app.jar\
         com.foo.bar.MyJeneticsAppjava 

@jenetics jenetics closed this as completed Aug 4, 2023
@jenetics jenetics self-assigned this Aug 4, 2023
@jenetics jenetics added this to the v7.2.0 milestone Aug 4, 2023
@sfeilmeier
Copy link

@jenetics We came accross the same problem when adopting Jenetics in OpenEMS. OpenEMS is an open-source Energy Management System. Its Edge part typically runs on IoT hardware like a Raspberry Pi, where a JRE is often preferred. We use Jenetics currently to evaluate when to charge, block or discharge a solar battery in combination with dynamic prices (for more info see Code, Screenshots, Video) Further integrations like electric vehicle charging, heat-pumps, etc. are planned - and will increase the search-space...

For our use-case the -Dio.jenetics.util.defaultRandomGenerator= setting is a bit impractical, as we would like to avoid steep learning curve for the users of the open-source project. Our Getting Started is already complicated...

Therefor we solved this issue by dynamically finding the best available RandomGenerator: https://github.com/OpenEMS/openems/blob/2024.2.0/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff/optimizer/Optimizer.java#L42-L50

A similar approach is also suggested in the JDK documentation: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/random/RandomGeneratorFactory.html

     RandomGeneratorFactory<RandomGenerator> best = RandomGeneratorFactory.all()
         .sorted(Comparator.comparingInt(RandomGenerator::stateBits).reversed())
         .findFirst()
         .orElse(RandomGeneratorFactory.of("Random"));
     System.out.println(best.name() + " in " + best.group() + " was selected");

Would you accept a pull-request that adds this feature in RandomRegistry.java?

@jenetics
Copy link
Owner

jenetics commented Feb 5, 2024

We could do some checks, when initializing the RandomRegistry.Env.defaultRandomGenerator.

  1. Check if the io.jenetics.util.defaultRandomGenerator is set. If so, take this value.
  2. Check if the L64X256MixRandom generator is available. If so, take this value.
  3. Find the best available random generator and take this value.
  4. Use the Random as default random generator.

Looking forward for your PR 👍 You might create a new issue for this enhancement and add a link to this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants