Oj-Algo - Matrix exponential - java

I resolve the following equation :
To solve it, I would like to use matrix exponential :
I thought about 3 ways to do it :
I could have missed it but Oj-Algo could have a simple way to compute exp(A) (I did not find it in MatrixStore javadoc)
I get matrix D and V from EigenValue methods ([A] = [V][D][V]-1) and then I compute
Then the question that comes first is how I apply x->exp(x*t) function to all diagonal elements of D ?
Last idea is basically the same as 2. but I previously store the scalar-matrix product in a new matrix ([X] = [D]*(-t)) and then I compute :
Can you help me find the best way/methods/class I should use ? Thank you
NB : This question is a "follow up question" : initial question
EDIT :
This is what i have tried for now, Is it the best way to do it ? :
import static org.ojalgo.function.PrimitiveFunction.EXP;
public class SolveDifferentialEquationTest
{
private static final PhysicalStore.Factory<Double, PrimitiveDenseStore> matrixFactory = PrimitiveDenseStore.FACTORY;
public static void main(String[] args)
{
SparseStore<Double> matrix;
final PhysicalStore<Double> diagMatrix;
final PhysicalStore<Double> eigenVectorMatrix;
final PhysicalStore<Double> inverseEigenVectorMatrix;
final Eigenvalue<Double> eigenvalue;
final int time = 100;
PhysicalStore<Double> initialVector;
final PhysicalStore<Double> finalVector;
int dim = 2000;
matrix = SparseStore.PRIMITIVE.make(dim, dim);
initialVector = matrixFactory.makeZero(dim,1);
// fill matrix and initialVector
//...
//Decompose matrix
eigenvalue = Eigenvalue.PRIMITIVE.make(matrix);
eigenvalue.decompose(matrix);
diagMatrix = eigenvalue.getD().copy();
eigenVectorMatrix = eigenvalue.getV().copy();
InverterTask<Double> inverter = InverterTask.PRIMITIVE.make(eigenVectorMatrix);
try {
inverseEigenVectorMatrix = inverter.invert(eigenVectorMatrix).copy();
} catch (RecoverableCondition e) {
throw new RuntimeException(e);
}
// Construct exp(Dt)
diagMatrix.multiply(time);
diagMatrix.modifyDiagonal(EXP);
// Compute
finalVector = inverseEigenVectorMatrix.multiply(diagMatrix)
.multiply(eigenVectorMatrix)
.multiply(initialVector)
.copy();
}
}

Related

Java Multithreading Implementation for generating unique codes

