Stochastic Search to lambda expression - java

Thanks for all your help and sharing.
My question is in regards of the Stochastic Search. This technique is used to do approximations of data through a defined amount of cicles over a, an in general, mathematical calculation. Please see following code, I tried to reduce it to its minimum. My expectation is to have this code setup as a lambda expression, the for loop, I would like to have the best performance of it. I have some intents but I'm not sure if I got the most of it.
package stochasticsearch;
import java.util.Random;
public class StochasticSearch {
public static double f(double x) {
return -(x - 1) * (x - 1) + 2;
}
public static void main(String[] args) {
final Random random = new Random();
double startPointX = 0;
double max = f(startPointX);
long begin = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
double index = 2 * random.nextDouble();
if (f(index) > max) {
max = f(index);
}
}
System.out.println("Elapsed time: " + (System.currentTimeMillis() - begin));
System.out.println("Maximum value y=f(x) is " + max);
}
}
Thanks, have a nice day.

Your code completes in a little under 23 seconds on my system, and I was able to modify it so that it takes under 2 seconds. Here's what I found:
You're using Random when you could be using ThreadLocalRandom instead; this switch results in a relatively-large speedup.
You're calculating f(index) twice inside your for-loop in certain cases when it should only be computed once per iteration.
Because you're iterating over a large range of values, you could utilize a parallel stream instead; this results in a relatively-large speedup as well.
You're adding 2 to every result in f, so it's better to add it a single time once max has been calculated.
public static double f(double x) {
double y = x - 1;
return -y * y;
}
public static void main(String[] args) {
final ThreadLocalRandom random = ThreadLocalRandom.current();
long begin = System.currentTimeMillis();
double max = IntStream.range(0, 1_000_000_000)
.parallel()
.mapToDouble(i -> f(random.nextDouble() * 2))
.max()
.orElse(f(0)) + 2;
System.out.println("Elapsed time: " + (System.currentTimeMillis() - begin));
System.out.println("Maximum value y=f(x) is " + max);
}

Related

Optimisation in Java Using Apache Commons Math

I'm trying to minimise a value in Java usingcommons-math. I've had a look at their documentation but I don't really get how to implement it.
Basically, in my code below, I have a Double which has the expected goals in a soccer match and I'd like to optimise the probability value of under 3 goals occurring in a game to 0.5.
import org.apache.commons.math3.distribution.PoissonDistribution;
public class Solver {
public static void main(String[] args) {
final Double expectedGoals = 2.9d;
final PoissonDistribution poissonGoals = new PoissonDistribution(expectedGoals);
Double probabilityUnderThreeGoals = 0d;
for (int score = 0; score < 15; score++) {
final Double probability =
poissonGoals.probability(score);
if (score < 3) {
probabilityUnderThreeGoals = probabilityUnderThreeGoals + probability;
}
}
System.out.println(probabilityUnderThreeGoals); //prints 0.44596319855718064, I want to optimise this to 0.5
}
}
The cumulative probability (<= x) of a Poisson random variable can be calculated by:
In your case, x is 2 and you want to find lambda (the mean) such that this is 0.5. You can type this into WolframAlpha and have it solve it for you. So rather than an optimisation problem, this is just a root-finding problem (though one could argue that optimisation problems are just finding roots.)
You can also do this with Apache Commons Maths, with one of the root finders.
int maximumGoals = 2;
double expectedProbability = 0.5;
UnivariateFunction f = x -> {
double sum = 0;
for (int i = 0; i <= maximumGoals; i++) {
sum += Math.pow(x, i) / CombinatoricsUtils.factorialDouble(i);
}
return sum * Math.exp(-x) - expectedProbability;
};
// the four parameters that "solve" takes are:
// the number of iterations, the function to solve, min and max of the root
// I've put some somewhat sensible values as an example. Feel free to change them
double answer = new BisectionSolver().solve(Integer.MAX_VALUE, f, 0, maximumGoals / expectedProbability);
System.out.println("Solved: " + answer);
System.out.println("Cumulative Probability: " + new PoissonDistribution(answer).cumulativeProbability(maximumGoals));
This prints:
Solved: 2.674060344696045
Cumulative Probability: 0.4999999923623868

The golden ratio in java

