From 3bb0c3648cfc8cac8c3490d25d9e84150170f0d2 Mon Sep 17 00:00:00 2001 From: tomtuamnuq <76523782+tomtuamnuq@users.noreply.github.com> Date: Tue, 2 Apr 2024 10:41:13 -0600 Subject: [PATCH] Reverse Probability Discrete Map and Transcendental Fractal Generator (#9) * change probability to transcendental fractal generator * add ReverseProbability DiscreteMap variant * fine adjustements defaults and info hover --- Cargo.lock | 1 + README.md | 5 +- src/chaos/execution/controller_exec.rs | 19 +-- src/chaos/execution/executor_variants.rs | 3 +- src/chaos/fractal/descriptions.rs | 41 +++--- src/chaos/fractal/fractal_conf.rs | 127 ++++++++++++------ src/chaos/fractal/fractal_generator.rs | 101 +++++++++++--- src/chaos/fractal/julia.rs | 30 +++++ src/chaos/fractal/mandelbrot.rs | 34 +++++ src/chaos/fractal/simple_variants.rs | 33 +---- .../functions/chaotic_function_configs.rs | 17 +-- src/chaos/functions/discrete_maps.rs | 47 +++++++ .../execute_chaotic_function_view.rs | 20 +-- 13 files changed, 335 insertions(+), 143 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f458109..6f0a690 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -607,6 +607,7 @@ dependencies = [ [[package]] name = "egui-plotter" version = "0.3.0" +source = "git+https://github.com/Gip-Gip/egui-plotter.git?branch=main#00888c032a2121c568c4174f898ed8402cc0e96e" dependencies = [ "egui", "plotters", diff --git a/README.md b/README.md index a346a2e..699e360 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ Special thanks to the following Rust crates that made this project possible: I would like to express my gratitude to the following authors and sources for providing the mathematical foundations of the chaotic discrete maps, systems of ordinary differential equations, and fractal set generators that power this project. Their work has been instrumental in creating this interactive exploration tool for chaos theory. All references can also be found in the **Info** tooltips of the GUI. ### Discrete Maps -- Paul Bourke for the **De Jong Ring** and **Clifford** attractors, which are two-dimensional chaotic maps that produce complex and beautiful patterns. [Website](https://paulbourke.net/fractals/) +- Paul Bourke for the **Reverse Probability**, **De Jong Ring** and **Clifford** attractors, which are two-dimensional chaotic maps that produce complex and beautiful patterns. [Website](https://paulbourke.net/fractals/) - Shah et al. for a **three-dimensional** chaotic map that has applications in digital audio security. [Publication](https://doi.org/10.1007/s11042-021-10697-3) - Huang et al. for a *three-dimensional discrete **memristive** chaotic system that has infinite wide parameter range and coexisting attractors*. [Publication](http://dx.doi.org/10.21203/rs.3.rs-1109068/v1) - Hamadneh et al. for a **four-dimensional** *fractional chaotic map with constant and variable order*. [Publication](https://doi.org/10.3390/math11204332) @@ -106,9 +106,10 @@ I would like to express my gratitude to the following authors and sources for pr - Wang, Feng and Chen for a new **four-dimensional** chaotic system. [Publication](https://doi.org/10.3389/fphy.2022.906138) ### Fractal Configurations and Algorithms -- Paul Bourke for the probability, sinus, sinh, and zubieta Julia set generators, which are complex functions that produce fractal patterns based on the initial conditions. [Website](https://paulbourke.net/fractals/) +- Paul Bourke for the sinus, sinh, and zubieta Julia set generators, which are complex functions that produce fractal patterns based on the initial conditions. [Website](https://paulbourke.net/fractals/) - Gdawiec, Fariello and Santos for Algorithm 1 in *On the **quaternion** Julia sets via Picard–Mann iteration*. [Paper](https://doi.org/10.1007/s11071-023-08785-0) - Kumari et al. for Algorithm 3 in *A novel approach to generate Mandelbrot sets, Julia sets and **biomorphs** via viscosity approximation method*. [Paper](https://doi.org/10.1016/j.chaos.2022.112540) - Bankers et al. for their work *Julia and Mandelbrot Sets for Dynamics over the Hyperbolic Numbers*, which motivated me to include **Perplex** numbers in this project. Perplex (also known as hyperbolic) numbers are a variation of complex numbers that encode geometric properties of the Minkowski space. [Paper](https://doi.org/10.3390/fractalfract3010006) +- Prajapati et al. for *A Brief Study on Julia Sets in the Dynamics of Entire Transcendental Function Using Mann Iterative Scheme*, which inspired me to include a fractal generator with an **exponential** term. See my crate [perplex_num](https://github.com/tomtuamnuq/perplex_num) for additional information. \ No newline at end of file diff --git a/src/chaos/execution/controller_exec.rs b/src/chaos/execution/controller_exec.rs index 3522a65..c92d5a8 100644 --- a/src/chaos/execution/controller_exec.rs +++ b/src/chaos/execution/controller_exec.rs @@ -38,7 +38,8 @@ macro_rules! try_init_from_chaos_data { Gingerbreadman, KaplanYorke, Rulkov, - Zaslavskii + Zaslavskii, + ReverseProbability ], [Brusselator, VanDerPol, QuadrupTwoOrbit] ); @@ -87,14 +88,14 @@ macro_rules! try_init_from_chaos_data { initial_chaos_data, [ MandelbrotPowerComplex, - MandelbrotProbabilityComplex, + MandelbrotTranscendentalComplex, MandelbrotSinusComplex, MandelbrotSinhComplex, MandelbrotZubietaComplex, MandelbrotPicardComplex, MandelbrotBiomorphComplex, JuliaPowerComplex, - JuliaProbabilityComplex, + JuliaTranscendentalComplex, JuliaSinusComplex, JuliaSinhComplex, JuliaZubietaComplex, @@ -111,14 +112,14 @@ macro_rules! try_init_from_chaos_data { initial_chaos_data, [ MandelbrotPowerDual, - MandelbrotProbabilityDual, + MandelbrotTranscendentalDual, MandelbrotSinusDual, MandelbrotSinhDual, MandelbrotZubietaDual, MandelbrotPicardDual, MandelbrotBiomorphDual, JuliaPowerDual, - JuliaProbabilityDual, + JuliaTranscendentalDual, JuliaSinusDual, JuliaSinhDual, JuliaZubietaDual, @@ -135,14 +136,14 @@ macro_rules! try_init_from_chaos_data { initial_chaos_data, [ MandelbrotPowerPerplex, - MandelbrotProbabilityPerplex, + MandelbrotTranscendentalPerplex, MandelbrotSinusPerplex, MandelbrotSinhPerplex, MandelbrotZubietaPerplex, MandelbrotPicardPerplex, MandelbrotBiomorphPerplex, JuliaPowerPerplex, - JuliaProbabilityPerplex, + JuliaTranscendentalPerplex, JuliaSinusPerplex, JuliaSinhPerplex, JuliaZubietaPerplex, @@ -159,14 +160,14 @@ macro_rules! try_init_from_chaos_data { initial_chaos_data, [ MandelbrotPowerQuaternion, - MandelbrotProbabilityQuaternion, + MandelbrotTranscendentalQuaternion, MandelbrotSinusQuaternion, MandelbrotSinhQuaternion, MandelbrotZubietaQuaternion, MandelbrotPicardQuaternion, MandelbrotBiomorphQuaternion, JuliaPowerQuaternion, - JuliaProbabilityQuaternion, + JuliaTranscendentalQuaternion, JuliaSinusQuaternion, JuliaSinhQuaternion, JuliaZubietaQuaternion, diff --git a/src/chaos/execution/executor_variants.rs b/src/chaos/execution/executor_variants.rs index d4ab4cc..2f98d88 100644 --- a/src/chaos/execution/executor_variants.rs +++ b/src/chaos/execution/executor_variants.rs @@ -138,11 +138,12 @@ create_and_implement_executor_variants! { KaplanYorke 2, Rulkov 2, Zaslavskii 2, + ReverseProbability 2, Shah 3, Memristive 3, Sfsimm 4 ] - [Power, Probability, Sinus, Sinh, Zubieta, Picard, Biomorph] + [Power, Transcendental, Sinus, Sinh, Zubieta, Picard, Biomorph] [ Brusselator 2, VanDerPol 2, diff --git a/src/chaos/fractal/descriptions.rs b/src/chaos/fractal/descriptions.rs index 7fde7ae..5ddad2e 100644 --- a/src/chaos/fractal/descriptions.rs +++ b/src/chaos/fractal/descriptions.rs @@ -35,6 +35,7 @@ impl PrettyPrintElem for Quaternion { macro_rules! implement_description { ($($elem:ident ),*)=> { const LABEL_ITER_ESCAPE_COLOR: &str = "Iteration criteria: num iter < 255"; + const LABEL_ITER_ESCAPE_TRANS: &str = "Iteration criteria: num iter < 50"; const LABEL_ITER_ESCAPE_PICARD: &str = "Iteration criteria: num iter < 30"; const LABEL_ITER_ESCAPE_BIOMORPH: &str = "Iteration criteria: num iter < 10"; paste!{ @@ -76,45 +77,45 @@ macro_rules! implement_description { } } - impl ChaosDescription for [] { + impl ChaosDescription for [] { fn description(&self) -> String{ - format!("Adjusted probability reverse Julia adaptation for a Mandelbrot set. Inspired by Roger Bagula and Paul Bourke. Chosen is n={} and a={:.2}", self.power_n(), self.par_a()) + format!("Entire transcendental function adaptation for a Mandelbrot set. Chosen is n={} a={:.2} and b={:.2} ", self.power_n(), self.par_a(), self.par_b()) } fn reference(&self) -> &'static str{ - "https://paulbourke.net/fractals/reversejulia/" + "https://www.mdpi.com/2504-3110/6/7/397" } } - impl ChaosFormula for []{ + impl ChaosFormula for []{ fn formula(&self) -> &[&'static str]{ &[ - "p= Uniform(0, 1)", - "s= 1 if p > a else -1", - "z re= s (||z - z0||)^(1/n) cos(arg(z)/2)", - "z im= s (||z - z0||)^(1/n) sin(arg(z)/2)", + "q= a exp(z^n) + b z + z0", + "z= α q + (1 - α) z", "z0 from initial distribution", - "Bounding criteria: |z| < r", - LABEL_ITER_ESCAPE_COLOR + "R_1= max(|z0|, (|b| + 2 / α)^(1 / (n - 1) )", + "R_2= (|a| Re(z0^n))^(1 / n)", + "Bounding criteria: |z| < R_1 & R_2 < |z|", + LABEL_ITER_ESCAPE_TRANS ] } } - impl ChaosDescription for [] { + impl ChaosDescription for [] { fn description(&self) -> String{ - format!("Adjusted probability reverse Julia by Roger Bagula and Paul Bourke. Chosen is n={}, a={:.2} and c={}", self.power_n(), self.par_a(), self.c().pretty_print()) + format!("Transcendental function using mann iterative scheme. See the paper 'A Brief Study on Julia Sets in the Dynamics of Entire Transcendental Function Using Mann Iterative Scheme' by Prajapati et al. Chosen is n={}, a={:.2} b={:.2} and c={}", self.power_n(), self.par_a(), self.par_b(), self.c().pretty_print()) } fn reference(&self) -> &'static str{ - "https://paulbourke.net/fractals/reversejulia/" + "https://www.mdpi.com/2504-3110/6/7/397" } } - impl ChaosFormula for []{ + impl ChaosFormula for []{ fn formula(&self) -> &[&'static str]{ &[ - "p= Uniform(0, 1)", - "s= 1 if p > a else -1", - "z re= s (||z - c||)^(1/n) cos(arg(z)/2)", - "z im= s (||z - c||)^(1/n) sin(arg(z)/2)", + "q= a exp(z^n) + b z + c", + "z= α q + (1 - α) z", "z0 from initial distribution", - "Bounding criteria: |z| < r", - LABEL_ITER_ESCAPE_COLOR + "R_1= max(|c|, (|b| + 2 / α)^(1 / (n - 1) )", + "R_2= (|a| Re(z0^n))^(1 / n)", + "Bounding criteria: |z| < R_1 & R_2 < |z|", + LABEL_ITER_ESCAPE_TRANS ] } } diff --git a/src/chaos/fractal/fractal_conf.rs b/src/chaos/fractal/fractal_conf.rs index cde94af..11353ad 100644 --- a/src/chaos/fractal/fractal_conf.rs +++ b/src/chaos/fractal/fractal_conf.rs @@ -9,6 +9,7 @@ const DEFAULT_MANDELBROT_R: ChaosFloat = 2.0; const DEFAULT_BIOMORPH_R: ChaosFloat = 10.0; const DEFAULT_ITERATIONS_COLOR: usize = 255; pub const DEFAULT_ITERATIONS_PICARD: usize = 30; +pub const DEFAULT_ITERATIONS_TRANSCENDENTAL: usize = 50; const DEFAULT_ITERATIONS_BIOMORPH: usize = 10; pub trait EscapeConf { fn max_iterations(&self) -> usize; @@ -36,13 +37,11 @@ macro_rules! implement_escape_conf { implement_escape_conf! { MandelbrotPower DEFAULT_ITERATIONS_COLOR, [Complex, Dual, Perplex, Quaternion], - MandelbrotProbability DEFAULT_ITERATIONS_COLOR, [Complex, Dual, Perplex, Quaternion], MandelbrotSinus DEFAULT_ITERATIONS_COLOR, [Complex, Dual, Perplex, Quaternion], MandelbrotSinh DEFAULT_ITERATIONS_COLOR, [Complex, Dual, Perplex, Quaternion], MandelbrotZubieta DEFAULT_ITERATIONS_COLOR, [Complex, Dual, Perplex, Quaternion], MandelbrotBiomorph DEFAULT_ITERATIONS_BIOMORPH, [Complex, Dual, Perplex, Quaternion], JuliaPower DEFAULT_ITERATIONS_COLOR, [Complex, Dual, Perplex, Quaternion], - JuliaProbability DEFAULT_ITERATIONS_COLOR, [Complex, Dual, Perplex, Quaternion], JuliaSinus DEFAULT_ITERATIONS_COLOR, [Complex, Dual, Perplex, Quaternion], JuliaSinh DEFAULT_ITERATIONS_COLOR, [Complex, Dual, Perplex, Quaternion], JuliaZubieta DEFAULT_ITERATIONS_COLOR, [Complex, Dual, Perplex, Quaternion], @@ -106,9 +105,7 @@ macro_rules! implement_simple_conf_with_a { } implement_simple_conf_with_a! { - MandelbrotProbability [Complex, Dual, Perplex, Quaternion], MandelbrotPicard [Complex, Dual, Perplex, Quaternion], - JuliaProbability [Complex, Dual, Perplex, Quaternion], JuliaPicard [Complex, Dual, Perplex, Quaternion] } @@ -152,7 +149,7 @@ macro_rules! implement_simple_julia_conf { } implement_simple_julia_conf! { - Power, Probability, Sinus, Sinh, Zubieta, Picard, Biomorph + Power, Transcendental, Sinus, Sinh, Zubieta, Picard, Biomorph } pub trait MannConf { @@ -178,8 +175,10 @@ macro_rules! implement_mann_conf { implement_mann_conf! { MandelbrotPicard [Complex, Dual, Perplex, Quaternion], MandelbrotBiomorph [Complex, Dual, Perplex, Quaternion], + MandelbrotTranscendental [Complex, Dual, Perplex, Quaternion], JuliaPicard [Complex, Dual, Perplex, Quaternion], - JuliaBiomorph [Complex, Dual, Perplex, Quaternion] + JuliaBiomorph [Complex, Dual, Perplex, Quaternion], + JuliaTranscendental [Complex, Dual, Perplex, Quaternion] } pub trait ViscosityConf { @@ -377,6 +376,39 @@ impl ViscosityConf for JuliaBiomorphQuaternion { } } +pub trait TransConf { + fn power_n(&self) -> i32; + fn par_a(&self) -> ChaosFloat; + fn par_b(&self) -> ChaosFloat; +} +macro_rules! implement_trans_conf { + ($($variant:ident [ $($elem:ident),* ] ),*)=> { + $( + paste!{ + $( + impl TransConf for [<$variant $elem>] { + fn power_n(&self) -> i32 { + self.n.round() as i32 + } + fn par_a(&self) -> ChaosFloat{ + self.a + } + fn par_b(&self) -> ChaosFloat{ + self.b + } + } + )* + } + + )* + }; +} + +implement_trans_conf! { + MandelbrotTranscendental [Complex, Dual, Perplex, Quaternion], + JuliaTranscendental [Complex, Dual, Perplex, Quaternion] +} + impl Default for MandelbrotPowerComplex { fn default() -> Self { Self { @@ -406,38 +438,43 @@ impl Default for MandelbrotPowerQuaternion { } } -impl Default for MandelbrotProbabilityComplex { +impl Default for MandelbrotTranscendentalComplex { fn default() -> Self { Self { - a: 0.99, - r: 1.0, - n: 2.0, + alpha: 0.25, + a: 1.0, + b: -0.5, + n: 3.0, } } } -impl Default for MandelbrotProbabilityDual { +impl Default for MandelbrotTranscendentalDual { fn default() -> Self { Self { - a: 0.99, - r: 1.0, - n: 2.0, + alpha: 0.3, + a: 0.1, + b: -0.1, + n: 3.0, } } } -impl Default for MandelbrotProbabilityPerplex { +impl Default for MandelbrotTranscendentalPerplex { fn default() -> Self { Self { - a: 0.25, - r: 0.75, + alpha: 0.1, + a: 0.2, + b: -1.0, n: 2.0, } } } -impl Default for MandelbrotProbabilityQuaternion { +impl Default for MandelbrotTranscendentalQuaternion { + // Table 2 - test Area -2 to 2 fn default() -> Self { Self { - a: 0.99, - r: 1.0, + alpha: 0.3, + a: 3.0, + b: -0.00000001, n: 2.0, } } @@ -582,49 +619,53 @@ impl Default for JuliaPowerQuaternion { } } -impl Default for JuliaProbabilityComplex { +impl Default for JuliaTranscendentalComplex { fn default() -> Self { Self { - c_re: -0.75, - c_im: 0.1, - a: 0.99, - r: 1.0, + c_re: 2.0, + c_im: 0.0, + alpha: 0.2, + a: 2.0, + b: -1.0, n: 2.0, } } } -impl Default for JuliaProbabilityDual { +impl Default for JuliaTranscendentalDual { fn default() -> Self { Self { - c_re: -0.75, - c_im: 0.1, - a: 0.99, - r: 1.0, + c_re: 1.0, + c_im: 0.0, + alpha: 0.0487654321, + a: 0.1, + b: -0.1, n: 2.0, } } } -impl Default for JuliaProbabilityPerplex { +impl Default for JuliaTranscendentalPerplex { fn default() -> Self { Self { - c_re: -0.75, + c_re: 0.5, c_im: 0.0, - a: 0.99, - r: 2.0, - n: -2.0, + alpha: 0.1, + a: 0.1, + b: 1.0, + n: 2.0, } } } -impl Default for JuliaProbabilityQuaternion { +impl Default for JuliaTranscendentalQuaternion { fn default() -> Self { Self { - c_w: -0.75, - c_i: 0.1, - c_j: 0.1, - c_k: 0.1, - a: 0.99, - r: 1.0, - n: 2.0, + c_w: 1.0, + c_i: 1.0, + c_j: 0.0, + c_k: 0.0, + alpha: 0.0487654321, + a: 2.0, + b: -1.0, + n: 3.0, } } } diff --git a/src/chaos/fractal/fractal_generator.rs b/src/chaos/fractal/fractal_generator.rs index 7ee21c0..afb1e75 100644 --- a/src/chaos/fractal/fractal_generator.rs +++ b/src/chaos/fractal/fractal_generator.rs @@ -26,7 +26,6 @@ pub trait AlgebraElement { fn norm(&self) -> ChaosFloat; fn zero_element() -> Self; fn large_element() -> Self; - fn with_xy(&self, x: ChaosFloat, y: ChaosFloat) -> Self; fn real_norm(&self) -> ChaosFloat; fn imaginary_norm(&self) -> ChaosFloat; } @@ -87,9 +86,6 @@ impl AlgebraElement for Complex { fn large_element() -> Self { Self::new(ChaosFloat::MAX, 0.0) } - fn with_xy(&self, x: ChaosFloat, y: ChaosFloat) -> Self { - Self::new(x, y) - } fn real_norm(&self) -> ChaosFloat { self.re.abs() } @@ -144,9 +140,6 @@ impl AlgebraElement for Perplex { fn large_element() -> Self { Self::new(ChaosFloat::MAX, 0.0) } - fn with_xy(&self, x: ChaosFloat, y: ChaosFloat) -> Self { - Self::new(x, y) - } fn real_norm(&self) -> ChaosFloat { self.t.abs() } @@ -212,9 +205,6 @@ impl AlgebraElement for Dual { fn large_element() -> Self { Self::new(ChaosFloat::MAX, 0.0) } - fn with_xy(&self, x: ChaosFloat, y: ChaosFloat) -> Self { - Self::new(x, y) - } fn real_norm(&self) -> ChaosFloat { self.re.abs() } @@ -277,9 +267,6 @@ impl AlgebraElement for Quaternion { fn large_element() -> Self { Self::new(ChaosFloat::MAX, 0.0, 0.0, 0.0) } - fn with_xy(&self, x: ChaosFloat, y: ChaosFloat) -> Self { - Self::new(x, y, self.j, self.k) - } fn real_norm(&self) -> ChaosFloat { self.w.abs() } @@ -367,9 +354,6 @@ impl Picard { alpha: params.alpha(), } } -} - -impl Picard { pub fn alpha_k_max(params: &P) -> ChaosFloat { let (alpha, k) = (params.alpha(), params.power_n()); if k < 2 { @@ -416,9 +400,6 @@ impl Biomorph { escape, } } -} - -impl Biomorph { pub fn next_z_n(&self, z: &E, r: &E) -> E { if let Some(z_pow) = z.power(self.power_n) { let g_z = self.a.mul(z).add(&self.b); @@ -439,3 +420,85 @@ impl Biomorph { } } } + +#[derive(Clone, Debug)] +pub struct Transcendental { + a: ChaosFloat, + b: ChaosFloat, + power_n: i32, + alpha: ChaosFloat, + alpha_b_max: ChaosFloat, +} + +impl Transcendental { + pub fn new(params: P) -> Self { + Self { + a: params.par_a(), + b: params.par_b(), + power_n: params.power_n(), + alpha: params.alpha(), + alpha_b_max: Self::alpha_b_max(¶ms), + } + } + pub fn alpha_b_max(params: &P) -> ChaosFloat { + let (alpha, n) = (params.alpha(), params.power_n()); + if n < 2 { + 0.0 + } else { + let n = n as ChaosFloat; + let b = params.par_b().abs(); + (b + 2.0 / alpha).powf(1.0 / (n - 1.0)) + } + } + fn q_c(&self, z: &E, c: &E) -> E { + match z.power(self.power_n) { + Some(z_pow) => z_pow + .exponential() + .scale(self.a) + .add(&z.scale(self.b)) + .add(c), + None => E::large_element(), + } + } + pub fn is_set_element(&self, c: &E, fractal: &mut FractalData) -> bool { + let n = fractal.num_iterations(); + match n.cmp(&DEFAULT_ITERATIONS_TRANSCENDENTAL) { + Ordering::Less => { + let is_set_element = { + let z_norm = fractal.z_n().norm(); + let r_1 = c.norm().max(self.alpha_b_max); + if r_1 < z_norm { + false + } else { + let power_1_n = if self.power_n == 0 { + 1.0 + } else { + 1.0 / (self.power_n as f64) + }; + match fractal.z_0().power(self.power_n) { + Some(z_pow) => { + let r_2 = (self.a.abs() * z_pow.real()).powf(power_1_n); + r_2 < z_norm + } + None => false, + } + } + }; + + if !is_set_element && n == 0 { + fractal.set_first() + } + is_set_element + } + Ordering::Equal => { + fractal.set_last(); + false + } + Ordering::Greater => false, + } + } + pub fn next_z_n(&self, z: &E, c: &E) -> E { + let q_z = self.q_c(z, c); + q_z.scale(self.alpha).add(&z.scale(1.0 - self.alpha)) + } +} diff --git a/src/chaos/fractal/julia.rs b/src/chaos/fractal/julia.rs index 045025c..e75298f 100644 --- a/src/chaos/fractal/julia.rs +++ b/src/chaos/fractal/julia.rs @@ -111,6 +111,36 @@ impl DiscreteMap for JuliaBiomorph { } } +#[derive(Clone, Debug)] +pub struct JuliaTranscendental { + c: E, + trans: Transcendental, +} + +impl JuliaTranscendental { + pub fn new + MannConf + TransConf>(params: P) -> Self { + let c = params.c(); + let trans = Transcendental::new(params); + Self { c, trans } + } +} + +impl FractalGenerator for JuliaTranscendental { + type Element = E; + fn is_set_element(&self, fractal: &mut FractalData) -> bool { + self.trans.is_set_element(&self.c, fractal) + } + fn next_z_n(&self, fractal: &FractalData) -> Self::Element { + self.trans.next_z_n(fractal.z_n(), &self.c) + } +} + +impl DiscreteMap for JuliaTranscendental { + type State = FractalData; + fn execute(&self, v: &mut FractalData, t: &Time) { + self.iteration(v, t) + } +} #[cfg(test)] mod tests { use super::*; diff --git a/src/chaos/fractal/mandelbrot.rs b/src/chaos/fractal/mandelbrot.rs index 281ace8..20479bd 100644 --- a/src/chaos/fractal/mandelbrot.rs +++ b/src/chaos/fractal/mandelbrot.rs @@ -113,6 +113,40 @@ impl DiscreteMap for MandelbrotBiomorph { } } +#[derive(Clone, Debug)] +pub struct MandelbrotTranscendental { + trans: Transcendental, + algebra_element_type: PhantomData, +} + +impl MandelbrotTranscendental { + pub fn new(params: P) -> Self { + let trans = Transcendental::new(params); + Self { + trans, + algebra_element_type: PhantomData, + } + } +} + +impl FractalGenerator for MandelbrotTranscendental { + type Element = E; + fn is_set_element(&self, fractal: &mut FractalData) -> bool { + let z_0 = fractal.z_0().clone(); + self.trans.is_set_element(&z_0, fractal) + } + fn next_z_n(&self, fractal: &FractalData) -> Self::Element { + self.trans.next_z_n(fractal.z_n(), fractal.z_0()) + } +} + +impl DiscreteMap for MandelbrotTranscendental { + type State = FractalData; + fn execute(&self, v: &mut FractalData, t: &Time) { + self.iteration(v, t) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/chaos/fractal/simple_variants.rs b/src/chaos/fractal/simple_variants.rs index 8200cae..9c38a74 100644 --- a/src/chaos/fractal/simple_variants.rs +++ b/src/chaos/fractal/simple_variants.rs @@ -3,11 +3,9 @@ use super::fractal_data::*; use super::fractal_generator::*; use super::julia::JuliaSimple; use super::mandelbrot::MandelbrotSimple; -use crate::chaos::data::ChaosFloat; use crate::chaos::data::Time; use crate::chaos::functions::DiscreteMap; use paste::paste; -use rand_distr::Distribution; #[derive(Clone, Debug)] pub struct SimplePower { @@ -28,35 +26,6 @@ impl SimpleFractalFn for SimplePower { } } -#[derive(Clone, Debug)] -pub struct SimpleProbability { - r_gen: rand_distr::Uniform, - r_threshold: ChaosFloat, - power_1_n: ChaosFloat, -} - -impl SimpleFractalFn for SimpleProbability { - fn new(conf: C) -> Self { - let r_gen = rand_distr::Uniform::new(0.0, 1.0); - Self { - r_gen, - r_threshold: conf.par_a(), - power_1_n: 1.0 / (conf.power_n() as ChaosFloat), - } - } - fn next_z_n(&self, z: &E, c: &E) -> E { - // https://paulbourke.net/fractals/reversejulia/ - let mut rng = rand::thread_rng(); - let r = self.r_gen.sample(&mut rng); - let s = if r <= self.r_threshold { -1.0 } else { 1.0 }; - let scalar = s * z.sub(c).norm().powf(self.power_1_n); - let sigma = z.arg() / 2.0; - let re = scalar * sigma.cos(); - let im = scalar * sigma.sin(); - z.with_xy(re, im) - } -} - #[derive(Clone, Debug)] pub struct SimpleSinus { power_n: i32, @@ -161,4 +130,4 @@ macro_rules! generate_simple_variants { }; } -generate_simple_variants! {Power, Probability, Sinus, Sinh, Zubieta} +generate_simple_variants! {Power, Sinus, Sinh, Zubieta} diff --git a/src/chaos/functions/chaotic_function_configs.rs b/src/chaos/functions/chaotic_function_configs.rs index ef295de..cd57919 100644 --- a/src/chaos/functions/chaotic_function_configs.rs +++ b/src/chaos/functions/chaotic_function_configs.rs @@ -54,60 +54,61 @@ generate_chaotic_function_configs! { KaplanYorke no_check { alpha: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, Rulkov no_check { alpha: (0.0, 10.0), mu: (0.0, 0.1), delta: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, Zaslavskii check_zaslavskii { eps: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), nu: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), mu: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, + ReverseProbability no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r_threshold: (0.0, 1.0) }, Shah no_check { alpha: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), beta: (-10.0, 10.0), gamma: (-1.0, 1.0), delta: (-1.0, 1.0) }, Memristive no_check { k: (-10.0, 10.0), a: (-10.0, 10.0) }, Sfsimm no_check { p: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b: (0.0, 2.0*PI), r: (0.0, 2.0*PI) }, MandelbrotPowerComplex no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, - MandelbrotProbabilityComplex no_check { a: (0.0, 1.0), r: (0.0, 2.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, + MandelbrotTranscendentalComplex no_check { a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotSinusComplex no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotSinhComplex no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotZubietaComplex no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotPicardComplex no_check {a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotBiomorphComplex check_mandelbrotbiomorph_complex {r: (0.0, ChaosFloat::INFINITY), m_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a_re: (-1.0, 1.0), a_im: (-1.0, 1.0), b_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaPowerComplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, - JuliaProbabilityComplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a: (0.0, 1.0), r: (0.0, 2.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, + JuliaTranscendentalComplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaSinusComplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaSinhComplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaZubietaComplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaPicardComplex no_check {a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaBiomorphComplex check_juliabiomorph_complex {r: (0.0, ChaosFloat::INFINITY), c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a_re: (-1.0, 1.0), a_im: (-1.0, 1.0), b_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotPowerDual no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, - MandelbrotProbabilityDual no_check { a: (0.0, 1.0), r: (0.0, 2.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, + MandelbrotTranscendentalDual no_check { a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotSinusDual no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotSinhDual no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotZubietaDual no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotPicardDual no_check {a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotBiomorphDual check_mandelbrotbiomorph_dual {r: (0.0, ChaosFloat::INFINITY), m_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a_re: (-1.0, 1.0), a_im: (-1.0, 1.0), b_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaPowerDual no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, - JuliaProbabilityDual no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a: (0.0, 1.0), r: (0.0, 2.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, + JuliaTranscendentalDual no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaSinusDual no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaSinhDual no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaZubietaDual no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaPicardDual no_check {a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaBiomorphDual check_juliabiomorph_dual {r: (0.0, ChaosFloat::INFINITY), c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a_re: (-1.0, 1.0), a_im: (-1.0, 1.0), b_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotPowerPerplex no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, - MandelbrotProbabilityPerplex no_check { a: (0.0, 1.0), r: (0.0, 2.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, + MandelbrotTranscendentalPerplex no_check { a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotSinusPerplex no_check { r: (0.0, 20.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotSinhPerplex no_check { r: (0.0, 20.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotZubietaPerplex no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotPicardPerplex no_check {a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotBiomorphPerplex check_mandelbrotbiomorph_perplex {r: (0.0, ChaosFloat::INFINITY), m_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a_re: (-1.0, 1.0), a_im: (-1.0, 1.0), b_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaPowerPerplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, - JuliaProbabilityPerplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a: (0.0, 1.0), r: (0.0, 2.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, + JuliaTranscendentalPerplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaSinusPerplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, 20.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaSinhPerplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, 20.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaZubietaPerplex no_check { c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaPicardPerplex no_check {a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaBiomorphPerplex check_juliabiomorph_perplex {r: (0.0, ChaosFloat::INFINITY), c_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a_re: (-1.0, 1.0), a_im: (-1.0, 1.0), b_re: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b_im: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotPowerQuaternion no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, - MandelbrotProbabilityQuaternion no_check { a: (0.0, 1.0), r: (0.0, 2.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, + MandelbrotTranscendentalQuaternion no_check { a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotSinusQuaternion no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotSinhQuaternion no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotZubietaQuaternion no_check { r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotPicardQuaternion no_check {a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, MandelbrotBiomorphQuaternion check_mandelbrotbiomorph_quaternion {r: (0.0, ChaosFloat::INFINITY), m_w: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_i: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_j: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), m_k: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a_w: (-1.0, 1.0), a_i: (-1.0, 1.0), a_j: (-1.0, 1.0), a_k: (-1.0, 1.0), b_w: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b_i: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b_j: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b_k: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaPowerQuaternion no_check { c_w: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_i: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_j: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_k: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, - JuliaProbabilityQuaternion no_check { c_w: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_i: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_j: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_k: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a: (0.0, 1.0), r: (0.0, 2.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, + JuliaTranscendentalQuaternion no_check { c_w: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_i: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_j: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_k: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), a: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), b: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), alpha: (0.0, 1.0), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaSinusQuaternion no_check { c_w: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_i: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_j: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_k: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaSinhQuaternion no_check { c_w: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_i: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_j: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_k: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, JuliaZubietaQuaternion no_check { c_w: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_i: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_j: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), c_k: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY), r: (0.0, ChaosFloat::INFINITY), n: (ChaosFloat::NEG_INFINITY, ChaosFloat::INFINITY) }, diff --git a/src/chaos/functions/discrete_maps.rs b/src/chaos/functions/discrete_maps.rs index 669a67a..0a1ea0f 100644 --- a/src/chaos/functions/discrete_maps.rs +++ b/src/chaos/functions/discrete_maps.rs @@ -1,6 +1,7 @@ use super::chaotic_function_configs::*; use crate::chaos::data::*; use crate::chaos::labels::{ChaosDescription, ChaosFormula}; +use rand_distr::Distribution; use std::f64::consts::PI; pub trait DiscreteMap { type State; @@ -608,6 +609,52 @@ impl ChaosFormula for Zaslavskii { } } +impl DiscreteMap for ReverseProbability { + type State = State2; + fn execute(&self, v: &mut Self::State, _t: &Time) { + let x = v[0]; + let y = v[1]; + let r_gen: rand_distr::Uniform = rand_distr::Uniform::new(0.0, 1.0); + let mut rng = rand::thread_rng(); + let r = r_gen.sample(&mut rng); + let s = if r <= self.r_threshold { -1.0 } else { 1.0 }; + let re = x - self.c_re; + let im = y - self.c_im; + let scalar = s * (re * re + im * im).powf(0.25); + let sigma = y.atan2(x) / 2.0; + v[0] = scalar * sigma.cos(); + v[1] = scalar * sigma.sin(); + } +} +impl Default for ReverseProbability { + fn default() -> Self { + Self { + c_re: -0.745, + c_im: 0.113, + r_threshold: 0.97, + } + } +} + +impl ChaosDescription for ReverseProbability { + fn description(&self) -> String { + format!("Adjusted probability reverse Julia by Roger Bagula and Paul Bourke. Try the trajectory of the start state z=Complex(x=0, y=0). Currently chosen is c=Complex({:.2}, {:.2}) and R={:.2}", self.c_re, self.c_im, self.r_threshold) + } + fn reference(&self) -> &'static str { + "https://paulbourke.net/fractals/reversejulia/" + } +} +impl ChaosFormula for ReverseProbability { + fn formula(&self) -> &[&'static str] { + &[ + "p= Uniform(0, 1)", + "s= 1 if p > R else -1", + "z re= s √(||z - c||) cos(arg(z)/2)", + "z im= s √(||z - c||) sin(arg(z)/2)", + ] + } +} + impl DiscreteMap for Shah { type State = State3; fn execute(&self, v: &mut State3, t: &Time) { diff --git a/src/gui/egui_app/conf_panels/execute_chaotic_function_view.rs b/src/gui/egui_app/conf_panels/execute_chaotic_function_view.rs index 698061f..4072845 100644 --- a/src/gui/egui_app/conf_panels/execute_chaotic_function_view.rs +++ b/src/gui/egui_app/conf_panels/execute_chaotic_function_view.rs @@ -372,11 +372,12 @@ create_and_implement_map_view_variants! { KaplanYorke 2, Rulkov 2, Zaslavskii 2, + ReverseProbability 2, Shah 3, Memristive 3, Sfsimm 4 ] - [Power, Probability, Sinus, Sinh, Zubieta, Picard, Biomorph] + [Power, Transcendental, Sinus, Sinh, Zubieta, Picard, Biomorph] [ Brusselator 2, VanDerPol 2, @@ -521,60 +522,61 @@ impl_discrete_variants! { KaplanYorke, SimpleDiscreteMap, { [alpha, "α"] }, Rulkov, SimpleDiscreteMap, { [alpha, "α"], [mu, "μ"], [delta, "δ"] }, Zaslavskii, SimpleDiscreteMap, { [eps, "ε"], [nu, "ν"], [r, "r"] }, + ReverseProbability, SimpleDiscreteMap, { [c_re, "c real"], [c_im, "c imaginary"], [r_threshold, "R"] }, Shah, SimpleDiscreteMap, { [alpha, "α"], [beta, "β"], [gamma, "γ"], [delta, "δ"] }, Memristive, SimpleDiscreteMap, { [k, "k"], [a, "a"] }, Sfsimm, SimpleDiscreteMap, { [p, "p"], [b, "b"], [r, "r"] }, MandelbrotPowerComplex, MandelbrotPower, { [r, "r"], [n, "n"] }, - MandelbrotProbabilityComplex, MandelbrotProbability, { [a, "a"], [r, "r"], [n, "n"] }, + MandelbrotTranscendentalComplex, MandelbrotTranscendental, { [a, "a"], [b, "b"], [alpha, "α"], [n, "n"] }, MandelbrotSinusComplex, MandelbrotSinus, { [r, "r"], [n, "n"] }, MandelbrotSinhComplex, MandelbrotSinh, { [r, "r"], [n, "n"] }, MandelbrotZubietaComplex, MandelbrotZubieta, { [r, "r"], [n, "n"] }, MandelbrotPicardComplex, MandelbrotPicard, { [a, "a"], [alpha, "α"], [n, "n"] }, MandelbrotBiomorphComplex, MandelbrotBiomorph, { [r, "r"], [m_re, "m re"], [m_im, "m i"], [a_re, "a re"], [a_im, "a i"], [b_re, "b re"], [b_im, "b i"], [alpha, "α"], [n, "n"] }, JuliaPowerComplex, JuliaPower, { [c_re, "c re"], [c_im, "c i"], [r, "r"], [n, "n"] }, - JuliaProbabilityComplex, JuliaProbability, { [c_re, "c re"], [c_im, "c i"], [a, "a"], [r, "r"], [n, "n"] }, + JuliaTranscendentalComplex, JuliaTranscendental, { [c_re, "c re"], [c_im, "c i"], [a, "a"], [b, "b"], [alpha, "α"], [n, "n"] }, JuliaSinusComplex, JuliaSinus, { [c_re, "c re"], [c_im, "c i"], [r, "r"], [n, "n"] }, JuliaSinhComplex, JuliaSinh, { [c_re, "c re"], [c_im, "c i"], [r, "r"], [n, "n"] }, JuliaZubietaComplex, JuliaZubieta, { [c_re, "c re"], [c_im, "c i"], [r, "r"], [n, "n"] }, JuliaPicardComplex, JuliaPicard, { [a, "a"], [c_re, "c re"], [c_im, "c i"], [alpha, "α"], [n, "n"] }, JuliaBiomorphComplex, JuliaBiomorph, { [r, "r"], [c_re, "c re"], [c_im, "c i"], [m_re, "m re"], [m_im, "m i"], [a_re, "a re"], [a_im, "a i"], [b_re, "b re"], [b_im, "b i"], [alpha, "α"], [n, "n"] }, MandelbrotPowerDual, MandelbrotPower, { [r, "r"], [n, "n"] }, - MandelbrotProbabilityDual, MandelbrotProbability, { [a, "a"], [r, "r"], [n, "n"] }, + MandelbrotTranscendentalDual, MandelbrotTranscendental, { [a, "a"], [b, "b"], [alpha, "α"], [n, "n"] }, MandelbrotSinusDual, MandelbrotSinus, { [r, "r"], [n, "n"]}, MandelbrotSinhDual, MandelbrotSinh, { [r, "r"], [n, "n"]}, MandelbrotZubietaDual, MandelbrotZubieta, { [r, "r"], [n, "n"]}, MandelbrotPicardDual, MandelbrotPicard, { [a, "a"], [alpha, "α"], [n, "n"] }, MandelbrotBiomorphDual, MandelbrotBiomorph, { [r, "r"], [m_re, "m re"], [m_im, "m ε"], [a_re, "a re"], [a_im, "a ε"], [b_re, "b re"], [b_im, "b ε"], [alpha, "α"], [n, "n"] }, JuliaPowerDual, JuliaPower, { [c_re, "c re"], [c_im, "c ε"], [r, "r"], [n, "n"] }, - JuliaProbabilityDual, JuliaProbability, { [c_re, "c re"], [c_im, "c ε"], [a, "a"], [r, "r"], [n, "n"] }, + JuliaTranscendentalDual, JuliaTranscendental, { [c_re, "c re"], [c_im, "c ε"], [a, "a"], [b, "b"], [alpha, "α"], [n, "n"] }, JuliaSinusDual, JuliaSinus, { [c_re, "c re"], [c_im, "c ε"], [r, "r"], [n, "n"]}, JuliaSinhDual, JuliaSinh, { [c_re, "c re"], [c_im, "c ε"], [r, "r"], [n, "n"]}, JuliaZubietaDual, JuliaZubieta, { [c_re, "c re"], [c_im, "c ε"], [r, "r"], [n, "n"]}, JuliaPicardDual, JuliaPicard, { [a, "a"], [c_re, "c re"], [c_im, "c ε"], [alpha, "α"], [n, "n"] }, JuliaBiomorphDual, JuliaBiomorph, { [r, "r"], [c_re, "c re"], [c_im, "c ε"], [m_re, "m re"], [m_im, "m ε"], [a_re, "a re"], [a_im, "a ε"], [b_re, "b re"], [b_im, "b ε"], [alpha, "α"], [n, "n"] }, MandelbrotPowerPerplex, MandelbrotPower, { [r, "r"], [n, "n"] }, - MandelbrotProbabilityPerplex, MandelbrotProbability, { [a, "a"], [r, "r"], [n, "n"] }, + MandelbrotTranscendentalPerplex, MandelbrotTranscendental, { [a, "a"], [b, "b"], [alpha, "α"], [n, "n"] }, MandelbrotSinusPerplex, MandelbrotSinus, { [r, "r"], [n, "n"]}, MandelbrotSinhPerplex, MandelbrotSinh, { [r, "r"], [n, "n"]}, MandelbrotZubietaPerplex, MandelbrotZubieta, { [r, "r"], [n, "n"]}, MandelbrotPicardPerplex, MandelbrotPicard, { [a, "a"], [alpha, "α"], [n, "n"] }, MandelbrotBiomorphPerplex, MandelbrotBiomorph, { [r, "r"], [m_re, "m t"], [m_im, "m x"], [a_re, "a t"], [a_im, "a x"], [b_re, "b t"], [b_im, "b x"], [alpha, "α"], [n, "n"] }, JuliaPowerPerplex, JuliaPower, { [c_re, "c t"], [c_im, "c x"], [r, "r"], [n, "n"] }, - JuliaProbabilityPerplex, JuliaProbability, { [c_re, "c t"], [c_im, "c x"], [a, "a"], [r, "r"], [n, "n"] }, + JuliaTranscendentalPerplex, JuliaTranscendental, { [c_re, "c t"], [c_im, "c x"], [a, "a"], [b, "b"], [alpha, "α"], [n, "n"] }, JuliaSinusPerplex, JuliaSinus, { [c_re, "c t"], [c_im, "c x"], [r, "r"], [n, "n"]}, JuliaSinhPerplex, JuliaSinh, { [c_re, "c t"], [c_im, "c x"], [r, "r"], [n, "n"]}, JuliaZubietaPerplex, JuliaZubieta, { [c_re, "c t"], [c_im, "c x"], [r, "r"], [n, "n"]}, JuliaPicardPerplex, JuliaPicard, { [a, "a"], [c_re, "c t"], [c_im, "c x"], [alpha, "α"], [n, "n"] }, JuliaBiomorphPerplex, JuliaBiomorph, { [r, "r"], [c_re, "c t"], [c_im, "c x"], [m_re, "m t"], [m_im, "m x"], [a_re, "a t"], [a_im, "a x"], [b_re, "b t"], [b_im, "b x"], [alpha, "α"], [n, "n"] }, MandelbrotPowerQuaternion, MandelbrotPower, { [r, "r"], [n, "n"] }, - MandelbrotProbabilityQuaternion, MandelbrotProbability, { [a, "a"], [r, "r"], [n, "n"] }, + MandelbrotTranscendentalQuaternion, MandelbrotTranscendental, { [a, "a"], [b, "b"], [alpha, "α"], [n, "n"] }, MandelbrotSinusQuaternion, MandelbrotSinus, { [r, "r"], [n, "n"]}, MandelbrotSinhQuaternion, MandelbrotSinh, { [r, "r"], [n, "n"]}, MandelbrotZubietaQuaternion, MandelbrotZubieta, { [r, "r"], [n, "n"]}, MandelbrotPicardQuaternion, MandelbrotPicard, { [a, "a"], [alpha, "α"], [n, "n"] }, MandelbrotBiomorphQuaternion, MandelbrotBiomorph, { [r, "r"], [m_w, "m w"], [m_i, "m i"], [m_j, "m j"], [m_k, "m k"], [a_w, "a w"], [a_i, "a i"], [a_j, "a j"], [a_k, "a k"], [b_w, "b w"], [b_i, "b i"], [b_j, "b j"], [b_k, "b k"], [alpha, "α"], [n, "n"] }, JuliaPowerQuaternion, JuliaPower, { [c_w, "c w"], [c_i, "c i"], [c_j, "c j"], [c_k, "c k"], [r, "r"], [n, "n"] }, - JuliaProbabilityQuaternion, JuliaProbability, { [c_w, "c w"], [c_i, "c i"], [c_j, "c j"], [c_k, "c k"], [a, "a"], [r, "r"], [n, "n"] }, + JuliaTranscendentalQuaternion, JuliaTranscendental, { [c_w, "c w"], [c_i, "c i"], [c_j, "c j"], [c_k, "c k"], [a, "a"], [b, "b"], [alpha, "α"], [n, "n"] }, JuliaSinusQuaternion, JuliaSinus, { [c_w, "c w"], [c_i, "c i"], [c_j, "c j"], [c_k, "c k"], [r, "r"], [n, "n"]}, JuliaSinhQuaternion, JuliaSinh, { [c_w, "c w"], [c_i, "c i"], [c_j, "c j"], [c_k, "c k"], [r, "r"], [n, "n"]}, JuliaZubietaQuaternion, JuliaZubieta, { [c_w, "c w"], [c_i, "c i"], [c_j, "c j"], [c_k, "c k"], [r, "r"], [n, "n"]},