本文主要是介绍数字水印 | 混沌逻辑斯谛映射(Chaotic Logistic Map)基本原理及 Python 代码实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- 1 基本原理
- 2 代码实现
- 3 分岔图代码实现
1 基本原理
参考:维基百科 - 逻辑斯谛映射
逻辑斯谛映射(Logistic Map)是一种二次多项式的映射递推关系式,是一个由简单非线性方程式产生混沌现象的经典范例。其数学表达为:
x n + 1 = μ x n ( 1 − x n ) x_{n+1}=\mu x_n(1-x_n) xn+1=μxn(1−xn)
其中,参数 μ \mu μ 通常取 ( 0 , 4 ] (0, 4] (0,4] 区间内的值,因此 x n x_n xn 在 [ 0 , 1 ] [0, 1] [0,1] 上保持有界。
个人理解:可以把 x n x_n xn 看作是变量 X X X 在第 n n n 时刻的值,把 x n + 1 x_{n+1} xn+1 看作是变量 X X X 在第 n + 1 n+1 n+1 时刻的值。根据上述公式可知, x n + 1 x_{n+1} xn+1 的值是根据 x n x_n xn 的值计算出来的,即当前时刻的值是由上一时刻的值计算而来的,因此被称为递推关系式。
针对 x n x_n xn 在 [ 0 , 1 ] [0, 1] [0,1] 上保持有界,参考下图:
个人理解:如果初值 x 0 x_0 x0 的值在 0 0 0 到 1 1 1 之间,那么根据二次函数的表达式, x n x_n xn 的值也必定在 0 0 0 到 1 1 1 之间。因此,我们说 x n x_n xn 在 [ 0 , 1 ] [0, 1] [0,1] 上保持有界。
参数 μ \mu μ 的取值
- 0 0 0 和 1 1 1 之间:不论起始数值 x 0 x_0 x0 为何, x n x_n xn 会越来越少,最后趋近于 0 0 0;
- 1 1 1 和 2 2 2 之间:不论起始数值 x 0 x_0 x0 为何, x n x_n xn 会快速地趋近 μ − 1 μ \frac{\mu-1}{\mu} μμ−1;
- 2 2 2 和 3 3 3 之间:经过几次迭代, x n x_n xn 会越来越接近 μ − 1 μ \frac{\mu-1}{\mu} μμ−1,而且收敛速度是线性的;
- 3 3 3: x n x_n xn 仍然会越来越接近 μ − 1 μ \frac{\mu-1}{\mu} μμ−1,但收敛速度较为缓慢,而且不是线性的;
个人理解:迭代次数就是指 x n + 1 = μ x n ( 1 − x n ) x_{n+1}=\mu x_n(1-x_n) xn+1=μxn(1−xn) 计算了多少次,即 x n + 1 x_{n+1} xn+1 是初值 x 0 x_0 x0 迭代 n + 1 n+1 n+1 次的结果。
说明:由于散点图中的点粘在一起,看不出值的变化,因此我画的是折线图。但需要注意的是, x n + 1 x_{n+1} xn+1 的取值只会是一个个的点,而不包含图中的直线。
- 3 3 3 和 1 + 6 ≈ 3.45 1+\sqrt{6}\approx3.45 1+6≈3.45 之间:不论起始数值 x 0 x_0 x0 为何, x n x_n xn 最终会在 2 2 2 个值之间持续震荡;
- 1 + 6 ≈ 3.45 1+\sqrt{6}\approx3.45 1+6≈3.45 和 ≈ 3.54 \approx3.54 ≈3.54 之间: x n x_n xn 最终会在 8 , 16 , 32 , . . . 8,16,32,... 8,16,32,... 个值之间持续震荡;
- ≈ 3.5699 \approx3.5699 ≈3.5699:震荡消失,系统进入混沌状态。不论起始数值 x 0 x_0 x0 为何,都不会再出现固定周期的震荡;
可以看出 μ \mu μ 越大, x n x_{n} xn 的震荡越没有周期性。
2 代码实现
参考:https://www.jianshu.com/p/580e36a34378
控制参数 μ \mu μ 的值不变,迭代 100 100 100 次,观察这 100 100 100 次中 x n x_{n} xn 值的变化:
import matplotlib.pyplot as plt
import numpy as npn = 1 # 控制迭代次数
x = 0.2 # 初值
mu = 2 # 参数μnum = [] # 存放x轴坐标
logistic_num = [] # 存放y轴坐标while n < 100:x = mu * x * (1.0 - x) # 计算x_{n+1}的值num.append(n) # 纳入该点的x轴坐标logistic_num.append(x) # 纳入该点的y轴坐标n = n + 1# 画图
plt.plot(num, logistic_num, linestyle='-', linewidth=1.0)
plt.ylim(0, 1)
plt.yticks(np.arange(0, 1.2, 0.2))plt.savefig('{mu}.jpg'.format(mu=mu), dpi=400, bbox_inches='tight')
plt.show()
前文的两张图就是用这段代码绘制的。
3 分岔图代码实现
参考:https://blog.csdn.net/laplacebh/article/details/104598545
为参数 μ \mu μ 设置不同的值,迭代 1100 1100 1100 次,观察 1000 1000 1000 到 1100 1100 1100 次中 x n x_{n} xn 值的变化:
import matplotlib.pyplot as plt
import numpy as npdef logistic_map():mu = np.arange(2, 4, 0.0001)print(mu) # [2. 2.0001 2.0002 ... 3.9997 3.9998 3.9999]x = 0.2 # 初值t1 = 1000 # 前1000次t2 = 100 # 后100次for i in range(t1 + t2):x = mu * x * (1 - x)if i >= t1: # 只绘制1000~1100次的结果plt.plot(mu, x, ',k', alpha=0.25)plt.show()logistic_map()
由于我们想要观察的是 x n x_n xn 最终收敛或者未收敛的值,因此虽然做了 1100 1100 1100 次的迭代,但是我们只会绘制最后 100 100 100 次 x n ( x 1000 , . . . , x 1100 ) x_n(x_{1000},...,x_{1100}) xn(x1000,...,x1100) 的值。
效果如下图所示:
个人理解:
当 μ \mu μ 在 2 2 2 和 3 3 3 之间时,由于 x n x_n xn 最终会收敛到一个固定的值上,因此迭代 1000 1000 1000 到 1100 1100 1100 次之间的 x n x_n xn 值相同,汇聚在了上图中的一个点上。当 μ \mu μ 在 3 3 3 和 ≈ 3.45 \approx3.45 ≈3.45 之间时,由于 x n x_n xn 最终会在 2 2 2 个值之间震荡,因此汇聚在了上图中的两个点上。
我们也可以反过来看,即根据结果推测原因。当 μ \mu μ 在 ≈ 3.45 \approx3.45 ≈3.45 和 ≈ 3.54 \approx3.54 ≈3.54 之间时,由于 x n x_n xn 的值汇聚在了上图中的四个点上,因此可以看出 x n x_n xn 最终会在 4 4 4 个值之间震荡。
这篇关于数字水印 | 混沌逻辑斯谛映射(Chaotic Logistic Map)基本原理及 Python 代码实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!