Consider the sequence X1=1, X2= 1+1/1, X3= 1+1/1+1/1... . In this sequence Xn+1 = 1+1/Xn (for n>= 1). Write a method in Java that computes Xn. As n increases, the terms of this sequence get closer and closer to the golden ratio 1+sqrt 5/ 2 ~ 1.61803398875. How close is X10 to the golden ratio?
This is the program that I have written but when I run it in java it does not compile. I do not know what to do and it is due tomorrow. Please help!
public class Golden Ratio
{
public static final double GOLDEN = ( 1 + Math.sqrt(5))/2;
/**
* precondition: Class(Golden Ratio), n values
* precondition: sequence values found
*/
public static double sequence (int n)
{
if (n == 0) {
return 1;
{
public static void main(String[] args)
{
for (int n = 0; n < 40; n++)
{
double diff = Math.abs(sequence(n) - GOLDEN);
System.out.print(n+1+")");
System.out.print(n + 1 < 10 ? " seq " + sequence(n): "seq " + sequence (n))
System.out.print("gld " + GOLDEN);
System.out.print("diff = %.32f\t". diff);
System.out.print("\n");
}
System.out.print("\n");
System.out.print("10)" + "sqe " + sequence(9) + "ln gld + GOLDEN"\t diff = %.32 f\t" + diff);
System.out.print("");
}
}
}
Your function should do all the calculating work. Your main method just calls it and presents the results. Here is how it's structured. You'll still need to do the part that calculates the sequence. Double-check the definition, before you do the work, though. If X3=1 + 1/1 + 1/1, then that's the same as saying X3=3, which is obviously wrong.
public static double calculateSequence(int n) {
double sum=0.0;
for (int i=0; i<n; i++) {
// do your magic
}
return sum;
}
public static void main(String[] args) {
double answer=calculateSequence(10);
System.out.println("%f is off by %f", answer, GOLDEN_RATIO - answer);
}

Parallel factorial calculation of ALL elements up until a given number

I have a task to write a parallel program that calculates pi (Chudnovsky formula). However, it has factorial in the calculations. So for decomposition of the task, I want to calculate the factorials before I start calculating the formula (that is, calculate all factorials, store them somewhere, and then just read them when they need to be read, instead of calculating those factorials on the spot).
I've read several questions here, but they are about the parallel calculation of a single factorial number. They aren't very helpful when I need to calculate ALL the numbers up until a given index (they are based on the parallel sum/product method). Does anyone have an idea for a good decomposition of the task?
For this you can apply dynamic programmig. Dynamic programming is a way to solve problems in most efficient way. It’s actually avoid to compute sub problem again and again. For the factorial n you always multiply n by (n-1)! If you apply this I think the faster way to compute all factorials is serial:
BigInteger current = BigInteger.ONE;
List<BigInteger> fact = new ArrayList<>();
fact.add(BigInteger.ONE);
for (int i = 1; i <= n; i++) {
current = current.multiply(BigInteger.valueOf(i));
fact.add(current);
}
You can use fork and join parallel strategy here.
Let's say you have to calculate factorial of 10. For this you'll have to multiply numbers from 2 to 10. You can divide this task till your task becomes multiplication of 2 or 3 numbers.
Here is sample code for this:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
public class ForkTest {
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool(4);
for (int i = 2; i < 11; i++) {
Factorial myRecursiveAction = new Factorial(2, i);
forkJoinPool.invoke(myRecursiveAction);
System.out.println("i=" + i + " result=" + myRecursiveAction.getRawResult());
}
}
}
class Factorial extends RecursiveTask<Long> {
private int low;
private int high;
public Factorial(int low, int high) {
this.low = low;
this.high = high;
}
protected Long compute() {
if (high - low >= 2) {
//System.out.println("Dividing number from : " + low + " - " + high);
int mid = (high + low) / 2;
Factorial lowerRange = new Factorial(low, mid);
Factorial higherRange = new Factorial(mid + 1, high);
List<Factorial> subtasks = new ArrayList<Factorial>();
subtasks.add(lowerRange);
subtasks.add(higherRange);
for (Factorial subtask : subtasks) {
subtask.fork();
}
long result = 1;
for (Factorial subtask : subtasks) {
result *= subtask.join();
}
return result;
} else {
long facto = low;
for (int i = low + 1; i <= high; i++) {
facto = facto * i;
}
//System.out.println("Multiplying number from : " + low + " - " + high + " result=" + facto);
return facto;
}
}
}

Efficient way to count the digits of very big factorials

Suppose that we have a very large factorial such as (10^7)!, Is there an efficient way to count its exact digits? (Wolfram alpha result says (10^7)! has 65,657060 digits)
Of course, I can't use the naive implementation by successively multiplying the value one by one since it will be too slow to evaluate the result.
I think the solution to this question might ended up in either
How to find the digit of the factorial without calculating the factorial
How to compute the factorial more efficiently (BigInteger or BigDecimal is preferable)
I would prefer 1. rather than 2. since I just want to know how many digits of the factorial.
Any suggestion?
Adding up the logs of all the numbers you would multiply by should do the trick:
public long facDigits(long n) {
double logFacN = 0;
for (long i = 2; i <= n; i++) {
logFacN += Math.log10(i);
}
return (long) logFacN + 1;
}
public void test() {
double tenToThe7th = Math.pow(10, 7);
long digits = facDigits((long) tenToThe7th);
System.out.println("Digits in " + tenToThe7th + "! = " + digits);
}
prints
Digits in 1.0E7! = 65657060
The logic here is that as you multiply by x while calculating the factorial you are actually adding log10(x) digits so here I just add those up.
#OldCurmudgeon's solution is good but you can try to use Kamentsky's formula:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int numOfTests = Integer.parseInt(in.readLine());
in.lines()
.limit(numOfTests)
.map(n -> Integer.parseInt(n))
.forEach(n -> System.out.println(KamenetskyFormula(n)));
}
private static long KamenetskyFormula(int n) {
if (n < 2) {
return 1;
}
double x = n * Math.log10(n / Math.E) + Math.log10(2 * Math.PI * n) / 2.0;
return (long) (Math.floor(x) + 1);
}
}
connected to Count number of digits in factorial - performance issue

