So I have text files that I can parse with the code I have and make the calculations for some atoms in space. Thing is I have to make the program parallel using threads and I don't know how I am supposed to pass the text file in every thread.
If I try to do something like double kx = console.nextDouble(); it doesn't recognize what console is because its Scanner object inside of main(). What am I missing?
(Note: it's not strictly necessary to use threads directly; I could use fork-join pool, etc.)
public class NBodyBH {
//Set value to simulate <execTime> seconds of the bodies
static final int execTime = 100;
static final boolean draw = false;
public static void main(String[] args) throws FileNotFoundException {
String fname = args[0];
FileInputStream is = new FileInputStream(new File(fname));
System.setIn(is);
Scanner console = new Scanner(System.in);
final double dt = 0.1; // time quantum
int N = console.nextInt(); // number of particles
double radius = console.nextDouble(); // radius of universe
//BELOW HERE IS THE PART I WANT TO MAKE PARALLEL
Body[] bodies = new Body[N]; // array of N bodies
for (int i = 0; i < N; i++) {
double px = console.nextDouble();
double py = console.nextDouble();
double vx = console.nextDouble();
double vy = console.nextDouble();
double mass = console.nextDouble();
int red = console.nextInt();
int green = console.nextInt();
int blue = console.nextInt();
Color color = new Color(red, green, blue);
bodies[i] = new Body(px, py, vx, vy, mass, color);
}
}
}
I believe what you're looking for is AsynchronousFileChannel. It was introduced in Java 7 for async operations on files.
Although, you're saying you'll run a complex calculation so maybe the time intensive task is the calculation itself instead of the file reading, you could read the file in your main thread and use parallelism to run the complex calculations.
List<Integer> calculationResults = bodies.parallelStream()
.map(doComplexCalculation)
.collect(toList())
In the example I'm assuming the calculation returns an Integer and that bodies is a Collection like a List, but adapt it as you see fit.
Passing the file to each thread sounds like a bad idea. Then you'd have to coordinate which thread reads which data, which would be unnecessarily complicated, or (more likely), each thread needs all the data, and making each thread re-read the file is inefficient.
First, read all the data. Then pass each thread the data it needs.
Don't assign your new FileInputStream to System.in. Just create a Scanner with it directly:
Scanner input = new Scanner(Paths.get(arg[0]));
...
List<Body> bodies = new ArrayList<>(N);
for (int i = 0; i < N; ++i) {
...
bodies.add(new Body(...));
}
for (int step = 0; step < 10; ++step) { /* Simulate 10 time steps, or whatever. */
List<Body> next = bodies.parallelStream() /* Here's your threads. */
.map(body -> step(body, dt, bodies))
.collect(Collectors.toList());
/* Render new state */
...
bodies = next; /* Throw away your old state. */
}
Here, step() is a function you need to write. If I've guessed what you are doing correctly, it will create a clone of the body, with a new position and velocity, based on the positions of the others. If you can modify the code of the Body class, this method should probably be a member of that class.
You must be careful not to modify the "current" bodies, but only create replacement for each. This upholds the "non-interference" requirement of Stream parallelism. Each time step will take O(N2) time to compute, since each new state of each body (N) depends on the state of every other body (× N).
Related
I am new to parallel processing and trying to learn it. I got an assignment for my university and i have to turn a serial "barnes-hut" algorithm into a parallel one.
I've been searching and i don't seem to find anything useful.
I've figured i need to parallel with max thread number 4
for (int i = 0; i < N; i++) {
double px = console.nextDouble();
double py = console.nextDouble();
double vx = console.nextDouble();
double vy = console.nextDouble();
double mass = console.nextDouble();
int red = console.nextInt();
int green = console.nextInt();
int blue = console.nextInt();
Color color = new Color(red, green, blue);
bodies[i] = new Body(px, py, vx, vy, mass, color);
}
Thing is: you are actually looking at more than just "adding some parallel" to your code.
You see, your code does:
read multiple values from some input source
a bit of processing
store the final "results" within an ordered data structure (that array)
You can't just do the above in parallel. Because when you use more than one thread, you lose control when exactly things happen.
In your case: you lose control about the order of "reading from input". Yes, when you as the other answer suggests, you will run into your first multi-threading problem, because that other code isn't thread safe, therefore you will end up with unexpected, unpredictable outcome!
Also note: your code is really not well suited for "running in parallel". Using multiple threads only "helps" when your workload benefits from the multiple threads. Reading sequential data from one file, to end up with objects within a sequential data structure ... isn't such a workload!
Thus the real answer is: step back. Multi-threading is really complicated. You can't learn that stuff by picking "random" code, and then trying to "add parallels" to it. Pick a good book, or tutorial ... and research the topic. Look at well written examples, and then see how those are handled. Then search for assignments that are meant to learn about multi-threading.
One starting point: the concurrency tutorials from oracle.
You can look at IntStream to parallel your for loop:
IntStream.range(0,N).parallel().forEach(i -> {
double px = console.nextDouble();
double py = console.nextDouble();
double vx = console.nextDouble();
double vy = console.nextDouble();
double mass = console.nextDouble();
int red = console.nextInt();
int green = console.nextInt();
int blue = console.nextInt();
Color color = new Color(red, green, blue);
bodies[i] = new Body(px, py, vx, vy, mass, color);
});
Bear in mind this is just an example for the for loop to get you started. This could lead to the wrong results and will need modification for what you're doing.
To look at documentation on the parallel of "Barnes-Hut" check out:
https://www.cs.vu.nl/ibis/papers/nijhuis_barnes_2004.pdf
It is old and not using latest java techniques to simplify some of the parallelism but should be able to lead you down the right path
There is also a Scala project that simulates it as well:
https://github.com/tadjik1/Barnes-Hut-Simulation
Before I start I want to state that I am learning, I am completely new. Here i have added as much detail as possible.
So, I have an array of textures of different colors, and set a Random to randomize the textures, Like this:
Texture[] bubbles;
Random random = new Random();
int lowRange = 0;
int highRange = 3;
int result = random.nextInt(highRange -lowRange) + 1; //my random
ArrayList<Integer> BubbleXs = new ArrayList<>();
ArrayList<Integer> BubbleYs = new ArrayList<>();
#Override
public void create () {
bubbles = new Texture[4];
bubbles[0] = new Texture("blue.png");
bubbles[1] = new Texture("red.png");
bubbles[2] = new Texture("green.png");
bubbles[3] = new Texture("yellow.png");
}
Then I proceed to draw the texture at a random color falling from the top of the screen using a for loop, like this:
#Override
public void render () {
if (BubbleCount < 120) {
BubbleCount++;
} else {
BubbleCount = 0;
makeBubble();
}
public void makeBubble () {
float width = random.nextFloat() * Gdx.graphics.getWidth();
BubbleXs.add((int)width);
BubbleYs.add(Gdx.graphics.getHeight());
}
for (int i=0; i < BubbleYs.size(); i++) {
batch.draw(bubbles[result], BubbleXs.get(i), BubbleYs.get(i));
BubbleYs.set(i, BubbleYs.get(i) -4);
}
and it draws the textures at a a random perfectly, but only once, when its created, I want them to be a new random each time its looped, so its a different one every time one falls. why is it not doing that? what am I missing?
Thanks in advance!
Edit: I checked out this post: Change texture with random
but its not really helping any.
The reason they're all the same is that you assign a value to result only once, when it is initialized, and you never change it. If you want it to change, you need to use your Random to assign another value.
Your formula random.nextInt(highRange -lowRange) + 1 isn't right if you're wanting a random number between lowRange and highRange inclusive. That's giving you a number between lowRange + 1 and highRange + 1. The correct formula would be random.nextInt(highRange - lowRange) + lowRange.
The way to solve this would be create an additional variable for each bubble that stores the random int. You are already keeping a list for each of the two variables you're already storing (x and y). You could theoretically add a third, but it's to the point where you really just need to create a class for each bubble, so you can expand it easily if you add more features.
class Bubble {
int x;
int y;
int textureIndex;
}
Then replace your two array lists with:
ArrayList<Bubble> bubbles = new ArrayList<>();
And your makeBubble method should look like this:
void makeBubble(){
Bubble bubble = new Bubble();
bubble.x = (int)(random.nextFloat() * Gdx.graphics.getWidth());
bubble.y = Gdx.graphics.getHeight();
bubble.textureIndex = random.nextInt(3);
}
And your for loop for drawing them would look like this. I changed your textures array name here to bubbleTextures so bubbles can be used for the list of Bubble objects.
for (Bubble bubble : bubbles) {
batch.draw(bubbleTextures[bubble.textureIndex], bubble.x, bubble.y);
bubble.y -= 4;
}
There are numerous other issues I'm seeing with your code, but I think it would be overwhelming to explain them all. This at least gets you going in the right direction.
Hi I coded a single neuron to predict a student's mark for subject D based of the marks they got for subject A, B and C.
After training my neuron with some historical data that contain the 3 marks as well as the actual mark they got for subject D, I then inputed test data to see how closely the predicted mark would match with the actual one.
Below is my Neuron class
public class Neuron
{
double[] Weights = new double[3];
public Neuron(double W1, double W2, double W3)
{
Weights[0] = W1;
Weights[1] = W2;
Weights[2] = W3;
}
public double FnetLinear(int Z1, int Z2, int Z3)
{
return (Z1*Weights[0] + Z2*Weights[1] + Z3*Weights[2]);
}
public void UpdateWeight(int i, double Wi)
{
Weights[i] = Wi;
}
}
And here is my main class
public class Main
{
public int t;
public Neuron neuron;
double LearningRate = 0.00001;
public ArrayList<Marks> TrainingSet, TestSet;
public static void main(String[] args) throws IOException
{
Main main = new Main();
main.run();
}
public void run()
{
TrainingSet = ReadCSV("G:\\EVOS\\EVO_Assignemnt1\\resources\\Streamdata.csv");
TestSet = ReadCSV("G:\\EVOS\\EVO_Assignemnt1\\resources\\Test.csv");
Random ran = new Random();
neuron = new Neuron(ran.nextDouble(), ran.nextDouble(), ran.nextDouble());
train();
Test();
}
public void train()
{
t = 0;
while(t<1000000)
{
for(Marks mark: TrainingSet)
{
for(int i=0; i<neuron.Weights.length; i++)
{
double yp = neuron.FnetLinear(mark.marks[0] , mark.marks[1], mark.marks[2]);
double wi = neuron.Weights[i] - LearningRate*(-2*(mark.marks[3]-yp))*mark.marks[i];
neuron.UpdateWeight(i, wi);
}
}
t++;
}
}
public void Test()
{
System.out.println("Test Set results:");
int count = 1;
for(Marks mark: TestSet)
{
double fnet = neuron.FnetLinear(mark.marks[0] , mark.marks[1], mark.marks[2]);
System.out.println("Mark " + count + ": " + fnet);
count++;
}
}
public static ArrayList<Marks> ReadCSV(String csv)
{
ArrayList<Marks> temp = new ArrayList<>();
String line;
BufferedReader br;
try
{
br = new BufferedReader(new FileReader(csv));
while((line=br.readLine()) != null)
{
String[] n = line.split(",");
Marks stud = new Marks(Integer.valueOf(n[0]), Integer.valueOf(n[1]), Integer.valueOf(n[2]), Integer.valueOf(n[3]));
temp.add(stud);
}
}
catch (Exception e)
{
System.out.println("ERROR");
}
return temp;
}
}
This is the test data with the last number being the actual mark.
After running the test data i get results around these:
As you can see the first 4 marks predictions are way off from the actual mark.
I followed the text book's explenation of Computational Intlligence An Introduction (Chapter 2 if u are curious).
However I would like to know what I im doing wrong. How can I get more accurate results?
Neural networks are very black-box esque; Due to this, it's pretty hard to say exactly why your marks results are way off.
That being said, here are some of the main methods of increasing the accuracy of your neural network:
Adjust the number of layers and neurons; I notice you're only using a single neuron. A single neuron in a neural network is typically just... bad. You're never going to get any good results like that. Neural networks need enough complexity in the form of layering and neuron count in order to calculate or predict whatever it is you're trying to teach it to do. A single neuron by itself really can't learn anything useful. This is also probably a big reason why your network accuracy is so bad.
Train for longer; I notice you're only training your network 1 million times; this is not always enough. For reference, the last time I trained a neural network, I used over 30 million sets of input/output.
Retrain your network with different starting weights; Randomized starting weights are great, but sometimes you just get a bad batch of starting weights. In the same project where I used 30 million input/output sets, I also tried over 25 different configurations of initial starting weights across 15 different layouts of nodes and layers.
Pick a different activation function; Linear activation functions are usually not that useful. I usually default to using a sigmoid function to start off, unless there are specific other functions that fulfill the use case I'm trying to train.
A common pitfall that can cause low accuracy is bad training data; Make sure the training data you're using is correct and is internally consistent with whatever it is you're trying to teach.
As a final note, I find myself having some trouble understanding what kind of a neural network you're trying to write exactly; I've made the assumption that this is some sort of attempt at a feed forward, back propagation neural network with a single neuron in it, but most of the advice here should still apply.
Complete newbie here guys. I'm working on a Java program to prompt the user for 3 variables which are used to calculate a future investment's value. Everything works perfectly, except when it comes time to put both my datatypes into ONE array.
Here's what the output SHOULD look like:
Year Future Value
1 $1093.80
2 $1196.41
3 $1308.65
...
This is what mine looks like:
Year 1
Future Value 1093.81
Year 2
Future Value 1196.41
Year 3
Future Value 1308.65
...
My year is an int value and my Future value is a double (rounded). I've been sitting here racking my brain and all the forums I can find and haven't been successful. Every time I put both value into an array I get an error about putting two different datatypes together. Any insight would be greatly appreciated. Below is the code for my full program:
import java.util.Scanner;
class investmentValue {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.print("Enter investment amount: $");
double i = s.nextDouble();
System.out.print("Enter percentage rate: ");
double r = s.nextDouble()/100;
System.out.print("Enter number of years: ");
int y = s.nextInt();
for (y=1; y<=30; y++) {
double f = futureInvestmentValue(i,r,y);
System.out.println("Year " + y);
System.out.println("Future Value " + f);
}
}
public static double futureInvestmentValue (double investmentAmount, double monthlyInterestRate, int years){
double value=1;
value = investmentAmount*Math.pow((1+(monthlyInterestRate/12)),(years * 12));
double roundValue = Math.round(value*100.0)/100.0;
return roundValue;
}
}
One solution is to start by implementing a pad function. Something like,
public static String pad(String in, int len) {
StringBuilder sb = new StringBuilder(len);
sb.append(in);
for (int i = in.length(); i < len; i++) {
sb.append(' ');
}
return sb.toString();
}
Now we can combine that with String.format() to get the dollars and cents, use a consistent printf() for the header and output lines. To get something like,
// Print the header.
System.out.printf("%s %s%n", pad("Year", 12), "Future Value");
for (int y = 1; y <= 30; y++) {
String year = pad(String.valueOf(y), 13); // <-- One more in your alignment.
String fv = String.format("$%.2f", futureInvestmentValue(i,r,y));
System.out.printf("%s %s%n", year, fv);
}
The System.out.println command isn't the only method available to you!
Try this in your loop:
System.out.print(y); // note that we use print() instead of println()
System.out.print('\t'); // tab character to format things nicely
System.out.println(f); // ok - now ready for println() so we move to the next line
Naturally, you'll want to do something similar to put your headings in.
PS - I'm pretty sure this is just an output formatting question - you don't really want to put all these values into a single array, right?
Given that you really are looking for formatted output, it may be better to use the printf() method.
The following inside the loop (instead of the 3 lines I wrote above) should do the trick (untested - I haven't used printf() format strings in a long, long time).
System.out.printf("%i\t$%0.2f", y, f);
EDIT: edited to answer your question in the comments about constructors... You should also check out this for further understanding
You could create a class that will hold both of the arrays...
This would give you a single object, let's call it StockData, that holds two arrays for the two separate types you need. You need to create the object once and then insert the data separately by type.
class StockData {
double[] data1;
int[] data2;
// default constructor
StockData() {
}
// constructor
StockData(double[] data1, int[] data2) {
this.data1 = data1;
this.data2 = data2;
}
// getters, setters...
}
Then you add data to an array of its type:
// using default constructor to add a single value to both arrays
StockData sd = new StockData();
sd.data1[INDEX_X] = YOUR_DOUBLE;
sd.data2[INDEX_X] = YOUR_INT;
// using default constructor to add all data to both arrays
StockData sd = new StockData();
sd.data1 = YOUR_ARRAY_OF_DOUBLE;
sd.data2 = YOUR_ARRAY_OF_INTS;
// using constructor to add all array data directly
StockData sd = new StockData(YOUR_ARRAY_OF_DOUBLE, YOUR_ARRAY_OF_INTS);
You could also have an object that will hold the double and int value, so the object will represent a single stock information of 2 values and then create an array containing those objects...
class StockData {
double data1;
int data2;
// default constructor same as before
// constructor
StockData(double data1, int data2) {
this.data1 = data1;
this.data2 = data2;
}
// getters, setters...
}
// ...
Adding data:
// create an array of StockData objects
StockData[] sd = new StockData[TOTAL_AMOUNT_OF_DATA];
// ... obtain your data
// using default constructor to add a single value to the array
sd[INDEX_X] = new StockData();
sd[INDEX_X].data1 = YOUR_DOUBLE;
sd[INDEX_X].data2 = YOUR_INT;
// using constructor to add all data directly
sd[INDEX_X] = new StockData(YOUR_DOUBLE, YOUR_INT);
If you want the program to have an specific format you could try to change your code and put this where your for is:
System.out.println("Year Future Value");
for (y=1; y<=30; y++) {
double f = futureInvestmentValue(i,r,y);
System.out.print(y);
System.out.println(" " + f);
}
this way you will have your output in the format you need without using arrays. But if you want to do an array for this you could declare an array of objects and create a new object with two attributes (year and future value)
Also your class name is investmentValue and it is recommended that all classes start with upper case it should be InvestmentValue
I hope that this can help you
A fun data structure you would be able to use here is a Map (more specifically in Java, a HashMap). What you are doing is associating one value with another, an integer to a double, so you could make something that looks like this:
Map<Integer, Double> myMap = new HashMap<>();
This would take the year as the integer, and the double as the price value, and you could iterate over the map to print each value.
Additionally if you really are looking for a "multidata type array," Java automatically casts from integer to double should you need to. For example:
int i = 2;
double[] arr = new double[2];
arr[0] = 3.14
arr[1] = i;
The above code is perfectly valid.
I have started how to learn Java programming and I a got a problem while doing an asignment:
ps this is a c programming assignment, using it to do a java programming:
Consider a (potentially large commercial) room that has floor dimensions length len and width wid. The area of the floor is given by multiplying len by wid.
Carpet tiles are provided as individual squares (2 feet by 2 feet). Write, compile and run a C program, carpet.c, that
-calculates the minimum number of carpet tiles that are needed to cover a room whose dimensions (len and wid) are input from the terminal (measurements are in inches). NB: floor tiles can be cut to fit at the edges of the room - try to minimise waste.
-calculates how many carpet-tile packs are needed. The supplier only provides carpet tiles in packs of ten (i.e. individual tiles cannot be purchased separately).
-calculates how many spare tiles are left over once the minimum number of packs have been purchased.
-prints out all these results in a neat table along with the total cost of the order. (A pack of tiles costs $50 for each of the first four packs, and the price reduces to $45 for each subsequent pack.)
Think carefully about how are you going to test your program? The calculations are non-trivial and easy to get wrong. If your program doesn't work then you will waste the company a lot of money and you will probably lose the contract to supply the software.
You should write out a number of test cases (by hand) that cover all the different possibilities that could happen. Don't forget to consider various boundary cases too - these are often where errors are detected.
So far I have done:
import java.util.Scanner;
public class carpet {
public static void main (String args[]){
Scanner scanf = new Scanner (System.in);
float len, wid;
float area;
int roundTiles;
int roundPacks;
float tarea;
float tpack;
float NoOfTiles;
float NoOfPacks;
float tspares1;
float tspares2;
int packCost;
int cost;
tarea= 12* 12;
tpack= 10;
System.out.format("Enter the length of the room, Inches: ");
len = scanf.nextFloat();
System.out.format("Enter the width of the room, Inches: ");
wid = scanf.nextFloat();
area = len * wid;
NoOfTiles = area/ tarea;
NoOfPacks = NoOfTiles/tpack;
roundTiles = (int) Math.ceil(NoOfTiles);
roundPacks = (int) Math.ceil(NoOfPacks);
tspares1 = roundPacks * 10;
tspares2 = tspares1 - roundTiles;
if (roundPacks <= 4)
packCost =50;
else if(roundPacks > 4)
{
packCost = 45;
packCost = packCost + 20; *<<-----******LINE 50-----*********
}
cost =roundPacks * packCost; *<<*******---ERROR-------------*********
System.out.println(cost);
}
}
The error says: "The local variable packCost may not have been initialized"
AND the compiler says: "Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The local variable packCost may not have been initialized
at carpet.main(carpet.java:50)
"
You need to initialize the variable packCost by doing replacing the current line:
int packCost;
by
int packCost=0;
You are initializing your packCost variable in a conditional statement and the compiler is not smart enough to detect it.
Using else instead of else-if makes it clear to the compiler that one of the conditions will be executed, so packCost is always set:
if (roundPacks <= 4)
packCost = 50;
else
{
packCost = 45;
packCost = packCost + 20;
}
You need to initialise packetCost:
int packCost = 0;
In Java, local variables need to be initialized. If this was a field variable, it would have an implicit default value of 0 (zero).
Here is a link that explains this: http://www.janeg.ca/scjp/lang/defaults.html (disclaimer: not my page)
From this page:
Field variables (class members) are automatically initialized to default values
Local variables (method or constructor variables) are not automatically initialized