I am trying to do the famous Monte Carlo simulation to estimate pi for my Java course.
Here is the Simulation:
public class Darts
{
//"throwing" a dart
public static boolean [] dartThrow(int r, int d){
boolean [] booleanArray = new boolean[d];
for(int i = 0; i < d; i++){
double xCoord = Math.random() * 2;
double yCoord = Math.random() * 2;
if((Math.pow(xCoord,2) + Math.pow(yCoord,2)) <= r){
booleanArray[i] = true;
}
else{
booleanArray [i] = false;
}
}
return booleanArray;
}
//calculating pi from throwing results
public static double piEstimater(boolean [] h, int d){
int trueCounter = 0;
for(int i = 0; i < h.length; i++){
if(h[i] == true){
trueCounter++;
}
}
return 4 * ((double)trueCounter / d);
}
//printing results
public static void printer(double [] a){
System.out.println(" Pi Estimation Tool ");
System.out.println("---------------------------");
for(int i = 0; i < a.length; i++){
System.out.print("Trial [" + i + "]: pi = ");
System.out.printf("%6f\n", a[i]);
}
}
public static void main(String[] args){
//variables
Scanner in = new Scanner(System.in);
int radius = 1;
int darts;
int trials;
System.out.println("Enter the number of darts to calculate for: ");
darts = in.nextInt();
System.out.println("Enter the number of trials to calculate for: ");
trials = in.nextInt();
double [] arrayOfEstimates = new double [trials];
int i = 0;
for(double a : arrayOfEstimates){
boolean [] hitCounter = dartThrow(radius, darts);
double piEstimate = piEstimater(hitCounter, darts);
arrayOfEstimates[i] = piEstimate;
i++;
}
printer(arrayOfEstimates);
}
}
I have created code that executes correctly, except for that the results never go above ~ .8. I would like to just assume that this is happening because the random numbers are so low, but if it happens every time something HAS to be wrong, right? Please keep in mind that this code contains about all the Java techniques I know, so I would appreciate it if you kept from including anything more "advanced." Thanks!
The idea of the calculation of PI using the Monte Carlo method is to sample random points in a square, and count the fraction of them that fall within the area of a circle bound by that square. If enough points are uniformly sampled, the fraction would be close to the area of the circle divided by the area of the bounding square :
fraction = PI*r^2/(2r)^2
and therefore
PI = fraction * 4.
Now, since you are sampling only positive coordinates, if we assume that the circle is centered at the origin (0,0), we only sample points within the top-right quarter of the circle and its bounding square, but the equation remains the same.
If your circle has radius r, you should sample coordinates between 0 and r.
Therefore you should change this :
double xCoord = Math.random() * 2;
double yCoord = Math.random() * 2;
To this :
double xCoord = Math.random() * r;
double yCoord = Math.random() * r;
In addition the condition should be ((Math.pow(xCoord,2) + Math.pow(yCoord,2)) <= r*r).
Of course, you can simplify it by eliminating r and assuming the radius is 1.
In that case the condition would be ((Math.pow(xCoord,2) + Math.pow(yCoord,2)) <= 1) and the coordinates would be sampled between 0 and 1.
Related
I have been trying to code a program whereby the user inputs an angle, assuming it is degrees, it gets converted from degrees to radians and then calculates its sine or cosine. I tried to do this in a way which is convenient for the user but it turns out I have some issues trying to calculate both of these(cosine and sine) and outputting correct results. I appreciate your help. Also assuming constant number of terms which is 30.
import java.util.Scanner;
public class Question8 {
public static double radians(double angle)
{
double pi = 3.141592653589793238462643;
return angle / 180.0 * pi; //conversion from degrees to radians
}
public static void main( String [] args)
{
Scanner sc = new Scanner(System.in);
int sw = 0, n, j=1, m=-1;
double sine, i=0, r=0, cosine, c=0, rad; //initialising variables of type double and int
do{
System.out.println("Please input either 1 or 2 to calculate Sine or Cosine respectively.");
sw = sc.nextInt();
switch(sw) { //implementing a switch to differentiate between sine and cosine
case 1:{ //this calculates the sine
System.out.println("Please input Angle and n (number of terms) to calculate sine");
sine = sc.nextDouble();
n = sc.nextInt();
rad = radians(sine);
i = rad;
for(int k = 3; k < n; k = k+2) {
double o = Math.pow(rad,k);
j = j*(k-1)*k;
r = o/j;
i=i+m*r;
m=m*(-1);
}
System.out.println("Sine " + sine + " = " + i);
}
break;
case 2:{ //this calculates cosine
System.out.println("Please input angle and n to calculate cosine");
cosine = sc.nextDouble();
n = sc.nextInt();
rad = radians(cosine);
c = 1.0;
for(int k = 2; k < n; k = k+2) {
double o = Math.pow(rad,k);
j = j*(k-1)*k;
r = o/j;
c=c+m*r;
m = m*(-1);
}
System.out.println("Cosine " + cosine + " = " + c);
}
break;
default: {
System.out.println("Invalid choice"); //user selects invalid numbers
}
break;
}
} while(sw != 0);
}
}
Your algorithm for calculating sin and cos is correct. You should reinitialize variables m,j and r after each calculus. You can use CORDIC algorithm or chebyshev polynomial as more accurate substitute for Taylor series.
I coded a very simple neural net with 1 neuron and 2 inputs and 1 bias in java, trying to classify dots on either the left or right side of a line. The problem is that the neural net recognizes the slope of the line but not the y-intercept (e.g. the function of the line may be y = m*x + c and the NN recognizes the m but not the c).
I tried to use a bias value=1 in order to enable the NN to calculate the weight for the bias which should be the y-intercept. But it doesnt. You will see that I am very new to Java programming. Unfortunately also new to NN. In that case I guess my problem is rather in the understanding of the underlying methodology of the bias in the NN.
Remark: In the output line at the very end of the code, I would expect in case of the function y = 3*x + 5 following figures: weight[0]=3 (which is the m) , weight[1]=1 (which is the factor for y) and weight[2]=5 (this is c). The weight[2] is always wrong.
package nn2;
public class anfang_eng {
public static void main(String[] args)
{
double[][] points = new double[5][10000];
double[] weights = new double[3];
double[][] normpoints = new double[5][10000];
// create 1000 dots with desired result for training afterwards
points = createPoints();
// the before randomly created x and y values of the 1000 dots
// shall be normalized between 0 and 1
normpoints = normalize(points);
// create two random initial weights
weights = createinitialWeights();
// training function, calculation of three different weights
calculateWeights(normpoints, weights);
testnewPoints(weights);
}
// thats the function of the line, that seperates all dots in
// two groups: all the dots at the left side of the line and all the dots
// at the right side.
static double function(double x, double y)
{
double result;
result = 3*x - y + 5;
return result;
}
static double[][] createPoints()
{
// 1. step: lets create for training reasons some dots and calculate
// the result for each dot (result is either "1" or "-1").
// point[0] is x, point[1] is y, point[2] is bias and point[3] is
// result (left or right side of the function above
int x;
int y;
int quantity= 1000;
double[][] point = new double[5][quantity];
for (int i=0; i<quantity; i++)
{
x = (int) (2000 * Math.random()-1000);
y = (int) (2000 * Math.random()-1000);
point[0][i] = x;
point[1][i] = y;
// point[2] is our bias
point[2][i] = 1;
// all dots which are at the right side of the function above get
// result "1". otherwise "-1"
if ( function(x,y) > 0)
point[3][i] = 1;
else
point[3][i] =-1;
// point[3] contains the result
}
// in the variable point, there are e.g. 1000 or 5000 dots with x, y,
// bias and the result (1=left side and -1=right side)
return point;
}
// normalize x and y values between 0 and 1
static double[][] normalize(double[][]points)
{
int quantity = points[0].length;
double minpoint_x=1000;
double minpoint_y=1000;
double maxpoint_x=-1000;
double maxpoint_y=-1000;
double[][] normpoints = new double[5][quantity];
minpoint_x= points[0][0];
minpoint_y = points[1][0];
maxpoint_x = points[0][0];
maxpoint_y = points[1][0];
for (int i=0; i<quantity;i++)
{
if (points[0][i]<minpoint_x)
minpoint_x=points[0][i];
if (points[1][i]<minpoint_y)
minpoint_y=points[1][i];
if (points[0][i]>maxpoint_x)
maxpoint_x=points[0][i];
if (points[1][i]>maxpoint_y)
maxpoint_y=points[1][i];
}
for (int u=0; u<quantity; u++)
{
normpoints [0][u]= (points[0][u]-minpoint_x)/(maxpoint_x-minpoint_x);
normpoints [1][u]= (points[1][u]-minpoint_y)/(maxpoint_y-minpoint_y);
normpoints [2][u] = 1; //bias is always 1
normpoints [3][u] = points[3][u];
}
return normpoints;
}
static double[] createinitialWeights()
{
// creation of initial weights between -1 and 1
double[] weight = new double[3];
weight[0] = 2*Math.random()-1;
weight[1] = 2*Math.random()-1;
weight[2] = 2*Math.random()-1;
return weight;
}
static void calculateWeights(double[][] normpoints, double[] weight)
// new weight = weight + error * input * learning constant
// c is learning constant
{
double c = 0.01;
double error = 0;
double sumguess = 0;
double guess = 0;
int quantity = normpoints[0].length;
for (int i=0; i < quantity; i++)
{
// normpoint[0][i] stands for the factor at x, normpoint[0][i] is
// for y and normpoint[2][i] is for bias
sumguess = normpoints[0][i] * weight[0] + normpoints[1][i]*weight[1] + normpoints[2][i]*weight[2];
if (sumguess > 0)
guess = 1;
else
guess = -1;
error = normpoints[3][i]- guess;
weight[0] = weight[0] + error * normpoints[0][i] * c;
weight[1] = weight[1] + error * normpoints[1][i] * c;
weight[2] = weight[2] + error * normpoints[2][i] * c;
System.out.println("i: " + i + " ;value_normpoint[0]:" + normpoints[0][i]+ " ;value_normpoint[1]" + normpoints[1][i]+ " ;value_normpoint[2]" + normpoints[2][i] + " result:" + normpoints[3][i]);
System.out.println("weight[0]: " + Math.round(weight[0]*100)/100.0 + " ;weight[1]: " +Math.round(weight[1]*100)/100.0 + " ;weight[2]: " + Math.round(weight[2]*100)/100.0 );
System.out.println("guess: "+ guess+ " result " + normpoints[3][i] + " error: " + error);
System.out.println();
}
System.out.println("final weights: x: " + weight[0] + " y: "+ weight[1] + " bias: " +weight[2]);
System.out.println("final weights normalized on y=1: x:" + weight[0]/weight[1] + " y: "+ weight[1]/weight[1] + " bias: " +weight[2]/weight[1]);
}
// lets test if the trained weights classify the test dot on the correct side of the line y=4*x+3
// again 500 random dots with "x", "y" and "results" are created and tested if the NN calculated correct weights
static void testnewPoints(double[] weights)
{
int x;
int y;
double[][] testpoint = new double[5][10000];
double[][] normalizedtestpoint = new double[5][10000];
int quantity = 500;
double sumcheck = 0;
double sumtest = 0;
int correct = 0;
int wrong = 0;
for (int i=0; i<quantity; i++)
{
// calculation of test points with x and y between -100 and 100
x = (int) (200 * Math.random()-100);
y = (int) (200 * Math.random()-100);
testpoint[0][i] = x;
testpoint[1][i] = y;
testpoint[2][i] = 1;
// lets classify the points: at the rights side of the line the result for each point is "1", on the left side "-1"
if (function(x,y) > 0)
testpoint[3][i] = 1;
else
testpoint[3][i] = -1;
// punkt[3] is the result
}
normalizedtestpoint= normalize(testpoint);
// are the test points with our calculated weights classified on the correct side of the line?
for (int i=0; i<quantity; i++)
{
sumcheck = normalizedtestpoint[0][i] * weights[0] + normalizedtestpoint[1][i] * weights[1] + normalizedtestpoint[2][i] * weights[2];
if (sumcheck > 0)
sumtest = 1;
else
sumtest = -1;
if (sumtest == normalizedtestpoint[3][i])
correct++;
else
wrong++;
}
System.out.println("correct: "+ correct + " wrong: " + wrong);
}
}
Please let me also know if you see some major issues in my coding style, quite an beginner style I guess.
Many thanks in advance!
Lonko
According to this video the substantive difference between the perceptron and gradient descent algorithms are quite minor. They specified it as essentially:
Perceptron: Δwi = η(y - ŷ)xi
Gradient Descent: Δwi = η(y - α)xi
I've implemented a working version of the perceptron algorithm, but I don't understand what sections I need to change to turn it into gradient descent.
Below is the load-bearing portions of my perceptron code, I suppose that these are the components I need to modify. But where? What do I need to change? I don't understand.
This is left for pedagogical reasons, I've sort of figured this out but am still confused about the gradient, please see UPDATE below
iteration = 0;
do
{
iteration++;
globalError = 0;
//loop through all instances (complete one epoch)
for (p = 0; p < number_of_files__train; p++)
{
// calculate predicted class
output = calculateOutput( theta, weights, feature_matrix__train, p, globo_dict_size );
// difference between predicted and actual class values
localError = outputs__train[p] - output;
//update weights and bias
for (int i = 0; i < globo_dict_size; i++)
{
weights[i] += ( LEARNING_RATE * localError * feature_matrix__train[p][i] );
}
weights[ globo_dict_size ] += ( LEARNING_RATE * localError );
//summation of squared error (error value for all instances)
globalError += (localError*localError);
}
/* Root Mean Squared Error */
if (iteration < 10)
System.out.println("Iteration 0" + iteration + " : RMSE = " + Math.sqrt( globalError/number_of_files__train ) );
else
System.out.println("Iteration " + iteration + " : RMSE = " + Math.sqrt( globalError/number_of_files__train ) );
}
while(globalError != 0 && iteration<=MAX_ITER);
This is the crux of my perceptron:
static int calculateOutput( int theta, double weights[], double[][] feature_matrix, int file_index, int globo_dict_size )
{
//double sum = x * weights[0] + y * weights[1] + z * weights[2] + weights[3];
double sum = 0;
for (int i = 0; i < globo_dict_size; i++)
{
sum += ( weights[i] * feature_matrix[file_index][i] );
}
//bias
sum += weights[ globo_dict_size ];
return (sum >= theta) ? 1 : 0;
}
Is it just that I replace that caculateOutput method with something like this:
public static double [] gradientDescent(final double [] theta_in, final double alpha, final int num_iters, double[][] data )
{
final double m = data.length;
double [] theta = theta_in;
double theta0 = 0;
double theta1 = 0;
for (int i = 0; i < num_iters; i++)
{
final double sum0 = gradientDescentSumScalar0(theta, alpha, data );
final double sum1 = gradientDescentSumScalar1(theta, alpha, data);
theta0 = theta[0] - ( (alpha / m) * sum0 );
theta1 = theta[1] - ( (alpha / m) * sum1 );
theta = new double [] { theta0, theta1 };
}
return theta;
}
UPDATE EDIT
At this point I think I'm very close.
I understand how to calculate the hypothesis and I think I've done that correctly, but nevertheless, something remains terribly wrong with this code. I'm pretty sure it has something to do with my calculation of the gradient. When I run it the error fluctuates wildly and then goes to infinity then just NaaN.
double cost, error, hypothesis;
double[] gradient;
int p, iteration;
iteration = 0;
do
{
iteration++;
error = 0.0;
cost = 0.0;
//loop through all instances (complete one epoch)
for (p = 0; p < number_of_files__train; p++)
{
// 1. Calculate the hypothesis h = X * theta
hypothesis = calculateHypothesis( theta, feature_matrix__train, p, globo_dict_size );
// 2. Calculate the loss = h - y and maybe the squared cost (loss^2)/2m
cost = hypothesis - outputs__train[p];
// 3. Calculate the gradient = X' * loss / m
gradient = calculateGradent( theta, feature_matrix__train, p, globo_dict_size, cost, number_of_files__train);
// 4. Update the parameters theta = theta - alpha * gradient
for (int i = 0; i < globo_dict_size; i++)
{
theta[i] = theta[i] - LEARNING_RATE * gradient[i];
}
}
//summation of squared error (error value for all instances)
error += (cost*cost);
/* Root Mean Squared Error */
if (iteration < 10)
System.out.println("Iteration 0" + iteration + " : RMSE = " + Math.sqrt( error/number_of_files__train ) );
else
System.out.println("Iteration " + iteration + " : RMSE = " + Math.sqrt( error/number_of_files__train ) );
//System.out.println( Arrays.toString( weights ) );
}
while(cost != 0 && iteration<=MAX_ITER);
}
static double calculateHypothesis( double[] theta, double[][] feature_matrix, int file_index, int globo_dict_size )
{
double hypothesis = 0.0;
for (int i = 0; i < globo_dict_size; i++)
{
hypothesis += ( theta[i] * feature_matrix[file_index][i] );
}
//bias
hypothesis += theta[ globo_dict_size ];
return hypothesis;
}
static double[] calculateGradent( double theta[], double[][] feature_matrix, int file_index, int globo_dict_size, double cost, int number_of_files__train)
{
double m = number_of_files__train;
double[] gradient = new double[ globo_dict_size];//one for bias?
for (int i = 0; i < gradient.length; i++)
{
gradient[i] = (1.0/m) * cost * feature_matrix[ file_index ][ i ] ;
}
return gradient;
}
The perceptron rule is just an approximation to the gradient descent when you have non-differentiable activation functions like (sum >= theta) ? 1 : 0. As they ask in the end of the video, you cannot use gradients there because this threshold function isn't differentiable (well, its gradient is not defined for x=0 and the gradient is zero everywhere else). If, instead of this thresholding, you had a smooth function like the sigmoid you could calculate the actual gradients.
In that case your weight update would be LEARNING_RATE * localError * feature_matrix__train[p][i] * output_gradient[i]. For the case of sigmoid, the link I sent you also shows how to calculate the output_gradient.
In summary to change from perceptrons to gradient descent you have to
Use an activation function whose derivative (gradient) is not zero
everywhere.
Apply the chain rule to define the new update rule
I'm working on a question where i need to find the length of the side given the coordinates of a polygon.
N is the number of rows and 2 is number of columns ( x and y coordinates) and i've collected the coordinates in a multi-dimensional array.
what my idea was to collect the x coordinates in a array say x1 and collect y coordinates in a array say y1. now find the difference between the numbers in the array and perform the distance formula operation. but im not able to proceed any further. im not able to find the length using it as the answer is always short of the actual number. kindly help on how can i find the length of the sides of a given polygon. please find my code below:
import java.util.Scanner;
public class Rope {
public static void main(String[] args) {
int N = 1, R=1;
double AoN=1;
float d=0 , e=0, f=0, h=0, s=0, length=0, g=0;;
Scanner in = new Scanner(System.in);
int[] arr = new int[2];
System.out.println("Enter number of Nails (N) and Radius of Nail (R) seperated by space: ");
for (int i=0;i<arr.length;i++) {
arr[i]=in.nextInt();
}
if (arr[0]>=1 && arr[0]<=100) {
N=arr[0]; // N is the number of rows of the multi-dimensional array and rows is fixed to 2 as coordinates are fixed to x and y so 2.
}
R=arr[1]; // kindly ignore R as it is used for other purpose.
float[ ][ ] arr1 = new float[N][2];
System.out.println("Enter Coordinates separated by spaces: ");
for(int i=0; i<N;i++) {
for (int j=0;j<2;j++) {
arr1[i][j]=in.nextFloat();
//System.out.println(arr1[i][j]);
}
}
float[] x = new float[N];
float[] y = new float[N];
for(int i=0; i<N;i++) {
x[i] = arr1[i][0];
}
for (int j=0;j<N;j++) {
y[j] = arr1[j][1];
}
for (int i=0; i<x.length-1;i++) {
d = (float) (d + (Math.pow((x[i+1] - x[i]),2)));
}
for (int i=0; i<y.length-1;i++) {
e = (float) (e + (Math.pow((y[i+1] - y[i]),2)));
}
g = d+e;
s = (float) Math.sqrt(g);
sysout(s);
in.close();
}
}
because you have a logical glitch in your code. Here if you notice in the following section :
for (int i=0; i<x.length-1;i++) {
d = (float) (d + (Math.pow((x[i+1] - x[i]),2)));
}
for (int i=0; i<y.length-1;i++) {
e = (float) (e + (Math.pow((y[i+1] - y[i]),2)));
}
Lets say,
x1-x2 = X1
x2-x3 = X2
and so on
similarly,
y1-y2 = Y1
y2-y3 = Y2
and so on
now what your code does is it calculates
sqrt(X1*X1 + X2*X2.... +Y1*Y1 + Y2*Y2....)
But what actually it is supposed to do is,
sqrt(Math.pow((X1-X2),2) + Math.pow(Y1-Y2),2)) + sqrt (Math.pow((X2-X3),2) + Math.pow((Y2-Y3), 2) + ...
thus your code generates wrong values.
You should try the following :
for (int i=0; i<x.length-1;i++) {
float temp;
temp = (Math.pow((x[i+1] - x[i]),2)) + (Math.pow((y[i+1] - y[i]),2));
d = (float) (d + sqrt(temp));
}
// for first and last values / coordinates w.r.t distance formula
for (int i=x.length-1; i<x.length;i++) {
float temp;
temp = (float) ((Math.pow((x[i] - x[0]),2)) + (Math.pow((y[i] - y[0]),2)));
d = (float) (d + Math.sqrt(temp));
}
Instead of that above mentioned two lines.
Hope this helps !!!
If a user enters a value for
x y and z coordinates, what steps would need to take in order to create a range from -x/y/z to +x/y/z? Is there a function that will give the numbers in that range even though a double is entered?
This is my code so far im not finished yet, I'm not sure if its right. After it gets the x,y,z points and the number of data points the user wants, it will then print the n number of points with random points (x , y, z) x, y, z being anywhere from -x to x etc.
import java.io.*;
public class MultiDimArray
{
public static void main (String [] args) throws IOException
{
BufferedReader myInput = new BufferedReader (new InputStreamReader (System.in));// Buffered Reader reads the number inputed
double range;
System.out.println("How many points do you want returned? ");
String numPointsA = myInput.readLine();
int numPoints = Integer.parseInt(numPointsA);
System.out.println("Enter X length: ");
String xlengthA = myInput.readLine();
double xlength = Double.parseDouble(xlengthA);
System.out.println("Enter Y length: ");
String ylengthA = myInput.readLine();
double ylength = Double.parseDouble(ylengthA);
System.out.println("Enter Z length: ");
String zlengthA = myInput.readLine();
double zlength = Double.parseDouble(zlengthA);
int[][][][] dataPoint = new int[3][xlength][ylength][zlength];
for (int i = 0; i < (xlength * 2); i++){
range = (0 -( xlength - i) + 1);
System.out.println(range);
}
for (int i = 0; i < (ylength * 2); i++){
range = (0 -( ylength - i) + 1);
}
for (int i = 0; i < (zlength * 2); i++){
range = (0 -( zlength - i) + 1);
}
}
}
range is infinite if you want to include all fractional numbers otherwise you can do that manually.
for (int i=-x; i<=x; i++)
operate(i, y, z);
another solution for your problem is that you don't generate range.
you just store those values x y and z.
then, when you need to test if a number is in range you can do it easily with if statement.
what I mean that this a wrong way to design your solution. try to get values you want in another way. something like reverse engineering. then you test if those values are in range.
post your problem. then we can help you.
Code that generates numPointsA random numbers between -x and x:
Random random = new Random();
double start = -x;
double end = x;
for (int i=0;i<numPointsA;i++)
{
double ran = random.nextDouble();
double result = start + (ran * (end - start));
System.out.println(result);
}
To get a random number between 0 and n-1, use
Random rand = new Random();
int r = rand.nextInt(n);