分形/数学/导数
外观
< 分形
- 变量 z
- 常数参数 c
- 函数 f
- 导数 d
- 迭代次数 p
- wrt = 关于
符号类型[6]
- 莱布尼茨符号
- 欧拉符号
- 牛顿符号(点符号)
- 拉格朗日符号(撇号符号)
The derivative gives you what is called the gradient. For 2D, consider the terrain as a contour map. The gradient tells you the rate of change in x and y directions. The slope is the magnitude of the gradient, and the contours are closer together for higher slope. For 3D the gradient is the rate of change in x, y and z, and the slope is still the magnitude of the gradient. Technically, slope is only 1D, and the gradient also tells you the direction of the slope. When we talk about derivative giving you the slope we are being casual. ( xenodreambuie )[7]
"the derivative basically as it's calculated for anlytical DE using the implementation of the chain rule for the derivative of f(g(x)) where f(x) is say g(x)^p+c and the value of g(x) is current z. So f'(g(x)) is p*z^(p-1) and g'(x) is the derivative from the previous iteration, so on each iteration the new derivative is: dz = dz*p*z^(p-1) and new z = z^p+c as normal" FractalDave[8]
对于Julia 集
// initial values: c is const z = z0 ( z is a variable, read initial value from the pixel) dz = 1 // Recurrence steps: dz = f'(z)*dz // calculating dz and multiply the previous d z = f(z) // forward iteration
对于Mandelbrot 集
// initial values: z = critical point ( critical pointis 0 for multibrot sets, z is variable) c = ( c is a variable, read initial value from the pixel) dc = 0 // Recurrence steps: dc = f'(z)*dc + 1 // calculating dc and multiply the previous dc z = f(z) // forward iteration
可以使用 Maxima CAS 计算
display2d:false; f:1/(z^3+d*z); dz : diff(f,z,1); // first derivative of f wrt variable z dc : diff(f,c,1); // first derivative of f wrt parameter c
关于 z
// function f(z)= 1/(z^3 + c*z ) // first derivativwe wrt z d = f'(z) = -(3z^2 +c)/(z^3 + cz)^2 // iteration: z_(n+1) = f(z_n) // initial values: z = z d = 1 // Recurrence steps: d = - d*(3z^2 +c)/(z^3 + cz)^2 z = 1/(z^3 + c*z)
display2d:false; f: 1/(a*z^5+ z^3 + b*z); dz: diff(f,z,1);
纯文本
dz = -(5*a*z^4+3*z^2+b)/(a*z^5+z^3+b*z)^2
示例
- 1/((0.15*I+0.15)*z^5+(3*I-3)*z + z^3)
f(z):=z^5/(4*z+2)-z^2+c+1 (%i4) diff(f(z), z,1); (%o4) (5*z^4)/(4*z+2)-(4*z^5)/(4*z+2)^2-2*z
次数 | 函数 f(z) | 关于 z 的导数 |
---|---|---|
2 | ||
3 | ||
4 | ||
d |
C 代码用于制作多重分形集的外部 DEM/M 图像:Mandelbrot 集,其中 q 是单临界单项式的阶数
#include <complex.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <omp.h> //OpenM
/*
fork of
mandelbrot-book how to write a book about the Mandelbrot set by Claude Heiland-Alle
https://code.mathr.co.uk/mandelbrot-book/blob/HEAD:/book/
https://stackoverflow.com/questions/77135883/why-do-my-functions-not-work-in-parallel
gcc s.c -lm -Wall -fopenmp
./a.out >ed.ppm // P6 = binary Portable PixMap see en wikipedia: Netpbm#File_formats
*/
const double pi = 3.141592653589793;
/*
int q = 5 ;
complex double f(complex double z, int q){ return cpow(z,q) + c;}
complex double d(complex double z, int q) {return q*cpow(z, q-1); }
*/
complex double f(complex double z, complex double c){ return z*z*z*z*z + c;}
complex double d(complex double z) {return 5*z*z*z*z; }
double cnorm(double _Complex z) // https://stackoverflow.com/questions/6363247/what-is-a-complex-data-type-and-an-imaginary-data-type-in-c
{
return creal(z) * creal(z) + cimag(z) * cimag(z);
}
void hsv2rgb(double h, double s, double v, int *red, int *grn, int *blu) {
double i, f, p, q, t, r, g, b;
int ii;
if (s == 0.0) { r = g = b = v; } else {
h = 6 * (h - floor(h));
ii = i = floor(h);
f = h - i;
p = v * (1 - s);
q = v * (1 - (s * f));
t = v * (1 - (s * (1 - f)));
switch(ii) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
default:r = v; g = p; b = q; break;
}
}
*red = fmin(fmax(255 * r + 0.5, 0), 255);
*grn = fmin(fmax(255 * g + 0.5, 0), 255);
*blu = fmin(fmax(255 * b + 0.5, 0), 255);
}
int main()
{
const int aa = 4;
const int w = 800 * aa;
const int h = 800 * aa;
const int n = 1024;
const double r = 2;
const double px = r / (h/2);
const double r2 = 25 * 25;
unsigned char *img = malloc(3 * w * h);
#pragma omp parallel for schedule(dynamic)
for (int j = 0; j < h; ++j)
{
double _Complex c;
double _Complex z;
double _Complex dc;
double y = (h/2 - (j + 0.5)) / (h/2) * r;
for (int i = 0; i < w; ++i)
{
double x = (i + 0.5 - w/2) / (h/2) * r; // for q=2 add -0.5
c = x + I * y;
//double _Complex
dc = 0; // first derivative of zn with respect to c
//double _Complex z = 0;
z = 0;
int k;
for (k = 0; k < n; ++k)
{
//
dc = d(z)*dc +1;
z = f(z,c);
if (cnorm(z) > r2)
break;
}
// color
double hue = 0, sat = 0, val = 1; // interior color = white
if (k < n)
{ // exterior and boundary color
double _Complex de = 2 * z * log(cabs(z)) / dc;
hue = fmod(1 + carg(de) / (2 * pi), 1); // ? slope of de
sat = 0.25;
val = tanh(cabs(de) / px / aa);
}
// hsv to rgb conversion
int red, grn, blu;
hsv2rgb(hue, sat, val, &red, &grn, &blu);
// save rgb color to array
img[3*(j * w + i)+0] = red;
img[3*(j * w + i)+1] = grn;
img[3*(j * w + i)+2] = blu;
}
}
//
printf("P6\n%d %d\n255\n", w, h);
fwrite(img, 3 * w * h, 1, stdout);
free(img);
return 0;
}
C 代码用于制作 的外部 DEM/J 图像,其中 q 是单临界单项式的阶数
#include <complex.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <omp.h> //OpenM
/*
fork of
mandelbrot-book how to write a book about the Mandelbrot set by Claude Heiland-Alle
https://code.mathr.co.uk/mandelbrot-book/blob/HEAD:/book/
https://stackoverflow.com/questions/77135883/why-do-my-functions-not-work-in-parallel
gcc j.c -lm -Wall -fopenmp
./a.out >ed.ppm // P6 = binary Portable PixMap see en.wikipedia: Netpbm#File_formats
*/
complex double examples [6] = {0, 0, I, -0.0649150006787816892861875745218343125883 +0.76821968591243610206311097043854440463 *I, -0.239026451915233+0.415516996006582*I, 0};
const double pi = 3.141592653589793;
int q = 4 ; // degree of multibrot set
/*
complex double f(complex double z, int q){ return cpow(z,q) + c;}
complex double d(complex double z, int q) {return q*cpow(z, q-1); }
*/
complex double f(complex double z, complex double c){ return z*z*z*z + c;} // multibrot z^q + c
complex double d(complex double z) {return 4*z*z*z; } // q*z^{q-1}
double cnorm(double _Complex z) // https://stackoverflow.com/questions/6363247/what-is-a-complex-data-type-and-an-imaginary-data-type-in-c
{
return creal(z) * creal(z) + cimag(z) * cimag(z);
}
void hsv2rgb(double h, double s, double v, int *red, int *grn, int *blu) {
double i, f, p, q, t, r, g, b;
int ii;
if (s == 0.0) { r = g = b = v; } else {
h = 6 * (h - floor(h));
ii = i = floor(h);
f = h - i;
p = v * (1 - s);
q = v * (1 - (s * f));
t = v * (1 - (s * (1 - f)));
switch(ii) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
default:r = v; g = p; b = q; break;
}
}
*red = fmin(fmax(255 * r + 0.5, 0), 255);
*grn = fmin(fmax(255 * g + 0.5, 0), 255);
*blu = fmin(fmax(255 * b + 0.5, 0), 255);
}
int main()
{
const int aa = 4;
const int w = 800 * aa;
const int h = 800 * aa;
const int n = 1024;
const double r = 2;
const double px = r / (h/2);
const double r2 = 25 * 25;
unsigned char *img = malloc(3 * w * h);
double _Complex c = examples[q];
#pragma omp parallel for schedule(dynamic)
for (int j = 0; j < h; ++j)
{
double y = (h/2 - (j + 0.5)) / (h/2) * r;
for (int i = 0; i < w; ++i)
{
double x = (i + 0.5 - w/2) / (h/2) * r; // for q=2 add -0.5
double _Complex z = x + I * y;
double _Complex dz = 1.0; // first derivative of zn with respect to z
int k;
for (k = 0; k < n; ++k)
{
//
dz = d(z)*dz ;
z = f(z,c);
if (cnorm(z) > r2)
break;
}
// color
double hue = 0, sat = 0, val = 1; // interior color = white
if (k < n)
{ // exterior and boundary color
double _Complex de = 2 * z * log(cabs(z)) / dz;
hue = fmod(1 + carg(de) / (2 * pi), 1); // ? slope of de
sat = 0.25;
val = tanh(cabs(de) / px / aa);
}
// hsv to rgb conversion
int red, grn, blu;
hsv2rgb(hue, sat, val, &red, &grn, &blu);
// save rgb color to array
img[3*(j * w + i)+0] = red;
img[3*(j * w + i)+1] = grn;
img[3*(j * w + i)+2] = blu;
}
}
//
printf("P6\n%d %d\n255\n", w, h);
fwrite(img, 3 * w * h, 1, stdout);
free(img);
return 0;
}
复二次多项式
[edit | edit source]z^2+c
[edit | edit source]对 c 的一阶导数
[edit | edit source]在参数平面上
- 是一个变量
- 是一个常数
然后(在计算下一个 z 之前计算导数,因为它使用 z 的先前值)
这可以通过使用导数的 链式法则 来验证。
- Maxima CAS 函数
dcfn(p, z, c) := if p=0 then 1 else 2*fn(p-1,z,c)*dcfn(p-1, z, c)+1;
示例值
它可用于
是关于 z 的 一阶导数。
然后
描述 | 任意名称 | 公式 | 初始条件 | 递归步骤 | 常用名称 |
---|---|---|---|---|---|
迭代复二次多项式 | z 或 f | ||||
关于 z 的一阶导数 | f' 的 dz,d(来自导数)或 p(来自素数) |
递归关系的推导
以下是导数的应用:
"As we iterate z, we can look at the derivatives of P at z. In our case it is quite simple: P′(z)=2z. Multiplying all these numbers along an orbit yields the derivative at z of the composition Pn. This multiplication can be carried on iteratively as we iterate z " A Cheritat
der = 1 z = c # note that we start with c instead of 0, to avoid multiplying the derivative by 0 for n in range(0,N): new_z = z*z+c new_der = der*2*z z = new_z der = new_der
它可以用于:
- 计算 茱莉亚集的外部距离 (DEM/J)
- 检测曼德布罗特集分量的内部点[9]
unsigned char ComputeColorOfDEMJ(complex double z){
int nMax = IterMax_DEM;
complex double dz = 1.0; // is first derivative with respect to z.
double distance;
double cabsz;
int n;
for (n=0; n < nMax; n++){ //forward iteration
if (cabs2(z)> ER2 || cabs(dz)> 1e60) break; // big values
dz = derivative_wrt_z(z) * dz;
z = f(z); /* forward iteration : complex quadratic polynomial */
}
if (n==nMax) return iColorOfInterior; // not escaping
// escaping and boundary
cabsz = cabs(z);
distance = 2.0 * cabsz* log(cabsz)/ cabs(dz);
double g = tanh(distance / PixelWidth);
return 255*g; // iColorOfExterior;
}
逻辑斯谛映射
[edit | edit source]逻辑斯谛映射[10]
复三次多项式
[edit | edit source]关于 z
(%i2) display2d:false; (%o2) false (%i3) f(z):= z^3 + c; (%o3) f(z):=z^3+c (%i4) diff(f(z), z,1); (%o4) 3*z^2 (%i5) diff(f(z), c,1); (%o5) 1
// function f(z)= z^3 + c*z // first derivativwe wrt z d = f'(z) = 3*z^2 + c // iteration: z_(n+1) = f(z_n) // initial values: z = z d = 1 // Recurrence steps: d = (3*z^2 + c)*d z = z^3 + c*z
四次方程
[edit | edit source](%i1) display2d:false; (%o1) false (%o4) f(z):=z^4+c (%i5) diff(f(z), z,1); (%o5) 4*z^3
常见问题解答
[edit | edit source]- 为什么新的d必须在新的z计算之前计算?[11]
应用
[edit | edit source]- 向量场梯度
- 牛顿法和递推关系
- eDEM = 集外部的距离估计方法
- iDEM = 集内部的 DEM
- 周期点的稳定性(乘子)
- 寻找临界点
- 斜率 - 将二维图像转换为三维的算法
Keep track of derivatives of Z+z wrt. Z1+z1 (where Z0+z0 is at the critical point, usually 0 ). When the absolute value of the derivative drops below a threshold such as 0.001, classify it as interior and stop iterating. Keep track of derivatives of Z+z wrt. pixel coordinates k . As Z is constant for the whole image, you just need dzdk . An easy way to do this is with dual numbers for automatic numeric differentiation. Set up the pixel coordinates as dual numbers with dual part 1+0i , then transform them to the complex C+c plane of the fractal iterations. At the end you plug the complex derivative into the (directional) distance estimate formula, it is already prescaled by the pixel spacing (this also helps to avoid overflow during iteration). ( Claude Heiland-Allen)
寻找曲线法线和切线的方程
[edit | edit source]根据 Krista King Math 的说法,要找到在给定点处曲线法线的方程:[12]
- 对原始曲线求导,并在给定点处计算其值。这是切线斜率,称为 m。
- 找到 m 的负倒数。这是法线斜率,我们将其称为 n。所以 n = −1/m。
- 将 n 和给定点代入直线方程的点斜式公式[13] 中,(y−y1)=n(x−x1)
- 通过解出 y 来简化方程
内部距离估计
[edit | edit source]内部距离估计 由下式给出:
其中
是要估计的来自 参数平面 的点
是 复二次多项式
是 -次迭代的
是构成周期轨道(极限环) 的 个点中的任意一个
在 处计算 的 4 个 导数
First partial derivative with respect to z
必须通过应用链式法则递归计算
起点:
第一次迭代:
第二次迭代:
第 p 次迭代的一般规则:
关于 c 的一阶偏导数
必须通过应用链式法则递归计算
起点:
第一次迭代:
第二次迭代:
对p次迭代的一般规则:
关于z的二阶偏导数
必须与:
- 和 一起计算
- 通过应用链式法则递归
起点:
第一次迭代:
第二次迭代:
p 迭代的一般规则:
二阶混合偏导数
梯度的 p 范数是:[14]
并将 p 设置为 -2。
- 自动微分[15]
- 像素 = (x + i y);x 在 [0..w) 中,y 在 [0..h) 中(如果使用抖动,则可能是分数)
- C = r exp(i pi (Pixel - (w + i h) /2) / w) + C0
- dc/dpixel = r i pi / w exp(i pi (Pixel - (w + i h) /2) / w)
- 对于 z <- z^2 + c
- dz/dpixel <- 2 z dz/dpixel + dc/dpixel
- 屏幕空间中的距离估计:de = |z| log |z| / |dz/dpixel|
这里
- 像素大小 = |dc/dpixel|(只需除以 dc/dpixel 即可得到 dz/dpixel / dc/dpixel = dz/dc 等)
- dy = (2 * circle_period * Math.PI) / image_size;
- dx = dy * height_ratio;
- height_ratio 通常为 1。它只是用来在一个方向上拉伸图像。
关于像素的导数不太可能溢出,并自动给出屏幕空间 de。[16]
另外,现在我再次检查了 e^(x*dx) 项,实际上是 e^(x*dx + offset)。我不知道这是否会改变很多事情。
C value = (e^(x*dx + offset)) * (cos(y * dy) + sin(y* dy)i) + C0
- ↑ mathoverflow 问题 : whats-a-natural-candidate-for-an-analytic-function-that-interpolates-the-tower/43003
- ↑ Faa di Bruno 和迭代函数的导数,发布于 2017 年 5 月 20 日,作者 DCHOYLE
- ↑ fractalforums.org : 关于曼德博集导数的一些问题
- ↑ A Cheritat wiki : 曼德博集 - 跟踪导数
- ↑ fractalforums.org: 周期检测
- ↑ 维基百科上的微分符号
- ↑ fractalforums.org : 关于曼德博集导数的一些问题
- ↑ fractalforums.org : 所有周期瓣作为点吸引子
- ↑ A Cheritat wiki : 曼德博集 - 内部检测方法
- ↑ Fractalforums.org : 逻辑斯蒂映射的外部距离估计
- ↑ Arnaud Cheritat 的 跟踪导数
- ↑ 求曲线的法线方程,作者 Krista King Math
- ↑ 维基百科上的点斜式或点梯度式直线方程
- ↑ fractalforums.org : m-brot 距离估计与 Claude 的假 DE
- ↑ 维基百科上的自动微分
- ↑ fractalforums.org: 超级分形指数映射变换