Project Euler #6 Two codes, different answers ONLY for big inputs. Why?

Here are two codes for solving problem 6 in project euler: Why do they give similar answers until I make the number larger? (100,000)
The sum of the squares of the first ten natural numbers is,
12 + 22 + ... + 102 = 385
The square of the sum of the first ten
natural numbers is,
(1 + 2 + ... + 10)2 = 552 = 3025
Hence the difference between the sum
of the squares of the first ten natural numbers and the square of the
sum is 3025 − 385 = 2640.
Find the difference between the sum of the squares of the first one
hundred natural numbers and the square of the sum.
Code 1:
public class Problem_Six_V2 {
public static void main(String[] args) {
long limit = 100000;
long sum = (limit * (limit + 1)) / 2;
long sumOfSqr = (long)((((2*limit)*limit)+((2*limit)*1)+(1*limit)+(1*1))*limit)/6;
System.out.println(Math.pow(sum, 2) +" "+ sumOfSqr);
System.out.println(Math.pow(sum, 2) - sumOfSqr);
}
}
^^^ Outputs = 2.500016666416665E19
Here's code two:
public class Problem_Six {
public static void main(String[] args) {
long sum = 0;
long sumSqr = 0;
long sumOfSqr = 0;
for(long i = 1; i <= 100000; i++){
sum += i;
sumOfSqr += Math.pow(i,2);
}
sumSqr = (long) Math.pow(sum, 2);
System.out.println(sumSqr +" "+ sumOfSqr);
System.out.println(sumSqr - sumOfSqr);
}
}
^^ Outputs = 9223038698521425807
I guess it's something to two with the types being used, but they seem similar in both codes..hmm
Math.pow(i,2) accepts doubles as parameters. Doubles are not 100% precise,
you lose precision. Stick to operations on int/long only. The answer is pretty small
and fits even into an int.
Not sure why you use 100000 as your limit, problem 6 has 100 as a limit.
In Java when results of integer arithmetic don't fit into int variables,
you should use long, when they don't fit even into long variables, you
should use BigInteger.
But avoid doubles, they are not precise for such kinds of tasks.
Here is your program corrected.
import java.math.BigInteger;
public class Problem_Six {
public static void main(String[] args) {
BigInteger sum = BigInteger.ZERO;
BigInteger sumSqr = BigInteger.ZERO;
BigInteger sumOfSqr = BigInteger.ZERO;
for (long i = 1; i <= 100000; i++) {
sum = sum.add(BigInteger.valueOf(i));
sumOfSqr = sumOfSqr.add(BigInteger.valueOf(i * i));
}
sumSqr = sum.multiply(sum);
System.out.println(sumSqr + " " + sumOfSqr);
System.out.println(sumSqr.subtract(sumOfSqr).toString());
// System.out.println(Long.MAX_VALUE);
}
}

Categories