From af5287b34bbac0cd954108c14b85b61488f1508e Mon Sep 17 00:00:00 2001 From: algobytewise Date: Tue, 16 Mar 2021 09:03:42 +0530 Subject: [PATCH 1/7] Add Euler method (from master) trying to avoid to prettier-error by making the commit from the master-branch --- Maths/EulerMethod.java | 103 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 Maths/EulerMethod.java diff --git a/Maths/EulerMethod.java b/Maths/EulerMethod.java new file mode 100644 index 000000000000..a1dcc98bdf71 --- /dev/null +++ b/Maths/EulerMethod.java @@ -0,0 +1,103 @@ +import java.util.ArrayList; +import java.util.function.BiFunction; + +/** + * In mathematics and computational science, the Euler method (also called forward Euler method) is + * a first-order numerical procedure for solving ordinary differential equations (ODEs) with a given + * initial value. It is the most basic explicit method for numerical integration of ordinary + * differential equations. The method proceeds in a series of steps. At each step the y-value is + * calculated by evaluating the differential equation at the previous step, multiplying the result + * with the step-size and adding it to the last y-value: y_n+1 = y_n + stepSize * f(x_n, y_n). + * (description adapted from https://en.wikipedia.org/wiki/Euler_method ) (see also: + * https://www.geeksforgeeks.org/euler-method-solving-differential-equation/ ) + */ +public class EulerMethod { + + /** Illustrates how the algorithm is used in 3 examples and prints the results to the console. */ + public static void main(String[] args) { + System.out.println("example 1:"); + BiFunction exampleEquation1 = (x, y) -> x; + ArrayList points1 = eulerFull(0, 4, 0.1, 0, exampleEquation1); + assert points1.get(points1.size() - 1)[1] == 7.800000000000003; + points1.forEach( + point -> System.out.println(String.format("x: %1$f; y: %2$f", point[0], point[1]))); + + // example from https://en.wikipedia.org/wiki/Euler_method + System.out.println("\n\nexample 2:"); + BiFunction exampleEquation2 = (x, y) -> y; + ArrayList points2 = eulerFull(0, 4, 0.1, 1, exampleEquation2); + assert points2.get(points2.size() - 1)[1] == 45.25925556817596; + points2.forEach( + point -> System.out.println(String.format("x: %1$f; y: %2$f", point[0], point[1]))); + + // example from https://www.geeksforgeeks.org/euler-method-solving-differential-equation/ + System.out.println("\n\nexample 3:"); + BiFunction exampleEquation3 = (x, y) -> x + y + x * y; + ArrayList points3 = eulerFull(0, 0.1, 0.025, 1, exampleEquation3); + assert points3.get(points3.size() - 1)[1] == 1.1116729841674804; + points3.forEach( + point -> System.out.println(String.format("x: %1$f; y: %2$f", point[0], point[1]))); + } + + /** + * calculates the next y-value based on the current value of x, y and the stepSize the console. + * + * @param xCurrent Current x-value. + * @param stepSize Step-size on the x-axis. + * @param yCurrent Current y-value. + * @param differentialEquation The differential equation to be solved. + * @return The next y-value. + */ + public static double eulerStep( + double xCurrent, + double stepSize, + double yCurrent, + BiFunction differentialEquation) { + if (stepSize <= 0) { + throw new IllegalArgumentException("stepSize should be greater than zero"); + } + double yNext = yCurrent + stepSize * differentialEquation.apply(xCurrent, yCurrent); + return yNext; + } + + /** + * Loops through all the steps until xEnd is reached, adds a point for each step and then returns + * all the points + * + * @param xStart First x-value. + * @param xEnd Last x-value. + * @param stepSize Step-size on the x-axis. + * @param yStart First y-value. + * @param differentialEquation The differential equation to be solved. + * @return The points constituting the solution of the differential equation. + */ + public static ArrayList eulerFull( + double xStart, + double xEnd, + double stepSize, + double yStart, + BiFunction differentialEquation) { + if (xStart >= xEnd) { + throw new IllegalArgumentException("xEnd should be greater than xStart"); + } + if (stepSize <= 0) { + throw new IllegalArgumentException("stepSize should be greater than zero"); + } + + ArrayList points = new ArrayList(); + double[] firstPoint = {xStart, yStart}; + points.add(firstPoint); + double yCurrent = yStart; + double xCurrent = xStart; + + while (xCurrent < xEnd) { + // Euler method for next step + yCurrent = eulerStep(xCurrent, stepSize, yCurrent, differentialEquation); + xCurrent += stepSize; + double[] point = {xCurrent, yCurrent}; + points.add(point); + } + + return points; + } +} From 0f6a7432cb382365a7c6c3d7c3ba8bbf129557b5 Mon Sep 17 00:00:00 2001 From: algobytewise Date: Fri, 19 Mar 2021 21:24:49 +0530 Subject: [PATCH 2/7] delete file --- Maths/EulerMethod.java | 103 ----------------------------------------- 1 file changed, 103 deletions(-) delete mode 100644 Maths/EulerMethod.java diff --git a/Maths/EulerMethod.java b/Maths/EulerMethod.java deleted file mode 100644 index a1dcc98bdf71..000000000000 --- a/Maths/EulerMethod.java +++ /dev/null @@ -1,103 +0,0 @@ -import java.util.ArrayList; -import java.util.function.BiFunction; - -/** - * In mathematics and computational science, the Euler method (also called forward Euler method) is - * a first-order numerical procedure for solving ordinary differential equations (ODEs) with a given - * initial value. It is the most basic explicit method for numerical integration of ordinary - * differential equations. The method proceeds in a series of steps. At each step the y-value is - * calculated by evaluating the differential equation at the previous step, multiplying the result - * with the step-size and adding it to the last y-value: y_n+1 = y_n + stepSize * f(x_n, y_n). - * (description adapted from https://en.wikipedia.org/wiki/Euler_method ) (see also: - * https://www.geeksforgeeks.org/euler-method-solving-differential-equation/ ) - */ -public class EulerMethod { - - /** Illustrates how the algorithm is used in 3 examples and prints the results to the console. */ - public static void main(String[] args) { - System.out.println("example 1:"); - BiFunction exampleEquation1 = (x, y) -> x; - ArrayList points1 = eulerFull(0, 4, 0.1, 0, exampleEquation1); - assert points1.get(points1.size() - 1)[1] == 7.800000000000003; - points1.forEach( - point -> System.out.println(String.format("x: %1$f; y: %2$f", point[0], point[1]))); - - // example from https://en.wikipedia.org/wiki/Euler_method - System.out.println("\n\nexample 2:"); - BiFunction exampleEquation2 = (x, y) -> y; - ArrayList points2 = eulerFull(0, 4, 0.1, 1, exampleEquation2); - assert points2.get(points2.size() - 1)[1] == 45.25925556817596; - points2.forEach( - point -> System.out.println(String.format("x: %1$f; y: %2$f", point[0], point[1]))); - - // example from https://www.geeksforgeeks.org/euler-method-solving-differential-equation/ - System.out.println("\n\nexample 3:"); - BiFunction exampleEquation3 = (x, y) -> x + y + x * y; - ArrayList points3 = eulerFull(0, 0.1, 0.025, 1, exampleEquation3); - assert points3.get(points3.size() - 1)[1] == 1.1116729841674804; - points3.forEach( - point -> System.out.println(String.format("x: %1$f; y: %2$f", point[0], point[1]))); - } - - /** - * calculates the next y-value based on the current value of x, y and the stepSize the console. - * - * @param xCurrent Current x-value. - * @param stepSize Step-size on the x-axis. - * @param yCurrent Current y-value. - * @param differentialEquation The differential equation to be solved. - * @return The next y-value. - */ - public static double eulerStep( - double xCurrent, - double stepSize, - double yCurrent, - BiFunction differentialEquation) { - if (stepSize <= 0) { - throw new IllegalArgumentException("stepSize should be greater than zero"); - } - double yNext = yCurrent + stepSize * differentialEquation.apply(xCurrent, yCurrent); - return yNext; - } - - /** - * Loops through all the steps until xEnd is reached, adds a point for each step and then returns - * all the points - * - * @param xStart First x-value. - * @param xEnd Last x-value. - * @param stepSize Step-size on the x-axis. - * @param yStart First y-value. - * @param differentialEquation The differential equation to be solved. - * @return The points constituting the solution of the differential equation. - */ - public static ArrayList eulerFull( - double xStart, - double xEnd, - double stepSize, - double yStart, - BiFunction differentialEquation) { - if (xStart >= xEnd) { - throw new IllegalArgumentException("xEnd should be greater than xStart"); - } - if (stepSize <= 0) { - throw new IllegalArgumentException("stepSize should be greater than zero"); - } - - ArrayList points = new ArrayList(); - double[] firstPoint = {xStart, yStart}; - points.add(firstPoint); - double yCurrent = yStart; - double xCurrent = xStart; - - while (xCurrent < xEnd) { - // Euler method for next step - yCurrent = eulerStep(xCurrent, stepSize, yCurrent, differentialEquation); - xCurrent += stepSize; - double[] point = {xCurrent, yCurrent}; - points.add(point); - } - - return points; - } -} From ce7fdf30d2f3cf59757d1eba73235a39b8abc550 Mon Sep 17 00:00:00 2001 From: algobytewise Date: Fri, 19 Mar 2021 21:26:42 +0530 Subject: [PATCH 3/7] Add algorithm for the Mandelbrot set --- Others/Mandelbrot.java | 191 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 Others/Mandelbrot.java diff --git a/Others/Mandelbrot.java b/Others/Mandelbrot.java new file mode 100644 index 000000000000..1f451ba1275a --- /dev/null +++ b/Others/Mandelbrot.java @@ -0,0 +1,191 @@ +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; +import javax.swing.*; + +/** + * The Mandelbrot set is the set of complex numbers "c" for which the series "z_(n+1) = z_n * z_n + + * c" does not diverge, i.e. remains bounded. Thus, a complex number "c" is a member of the + * Mandelbrot set if, when starting with "z_0 = 0" and applying the iteration repeatedly, the + * absolute value of "z_n" remains bounded for all "n > 0". Complex numbers can be written as "a + + * b*i": "a" is the real component, usually drawn on the x-axis, and "b*i" is the imaginary + * component, usually drawn on the y-axis. Most visualizations of the Mandelbrot set use a + * color-coding to indicate after how many steps in the series the numbers outside the set cross the + * divergence threshold. Images of the Mandelbrot set exhibit an elaborate and infinitely + * complicated boundary that reveals progressively ever-finer recursive detail at increasing + * magnifications, making the boundary of the Mandelbrot set a fractal curve. (description adapted + * from https://en.wikipedia.org/wiki/Mandelbrot_set ) (see also + * https://en.wikipedia.org/wiki/Plotting_algorithms_for_the_Mandelbrot_set ) + */ +public class Mandelbrot { + + public static void main(String[] args) { + // Test black and white + BufferedImage blackAndWhiteImage = getImage(800, 600, -0.6, 0, 3.2, 50, false); + + // Pixel outside the Mandelbrot set should be white. + assert blackAndWhiteImage.getRGB(0, 0) == new Color(255, 255, 255).getRGB(); + + // Pixel inside the Mandelbrot set should be black. + assert blackAndWhiteImage.getRGB(400, 300) == new Color(0, 0, 0).getRGB(); + + // Test color-coding + BufferedImage coloredImage = getImage(800, 600, -0.6, 0, 3.2, 50, true); + + // Pixel distant to the Mandelbrot set should be red. + assert coloredImage.getRGB(0, 0) == new Color(255, 0, 0).getRGB(); + + // Pixel inside the Mandelbrot set should be black. + assert coloredImage.getRGB(400, 300) == new Color(0, 0, 0).getRGB(); + + // Save image + try { + ImageIO.write(coloredImage, "png", new File("Mandelbrot.png")); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Method to generate the image of the Mandelbrot set. Two types of coordinates are used: + * image-coordinates that refer to the pixels and figure-coordinates that refer to the complex + * numbers inside and outside the Mandelbrot set. The figure-coordinates in the arguments of this + * method determine which section of the Mandelbrot set is viewed. The main area of the Mandelbrot + * set is roughly between "-1.5 < x < 0.5" and "-1 < y < 1" in the figure-coordinates. + * + * @param imageWidth The width of the rendered image. + * @param imageHeight">The height of the rendered image. + * @param figureCenterX">The x-coordinate of the center of the figure. + * @param figureCenterY">The y-coordinate of the center of the figure. + * @param figureWidth">The width of the figure. + * @param maxStep">Maximum number of steps to check for divergent behavior. + * @param useDistanceColorCoding">Render in color or black and white. + * @return The image of the rendered Mandelbrot set. + */ + public static BufferedImage getImage( + int imageWidth, + int imageHeight, + double figureCenterX, + double figureCenterY, + double figureWidth, + int maxStep, + boolean useDistanceColorCoding) { + if (imageWidth <= 0) { + throw new IllegalArgumentException("imageWidth should be greater than zero"); + } + + if (imageHeight <= 0) { + throw new IllegalArgumentException("imageHeight should be greater than zero"); + } + + if (maxStep <= 0) { + throw new IllegalArgumentException("maxStep should be greater than zero"); + } + + BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); + double figureHeight = figureWidth / imageWidth * imageHeight; + + // loop through the image-coordinates + for (int imageX = 0; imageX < imageWidth; imageX++) { + for (int imageY = 0; imageY < imageHeight; imageY++) { + // determine the figure-coordinates based on the image-coordinates + double figureX = figureCenterX + ((double) imageX / imageWidth - 0.5) * figureWidth; + double figureY = figureCenterY + ((double) imageY / imageHeight - 0.5) * figureHeight; + + double distance = getDistance(figureX, figureY, maxStep); + + // color the corresponding pixel based on the selected coloring-function + image.setRGB( + imageX, + imageY, + useDistanceColorCoding + ? colorCodedColorMap(distance).getRGB() + : blackAndWhiteColorMap(distance).getRGB()); + } + } + + return image; + } + + /** + * Black and white color-coding that ignores the relative distance. The Mandelbrot set is black, + * everything else is white. + * + * @param distance Distance until divergence threshold + * @return The color corresponding to the distance. + */ + private static Color blackAndWhiteColorMap(double distance) { + return distance >= 1 ? new Color(0, 0, 0) : new Color(255, 255, 255); + } + + /** + * Color-coding taking the relative distance into account. The Mandelbrot set is black. + * + * @param distance Distance until divergence threshold. + * @return The color corresponding to the distance. + */ + private static Color colorCodedColorMap(double distance) { + if (distance >= 1) { + return new Color(0, 0, 0); + } else { + // simplified transformation of HSV to RGB + // distance determines hue + double hue = 360 * distance; + double saturation = 1; + double val = 255; + int hi = (int) (Math.floor(hue / 60)) % 6; + double f = hue / 60 - Math.floor(hue / 60); + + int v = (int) val; + int p = 0; + int q = (int) (val * (1 - f * saturation)); + int t = (int) (val * (1 - (1 - f) * saturation)); + + switch (hi) { + case 0: + return new Color(v, t, p); + case 1: + return new Color(q, v, p); + case 2: + return new Color(p, v, t); + case 3: + return new Color(p, q, v); + case 4: + return new Color(t, p, v); + default: + return new Color(v, p, q); + } + } + } + + /** + * Return the relative distance (ratio of steps taken to maxStep) after which the complex number + * constituted by this x-y-pair diverges. Members of the Mandelbrot set do not diverge so their + * distance is 1. + * + * @param figureX The x-coordinate within the figure. + * @param figureX The y-coordinate within the figure. + * @param maxStep Maximum number of steps to check for divergent behavior. + * @return The relative distance as the ratio of steps taken to maxStep. + */ + private static double getDistance(double figureX, double figureY, int maxStep) { + double a = figureX; + double b = figureY; + int currentStep = 0; + for (int step = 0; step < maxStep; step++) { + currentStep = step; + double a_new = a * a - b * b + figureX; + b = 2 * a * b + figureY; + a = a_new; + + // divergence happens for all complex number with an absolute value + // greater than 4 (= divergence threshold) + if (a * a + b * b > 4) { + break; + } + } + return (double) currentStep / (maxStep - 1); + } +} From bc36606a6810cdfab6121213d1db810f7c1e9b40 Mon Sep 17 00:00:00 2001 From: algobytewise Date: Fri, 19 Mar 2021 21:30:55 +0530 Subject: [PATCH 4/7] remove unnecessary import --- Others/Mandelbrot.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Others/Mandelbrot.java b/Others/Mandelbrot.java index 1f451ba1275a..9b0d232a6978 100644 --- a/Others/Mandelbrot.java +++ b/Others/Mandelbrot.java @@ -3,7 +3,6 @@ import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; -import javax.swing.*; /** * The Mandelbrot set is the set of complex numbers "c" for which the series "z_(n+1) = z_n * z_n + From ec9b4076f53a60ddc942da0e41b923835ad32548 Mon Sep 17 00:00:00 2001 From: algobytewise Date: Fri, 19 Mar 2021 21:56:34 +0530 Subject: [PATCH 5/7] fix comments --- Others/Mandelbrot.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Others/Mandelbrot.java b/Others/Mandelbrot.java index 9b0d232a6978..b43e58906d00 100644 --- a/Others/Mandelbrot.java +++ b/Others/Mandelbrot.java @@ -55,12 +55,12 @@ public static void main(String[] args) { * set is roughly between "-1.5 < x < 0.5" and "-1 < y < 1" in the figure-coordinates. * * @param imageWidth The width of the rendered image. - * @param imageHeight">The height of the rendered image. - * @param figureCenterX">The x-coordinate of the center of the figure. - * @param figureCenterY">The y-coordinate of the center of the figure. - * @param figureWidth">The width of the figure. - * @param maxStep">Maximum number of steps to check for divergent behavior. - * @param useDistanceColorCoding">Render in color or black and white. + * @param imageHeight The height of the rendered image. + * @param figureCenterX The x-coordinate of the center of the figure. + * @param figureCenterY The y-coordinate of the center of the figure. + * @param figureWidth The width of the figure. + * @param maxStep Maximum number of steps to check for divergent behavior. + * @param useDistanceColorCoding Render in color or black and white. * @return The image of the rendered Mandelbrot set. */ public static BufferedImage getImage( From 6df9082b559fbb3d3b7e4e8e9b44136fdb8f2c27 Mon Sep 17 00:00:00 2001 From: algobytewise Date: Sat, 20 Mar 2021 17:36:15 +0530 Subject: [PATCH 6/7] Changed variable name --- Others/Mandelbrot.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Others/Mandelbrot.java b/Others/Mandelbrot.java index b43e58906d00..10fc294ee877 100644 --- a/Others/Mandelbrot.java +++ b/Others/Mandelbrot.java @@ -175,9 +175,9 @@ private static double getDistance(double figureX, double figureY, int maxStep) { int currentStep = 0; for (int step = 0; step < maxStep; step++) { currentStep = step; - double a_new = a * a - b * b + figureX; + double aNew = a * a - b * b + figureX; b = 2 * a * b + figureY; - a = a_new; + a = aNew; // divergence happens for all complex number with an absolute value // greater than 4 (= divergence threshold) From 8b3bba3317657005825048edd4fbb9ebdc992553 Mon Sep 17 00:00:00 2001 From: algobytewise Date: Thu, 15 Apr 2021 19:48:37 +0530 Subject: [PATCH 7/7] add package --- Others/Mandelbrot.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Others/Mandelbrot.java b/Others/Mandelbrot.java index 10fc294ee877..940245fbae3a 100644 --- a/Others/Mandelbrot.java +++ b/Others/Mandelbrot.java @@ -1,3 +1,5 @@ +package Others; + import java.awt.*; import java.awt.image.BufferedImage; import java.io.File;