My question is how I would implement multithreading to this task correctly.
I have a program that takes quite a long time to finish executing. About an hour and a half. I need to generate about 10,000 random and unique number codes. The code below is how I first implemented it and have it right now.
import java.util.Random;
import java.util.ArrayList;
public class Main
{
public static void main(String[] args) {
Random random = new Random();
// This holds all the codes
ArrayList<String> database = new ArrayList<>();
int counter = 0;
while(counter < 10000){
// Generate a 10 digit long code and append to sb
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 10; i++){
sb.append(random.nextInt(10));
}
String code = String.valueOf(sb);
sb.setLength(0);
// Check if this code already exists in the database
// If not, then add the code and update counter
if(!database.contains(code)){
database.add(code);
counter++;
}
}
System.out.println("Done");
}
}
This of course is incredibly inefficient. So my question is: Is there is a way to implement multithreading that can work on this single piece of code? Best way I can word it is to give two cores/ threads the same code but have them both check the a single ArrayList? Both cores/ threads will generate codes but check to make sure the code it just made doesn't already exist either from the other core/ thread or from itself. I drew a rough diagram below. Any insight, advice, or pointers is greatly appreciated.
Using a more appropriate data structure and a more appropriate representation of the data, this should be a lot faster and easier to read, too:
Set<Long> database = new HashSet<>(10000);
while(database.size() < 10000){
database.add(ThreadLocalRandom.current().nextLong(10_000_000_000L);
}
Start with more obvious optimizations:
Do not use ArrayList, use HashSet. ArrayList contains() time complexity is O(n), while HashSet is O(1). Read this question about Big O summary for java collections framework. Read about Big O notation.
Initialize your collection with appropriate initial capacity. For your case that would be:
new HashSet<>(10000);
Like this underlying arrays won't be copied to increase their capacity. I would suggest to look/debug implementations of java collections to better understand how they work under the hood. Even try to implement them on your own.
Before you delve into complex multithreading optimizations, fix the simple problems - like bad collection choices.
Edit: As per suggestion from #Thomas in comments, you can directly generate a number(long) in the range you need - 0 to 9_999_999_999. You can see in this question how to do it. Stringify the resulting number and if length is less than 10, pad with leading zeroes.
Example:
(use ConcurrentHashMap, use threads, use random.nextLong())
public class Main {
static Map<String,Object> hashMapCache = new ConcurrentHashMap<String,Object>();
public static void main(String[] args) {
Random random = new Random();
// This holds all the codes
ArrayList<String> database = new ArrayList<>();
int counter = 0;
int NumOfThreads = 20;
int total = 10000;
int numberOfCreationsForThread = total/NumOfThreads;
int leftOver = total%NumOfThreads;
List<Thread> threadList = new ArrayList<>();
for(int i=0;i<NumOfThreads;i++){
if(i==0){
threadList.add(new Thread(new OneThread(numberOfCreationsForThread+leftOver,hashMapCache)));
}else {
threadList.add(new Thread(new OneThread(numberOfCreationsForThread,hashMapCache)));
}
}
for(int i=0;i<NumOfThreads;i++){
threadList.get(i).start();;
}
for(int i=0;i<NumOfThreads;i++){
try {
threadList.get(i).join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(String key : hashMapCache.keySet()){
database.add(key);
}
System.out.println("Done");
}}
OneThread:
public class OneThread implements Runnable{
int numberOfCreations;
Map<String,Object> hashMapCache;
public OneThread(int numberOfCreations,Map<String,Object> hashMapCache){
this.numberOfCreations = numberOfCreations;
this.hashMapCache = hashMapCache;
}
#Override
public void run() {
int counter = 0;
Random random = new Random();
System.out.println("thread "+ Thread.currentThread().getId() + " Start with " +numberOfCreations);
while(counter < numberOfCreations){
String code = generateRandom(random);
while (code.length()!=10){
code = generateRandom(random);
}
// Check if this code already exists in the database
// If not, then add the code and update counter
if(hashMapCache.get(code)==null){
hashMapCache.put(code,new Object());
counter++;
}
}
System.out.println("thread "+ Thread.currentThread().getId() + " end with " +numberOfCreations);
}
private static String generateRandom(Random random){
return String.valueOf(digits(random.nextLong(),10));
}
/** Returns val represented by the specified number of hex digits. */
private static String digits(long val, int digits) {
val = val > 0 ? val : val*-1;
return Long.toString(val).substring(0,digits);
}
}

java.lang.IllegalArgumentException: Matrix inner dimensions must agree

Here is my code:
package algorithms;
import Jama.Matrix;
import java.io.File;
import java.util.Arrays;
public class ThetaGetter {
//First column is one, second is price and third is BHK
private static double[][] variables = {
{1,1130,2},
{1,1100,2},
{1,2055,3},
{1,1047,2},
{1,1927,3},
{1,2667,3},
{1,1146,2},
{1,2020,3},
{1,1190,2},
{1,2165,3},
{1,1250,2},
{1,1185,2},
{1,2825,4},
{1,1200,2},
{1,1580,3},
{1,3200,3},
{1,715,1},
{1,1270,2},
{1,2403,3},
{1,1465,3},
{1,1345,2}
};
private static double[][] prices = {
{69.65},
{60},
{115},
{55},
{140},
{225},
{76.78},
{120},
{73.11},
{140},
{56},
{79.39},
{161},
{73.69},
{80},
{145},
{34.87},
{77.72},
{165},
{98},
{82}
};
private static Matrix X = new Matrix(variables);
private static Matrix y = new Matrix(prices);
public static void main(String[] args) {
File file = new File("theta.dat");
if(file.exists()){
System.out.println("Theta has already been calculated!");
return;
}
//inverse(Tra(X)*X)*tra(X)*y
Matrix transposeX = X.transpose();
Matrix inverse = X.times(transposeX).inverse();
System.out.println(y.getArray().length);
System.out.println(X.getArray().length);
Matrix test = inverse.times(transposeX);
Matrix theta = test.times(y);
System.out.println(Arrays.deepToString(theta.getArray()));
}
}
This algorithm basically tries to take housing prices and then get a few constants which are then used to guess prices of houses. However I am getting an exception on the line 'Matrix theta = test.times(y);' The error message is pretty much what's in the question. Is there some sort issue with the dimensions? Both of them have 21 items, so I don't know what's going on.
The mistake you are making is in the following line of code:
Matrix inverse = X.times(transposeX).inverse();
The formula you commented above is:
//inverse(Tra(X)*X)*tra(X)*y
but what you are actually calculating in code is:
(X*Tra(X) instead of Tra(X)*X)
//inverse(X*Tra(X))*tra(X)*y
If the dimension of X is (m,n) where
m = number of rows
n = number of columns
and the dimension of Y is (m,1), using the multiplications you used above you will have the following:
inverse(X * Tra(X)) *Tra(X)*Y = inverse * Tra(X) * Y = result * y
inverse((m,n)(n,m))(n,m)*(m,1)= (m,m) * (n,m) => which results in the error because the inner dimensions for a matrix multiplication must be equal
What would fix your code would be replacing the following line:
Matrix inverse = X.times(transposeX).inverse();
with
Matrix inverse = transposeX.times(X).inverse();

Finding all complex roots of cubic function by using Newton's Method in Java

I've looked everywhere for code I can understand which could help me on my way. I've found one but I'm struggling, so I hope someone could help me.
This is what I want to achieve:
Solve a cubic function (ax^3+bx^2+cx+d) where a,b,c and d are filled
in by the command line when you run it.
I need the roots and complex roots to be found using the Newton's Method. The code I'm struggling with is this, but I don't know if this works and I don't know how I can calculate all 3 roots (even knowing if it has multiplicity 1, 2 or 3).
Any help is appreciated.
import java.util.function.Function;
public class Newton {
static double a = Polynom.geta(); // these are to get the input from the class you run from calling this class to solve the roots
static double b = Polynom.getb();
static double c = Polynom.getc();
static double d = Polynom.getd();
public static void main(String args[]) {
}
private Complex[] sqrt(double x, double y) {
Complex com = new Complex(x,y); // Complex is my class that deals with Complexnumbers, com is supposed to get the value of the root in the end
double tolerance = 1e-11; // tolerance for the error
int iterations = 1, max = 512;
Complex aa = com.pow(3).multiply(a); // These put in the values from input to complex values and fill in the cubic function of ax^3+bx^2+cx+d
Complex bb = com.pow(2).multiply(b);
Complex cc = com.multiply(c);
Complex dd = com.pow(2).multiply(a).multiply(3.0);
Complex ee = com.multiply(2.0).add(com);
Complex function = aa.add(bb).add(cc).add(d,0);
Complex derivative = dd.add(ee);
for(int k = 0; k<3; k++) {
while(iterations<max) {
Complex difference = function.divide(derivative); //difference=fx/dx
com = com.subtract(difference);
if (Math.abs(difference.getReal()) < tolerance && Math.abs(difference.getImaginary()) < tolerance)
return com; // this is where i get an error atm "Cannot convert from Complex to Complex
iterations++;
}
}
}

How can I get full-ranged random float values?

I found that Random#nextFloat returns a value between 0.0 and 1.0.
How can I get a random float value such as -72.0F or 126.232F?
I currently doing like this.
float randomFloat() {
final ThreadLocalRandom random = ThreadLocalRandom.current();
float value = random.nextFloat() * Float.MAX_VALUE;
if (random.nextBoolean()) {
value = 0 - value;
}
return value;
}
Is this right? Is there any other way to do this?
I would suggest generating a bound double and then converting to float:
return Double.valueOf(random.nextDouble(Float.MIN_VALUE, Float.MAX_VALUE)).floatValue();
The nextDouble method has been replaced in Java 8 with a method to produce a stream of doubles. So in Java 8 you would use the following equivalent:
DoubleStream randomDoubles = new Random().doubles(Float.MIN_VALUE, Float.MAX_VALUE);
Double.valueOf(randomDoubles.findAny().getAsDouble()).floatValue();
This is based on a the general idea in the prior answer, but fixes a small bug and shows how to actually write the method using JDK 1.8:
import java.util.Iterator;
import java.util.concurrent.ThreadLocalRandom;
public class Test {
public static void main(String[] args) {
Test t = new Test();
for (int i = 0; i < 100; i++) {
System.out.println(t.randomFloat());
}
}
final ThreadLocalRandom random = ThreadLocalRandom.current();
Iterator<Double> randomDoubles = random.doubles(-Float.MAX_VALUE,
Math.nextUp((double) Float.MAX_VALUE)).iterator();
float randomFloat() {
return randomDoubles.next().floatValue();
}
}
The code in the question used ThreadLocalRandom, so I did the same. The Random doubles method excludes the upper limit. In order to get the required full range, use as limit the smallest double that is greater than all finite float values. Getting an iterator<Double> seemed simpler and more direct than using findAny etc.

Random numbers shared between canvases

I am new to Java, and I am also new to posting a question online. So please bear with me.
I am currently constructing a Java program which displays several canvases, and I require the different canvases to use shared and/or inherited information. Let's assume for simplicity that canvas C1 displays a polygon with random vertices on a circle. Currently these vertices are created in a coordinate class and are then instantiated by a drawing class. I am now trying to store these values in a way which allows the second canvas C2 (via drawing class) to use them, but without instantiating it, as I need the same sequence of random numbers.
Let this be a simplified example of my coordinate class:
public class Coord {
public Complex[] z = new Complex[5];
public Coord() {}
// create n random vertices (length of a and z will match)
public Complex[] randCoord(Complex[] a) {
for(int i = 0; i < a.length; i++){
z[i] = new Complex(200 * Math.random(), 200 * Math.random());
}
return z;
}
// public static Complex[] getCoord() {
// return z;
// }
}
The commented out section is one of my million attempts to generate a static version of the coordinate list, but I am not allowed to return z as it is not a static variable (in this case). I am probably missing something painfully obvious in regard to transferring between static and non-static methods, but any insight on how to store the random sequence (and likewise, how to call it) would be appreciated.
It sounds like the Singleton pattern would be helpful :
public class Coord {
private static final Complex[] z = fixedRandomPoints(5);
private Coord() {}
//this is the method you call from both canvases
public static Complex[] getInstance() {
return z;
}
private static Complex[] fixedRandomPoints(int n) {
final Complex[] results = new Complex[n];
for(int i = 0; i < n.length; i++){
results[i] = new Complex(200 * Math.random(), 200 * Math.random());
}
return results;
}
}
The only thing thats unclear is the relationship of this class to the 'a' variable, which I think you need to explain a little better.
First of all, you should read up on the MVC-pattern: Model-View-Controller.
Secondly, it looks like what you're currently trying to do can simply be done by declaring z to be static:
public static Complex[] z = new Complex[5];

Categories

Resources