隐式导数
iDiff(eq,y,x,n=1)返回dy/dx,并假设eq=0
y — 因变量或因变量列表(以y开头)
x — 取导数的变量
n — 导数的顺序(默认为1)
示例1:物理学中的等温过程 - 理想气体方程 PV = nRT
result4 = iDiff(P*V - T, V, P) # 在等温过程中,求体积对压强的变化率
print("理想气体等温过程 dV/dP:", result4)
#理想气体等温过程 dV/dP: -V/P
示例2:经济学中的生产可能性边界 - 2x² + 3y² = 100
result5 = iDiff(2*x**2 + 3*y**2 - 100, y, x) # 边际转换率
print("生产可能性边界 dy/dx:", result5)
#生产可能性边界 dy/dx: -2*x/(3*y)
在点(5, √(50/3))处求值
result5_point = iDiff(2*x**2 + 3*y**2 - 100, y, x, 1, [5, sqrt(50/3)])
print("在点(5, √(50/3))处的 dy/dx:", result5_point)
#在点(5, √(50/3))处的 dy/dx: -0.816496580927726
示例3:工程学中的悬链线方程 y = a*cosh(x/a)
result6 = iDiff(y - a*cosh(x/a), y, x) # 悬链线的斜率
print("悬链线方程 dy/dx:", result6)
#悬链线方程 dy/dx: sinh(x/a)
示例4:化学反应的平衡常数
result7 = iDiff(A*B - K*C**2, C, A) # 反应 A + B ⇌ 2C 中C浓度对A浓度的变化率
print("化学反应平衡 dC/dA:", result7)
#化学反应平衡 dC/dA: B/(2*C*K)
示例5:几何学中的椭圆方程
result8 = iDiff(x**2/a**2 + y**2/b**2 - 1, y, x) # 椭圆上任意点的切线斜率
print("椭圆切线斜率 dy/dx:", result8)
#椭圆切线斜率 dy/dx: -b**2*x/(a**2*y)
在具体椭圆 x²/4 + y²/9 = 1 上点(1, (3√3)/2)处求值
result8_point = iDiff(x**2/4 + y**2/9 - 1, y, x, 1, [1, 3*sqrt(3)/2])
print("在点(1, 3√3/2)处的切线斜率:", result8_point)
#在点(1, 3√3/2)处的切线斜率: -0.866025403784439
示例6:热力学中的状态方程
result9 = iDiff(P*V - R*T, T, P) # 温度对压强的变化率(等容过程)
print("等容过程 dT/dP:", result9)
#等容过程 dT/dP: V/R
示例7:二阶导数应用 - 曲线的凹凸性
result10 = iDiff(x**3 + y**3 - 6*x*y, y, x, 2) # 笛卡尔叶形线的二阶导数
print("笛卡尔叶形线 d²y/dx²:", result10)
#笛卡尔叶形线 d²y/dx²: 2*x*y*(x**3 - 6*x*y + y**3 + 8)/(8*x**3 - 12*x**2*y**2 + 6*x*y**4 - y**6)
示例8:金融学中的连续复利
result12 = iDiff(A - P*exp(r*t), r, t) # 利率对时间的变化率
print("连续复利 dr/dt:", result12)
#连续复利 dr/dt: -r/t
测试包含数值点的复杂情况
result13 = iDiff(x**2 + y**2 - 25, y, x, 2, [3, 4]) # 圆 x²+y²=25 在点(3,4)处的二阶导数
print("圆在点(3,4)处的二阶导数:", result13)
#圆在点(3,4)处的二阶导数: -0.390625000000000
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def get_result_value(symbols_set, points=None, result=None):
"""
将符号表达式代入具体数值点求值。
参数:
symbols_set (list): 符号列表,按字母顺序排列
points (list): 数值点列表,顺序需与symbols_set中的符号对应
result (sympy.Expr): 待代入的表达式
返回:
sympy.Expr 或 float: 代入后的数值结果或符号表达式
示例:
symbols = [x, y], points = [2, 3] 表示代入x=2, y=3
"""
if points is not None and result is not None:
if len(points) != len(symbols_set):
raise ValueError(f"提供的点数({len(points)})与符号数量({len(symbols_set)})不匹配。")
subs_dict = {symbol: value for symbol, value in zip(symbols_set, points)}
try:
# 尝试数值求值,保留浮点精度
result = result.subs(subs_dict).evalf()
except Exception as e:
# 非数值情况直接代入符号
result = result.subs(subs_dict)
return result
def implicit_diff_equation(input_str):
"""
处理隐函数求导请求,对标MathStudio的iDiff功能
参数:
input_str (str): 输入字符串,格式为Sympy可解析的元组形式:
(方程, 因变量, 自变量, 阶数(可选), 数值点(可选))
示例: "(Eq(x**2 + y**2, 1), y, x, 2, [0, 1])"
返回:
sympy.Expr 或 str: 求导结果或错误信息
"""
try:
# 预处理输入字符串
processed_str = input_str
error = False
result = None
def remove_last_element(tup):
"""移除元组最后一个元素(用于处理数值点)"""
return tup[:-1] if len(tup) > 1 else tup
# 解析输入字符串
if '==' in processed_str:
# 方程处理:转换为左式-右式=0的形式
expr = sp.sympify(processed_str, evaluate=False)
transformed_equation = f"{expr[0].lhs} - {expr[0].rhs}"
expr_func = sp.sympify(transformed_equation)
else:
expr = sp.sympify(processed_str)
expr_func = expr[0] if isinstance(expr, tuple) else expr
# 处理元组形式的参数
if isinstance(expr, tuple):
# 检查是否包含数值点参数
if len(expr) > 0 and isinstance(expr[-1], list) and all(item.is_number for item in expr[-1]):
points = expr[-1]
expr = remove_last_element(expr)
else:
points = None
# 解析求导参数
if len(expr) >= 3:
equation = expr_func
dep_var = expr[1] # 因变量
indep_var = expr[2] # 自变量
# 处理求导阶数
order = expr[3] if len(expr) > 3 and expr[3].is_number else 1
# 执行隐式求导
result = sp.idiff(equation, dep_var, indep_var, order).simplify()
# 处理符号代入
symbols = sorted(result.free_symbols, key=lambda s: str(s)) # 按字母顺序排序符号
result = get_result_value(symbols, points, result)
else:
error = True
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {str(e)}"
# 示例用法
if __name__ == "__main__":
# 示例1:计算 x² + y² = 1 的一阶导数
x, y = sp.symbols('x y')
input1 = "(x**2 + y**2==1, y, x)"
print("示例1结果:", implicit_diff_equation(input1))
# 输出: -x/y
# 示例2:计算二阶导数并代入点(0, 1)
input2 = "(x**2+y**2==1, y, x, 2, [0, 1])"
print("示例2结果:", implicit_diff_equation(input2))
# 输出 -1.0
# 示例3:带数值点的三阶导数
input3 = "(y**3 + x, y, x, 3)"
print("示例3结果:", implicit_diff_equation(input3))
# 输出 -10/(27*y**8)
带有舍入选项的整除
C = idivide(A,B) 将A的每个元素除以B的对应元素,朝零方向舍入到最接近的整数.A和B必须包含实数,并且其中有至少一个必须属于整数类.
如果A和B是数组,则它们必须属于同一整数类,并且大小兼容.
如果A或B是双精度标量,则另一个输入必须为整数类,但不能是int64或uint64.然后,idivide函数以相同的整数类形式返回C.
C = idivide(A,B,opt) 指定替代舍入选项:'fix'、'floor'、'ceil'.例如,idivide(A,B,'ceil') 将商朝正无穷方向舍入到最接近的整数.默认舍入选项是 'fix'.
示例1:资源分配问题 - 将100个物品平均分给7个人
result1 = idivide(100, 7, floor)
print(f"100个物品分给7人,每人得: {result1} 个")
remaining = 100 - result1 * 7
print(f"剩余物品: {remaining} 个")
#100个物品分给7人,每人得: 14 个
#剩余物品: 2 个
示例2:时间规划 - 将480分钟分配到25分钟的时间块中
result2 = idivide(480, 25, floor)
print(f"480分钟可以分成 {result2} 个25分钟的时间块") # 19个
remaining_time = 480 - result2 * 25
print(f"剩余时间: {remaining_time} 分钟")
#480分钟可以分成 19 个25分钟的时间块
#剩余时间: 5 分钟
示例3:财务计算 - 货币兑换(大额兑换)
将1000美元兑换成日元,假设1美元=110日元,只取整百日元
result3 = idivide(1000*110, 100, floor)
print(f"1000美元可兑换 {result3*100} 日元")
#1000美元可兑换 110000 日元
示例4:制造业 - 材料切割优化
从120cm长的材料上切割35cm的零件
result4 = idivide(120, 35, floor)
print(f"120cm材料可切割 {result4} 个35cm零件")
waste = 120 - result4 * 35
print(f"材料浪费: {waste} cm")
#120cm材料可切割 3 个35cm零件
#材料浪费: 15 cm
示例5:计算机科学 - 内存页分配
分配1024KB内存给36KB的页面
result5 = idivide(1024, 36, floor)
print(f"1024KB内存可分配 {result5} 个36KB页面")
unused_memory = 1024 - result5 * 36
print(f"未使用内存: {unused_memory} KB")
#1024KB内存可分配 28 个36KB页面
#未使用内存: 16 KB
示例6:运输物流 - 集装箱装载
每个集装箱最多装25吨,现有83吨货物
result6 = idivide(83, 25, ceil)
print(f"83吨货物需要 {result6} 个集装箱") # 4个
last_container_load = 83 - (result6 - 1) * 25
print(f"最后一个集装箱装载: {last_container_load} 吨")
#83吨货物需要 4 个集装箱
#最后一个集装箱装载: 8 吨
示例7:教育领域 - 学生分组
35名学生,每组最多8人
result7 = idivide(35, 8, ceil)
print(f"35名学生需要分成 {result7} 组") # 5组
last_group_size = 35 - (result7 - 1) * 8
print(f"最后一组人数: {last_group_size} 人")
#35名学生需要分成 5 组
#最后一组人数: 3 人
示例8:餐饮业 - 食材包装
每包250克面粉,需要制作1800克面团
result8 = idivide(1800, 250, ceil)
print(f"制作1800克面团需要 {result8} 包面粉") # 8包
excess_flour = result8 * 250 - 1800
print(f"多余面粉: {excess_flour} 克")
#制作1800克面团需要 8 包面粉
#多余面粉: 200 克
示例9:矩阵运算示例 - 图像像素处理
将像素矩阵除以16进行归一化(使用向下取整)
result9 = idivide([[64, 128, 192], [32, 96, 160], [16, 48, 80]], 16, floor)
print("像素矩阵归一化结果:")
print(result9)
#像素矩阵归一化结果:
#[[4,8,12]
[2,6,10]
[1,3,5]]
示例10:负数处理 - 温度计算
零下温度的分组计算
result10_floor = idivide(-15, 4, floor)
result10_fix = idivide(-15, 4, fix)
print(f"-15°C 每4°C一组 (floor): {result10_floor} 组")
print(f"-15°C 每4°C一组 (fix): {result10_fix} 组")
#-15°C 每4°C一组 (floor): -4 组
#-15°C 每4°C一组 (fix): -3 组
示例11:批量生产 - 产品包装
生产235个产品,每箱装24个
result11 = idivide(235, 24, floor)
print(f"235个产品可装满 {result11} 箱")
remaining_products = 235 - result11 * 24
print(f"零散产品: {remaining_products} 个")
#235个产品可装满 9 箱
#零散产品: 19 个
示例12:建筑行业 - 瓷砖铺设
墙面宽285cm,瓷砖宽30cm
result12 = idivide(285, 30, floor)
print(f"285cm墙面需要 {result12} 块30cm瓷砖")
gap = 285 - result12 * 30
print(f"两端留空: {gap} cm")
#285cm墙面需要 9 块30cm瓷砖
#两端留空: 15 cm
示例13:数据分析 - 数据分桶
将0-999的数据分成10个桶
result13 = idivide([0, 123, 456, 789, 999], 100, floor)
print("数据分桶索引:", result13)
#数据分桶索引: [0,1,4,7,9]
示例14:网络传输 - 数据包分割
传输1500字节数据,每个包最大1460字节
result14 = idivide(1500, 1460, ceil)
print(f"1500字节数据需要 {result14} 个数据包")
last_packet_size = 1500 - (result14 - 1) * 1460
print(f"最后一个包大小: {last_packet_size} 字节")
#1500字节数据需要 2 个数据包
#最后一个包大小: 40 字节
示例15:能源管理 - 电池组配置
需要提供48V电压,每个电池3.7V
result15 = idivide(48, 3.7, ceil)
print(f"提供48V电压需要 {result15} 个3.7V电池串联")
actual_voltage = result15 * 3.7
print(f"实际电压: {actual_voltage} V")
#提供48V电压需要 13 个3.7V电池串联
#实际电压: 48.1 V
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import numpy as np
import sympy as sp
def integer_division(input_str):
"""
执行整数除法运算,对标MATLAB的idivide函数
参数:
input_str (str): 输入字符串,支持以下格式:
- 标量运算: "(被除数, 除数, '舍入选项')"
- 矩阵运算: "(矩阵A, 矩阵B, '舍入选项')"
- 单矩阵运算: "(矩阵, 标量, '舍入选项')"
返回:
sympy.Expr/sympy.Matrix/str: 计算结果或错误信息
示例:
>>> integer_division("(10, 3, 'fix')") # 10 ÷ 3 向零取整
3
>>> integer_division("([[1,2],[3,4]], 2, 'floor')") # 矩阵逐元素除
Matrix([[0, 1], [1, 2]])
"""
try:
# 预处理输入
expr = sp.sympify(input_str)
error = False
result = None
def elementwise_divide(a, b, option='fix'):
"""
执行逐元素除法,支持不同维度的数值标量、向量和多维数组
参数:
a, b: 数值标量、列表(向量)、嵌套列表(多维数组)或NumPy数组
option: 舍入选项
'fix' - 向零取整 (默认)
'floor' - 向下取整
'ceil' - 向上取整
返回:
与输入维度匹配的结果(标量、列表或NumPy数组)
"""
# 将输入转换为NumPy数组
a_arr = np.asarray(a)
b_arr = np.asarray(b)
# 检查除数是否包含零
if np.any(b_arr == 0):
raise ZeroDivisionError("除数不能包含零")
# 执行逐元素除法
result = a_arr / b_arr
# 应用舍入选项
if option == 'fix':
# 向零取整
result = np.trunc(result)
elif option == 'floor':
# 向下取整
result = np.floor(result)
elif option == 'ceil':
# 向上取整
result = np.ceil(result)
else:
raise ValueError(f"无效舍入选项: {option}")
# 转换为整数类型
result = result.astype(int)
# 保持与输入相同的类型
if isinstance(a, (int, float)) and isinstance(b, (int, float)):
return int(result) # 标量输入返回整数
elif isinstance(a, list) or isinstance(b, list):
return result.tolist() # 列表输入返回列表
return result # NumPy数组输入返回数组
if isinstance(expr, tuple):
# 解析参数数量和类型
n = float(expr[0])
a = float(expr[1])
option = expr[2] if len(expr) > 2 else 'fix' # 默认舍入方式
result = elementwise_divide(n, a, str(option))
else:
error = True
return result if not error else f"输入错误: {input_str}"
except ZeroDivisionError:
return "错误: 除零错误"
except Exception as e:
return f"错误: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 标量测试
print("-10 ÷ 3 (floor):", integer_division("(-10, 3, 'floor')"))
# -4
print("7 ÷ 3 (ceil):", integer_division("(7, 3, 'ceil')"))
# 3
快速傅里叶逆变换
X = ifft(Y) 使用快速傅里叶变换算法计算 Y 的逆离散傅里叶变换。X 与 Y 的大小相同。
如果 Y 是向量,则 ifft(Y) 返回该向量的逆变换。
如果 Y 是矩阵,则 ifft(Y) 返回该矩阵每一列的逆变换。
X = ifft(Y,n) 通过用尾随零填充 Y 以达到长度 n,返回 Y 的 n 点傅里叶逆变换。
X = ifft(Y,n,dim) 返回沿维度 dim 的傅里叶逆变换。例如,如果 Y 是矩阵,则 ifft(Y,n,2) 返回每一行的 n 点逆变换。
Y — 输入数组, 向量 | 矩阵
n — 逆变换长度, 0 (默认) | 非负整数标量
dim — 沿其运算的维度, 正整数标量
示例1:音频信号处理 - 从频域恢复音频信号
模拟一个简单的音频频域信号(基频和几个谐波)
audio_reconstructed = ifft([10+0@i, 2+1@i, 1-0.5@i, 0.5+0.2@i, 0.3-0.1@i])
print("音频信号重建结果:", audio_reconstructed)
#音频信号重建结果:
#[[2.76 + 0.12*I],
[1.772500220836 + 0.486301819419587*I],
[1.45809661311434 - 0.0594227445000619*I],
[1.98301794868567 - 0.268905412799913*I],
[2.02638521736398 - 0.277973662119612*I]]
示例2:图像处理 - 从频域重建图像
模拟简单的2x2图像的频域表示
image_reconstructed = ifft([[100, 50+30@i], [20-10@i, 10+5@i]])
print("图像重建结果:")
print(image_reconstructed)
#图像重建结果:
#[[60.0 - 5.0*I, 30.0 + 17.5*I],
[40.0 + 5.0*I, 20.0 + 12.5*I]]
示例3:通信系统 - QAM调制信号解调
4-QAM调制的频域信号
qam_demodulated = ifft([ (1+1@i)*10, (1-1@i)*5, (-1+1@i)*3, (-1-1@i)*7 ])
print("QAM解调结果:", qam_demodulated)
#QAM解调结果:
#[[1.25 + 0.25*I],
[2.75 + 4.75*I],
[2.25 + 6.25*I],
[3.75 - 1.25*I]]
示例4:振动分析 - 机械振动信号重建
包含多个频率成分的振动信号频域表示
vibration_time = ifft([50+0@i, 15+8@i, 8-4@i, 3+2@i, 1-1@i, 0.5+0.3@i])
print("振动时域信号:", vibration_time)
#振动时域信号:
#[[12.9166666666667 + 0.883333333333333*I],
[7.69661343370219 + 3.87825769689424*I],
[5.24725469658442 + 1.14086508806388*I],
[6.75 - 2.55*I],
[8.33607863674892 - 1.02419842139721*I],
[9.05338656629781 - 2.32825769689424*I]]
示例5:电力系统 - 电网谐波分析重建
电网信号中的基波和谐波成分
power_waveform = ifft([100, 5+2@i, 3-1@i, 2+0.5@i, 1-0.3@i]) # 基波50Hz + 谐波
print("电网电压波形:", power_waveform)
#电网电压波形:
#[[22.2 + 0.24*I],
[19.300652977067 + 1.06436974101959*I],
[18.7824984301819 - 0.0259505789500291*I],
[19.8938947720681 - 0.585984376099925*I],
[19.822953820683 - 0.692434785969641*I]]
示例6:雷达信号处理 - 距离像重建
雷达回波的频域信号(多个目标反射)
radar_range_profile = ifft([20, 15-5@i, 8+3@i, 3-2@i, 1+1@i])
print("雷达距离像:", radar_range_profile)
#雷达距离像:
#[[9.4 - 0.6*I],
[3.76249956163666 + 2.84172650354396*I],
[3.74738182467117 + 1.40375918449872*I],
[0.434584186578931 + 0.0142748042511762*I],
[2.65553442711324 - 3.65976049229385*I]]
示例7:医学成像 - MRI图像重建
模拟MRI的k-space数据(频域)
mri_kspace = [[80, 25+15@i, 10-8@i], [18+12@i, 40+20@i, 5-3j], [8-6@i, 12+8@i, 30]]
mri_image = ifft(mri_kspace)
print("MRI图像重建结果:")
print(mri_image)
#MRI图像重建结果:
#[[35.3333333333333 + 2.0*I, 25.6666666666667 + 14.3333333333333*I, 15.0 - 3.66666666666667*I],
[17.1371809106267 + 1.88675134594813*I, -3.79743494847109 + 8.41623710198809*I, -1.63397459621556 - 9.38354503153699*I],
[27.52948575604 - 3.88675134594813*I, 3.13076828180442 - 7.74957043532143*I, -3.36602540378444 + 5.05021169820365*I]]
示例8:地震信号处理
地震波的频域表示
seismic_wave = ifft([45, 20+10@i, 12-6@i, 8+4@i, 5-2@i, 3+1@i, 1-0.5@i])
print("地震波时域信号:", seismic_wave)
#地震波时域信号:
#[[13.4285714285714 + 0.928571428571428*I],
[5.57926270451576 + 4.30923152078805*I],
[3.76213634794582 + 2.27300818609102*I],
[2.3801516499138 - 1.14137195495892*I],
[6.91677082451423 - 2.32196950854944*I],
[6.21440502135265 - 1.23361530876399*I],
[6.7187020231863 - 2.81385436317814*I]]
示例9:语音识别 - 语音特征重建
语音信号的MFCC频域表示(简化)
speech_signal = ifft([30, 12+6@i, 8-4@i, 5+2@i, 3-1@i, 2+0.5@i])
print("重建的语音信号:", speech_signal)
#重建的语音信号:
#[[10.0 + 0.583333333333333*I],
[4.05582274842315 + 2.7900635094611*I],
[2.52313067797205 + 0.930021169820365*I],
[3.66666666666667 - 2.25*I],
[4.97686932202795 - 0.513354503153699*I],
[4.77751058491018 - 1.5400635094611*I]]
示例10:金融时间序列 - 价格波动重建
股票价格波动的频域成分
stock_prices = ifft([100, 25-12@i, 15+8@i, 8-5@i, 5+3@i])
print("重建的价格序列:", stock_prices)
#重建的价格序列:
#[[30.6 - 1.2*I],
[19.45755168505 + 3.5854846318902*I],
[20.8034789071199 + 2.66130267285655*I],
[12.3312735086303 + 0.621978900143196*I],
[16.8076958991999 - 5.66876620488995*I]]
示例11:光学成像 - 相位恢复
光波的频域相位信息
optical_wavefront = ifft([[50+25@i, 30-15@i], [20+10@i, 40-20@i]])
print("光波波前重建:")
print(optical_wavefront)
#光波波前重建:
#[[35.0 + 17.5*I, 35.0 - 17.5*I],
[15.0 + 7.5*I, -5.0 + 2.5*I]]
示例12:量子计算 - 波函数重建
量子态的频域表示
quantum_wavefunction = ifft([0.7+0@i, 0.5+0.3@i, 0.3-0.2@i, 0.1+0.1@i])
print("量子波函数:", quantum_wavefunction)
#量子波函数:
#[[0.4 + 0.05*I],
[0.05 + 0.15*I],
[0.1 - 0.15*I],
[0.15 - 0.05*I]]
示例13:气象数据 - 天气模式重建
气象数据的频域成分
weather_freq = ""
weather_pattern = ifft([60, 20+10@i, 15-8@i, 10+5@i, 6-3@i])
print("天气模式时域序列:", weather_pattern)
#天气模式时域序列:
#[[22.2 + 0.8*I],
[8.61729811246802 + 4.1687774866688*I],
[5.33720800279718 - 0.623291798626124*I],
[13.3391851994528 - 2.01277617887367*I],
[10.506308685282 - 2.33270950916901*I]]
示例14:生物信号 - ECG心电图重建
心电信号的频域特征
ecg_signal = ifft([40, 15+7@i, 10-5@i, 6+3@i, 4-2@i, 2+1@i])
print("重建的ECG信号:", ecg_signal)
#重建的ECG信号:
#[[12.8333333333333 + 0.666666666666667*I],
[5.48365396477445 + 3.49241377865072*I],
[3.78429522765668 + 1.42702963774851*I],
[5.16666666666667 - 3.0*I],
[6.38237143900999 - 0.593696304415178*I],
[6.34967936855889 - 1.99241377865072*I]]
示例15:音乐合成 - 乐器音色重建
钢琴音的谐波结构
piano_sound = ifft([25, 12+6@i, 8-4@i, 6+3@i, 4-2@i, 3+1@i, 2-1@i])
print("合成的钢琴音:", piano_sound)
#合成的钢琴音:
#[[8.57142857142857 + 0.428571428571429*I],
[2.78626268021768 + 2.34925211529782*I],
[1.87488438967884 + 1.17571274243983*I],
[0.742661597596697 - 0.60261412512079*I],
[4.12008535390303 - 1.28248149746338*I],
[3.3276720092561 - 0.543200817929995*I],
[3.57700539791907 - 1.52523984579491*I]]
示例16:多通道EEG信号重建
沿通道方向(axis=1)
eeg_channels = ifft([[10+2@i, 8-1@i, 6+3@i], [5+1@i, 4-0.5@i, 3+1.5@i]],0,1)
print("各通道EEG信号:")
print(eeg_channels)
#各通道EEG信号:
#[[8.0 + 1.33333333333333*I, 2.15470053837925 + 0.910683602522959*I, -0.154700538379251 - 0.244016935856292*I],
[4.0 + 0.666666666666667*I, 1.07735026918963 + 0.455341801261479*I, -0.0773502691896257 - 0.122008467928146*I]]
示例17:指定变换长度
使用零填充到8点
padded_signal = ifft([1, 0.5+0.5@i, 0.2-0.1@i], 8)
print("零填充重建信号:", padded_signal)
#零填充重建信号:
#[[0.2125 + 0.05*I],
[0.1375 + 0.113388347648318*I],
[0.0375 + 0.075*I],
[0.0241116523516816 - 0.025*I],
[0.0875 - 0.075*I],
[0.1375 - 0.0633883476483184*I],
[0.1625 - 0.05*I],
[0.200888347648318 - 0.025*I]]
示例18:实数信号的复频域重建
实数信号的对称频域表示
real_signal = ifft([10+0@i, 3-2@i, 1+1@i, 0.5-0.3@i, 0.2+0.1@i])
print("重建的实数信号:", real_signal)
#重建的实数信号:
#[[2.94 - 0.24*I],
[2.2016853493354 + 0.360681337279561*I],
[2.0690787221121 + 0.584742926729242*I],
[1.08078972171294 + 0.116634747420703*I],
[1.70844620683956 - 0.822059011429506*I]]
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import numpy as np
import sympy as sp
def inverse_fft(input_str):
"""
模拟MATLAB的ifft函数行为
参数:
x: 输入数组
n: FFT点数(默认为输入长度)
axis: 计算轴(MATLAB默认按列,对应axis=0)
返回:
与MATLAB ifft结果一致的复数数组
"""
# 检验输入 x 是否为数组
try:
expr = sp.sympify(input_str)
error = False
result = None
n = 0
axis = 0
if isinstance(expr, tuple):
if len(expr) == 3:
matrix_sp = sp.Matrix(expr[0])
n = expr[1]
axis = expr[2]
elif len(expr) == 2:
matrix_sp = sp.Matrix(expr[0])
n = expr[1]
else:
error = True
else:
matrix_sp = sp.Matrix(expr)
# 校验矩阵有效性
if matrix_sp is None:
raise ValueError("输入无法转换为有效矩阵(支持 SymPy 矩阵或列表)")
# ---------------------- 转换为 NumPy 数组 ----------------------
# 保持原始矩阵的复数类型(SymPy 矩阵元素可能是复数)
x = np.array(matrix_sp, dtype=complex)
# 若输入是列矩阵,转换为二维数组(与 MATLAB 列优先一致)
if x.ndim == 1:
x = x.reshape(-1, 1)
# 检验输入 n 是否为有效的整数
if n != 0:
if not isinstance(n, (int, sp.Integer)) or n <= 0:
raise ValueError("参数 n 必须是正整数。")
else:
n = None
# 检验输入 axis 是否为有效的轴索引
if not isinstance(axis, (int, sp.Integer)):
raise ValueError("参数 axis 必须是整数。")
if axis < -x.ndim or axis >= x.ndim:
raise IndexError(f"参数 axis 超出了数组的有效轴范围 [-{x.ndim}, {x.ndim - 1}]。")
# 调整轴方向(MATLAB默认按列计算,对应NumPy的axis=0)
if not error:
result = sp.Matrix(np.fft.ifft(x, n=n, axis=axis))
if result.shape[1] == 1:
result = result.T
return result
except Exception as e:
return f"错误: {e}"
if __name__ == "__main__":
# 一维数组示例
result_1d = inverse_fft("[1, 1j, -1, -1j]")
print("一维数组逆傅里叶变换结果:", result_1d)
# Matrix([[0, 0, 0, 1.00000000000000]])
# 二维数组示例
# 沿第 0 轴进行逆傅里叶变换
result_2d_axis0 = inverse_fft("[[1, 1j], [-1, -1j]], 0, 0")
print("二维数组沿第 0 轴逆傅里叶变换结果:")
print(result_2d_axis0)
# Matrix([[0, 0],
[1.00000000000000, 1.0*I]])
# 沿第 1 轴进行逆傅里叶变换
result_2d_axis1 = inverse_fft("[[1, 1j], [-1, -1j]], 0, 1")
print("二维数组沿第 1 轴逆傅里叶变换结果:")
print(result_2d_axis1)
# Matrix([[0.5 + 0.5*I, 0.5 - 0.5*I],
[-0.5 - 0.5*I, -0.5 + 0.5*I]])
# 指定 FFT 点数示例
result_1d_n = inverse_fft("[[1, 1j], [-1, -1j]], 8")
print("\n一维数组指定 FFT 点数为 8 的逆傅里叶变换结果:", result_1d_n)
# Matrix([[0, 0],
# [0.0366116523516816 - 0.0883883476483184*I, 0.0883883476483184 + 0.0366116523516816*I],
# [0.125 - 0.125*I, 0.125 + 0.125*I],
# [0.213388347648318 - 0.0883883476483184*I, 0.0883883476483184 + 0.213388347648318*I],
# [0.250000000000000, 0.25*I],
# [0.213388347648318 + 0.0883883476483184*I, -0.0883883476483184 + 0.213388347648318*I],
# [0.125 + 0.125*I, -0.125 + 0.125*I],
# [0.0366116523516816 + 0.0883883476483184*I, -0.0883883476483184 + 0.0366116523516816*I]])
二维快速傅里叶逆变换
X = ifft2(Y) 使用快速傅里叶变换算法返回矩阵的二维离散傅里叶逆变换。如果 Y 是一个多维数组,则 ifft2 计算大于 2 的每个维度的二维逆变换。输出 X 的大小与 Y 相同。
X = ifft2(Y,m,n) 在计算逆变换之前截断 Y 或用尾随零填充 Y,以形成 m×n 矩阵。X 也是 m×n。如果 Y 是一个多维数组,ifft2 将根据 m 和 n 决定 Y 的前两个维度的形状。
Y — 输入数组, 矩阵
m — 逆变换行数, 正整数标量
n — 逆变换列数, 正整数标量
# 继续在 __main__ 中添加以下示例
示例1:图像处理 - 从频域重建图像
模拟一个简单图像的频域表示(4x4像素)
image_freq = [
[100, 50+30@i, 30-20@i, 10+5@i],
[40+20@i, 80+10@i, 20-15@i, 5+2@i],
[25-10@i, 15+8@i, 60, 8-3@i],
[10+5@i, 8-4@i, 6+2@i, 40]
]
image_reconstructed = ifft2(image_freq)
print("图像重建结果:")
print(image_reconstructed)
#图像重建结果:
#[[31.6875 + 1.875*I, 1.1875 + 8.625*I, 4.6875 - 4.125*I, 6.1875 - 2.625*I],
[4.25 + 6.3125*I, -3.0 + 4.1875*I, 1.625 - 2.0625*I, 12.125 + 1.5625*I],
[5.5625 - 0.625*I, -1.3125 - 1.5*I, 11.8125 - 4.625*I, 2.6875 - 2.0*I],
[6.0 - 3.8125*I, 14.375 + 3.6875*I, -0.625 - 2.9375*I, 2.75 - 1.9375*I]]
示例2:医学成像 - MRI图像重建
模拟MRI的k-space数据(频域)
mri_kspace = [
[80, 25+15@i, 10-8@i, 5+3@i],
[18+12@i, 40+20@i, 5-3@i, 2+1@i],
[8-6@i, 12+8@i, 30, 4-2@i],
[3+2@i, 6-4@i, 8+5@i, 20]
]
mri_image = ifft2(mri_kspace)
print("MRI图像重建:")
print(mri_image)
#MRI图像重建:
#[[17.25 + 2.6875*I, 1.1875 + 4.125*I, 3.0 - 2.4375*I, 5.8125 - 2.375*I],
[2.4375 + 2.375*I, 1.25 + 1.3125*I, 3.8125 - 1.125*I, 8.0 + 2.6875*I],
[4.5 - 1.4375*I, 2.0625 - 0.375*I, 7.25 - 2.3125*I, 2.9375 - 0.875*I],
[5.8125 - 1.125*I, 10.0 + 1.9375*I, 0.9375 - 0.625*I, 3.75 - 2.4375*I]]
示例3:地震勘探 - 地下结构成像
地震波场在频域的表示
seismic_data = [
[45, 20+10@i, 12-6@i, 8+4@i],
[15+8@i, 35+5@i, 10-5@i, 6+3@i],
[10-4@i, 8+6@i, 25, 5-2@i],
[6+3@i, 5-2@i, 4+1@i, 15]
]
seismic_image = ifft2(seismic_data)
print("地下结构图像:")
print(seismic_image)
#地下结构图像:
#[[14.3125 + 1.3125*I, 0.6875 + 3.1875*I, 1.5625 - 1.6875*I, 2.4375 - 1.0625*I],
[1.75 + 2.75*I, 1.125*I, 1.125 - 1.125*I, 4.625 + 0.5*I],
[2.3125 - 0.3125*I, -0.1875 - 1.0625*I, 4.8125 - 1.8125*I, 1.5625 - 0.5625*I],
[2.875 - 1.75*I, 6.25 + 1.25*I, -0.25 - 0.375*I, 1.125 - 0.375*I]]
示例4:光学成像 - 相位恢复
光波的频域相位和振幅信息
optical_field = [
[50+25@i, 30-15@i, 20+10@i, 15-8@i],
[25+12@i, 40-20@i, 18+9@i, 12-6@i],
[20-10@i, 15+7@i, 35, 10-5@i],
[12+6@i, 10-5@i, 8+4@i, 25]
]
optical_wavefront = ifft2(optical_field)
print("光波波前重建:")
print(optical_wavefront)
#光波波前重建:
#[[21.5625 + 0.25*I, 2.5 + 2.6875*I, 1.9375 + 6.75*I, 0.75 - 1.4375*I],
[2.8125 + 3.75*I, 1.25 + 2.9375*I, -2.3125 + 4.75*I, 4.25 + 0.5625*I],
[2.8125 + 0.25*I, -1.25 + 0.4375*I, 4.9375 - 1.0*I, 1.75 - 0.4375*I],
[1.5625 - 1.25*I, 6.75 + 1.4375*I, 1.6875 + 4.0*I, -1.0 + 1.3125*I]]
示例5:遥感图像处理
卫星采集的频域数据
satellite_data = [
[120, 45+20@i, 30-15@i, 20+10@i],
[35+15@i, 90+25@i, 25-12@i, 15+8@i],
[28-12@i, 22+10@i, 75, 18-9@i],
[15+7@i, 12-6@i, 10+5@i, 60]
]
satellite_image = ifft2(satellite_data)
print("卫星图像重建:")
print(satellite_image)
#卫星图像重建:
#[[38.75 + 2.875*I, 1.125 + 5.5*I, 3.5 - 4.375*I, 6.125 - 1.5*I],
[2.625 + 5.875*I, -0.125 + 1.875*I, 4.375 - 1.875*I, 14.125 + 2.125*I],
[6.0 - 2.375*I, 0.625 - 1.5*I, 15.0 - 2.875*I, 2.875 - 1.75*I],
[6.375 - 2.625*I, 18.375 + 4.125*I, -1.625 - 2.125*I, 1.875 - 1.375*I]]
示例6:材料科学 - 晶体结构分析
X射线衍射的频域数据
crystal_diffraction = [
[200, 60+25@i, 40-18@i, 25+12@i],
[50+20@i, 150+40@i, 35-15@i, 20+10@i],
[40-15@i, 30+12@i, 120, 22-11@i],
[18+9@i, 15-7@i, 12+6@i, 80]
]
crystal_structure = ifft2(crystal_diffraction)
print("晶体结构重建:")
print(crystal_structure)
#晶体结构重建:
#[[57.3125 + 4.25*I, 2.625 + 9.3125*I, 7.0625 - 5.875*I, 10.0 - 4.1875*I],
[4.125 + 10.1875*I, 1.4375 + 2.0*I, 7.125 - 3.6875*I, 24.5625 + 3.25*I],
[9.8125 - 3.625*I, 2.875 - 3.5625*I, 25.8125 - 3.0*I, 4.5 - 0.8125*I],
[10.0 - 6.0625*I, 29.8125 + 5.5*I, -1.25 - 1.1875*I, 4.1875 - 2.5*I]]
示例7:雷达成像 - 合成孔径雷达(SAR)
SAR数据的频域表示
sar_data = [
[150, 55+22@i, 35-16@i, 22+11@i],
[42+18@i, 110+35@i, 30-14@i, 18+9@i],
[32-14@i, 25+11@i, 95, 20-10@i],
[16+8@i, 14-6@i, 11+5@i, 70]
]
sar_image = ifft2(sar_data)
print("SAR图像重建:")
print(sar_image)
#SAR图像重建:
#[[46.5625 + 3.6875*I, 1.0625 + 6.9375*I, 4.8125 - 5.3125*I, 7.5625 - 2.3125*I],
[3.0625 + 7.4375*I, 0.6875 + 2.0625*I, 5.3125 - 2.0625*I, 17.9375 + 2.5625*I],
[7.6875 - 3.1875*I, 1.4375 - 1.9375*I, 18.9375 - 2.6875*I, 2.9375 - 2.1875*I],
[8.1875 - 3.6875*I, 22.8125 + 5.1875*I, -2.0625 - 2.1875*I, 3.0625 - 2.3125*I]]
示例8:计算机视觉 - 特征图重建
CNN特征图的频域表示
cnn_features = [
[80, 25+10@i, 15-7@i, 10+5@i],
[20+8@i, 45+15@i, 12-6@i, 8+4@i],
[15-6@i, 12+5@i, 35, 9-4@i],
[8+4@i, 7-3@i, 6+3@i, 25]
]
feature_map = ifft2(cnn_features)
print("特征图重建:")
print(feature_map)
#特征图重建:
#[[20.75 + 1.75*I, 2.0625 + 3.3125*I, 3.125 - 2.25*I, 4.8125 - 1.3125*I],
[2.625 + 3.25*I, 1.3125 + 1.0625*I, 3.625 - 1.125*I, 7.6875 + 1.3125*I],
[4.375 - 1.375*I, 1.8125 - 0.9375*I, 8.0 - 1.375*I, 2.5625 - 0.8125*I],
[4.75 - 1.625*I, 9.8125 + 2.0625*I, 0.25 - 0.75*I, 2.4375 - 1.1875*I]]
示例9:音频频谱图重建
音频信号的时频谱表示
audio_spectrogram = [
[60, 20+8@i, 12-5@i, 8+4@i],
[18+7@i, 40+12@i, 10-4@i, 6+3@i],
[12-4@i, 10+4@i, 30, 7-3@i],
[6+3@i, 5-2@i, 4+2@i, 20]
]
audio_signal = ifft2(audio_spectrogram)
print("音频信号重建:")
print(audio_signal)
#音频信号重建:
#[[16.75 + 1.5625*I, 1.375 + 2.9375*I, 2.25 - 1.6875*I, 3.625 - 1.3125*I],
[1.625 + 3.0625*I, 0.625 + 0.8125*I, 2.375 - 0.9375*I, 6.375 + 1.0625*I],
[3.125 - 1.0625*I, 1.0 - 0.9375*I, 6.375 - 1.0625*I, 1.5 - 0.4375*I],
[3.5 - 1.8125*I, 8.0 + 1.4375*I, -0.5625*I, 1.5 - 1.0625*I]]
示例10:流体动力学 - 流场重建
流体速度的频域表示
flow_field = [
[90, 30+12@i, 18-8@i, 12+6@i],
[25+10@i, 70+20@i, 15-7@i, 10+5@i],
[20-8@i, 15+6@i, 55, 12-6@i],
[10+5@i, 8-4@i, 7+3@i, 40]
]
velocity_field = ifft2(flow_field)
print("速度场重建:")
print(velocity_field)
#速度场重建:
#[[27.3125 + 2.125*I, 1.3125 + 4.25*I, 2.6875 - 2.75*I, 4.9375 - 1.875*I],
[1.5 + 4.5625*I, 0.375 + 1.1875*I, 3.25 - 1.6875*I, 11.125 + 1.6875*I],
[4.1875 - 1.875*I, 1.0625 - 1.625*I, 11.5625 - 1.5*I, 1.9375 - 0.75*I],
[4.5 - 2.3125*I, 13.75 + 2.6875*I, -1.0 - 0.5625*I, 1.5 - 1.5625*I]]
示例11:图像超分辨率重建(补零至8x8)
small_image = [
[100, 50+30@i],
[40+20@i, 80+10@ij]
]
high_res_image = ifft2(small_image,8,8)
print("超分辨率重建结果:")
print(high_res_image)
#超分辨率重建结果:
#[[4.21875 + 0.9375*I, 3.18186891104358 + 2.19075238752677*I, 1.5625 + 2.34375*I, 0.309247612473233 + 1.30686891104358*I, 0.15625 - 0.3125*I, 1.19313108895642 - 1.56575238752677*I, 2.8125 - 1.71875*I, 4.06575238752677 - 0.681868911043582*I],
[3.33811891104358 + 2.12603151840597*I, 1.84819173824159 + 2.79679608384557*I, 0.320351958077214 + 2.21756064928517*I, -0.350412607362389 + 0.727633476483184*I, 0.22882282719801 - 0.800206303681194*I, 1.71875 - 1.4709708691208*I, 3.24658978016438 - 0.891735434560398*I, 3.91735434560398 + 0.598191738241592*I],
[1.875 + 2.34375*I, 0.476601958077214 + 2.28228151840597*I, -0.46875 + 1.25*I, -0.407281518405971 - 0.148398041922786*I, 0.625 - 1.09375*I, 2.02339804192279 - 1.03228151840597*I, 2.96875000000000, 2.90728151840597 + 1.39839804192279*I],
[0.686468481594029 + 1.46311891104358*I, -0.129441738241592 + 0.948604345603981*I, -0.342560649285175 + 0.00785195807721362*I, 0.171953916154427 - 0.808058261758408*I, 1.11270630368119 - 1.02117717280199*I, 1.92861652351682 - 0.506662607362388*I, 2.1417354345604 + 0.434089780164379*I, 1.6272208691208 + 1.25*I],
[0.468750000000000, 0.38507282719801 - 0.422985434560398*I, 0.625 - 0.78125*I, 1.0479854345604 - 0.86492717280199*I, 1.40625 - 0.625*I, 1.48992717280199 - 0.202014565439602*I, 1.25 + 0.15625*I, 0.827014565439602 + 0.23992717280199*I],
[1.34938108895642 - 1.18853151840597*I, 1.71875 - 1.0290291308792*I, 1.86714804192279 - 0.655060649285175*I, 1.70764565439602 - 0.285691738241592*I, 1.33367717280199 - 0.137293696318806*I, 0.964308261758408 - 0.296796083845573*I, 0.815910219835621 - 0.670764565439602*I, 0.975412607362388 - 1.04013347648318*I],
[2.8125 - 1.40625*I, 3.09033978016438 - 0.514514565439602*I, 2.65625 + 0.3125*I, 1.7645145654396 + 0.590339780164379*I, 0.9375 + 0.15625*I, 0.659660219835621 - 0.735485434560398*I, 1.09375 - 1.5625*I, 1.9854854345604 - 1.84033978016438*I],
[4.00103151840597 - 0.525618911043582*I, 3.69638347648318 + 0.819162607362388*I, 2.53006064928517 + 1.55464804192279*I, 1.1852791308792 + 1.25*I, 0.449793696318806 + 0.0836771728019903*I, 0.754441738241592 - 1.26110434560398*I, 1.9207645654396 - 1.99658978016438*I, 3.26554608384557 - 1.69194173824159*I]]
示例12:数据压缩重建(截断至2x2)
compressed_data = [
[100, 50+30@i, 30-20@i, 10+5@i],
[40+20@i, 80+10@i, 20-15@i, 5+2@i],
[25-10@i, 15+8@i, 60, 8-3@i],
[10+5@i, 8-4@i, 6+2@i, 40]
]
reconstructed_compressed = ifft2(compressed_data,2,2)
print("压缩数据重建:")
print(reconstructed_compressed)
#压缩数据重建:
#[[67.5 + 15.0*I, 2.5 - 5.0*I],
[7.50000000000000, 22.5 - 10.0*I]]
示例13:频域滤波重建
原始信号 + 高频噪声
noisy_signal = [
[100, 50+30@i, 30-20@i, 10+5@i],
[40+20@i, 80+10@i, 20-15@i, 5+2@i],
[25-10@i, 15+8@i, 60, 8-3@i],
[10+5@i, 8-4@i, 6+2@i, 40]
]
通过截断高频分量来滤波
filtered_signal = ifft2(noisy_signal,3,3)
print("滤波后信号:")
print(filtered_signal)
#滤波后信号:
#[[46.6666666666667 + 2.55555555555556*I, -3.82001205712316 + 3.75676545916171*I, 12.1533453904565 - 2.97898768138393*I],
[5.03084090396273 + 4.23789068348639*I, -7.56908647387896 - 1.00106877147038*I, 16.3779915320718 - 0.573361559760487*I],
[8.30249242937061 - 3.46011290570862*I, 16.9553418012615 + 1.35113933753826*I, 5.9024198072123 - 3.88782011741851*I]]
示例14:模式识别 - 模板匹配
频域模板数据
template = [
[70, 20+8@i, 12-5@i, 8+3@i],
[15+6@i, 35+10@i, 8-3@i, 5+2@i],
[10-4@i, 8+3@i, 25, 6-2@i],
[5+2@i, 4-1@i, 3+1@i, 15]
]
matched_pattern = ifft2(template)
print("模板匹配结果:")
print(matched_pattern)
#模板匹配结果:
#[[15.5625 + 1.25*I, 2.1875 + 2.75*I, 2.9375 - 1.625*I, 4.3125 - 1.375*I],
[3.0 + 2.8125*I, 1.5 + 0.9375*I, 2.875 - 1.0625*I, 6.625 + 0.8125*I],
[4.3125 - 0.875*I, 1.9375 - 0.875*I, 6.4375 - 1.0*I, 2.3125 - 0.25*I],
[4.625 - 1.6875*I, 7.625 + 1.4375*I, 1.25 - 0.3125*I, 2.5 - 0.9375*I]]
示例15:量子计算 - 二维量子态重建
量子态的频域表示
quantum_state = [
[0.6, 0.2+0.1@i, 0.1-0.05@i, 0.05+0.02@i],
[0.15+0.06@i, 0.3+0.1@i, 0.08-0.03@i, 0.04+0.02@i],
[0.1-0.04@i, 0.08+0.03@i, 0.25, 0.06-0.02@i],
[0.04+0.02@i, 0.03-0.01@i, 0.02+0.01@i, 0.15]
]
quantum_wavefunction = ifft2(quantum_state)
print("量子波函数重建:")
print(quantum_wavefunction)
#量子波函数重建:
#[[0.140625 + 0.013125*I, 0.015 + 0.02625*I, 0.026875 - 0.016875*I, 0.04 - 0.0125*I],
[0.020625 + 0.026875*I, 0.01 + 0.01125*I, 0.023125 - 0.006875*I, 0.06125 + 0.00625*I],
[0.039375 - 0.008125*I, 0.0125 - 0.00375*I, 0.055625 - 0.010625*I, 0.02 - 0.0075*I],
[0.036875 - 0.014375*I, 0.0675 + 0.01625*I, 0.006875 - 0.008125*I, 0.02375 - 0.01125*I]]
示例16:实际工程数据验证
创建一个已知的简单模式来验证变换的正确性
test_pattern = [
[4, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
]
reconstructed_test = ifft2(test_pattern)
print("测试模式重建:")
print(reconstructed_test)
#测试模式重建:
#[[0.25, 0.25, 0.25, 0.25],
[0.25, 0.25, 0.25, 0.25],
[0.25, 0.25, 0.25, 0.25],
[0.25, 0.25, 0.25, 0.25]]
#应该是均匀的直流信号
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import numpy as np
import sympy as sp
def inverse_fft2(input_str):
"""
对标 MATLAB 的 ifft2(Y, m, n) 函数,实现二维逆快速傅里叶变换
参数:
Y: 输入的二维频域数组(实数/复数)
m: 变换后的行数(默认:Y 的行数)
n: 变换后的列数(默认:Y 的列数)
返回:
二维时域数组,与 MATLAB ifft2 结果一致(数值精度误差在 1e-10 以内)
"""
# Y, m=None, n=None
# ---------------------- 参数校验 ----------------------
# 校验 Y 是二维数组
expr = sp.sympify(input_str)
error = False
result = m = n = None
matrix = None
if isinstance(expr, tuple):
matrix = sp.Matrix(expr[0])
if len(expr) == 3:
m, n = expr[1], expr[2]
elif len(expr) == 2:
m = expr[1]
else:
error = True
else:
matrix = sp.Matrix(expr)
if matrix is None:
raise ValueError("输入 Y 必须是二维 NumPy 数组")
else:
Y = np.array(matrix)
# 校验 m 和 n 为正整数或 None
original_rows, original_cols = Y.shape
if m is not None:
if not isinstance(m, sp.Integer) or m <= 0:
raise ValueError(f"参数 m 必须是正整数(当前值:{m})")
else:
m = original_rows # 默认使用 Y 的行数
if n is not None:
if not isinstance(n, sp.Integer) or n <= 0:
raise ValueError(f"参数 n 必须是正整数(当前值:{n})")
else:
n = original_cols # 默认使用 Y 的列数
# ---------------------- 补零/截断逻辑 ----------------------
# 若 m/n 大于原尺寸,补零;若小于,截断
# 注意:MATLAB 补零在末尾,截断从开头保留
if not error:
rows_needed = m
cols_needed = n
Y_padded = np.zeros((rows_needed, cols_needed), dtype=Y.dtype)
# 计算实际截断的行数和列数(不超过原尺寸)
truncate_rows = min(original_rows, rows_needed)
truncate_cols = min(original_cols, cols_needed)
# 填充数据(截断或复制原数据)
Y_padded[:truncate_rows, :truncate_cols] = Y[:truncate_rows, :truncate_cols]
# ---------------------- 计算二维逆 FFT ----------------------
# numpy.fft.ifft2 会自动除以变换点数(m*n),与 MATLAB 一致
result = np.fft.ifft2(Y_padded, s=(m, n))
result = sp.Matrix(result)
return result
# ---------------------- 示例代码 ----------------------
if __name__ == "__main__":
# 示例 1:默认参数(m=原行数,n=原列数)
Y1 = np.array([[1, 1j], [-1, -1j]], dtype=complex)
result1 = inverse_fft2("[[1, 1j], [-1, -1j]]")
print("示例1(默认参数)结果:\n", result1)
# Matrix([[0, 0],
# [0.5 + 0.5*I, 0.5 - 0.5*I]])
# 示例 2:补零(m=4, n=4)
Y2 = np.array([[1, 1j], [-1, -1j]], dtype=complex)
result2 = inverse_fft2("[[1, 1j], [-1, -1j]],4,4")
print("\n示例2(补零至4x4):", result2)
# Matrix([[0, 0, 0, 0],
# [0.125000000000000, 0, -0.125*I, 0.125 - 0.125*I],
# [0.125 + 0.125*I, 0, 0.125 - 0.125*I, 0.250000000000000],
# [0.125*I, 0, 0.125000000000000, 0.125 + 0.125*I]])
# 示例3:截断(m=1, n=1)
Y3 = np.array([[1, 1j], [-1, -1j]], dtype=complex)
result3 = inverse_fft2("[[1, 1j], [-1, -1j]],1,1")
print("\n示例3(截断至1x1)结果:\n", result3)
# Matrix([[1.00000000000000]])
多维快速傅里叶逆变换
X = ifftn(Y) 使用快速傅里叶变换算法返回 N 维数组的多维离散傅里叶逆变换。N 维逆变换相当于沿 Y 的每个维度计算一维逆变换。输出 X 的大小与 Y 相同。
X = ifftn(Y,sz) 将在进行逆变换之前根据向量 sz 的元素截断 Y 或用尾随零填充 Y。sz 的每个元素定义对应变换维度的长度。例如,如果 Y 是一个 5×5×5 数组,X = ifftn(Y,[8 8 8]) 将用零填充每个维度,从而产生 8×8×8 逆变换 X。
Y — 输入数组, 向量 | 矩阵 | 多维数组
sz — 逆变换维度的长度, 正整数向量
示例1:三维医学成像 - CT扫描重建
模拟CT扫描的频域数据(4x4x4体素)
ct_scan_3d = [
[[100+0@i, 50+30@i, 30-20@i, 10+5@i],
[40+20@i, 80+10@i, 20-15@i, 5+2@i],
[25-10@i, 15+8@i, 60+0@i, 8-3@i],
[10+5@i, 8-4@i, 6+2@i, 40+0@i]],
[[90+0@i, 45+25@i, 28-18@i, 12+6@i],
[35+18@i, 75+15@i, 22-12@i, 8+4@i],
[22-12@i, 18+10@i, 55+0@i, 10-5@i],
[12+6@i, 10-5@i, 8+4@i, 35+0@i]],
[[80+0@i, 40+20@i, 25-15@i, 15+7@i],
[30+15@i, 70+12@i, 18-10@i, 10+5@i],
[20-10@i, 15+8@i, 50+0@i, 12-6@i],
[15+7@i, 12-6@i, 10+5@i, 30+0@i]],
[[70+0@i, 35+15@i, 22-12@i, 18+8@i],
[25+12@i, 65+10@i, 15-8@i, 12+6@i],
[18-8@i, 12+6@i, 45+0@i, 15-7@i],
[18+8@i, 15-7@i, 12+6@i, 25+0@i]]
]
ct_reconstructed = ifftn(ct_scan_3d)
print("三维CT扫描重建结果(形状):", np.array(ct_reconstructed).shape)
#三维CT扫描重建结果(形状): (4, 4, 4)
#返回三维体数据,用于医学诊断
示例2:气象数据 - 四维气候模型重建
模拟气候数据的频域表示(时间×高度×纬度×经度)
这里简化为3x3x3x3数组
climate_data_4d = [
[[[100+0@i, 80+20@i, 60-15@i],
[70+15@i, 90+10@i, 50-10@i],
[55-12@i, 65+8@i, 85+0@i]],
[[85+0@i, 65+18@i, 48-12@i],
[60+12@i, 80+8@i, 45-8@i],
[50-10@i, 55+6@i, 75+0@i]],
[[75+0@i, 55+15@i, 40-10@i],
[50+10@i, 70+6@i, 38-6@i],
[45-8@i, 50+4@i, 65+0@i]]],
[[[95+0@i, 75+18@i, 55-14@i],
[65+14@i, 85+9@i, 52-9@i],
[52-11@i, 62+7@i, 80+0@i]],
[[80+0@i, 60+16@i, 45-11@i],
[55+11@i, 75+7@i, 42-7@i],
[48-9@i, 52+5@i, 70+0@i]],
[[70+0@i, 50+13@i, 35-8@i],
[45+8@i, 65+5@i, 35-5@i],
[42-7@i, 45+3@i, 60+0@i]]],
[[[90+0@i, 70+15@i, 50-12@i],
[60+12@i, 80+7@i, 48-7@i],
[50-9@i, 60+5@i, 75+0@i]],
[[75+0@i, 55+14@i, 42-9@i],
[50+9@i, 70+5@i, 40-5@i],
[45-7@i, 50+4@i, 65+0@i]],
[[65+0@i, 45+11@i, 30-6@i],
[40+6@i, 60+3@i, 32-3@i],
[40-5@i, 40+2@i, 55+0@i]]]
]
climate_reconstructed = ifftn(climate_data_4d)
print("四维气候数据重建结果(形状):", np.array(climate_reconstructed).shape)
#四维气候数据重建结果(形状): (3, 3, 3, 3)
#用于气候预测和天气建模
示例3:材料科学 - 三维晶体结构分析
X射线三维衍射数据
crystal_3d = [
[[200+0@i, 80+30@i, 50-20@i, 30+15@i],
[60+25@i, 150+40@i, 40-18@i, 25+12@i],
[45-18@i, 35+15@i, 120+0@i, 30-15@i],
[25+12@i, 20-10@i, 15+8@i, 80+0@i]],
[[180+0@i, 70+28@i, 45-18@i, 28+13@i],
[55+22@i, 140+35@i, 38-16@i, 22+10@i],
[40-16@i, 30+13@i, 110+0@i, 28-13@i],
[22+10@i, 18-8@i, 12+6@i, 70+0@i]],
[[160+0@i, 60+25@i, 40-15@i, 25+10@i],
[50+20@i, 130+30@i, 35-14@i, 20+8@i],
[35-14@i, 25+10@i, 100+0@i, 25-10@i],
[20+8@i, 15-6@i, 10+4@i, 60+0@i]],
[[140+0@i, 50+20@i, 35-12@i, 22+8@i],
[45+18@i, 120+25@i, 32-12@i, 18+6@i],
[30-12@i, 20+8@i, 90+0@i, 22-8@i],
[18+6@i, 12-4@i, 8+3@i, 50+0@i]]
]
crystal_structure_3d = ifftn(crystal_3d)
print("三维晶体结构重建结果(形状):", np.array(crystal_structure_3d).shape)
#三维晶体结构重建结果(形状): (4, 4, 4)
#用于材料分析和纳米技术研究
示例4:视频处理 - 时空数据重建
视频数据的频域表示(时间×高度×宽度)
video_sequence = [
[[100+0@i, 60+25@i, 40-15@i],
[50+20@i, 120+30@i, 35-12@i],
[35-12@i, 45+15@i, 90+0@i]],
[[95+0@i, 55+22@i, 38-13@i],
[48+18@i, 115+25@i, 32-10@i],
[32-10@i, 42+12@i, 85+0@i]],
[[90+0@i, 50+20@i, 35-10@i],
[45+15@i, 110+20@i, 30-8@i],
[30-8@i, 40+10@i, 80+0@i]],
[[85+0@i, 45+18@i, 32-8@i],
[42+12@i, 105+15@i, 28-6@i],
[28-6@i, 38+8@i, 75+0@i]]
]
video_reconstructed = ifftn(video_sequence)
print("视频序列重建结果(形状):", np.array(video_reconstructed).shape)
#视频序列重建结果(形状): (4, 3, 3)
#用于视频压缩和流媒体处理
示例5:神经科学 - 三维fMRI脑部扫描重建
功能性磁共振成像数据
fmri_brain = [
[[150+0@i, 60+25@i, 40-18@i, 25+12@i],
[55+22@i, 130+35@i, 35-15@i, 20+10@i],
[40-15@i, 50+18@i, 110+0@i, 22-11@i],
[20+10@i, 18-8@i, 15+7@i, 70+0@i]],
[[140+0@i, 55+22@i, 38-16@i, 22+10@i],
[50+20@i, 120+30@i, 32-13@i, 18+8@i],
[38-13@i, 45+15@i, 100+0@i, 20-10@i],
[18+8@i, 15-6@i, 12+5@i, 65+0@i]],
[[130+0@i, 50+20@i, 35-14@i, 20+8@i],
[45+18@i, 110+25@i, 30-11@i, 15+6@i],
[35-11@i, 40+12@i, 90+0@i, 18-8@i],
[15+6@i, 12-4@i, 10+4@i, 60+0@i]],
[[120+0@i, 45+18@i, 32-12@i, 18+6@i],
[40+15@i, 100+20@i, 28-9@i, 12+4@i],
[32-9@i, 35+10@i, 80+0@i, 15-6@i],
[12+4@i, 10-3@i, 8+3@i, 55+0@i]]
]
brain_activity = ifftn(fmri_brain)
print("fMRI脑部活动重建结果(形状):", np.array(brain_activity).shape)
#fMRI脑部活动重建结果(形状): (4, 4, 4)
#用于神经科学研究和脑功能分析
示例6:地震勘探 - 四维地震数据
时间推移地震数据(时间×深度×纬度×经度)
time_lapse_seismic = [
[[[120+0@i, 50+20@i, 35-15@i],
[45+18@i, 100+25@i, 30-12@i],
[35-12@i, 40+15@i, 85+0@i]],
[[55+22@i, 25+10@i, 18-8@i],
[20+8@i, 45+12@i, 15-6@i],
[18-6@i, 22+8@i, 40+0@i]],
[[40+15@i, 18+7@i, 12-5@i],
[15+6@i, 35+8@i, 10-4@i],
[12-4@i, 15+5@i, 30+0@i]]],
[[[115+0@i, 48+18@i, 32-13@i],
[42+16@i, 95+22@i, 28-10@i],
[32-10@i, 38+13@i, 80+0@i]],
[[52+20@i, 22+8@i, 15-6@i],
[18+6@i, 42+10@i, 12-4@i],
[15-4@i, 20+6@i, 35+0@i]],
[[38+13@i, 15+5@i, 10-3@i],
[12+4@i, 32+6@i, 8-2@i],
[10-2@i, 12+3@i, 25+0@i]]],
[[[110+0@i, 45+15@i, 30-10@i],
[40+14@i, 90+18@i, 25-8@i],
[30-8@i, 35+10@i, 75+0@i]],
[[50+18@i, 20+6@i, 12-4@i],
[15+4@i, 40+8@i, 10-2@i],
[12-2@i, 18+4@i, 30+0@i]],
[[35+10@i, 12+3@i, 8-1@i],
[10+2@i, 30+4@i, 6-0@i],
[8-0@i, 10+1@i, 20+0@i]]]
]
seismic_4d = ifftn(time_lapse_seismic)
print("四维地震数据重建结果(形状):", np.array(seismic_4d).shape)
#四维地震数据重建结果(形状): (3, 3, 3, 3)
#用于石油勘探和储层监测
示例7:数据压缩 - 指定较小尺寸
compressed_3d = ifftn(ct_scan_3d, 2, 2, 2)
print("压缩后的三维数据形状:", np.array(compressed_3d).shape)
#压缩后的三维数据形状: (2, 2, 2)
#用于有损压缩和数据存储优化
示例8:三维超分辨率重建 - 指定较大尺寸
super_res_3d = ifftn(ct_scan_3d, 6, 6, 6)
print("超分辨率重建后的形状:", np.array(super_res_3d).shape)
#超分辨率重建后的形状: (6, 6, 6)
#通过频域插值提高空间分辨率
示例9:非对称尺寸调整
asymmetric_resize = ifftn(ct_scan_3d, 3, 5, 4)
print("非对称调整后的形状:", np.array(asymmetric_resize).shape)
#非对称调整后的形状: (3, 5, 4)
#根据不同维度的重要性进行定制化重建
示例10:五维数据示例(理论应用)
模拟五维数据(例如:时间×空间×频率×极化×通道)
five_d_data = [
[[[[100+0@i, 80+20@i], [60+15@i, 45-10@i]],
[[70+18@i, 55+12@i], [40-8@i, 30+8@i]]],
[[[90+0@i, 70+18@i], [50+12@i, 38-8@i]],
[[60+15@i, 45+10@i], [35-6@i, 25+6@i]]]],
[[[[85+0@i, 65+15@i], [45+10@i, 35-6@i]],
[[55+12@i, 40+8@i], [30-4@i, 22+4@i]]],
[[[80+0@i, 60+12@i], [40+8@i, 30-4@i]],
[[50+10@i, 35+6@i], [25-2@i, 18+2@i]]]]
]
five_d_reconstructed = ifftn(five_d_data)
print("五维数据重建结果(形状):", np.array(five_d_reconstructed).shape)
#五维数据重建结果(形状): (2, 2, 2, 2, 2)
#用于高级科学计算和理论研究
示例11:实际工程验证
创建一个简单的三维模式来验证变换
simple_3d_pattern = [
[[4+0@i, 0+0@i], [0+0@i, 0+0@i]],
[[0+0@i, 0+0@i], [0+0@i, 0+0@i]]
]
verified_pattern = ifftn(simple_3d_pattern)
print("验证模式重建结果:")
print(verified_pattern)
#验证模式重建结果:
#[[[0.5, 0.5], [0.5, 0.5]], [[0.5, 0.5], [0.5, 0.5]]]
#应该是均匀的三维直流信号
示例12:部分尺寸指定
partial_sizes = ifftn(ct_scan_3d, 3)
print("部分尺寸指定后的形状:", np.array(partial_sizes).shape)
#部分尺寸指定后的形状: (3, 4, 4)
#只指定第一个维度,其他维度使用默认值
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def inverse_fftn(input_str):
"""
对标MATLAB的ifftn函数,执行多维逆快速傅里叶变换。
参数:
input_str (str): 输入的字符串,格式为"Y"或"(Y, s1, s2, ...)",
其中Y是数组,s1, s2等是各维度的大小。
返回:
numpy.ndarray: 逆FFT结果。若指定sizes,则形状为sizes;否则与Y相同。
或返回错误信息字符串。
"""
try:
expr = sp.sympify(input_str)
arr = None
sizes = None
# 解析输入,判断是否为元组(包含数组和sizes参数)
if isinstance(expr, tuple):
if len(expr) < 1:
raise ValueError("输入格式错误,应为 (Y, s1, s2, ...)")
arr = expr[0]
sizes = list(expr[1:]) # 提取sizes参数
else:
arr = expr
if arr is None:
raise ValueError("输入 Y 必须是多维数组")
if isinstance(arr, list):
Y = np.array(arr)
original_shape = Y.shape
# 处理sizes参数
if sizes is not None:
# 补全sizes到原数组的维度数,不足部分使用原数组对应维度的大小
while len(sizes) < len(original_shape):
sizes.append(original_shape[len(sizes)])
# 校验并转换sizes为整数
for i in range(len(sizes)):
s = sizes[i]
if isinstance(s, sp.Integer):
s = int(s)
elif isinstance(s, int):
pass
else:
raise ValueError(f"参数 sizes[{i}] 必须是整数,当前类型为 {type(s)}")
if s <= 0:
raise ValueError(f"参数 sizes[{i}] 必须是正整数,当前值为 {s}")
sizes[i] = s
else:
sizes = list(original_shape)
# 创建补零/截断后的数组
padded_Y = np.zeros(sizes, dtype=Y.dtype)
# 计算各维度的切片范围
slices = tuple(slice(0, min(orig, new)) for orig, new in zip(original_shape, sizes))
padded_Y[slices] = Y[slices]
# 执行逆FFTn
result = np.fft.ifftn(padded_Y)
return sp.Array(result)
except Exception as e:
return f"错误: {e}"
# 示范代码
if __name__ == "__main__":
# 示例1:不指定sizes,结果形状与原数组相同
input1 = "[[1, 2], [3, 4]]"
result1 = inverse_fftn(input1)
print("示例1结果:", result1 if not isinstance(result1, str) else result1)
# [[2.5, -0.5],
# [-1.0, 0]]
# 示例2:指定sizes大于原数组维度
input2 = "([[1, 2], [3, 4]], 3, 3)"
result2 = inverse_fftn(input2)
print("示例2结果:", result2 if not isinstance(result2, str) else result2)
# [[1.11111111111111, 0.111111111111111 + 0.577350269189626*I, 0.111111111111111 - 0.577350269189626*I],
# [-0.0555555555555555 + 0.673575314054563*I, -0.388888888888889 + 0.0962250448649376*I, 0.277777777777778 + 0.0962250448649376*I],
# [-0.0555555555555555 - 0.673575314054563*I, 0.277777777777778 - 0.0962250448649376*I, -0.388888888888889 - 0.0962250448649376*I]]
# 示例3:三维数组,sizes部分指定
input3 = "([[[1, 2], [3, 4]], [[5, 6], [7, 8]]], 2, 2)"
result3 = inverse_fftn(input3)
print("示例3结果:", result3 if not isinstance(result3, str) else result3)
# [[[4.5, -0.5],
# [-1.0, 0]],
# [[-2.0, 0],
# [0, 0]]]
逆零频平移
X = ifftshift(Y) 将进行过零频平移的傅里叶变换 Y 重新排列回原始变换输出的样子。换言之,ifftshift 就是撤消 fftshift 的结果。
如果 Y 是向量,则 ifftshift 会将 Y 的左右两半部分进行交换。
如果 Y 是矩阵,则 ifftshift 会将 Y 的第一象限与第三象限交换,将第二象限与第四象限交换。
如果 Y 是多维数组,则 ifftshift 会沿每个维度交换 Y 的半空间。
X = ifftshift(Y,dim) 沿 Y 的维度 dim 执行运算。例如,如果 Y 是矩阵,其行表示多个一维变换,则 ifftshift(Y,2) 会将 Y 的每一行的左右两半部分进行交换。
示例1:图像处理 - 频域滤波后的图像重建
模拟经过频域中心化处理的图像频谱
image_spectrum_centered = [
[100+0@i, 50+30@i, 30-20@i, 10+5@i],
[40+20@i, 80+10@i, 20-15@i, 5+2@i],
[25-10@i, 15+8@i, 60+0@i, 8-3@i],
[10+5@i, 8-4@i, 6+2@i, 40+0@i]
]
在执行逆FFT前需要先进行ifftshift将零频移回角落
image_reconstructed = ifftshift(image_spectrum_centered, [1, 2])
print("频域图像重建前的零频调整:")
print(image_reconstructed)
#频域图像重建前的零频调整:
#[[60 8 - 3*I 25 - 10*I 15 + 8*I]
[6 + 2*I 40 10 + 5*I 8 - 4*I]
[30 - 20*I 10 + 5*I 100 50 + 30*I]
[20 - 15*I 5 + 2*I 40 + 20*I 80 + 10*I]]
#用于图像处理中的频域滤波操作
示例2:音频处理 - 频谱分析后的信号重建
经过fftshift中心化的音频频谱
audio_spectrum_centered = [0.1+0@i, 0.3-0.1@i, 0.5+0.2@i, 0.8+0@i, 0.5-0.2@i, 0.3+0.1@i]
audio_reconstructed = ifftshift(audio_spectrum_centered)
print("音频频谱重建前的零频调整:")
print(audio_reconstructed)
#音频频谱重建前的零频调整:
#[0.8, 0.5 - 0.2*I, 0.3 + 0.1*I, 0.1, 0.3 - 0.1*I, 0.5 + 0.2*I]
#用于音频信号处理和音乐分析
示例3:医学成像 - MRI k-space数据重建
MRI采集的k-space数据(已经过fftshift中心化)
mri_kspace_centered = [
[[80+0@i, 25+15@i], [10-8@i, 5+3@i]],
[[18+12@i, 40+20@i], [5-3@i, 2+1@i]],
[[8-6@i, 12+8@i], [30+0@i, 4-2@i]],
[[3+2@i, 6-4@i], [8+5@i, 20+0@i]]
]
mri_reconstructed = ifftshift(mri_kspace_centered, [1, 2, 3])
print("MRI k-space重建前的三维零频调整:")
print("调整后数组形状:", np.array(mri_reconstructed.tolist()).shape)
#MRI k-space重建前的三维零频调整:
#调整后数组形状: (4, 2, 2)
#用于医学图像重建
示例4:雷达信号处理 - 距离多普勒图重建
雷达的距离-多普勒谱(已经中心化)
radar_doppler_centered = [
[0.5+0@i, 0.8+0.2@i, 1.2+0@i, 0.8-0.2@i],
[0.3+0.1@i, 0.6+0.3@i, 0.9+0@i, 0.6-0.3@i],
[0.2+0@i, 0.4+0.1@i, 0.7+0@i, 0.4-0.1@i],
[0.1-0.1@i, 0.3+0@i, 0.5+0@i, 0.3+0.1@i]
]
radar_reconstructed = ifftshift(radar_doppler_centered, [1, 2])
print("雷达谱重建前的零频调整:")
print(radar_reconstructed)
#雷达谱重建前的零频调整:
#[[0.7, 0.4 - 0.1*I, 0.2, 0.4 + 0.1*I]
[0.5, 0.3 + 0.1*I, 0.1 - 0.1*I, 0.3]
[1.2, 0.8 - 0.2*I, 0.5, 0.8 + 0.2*I]
[0.9, 0.6 - 0.3*I, 0.3 + 0.1*I, 0.6 + 0.3*I]]
#用于目标检测和速度测量
示例5:地震数据处理 - 频率-波数域重建
地震数据的频率-波数谱(中心化)
seismic_fk_centered = [
[45+0@i, 20+10@i, 12-6@i, 8+4@i],
[15+8@i, 35+5@i, 10-5@i, 6+3@i],
[10-4@i, 8+6@i, 25+0@i, 5-2@i],
[6+3@i, 5-2@i, 4+1@i, 15+0@i]
]
seismic_reconstructed = ifftshift(seismic_fk_centered, 2)
print("地震数据列方向零频调整:")
print(seismic_reconstructed)
#地震数据列方向零频调整:
#[[12 - 6*I, 8 + 4*I, 45, 20 + 10*I]
[10 - 5*I, 6 + 3*I, 15 + 8*I, 35 + 5*I]
[25, 5 - 2*I, 10 - 4*I, 8 + 6*I]
[4 + I, 15, 6 + 3*I, 5 - 2*I]]
#用于地震波场重建和速度分析
示例6:通信系统 - OFDM子载波重建
OFDM信号的子载波分布(中心化)
ofdm_subcarriers_centered = [
0.1+0@i, 0.3-0.05@i, 0.5+0.1@i, 0.7+0@i, 0.9-0.1@i,
1.1+0@i, 0.9+0.1@i, 0.7+0@i, 0.5-0.1@i, 0.3+0.05@i
]
ofdm_reconstructed = ifftshift(ofdm_subcarriers_centered)
print("OFDM子载波重建前的零频调整:")
print(ofdm_reconstructed)
#OFDM子载波重建前的零频调整:
#[1.1, 0.9 + 0.1*I, 0.7, 0.5 - 0.1*I, 0.3 + 0.05*I, 0.1, 0.3 - 0.05*I, 0.5 + 0.1*I, 0.7, 0.9 - 0.1*I]
#用于5G和WiFi通信系统
示例7:天文观测 - 射电望远镜数据重建
射电望远镜的干涉测量数据(中心化)
radio_telescope_centered = [
[[120+0@i, 60+25@i], [30-15@i, 15+8@i]],
[[45+18@i, 90+30@i], [20-10@i, 10+5@i]],
[[25-12@i, 20+10@i], [70+0@i, 12-6@i]],
[[15+7@i, 12-6@i], [10+5@i, 50+0@i]]
]
telescope_reconstructed = ifftshift(radio_telescope_centered, [2, 3])
print("射电数据重建前的零频调整:")
print("调整后数组形状:", np.array(telescope_reconstructed.tolist()).shape)
#射电数据重建前的零频调整:
#调整后数组形状: (4, 2, 2)
#用于天体成像和宇宙学研究
示例8:材料科学 - 电子衍射图重建
透射电镜的衍射图样(中心化)
electron_diffraction_centered = [
[200+0@i, 80+30@i, 50-20@i, 30+15@i],
[60+25@i, 150+40@i, 40-18@i, 25+12@i],
[45-18@i, 35+15@i, 120+0@i, 30-15@i],
[25+12@i, 20-10@i, 15+8@i, 80+0@i]
]
diffraction_reconstructed = ifftshift(electron_diffraction_centered, [1, 2])
print("电子衍射图重建前的零频调整:")
print(diffraction_reconstructed)
#电子衍射图重建前的零频调整:
#[[120, 30 - 15*I, 45 - 18*I, 35 + 15*I]
[15 + 8*I, 80, 25 + 12*I, 20 - 10*I]
[50 - 20*I, 30 + 15*I, 200, 80 + 30*I]
[40 - 18*I, 25 + 12*I, 60 + 25*I, 150 + 40*I]]
#用于晶体结构分析
示例9:流体力学 - 湍流频谱重建
湍流速度场的频谱(中心化)
turbulence_spectrum_centered = [
[0.8+0@i, 0.6+0.2@i, 0.4-0.1@i, 0.3+0.05@i],
[0.5+0.15@i, 0.7+0.1@i, 0.35-0.08@i, 0.25+0.04@i],
[0.3-0.1@i, 0.4+0.08@i, 0.6+0@i, 0.2-0.03@i],
[0.2+0.05@i, 0.25-0.04@i, 0.18+0.02@i, 0.5+0@i]
]
turbulence_reconstructed = ifftshift(turbulence_spectrum_centered, 1)
print("湍流频谱行方向零频调整:")
print(turbulence_reconstructed)
#湍流频谱行方向零频调整:
#[[0.3 - 0.1*I, 0.4 + 0.08*I, 0.6, 0.2 - 0.03*I]
[0.2 + 0.05*I, 0.25 - 0.04*I, 0.18 + 0.02*I, 0.5]
[0.8, 0.6 + 0.2*I, 0.4 - 0.1*I, 0.3 + 0.05*I]
[0.5 + 0.15*I, 0.7 + 0.1*I, 0.35 - 0.08*I, 0.25 + 0.04*I]]
#用于计算流体动力学
示例10:量子计算 - 量子态频谱重建
量子系统的能谱(中心化)
quantum_spectrum_centered = [
[0.6+0@i, 0.2+0.1@i, 0.1-0.05@i, 0.05+0.02@i],
[0.15+0.06@i, 0.3+0.1@i, 0.08-0.03@i, 0.04+0.02@i],
[0.1-0.04@i, 0.08+0.03@i, 0.25+0@i, 0.06-0.02@i],
[0.04+0.02@i, 0.03-0.01@i, 0.02+0.01@i, 0.15+0@i]
]
quantum_reconstructed = ifftshift(quantum_spectrum_centered, [1, 2])
print("量子频谱重建前的零频调整:")
print(quantum_reconstructed)
#量子频谱重建前的零频调整:
#[[0.25, 0.06 - 0.02*I, 0.1 - 0.04*I, 0.08 + 0.03*I]
[0.02 + 0.01*I, 0.15, 0.04 + 0.02*I, 0.03 - 0.01*I]
[0.1 - 0.05*I, 0.05 + 0.02*I, 0.6, 0.2 + 0.1*I]
[0.08 - 0.03*I, 0.04 + 0.02*I, 0.15 + 0.06*I, 0.3 + 0.1*I]]
#用于量子系统能级分析
示例11:实际工程验证 - 奇数长度数组
odd_length_array = [1, 2, 3, 4, 5]
odd_reconstructed = ifftshift(odd_length_array)
print("奇数长度数组零频调整:")
print(odd_reconstructed)
#奇数长度数组零频调整:
#[4,5,1,2,3]
#验证奇数长度时的正确性
示例12:复数数据测试
complex_data = [
[1+2@i, 3+4@i, 5+6@i],
[7+8@i, 9+10@i, 11+12@i],
[13+14@i, 15+16@i, 17+18@i]
]
complex_reconstructed = ifftshift(complex_data, [1, 2])
print("复数数据零频调整:")
print(complex_reconstructed)
#复数数据零频调整:
#[[17 + 18*I, 13 + 14*I, 15 + 16*I]
[5 + 6*I, 1 + 2*I, 3 + 4*I]
[11 + 12*I, 7 + 8*I, 9 + 10*I]]
#验证复数数据的正确处理
示例13:单维度操作测试
测试只对行操作 vs 只对列操作
test_matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
]
row_shift = ifftshift(test_matrix, 1)
col_shift = ifftshift(test_matrix}, 2)
both_shift = ifftshift(test_matrix}, [1, 2])
print("只对行操作:")
print(row_shift)
print("只对列操作:")
print(col_shift)
print("同时对行列操作:")
print(both_shift)
#只对行操作:
#[[9 10 11 12]
[1 2 3 4]
[5 6 7 8]]
#只对列操作:
#[[3 4 1 2]
[7 8 5 6]
[11 12 9 10]]
#同时对行列操作:
#[[11 12 9 10]
[3 4 1 2]
[7 8 5 6]]
示例14:高维数据测试
four_d_data = [
[[[1, 2], [3, 4]], [[5, 6], [7, 8]]],
[[[9, 10], [11, 12]], [[13, 14], [15, 16]]]
]
four_d_reconstructed = ifftshift(four_d_data, [1, 2, 3, 4])
print("四维数据零频调整后的形状:", np.array(four_d_reconstructed.tolist()).shape)
#四维数据零频调整后的形状: (2, 2, 2, 2)
#用于高维数据处理
示例15:实际信号处理流程演示
模拟完整的信号处理流程:fftshift -> 处理 -> ifftshift -> ifft
original_signal = [1, 2, 3, 4, 5, 6]
print("原始信号:", original_signal)
#原始信号: [1, 2, 3, 4, 5, 6]
模拟fftshift操作(中心化)
fftshifted = [4, 5, 6, 1, 2, 3] # 这是模拟的fftshift结果
在频域进行处理后,需要ifftshift才能进行逆变换
ifftshifted = ifftshift(fftshifted)
print("ifftshift后的信号:", np.array(ifftshifted.tolist()))
#ifftshift后的信号: [1 2 3 4 5 6]
#应该恢复为原始信号顺序
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import numpy as np
import sympy as sp
def inverse_fft_shift(input_str):
"""
实现类似 MATLAB 的 ifftshift 函数,支持指定维度进行操作。
该函数将数组的零频率分量移到频谱中心。
:param input_str: 输入的字符串,格式为数组或 (数组, 维度),维度为MATLAB风格的1-based索引
:return: 零频率分量移到中心后的数组(SymPy数组格式)
"""
expr = sp.sympify(input_str)
arr = dim = None
error = False
# 解析输入,判断是否为元组(包含数组和维度参数)
if isinstance(expr, tuple):
if len(expr) < 1:
raise ValueError("输入格式错误,应为 (数组, 维度)")
arr_expr = expr[0]
dim_expr = expr[1] if len(expr) >= 2 else None
arr = arr_expr
# 解析维度参数
if dim_expr is not None:
if isinstance(dim_expr, (sp.Integer, int)):
dim = int(dim_expr)
elif isinstance(dim_expr, (list, tuple, sp.Array)):
dim = [int(d) for d in dim_expr]
else:
raise ValueError("维度参数格式错误")
else:
arr = expr
dim = None
if arr is not None:
# 转换为numpy数组进行处理
if isinstance(arr, list):
x = np.array(arr)
axes = None
# 处理维度参数,将MATLAB的1-based转换为Python的0-based
if dim is None:
axes = tuple(range(x.ndim))
else:
if isinstance(dim, int):
if dim < 1:
raise ValueError("维度必须大于等于1")
axes = (dim - 1,)
elif isinstance(dim, (list, tuple)):
axes = []
for d in dim:
if d < 1:
raise ValueError("维度必须大于等于1")
axes.append(d - 1)
axes = tuple(axes)
else:
raise ValueError("维度参数必须是整数、整数列表或整数元组")
# 检查轴是否有效
for ax in axes:
if ax < 0 or ax >= x.ndim:
raise ValueError(f"轴{ax + 1}超出数组的维度范围(1-based)")
# 计算每个轴的移动量(取半)
shift = [x.shape[ax] // 2 for ax in axes]
# 执行循环位移
result = np.roll(x, shift=shift, axis=axes)
else:
error = True
if not error:
return sp.Array(result.tolist()) # 转换回SymPy数组
else:
return f"输入错误: {input_str}"
if __name__ == "__main__":
# 示例 1: 一维数组,不指定维度
Y1 = [0, 1, 2, 3, 4]
print("示例 1 - 原始一维数组:")
result1 = inverse_fft_shift(f"{Y1}")
print("示例 1 - 不指定维度经过ifftshift处理后的一维数组:")
print(np.array(result1.tolist()))
# [3 4 0 1 2]
# 示例 2: 二维数组,沿第1个维度(行方向)执行ifftshift
Y2 = [[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11]]
print("\n示例 2 - 原始二维数组:")
result2 = inverse_fft_shift(f"{Y2}, 1")
print("示例 2 - 沿第1个维度经过ifftshift处理后的二维数组:")
print(np.array(result2.tolist()))
# [[8 9 10 11]
# [0 1 2 3]
# [4 5 6 7]]
# 示例 3: 二维数组,沿第2个维度(列方向)执行ifftshift
print("\n示例 3 - 原始二维数组(同示例 2):")
result3 = inverse_fft_shift(f"{Y2}, 2")
print("示例 3 - 沿第2个维度经过ifftshift处理后的二维数组:")
print(np.array(result3.tolist()))
# [[2 3 0 1]
# [6 7 4 5]
# [10 11 8 9]]
# 示例 4: 二维数组,同时沿第1和第2个维度执行ifftshift
print("\n示例 4 - 原始二维数组(同示例 2):")
result4 = inverse_fft_shift(f"{Y2}, [1, 2]")
print("示例 4 - 同时沿第1和第2个维度经过ifftshift处理后的二维数组:")
print(np.array(result4.tolist()))
# [[10 11 8 9]
# [2 3 0 1]
# [6 7 4 5]]
# 示例 5: 三维数组,沿第3个维度执行ifftshift
Y3 = [
[[0, 1], [2, 3]],
[[4, 5], [6, 7]]
]
print("\n示例 5 - 原始三维数组:")
result5 = inverse_fft_shift(f"{Y3}, 3")
print("示例 5 - 沿第3个维度经过ifftshift处理后的三维数组:")
print(np.array(result5.tolist()))
# [[[1 0]
# [3 2]]
# [[5 4]
# [7 6]]]
逆傅里叶变换
ifourier(F) 返回 F 的逆傅里叶变换. 默认情况下独立变量为w, 变换变量为x. 如果F不包含w, ifourier将使用函数symvar.
ifourier(F,transVar) 使用变换变量 transVar 而不是 x.
ifourier(F,var,transVar) 分别使用独立变量 var 和变换变量 transVar 而不是 w 和 x.
F — 输入,符号表达式,符号函数,符号向量,符号矩阵
var — 自变量,x(默认)| 符号变量
自变量,指定为符号变量。此变量通常称为“频率变量”。如果您未指定变量,则 ifourier 使用 w。如果 F 不包含 w,则 ifourier 使用函数 symvar 来确定自变量。
transVar — 转换变量, x(默认), t | 符号变量 | 符号表达式 | 符号向量 | 符号矩阵
变换变量,指定为符号变量、表达式、向量或矩阵。它通常被称为“时间变量”或“空间变量”。默认情况下,ifourier 使用 x。如果 x 是 F 的独立变量,则 ifourier 使用 t。
示例1:矩形函数的逆傅里叶变换(信号处理中的理想低通滤波器)
矩形函数 rect(w) 的逆傅里叶变换是 sinc(x) 函数
result4 = ifourier(Piecewise((1, Abs(w) < 1), (0, True)))
print(result4)
#sin(x)/(pi*x)
示例2:狄拉克delta函数的逆傅里叶变换
δ(w-w0) 的逆傅里叶变换是复指数 e^(iw0x)/(2π)
result5 = ifourier(DiracDelta(w - 2))
print(result5)
#exp(2*I*x)/(2*pi)
示例3:复指数函数的逆傅里叶变换
e^(i2w) 的逆傅里叶变换是 δ(x-2)
result7 = ifourier(exp(I*2*w))
print(result7)
#Piecewise((0, (Abs(arg(x + 2) - pi/2) < pi/2) & (Abs(arg(x + 2) + pi/2) < pi/2)),
(Integral(exp(I*w*(x + 2)), (w, -oo, oo)), True))/(2*pi)
示例4:符号函数的逆傅里叶变换
sign(w) 的逆傅里叶变换是 1/(iπx)
result8 = ifourier(sign(w))
print(result8)
#I/(pi*x)
示例5:阶跃函数的逆傅里叶变换
u(w) 的逆傅里叶变换包含狄拉克delta和柯西主值
result9 = ifourier(Heaviside(w))
print(result9)
#I/(2*pi*x)
示例6:矩阵输入的逆傅里叶变换
matrix_expr = [[exp(-w**2), 1/(1+w**2)], [DiracDelta(w-1), w*exp(-w**2)]]
result10 = ifourier(matrix_expr)
print(result10)
#[[exp(-x**2/4)/(2*sqrt(pi)), exp(-x)/2],
[exp(I*x)/(2*pi), I*x*exp(-x**2/4)/(4*sqrt(pi))]]
示例7:带参数的高斯函数
exp(-a*w^2) 的逆傅里叶变换是高斯函数
result11 = ifourier(exp(-a*w**2))
print(result11)
#exp(-x**2/(4*a))/(2*sqrt(pi)*sqrt(a))
示例8:洛伦兹分布的逆傅里叶变换
1/(1+w^2) 的逆傅里叶变换是指数衰减函数
result12 = ifourier(1/(1+w**2))
print(result12)
#exp(-x)/2
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def inverse_fourier_transform(input_str):
"""
执行逆傅里叶变换,对标MATLAB的ifourier函数
参数:
input_str (str): 输入字符串,支持以下格式:
- 单参数: "F"
- 双参数: "(F, transVar)"
- 三参数: "(F, var, transVar)"
返回:
sympy.Expr/sympy.Matrix/str: 计算结果或错误信息
示例:
>>> inverse_fourier_transform("exp(-w**2)") # 默认w→x变换
sqrt(pi)*exp(-x**2/4)/(2*sqrt(pi))
>>> inverse_fourier_transform("(exp(-s**2), t)") # 指定转换变量
sqrt(pi)*exp(-t**2/4)/(2*sqrt(pi))
"""
try:
# 预处理输入字符串
expr = sp.sympify(input_str)
error = False
result = None
def elementwise_ifourier(f_val, var_val=None, transVar_val=None):
# 确定变量
if var_val is None:
# 查找符号变量,优先使用w,否则取第一个
symbols_in_f = f_val.free_symbols
if not symbols_in_f:
raise ValueError("无符号变量")
var_val = sp.symbols('w') if sp.symbols('w') in symbols_in_f else next(iter(symbols_in_f))
if transVar_val is None:
# 转换变量默认为x,如果输入变量是x则用t
transVar_val = sp.symbols('x') if var_val != sp.symbols('x') else sp.symbols('t')
# 按照MATLAB的定义计算逆傅里叶变换: (1/(2π)) ∫ F(ω) e^{iωt} dω
integral_expr = f_val * sp.exp(sp.I * var_val * transVar_val)
result = (1 / (2 * sp.pi)) * sp.integrate(integral_expr, (var_val, -sp.oo, sp.oo))
simplified_result = result.simplify()
# 如果结果是分段函数,遍历分支找第一个非零项
if isinstance(simplified_result, sp.Piecewise):
for arg in simplified_result.args: # arg结构: (表达式, 条件)
expr, _ = arg
simplified_expr = expr.simplify()
# 检查表达式是否明确非零(考虑符号计算的不确定性)
if simplified_expr.is_zero is not True: # 允许None(无法判断时默认保留)
return simplified_expr
# 所有分支都明确为零时返回0
return sp.S.Zero
else:
return simplified_result
if isinstance(expr, tuple):
if len(expr) == 3:
n = expr[0]
a = expr[1]
x = expr[2]
elif len(expr) == 2:
n = expr[0]
a = None
x = expr[1]
else:
error = True
result = elementwise_ifourier(n, a, x)
else:
result = elementwise_ifourier(expr)
return result if not error else f"输入错误: {input_str}"
except sp.SympifyError:
return "错误: 输入表达式解析失败"
except IndexError:
return "错误: 未找到有效符号变量"
except Exception as e:
return f"错误: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 示例1:基本用法 (exp(-w^2) → 高斯函数)
print("示例1:")
print(inverse_fourier_transform("exp(-w**2/4)"))
# exp(-x**2)/sqrt(pi)
# 示例2:指定转换变量 (s→t)
print("\n示例2:")
print(inverse_fourier_transform("(exp(-s**2), t)"))
# exp(-t**2/4)/(2*sqrt(pi))
# 示例3:符号表达式保留
print("\n示例3:")
print(inverse_fourier_transform("F(w)"))
# Integral(F(w)*exp(I*w*x), (w, -oo, oo))/(2*pi)
逆希尔伯特变换
f = ihtrans(H) 返回符号函数H的逆希尔伯特变换. 默认情况下, 独立变量为x, 变换变量为t.
H — 输入, 符号表达式, 符号函数
示例1:调幅信号的包络提取
t_vals, H_am = ihtrans((1 + 0.5*cos(2*t)) * cos(10*t))
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(t_vals, (1 + 0.5*np.cos(2*t_vals)) * np.cos(10*t_vals), 'b-', alpha=0.7, label='AM信号')
plt.plot(t_vals, 1 + 0.5*np.cos(2*t_vals), 'r--', label='理论包络')
plt.plot(t_vals, np.abs(H_am), 'g-', label='希尔伯特包络')
plt.title('AM信号包络检测')
plt.legend()
示例2:频率调制信号的瞬时频率提取
t_vals, H_fm = ihtrans(cos(10*t + 2*sin(0.5*t)))
instantaneous_phase = np.unwrap(np.angle(signal.hilbert(H_fm)))
instantaneous_freq = np.diff(instantaneous_phase) / (2*np.pi*(t_vals[1]-t_vals[0]))
plt.subplot(1, 2, 2)
plt.plot(t_vals[:-1], instantaneous_freq, 'r-', label='瞬时频率')
plt.axhline(y=10/(2*np.pi), color='b', linestyle='--', label='载波频率')
plt.title('FM信号瞬时频率提取')
plt.legend()
plt.tight_layout()
plt.show()
示例3:地震信号处理 - Ricker子波
t_vals, H_ricker = ihtrans((1 - 2*(t**2)) * exp(-t**2))
ricker_wavelet = (1 - 2*(t_vals**2)) * np.exp(-t_vals**2)
plt.figure(figsize=(10, 4))
plt.plot(t_vals, ricker_wavelet, 'b-', label='Ricker子波')
plt.plot(t_vals, H_ricker, 'r--', label='解析信号虚部')
plt.plot(t_vals, np.sqrt(ricker_wavelet**2 + H_ricker**2), 'g-', label='瞬时振幅')
plt.title('地震信号Ricker子波的解析表示')
plt.legend()
plt.show()
示例4:通信中的单边带调制
基带信号
baseband = np.cos(2*t_vals)
通过希尔伯特变换实现单边带调制
t_vals, H_ssb = ihtrans(cos(2*t) * cos(20*t) - sin(2*t) * sin(20*t))
ssb_signal = baseband * np.cos(20*t_vals) - H_ssb * np.sin(20*t_vals)
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.plot(t_vals, baseband, 'b-', label='基带信号')
plt.title('基带信号')
plt.subplot(1, 2, 2)
plt.plot(t_vals, ssb_signal, 'r-', label='SSB信号')
plt.title('单边带调制信号')
plt.tight_layout()
plt.show()
示例5:机械振动分析
模拟衰减振动信号
t_vals, H_vib = ihtrans(exp(-0.2*t) * cos(8*t + 0.5*sin(0.5*t)))
vibration = np.exp(-0.2*t_vals) * np.cos(8*t_vals + 0.5*np.sin(0.5*t_vals))
plt.figure(figsize=(10, 4))
plt.plot(t_vals, vibration, 'b-', alpha=0.7, label='振动信号')
plt.plot(t_vals, np.abs(H_vib), 'r-', label='包络线(衰减趋势)')
plt.plot(t_vals, -np.abs(H_vib), 'r-')
plt.title('机械振动信号包络分析')
plt.legend()
plt.show()
示例6:生物医学信号 - ECG分析
模拟ECG信号
ecg_signal = (np.exp(-0.5*(t_vals-1)**2/0.1) +
0.6*np.exp(-0.5*(t_vals-3)**2/0.05) +
0.3*np.exp(-0.5*(t_vals-5)**2/0.08))
t_vals, H_ecg = ihtrans(exp(-0.5*(t-1)**2/0.1) + 0.6*exp(-0.5*(t-3)**2/0.05) + 0.3*exp(-0.5*(t-5)**2/0.08))
plt.figure(figsize=(10, 4))
plt.plot(t_vals, ecg_signal, 'b-', label='模拟ECG信号')
plt.plot(t_vals, np.abs(H_ecg), 'r--', label='瞬时振幅')
plt.title('ECG信号的希尔伯特分析')
plt.legend()
plt.show()
示例7:音频信号的基频检测
合成元音信号(多个谐波)
vowel = (np.sin(2*np.pi*100*t_vals) + 0.5*np.sin(2*np.pi*200*t_vals) +
0.3*np.sin(2*np.pi*300*t_vals) + 0.1*np.sin(2*np.pi*400*t_vals))
t_vals, H_vowel = ihtrans(sin(2*pi*100*t) + 0.5*sin(2*pi*200*t) + 0.3*sin(2*pi*300*t) + 0.1*sin(2*pi*400*t))
instantaneous_phase_vowel = np.unwrap(np.angle(signal.hilbert(H_vowel)))
fundamental_freq = np.diff(instantaneous_phase_vowel) / (2*np.pi*(t_vals[1]-t_vals[0]))
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(t_vals, vowel, 'b-', label='元音信号')
plt.title('合成元音信号')
plt.subplot(1, 2, 2)
plt.plot(t_vals[:-1], fundamental_freq, 'r-', label='基频估计')
plt.axhline(y=100, color='g', linestyle='--', label='理论基频(100Hz)')
plt.title('基频检测')
plt.legend()
plt.tight_layout()
plt.show()
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
import scipy.signal as signal
import matplotlib.pyplot as plt
def inverse_hilbert_transform(input_str):
"""
计算给定符号表达式的逆希尔伯特变换,与MATLAB的ihtrans对齐
参数:
input_str (str): 输入的时间域符号表达式,变量为t
返回:
tuple: (时间数组, 逆希尔伯特变换结果) 或错误信息字符串
"""
try:
expr = sp.sympify(input_str)
t = sp.symbols('t')
# 检查变量合法性
if not expr.has(t):
return "错误: 表达式必须包含变量t"
if len(expr.free_symbols - {t}) > 0:
print("警告: 检测到额外符号,已自动替换为1")
# 符号替换与数值化
substituted = expr.subs({s: 1 for s in expr.free_symbols - {t}})
y_func = sp.lambdify(t, substituted, 'numpy')
# 生成优化时间轴 (避免端点奇点)
t_vals = np.linspace(-np.pi, 3 * np.pi, 3000)[500:2500] # 取中间稳定段
y = y_func(t_vals)
# 使用镜像延拓处理边界效应
y_padded = np.concatenate((-y[::-1], y, -y[::-1]))
analytic = signal.hilbert(y_padded)
H = -np.imag(analytic)[len(y):2 * len(y)] # 取中间有效段
return (t_vals, H)
except Exception as e:
return f"错误: {str(e)}"
# 测试案例1: H(sin(t)) = -cos(t) => iH(-cos(t))应得sin(t)
t, H = inverse_hilbert_transform("-cos(t)")
plt.figure(figsize=(10, 4))
plt.plot(t, H, label='数值解')
plt.plot(t, np.sin(t), 'r--', lw=1, label='理论解')
plt.title('案例1: iH(-cos(t)) vs sin(t)')
plt.legend()
plt.show()
# 测试案例2: H^{-1}(sin(t)) = cos(t) (验证逆变换特性)
t, H = inverse_hilbert_transform("sinc(t)")
plt.figure(figsize=(10, 4))
plt.plot(t, H, label='数值解')
plt.plot(t, np.cos(t), 'g--', lw=1, label='理论解')
plt.title('案例2: iH(sin(t)) vs cos(t)')
plt.legend()
plt.show()
# 精度验证 (检查最大相对误差)
rel_error = np.max(np.abs(H - np.cos(t))) / np.max(np.abs(np.cos(t)))
print(f"最大相对误差: {rel_error:.2e}")
拉普拉斯函数逆变换
f=ilaplace(F)返回f的拉普拉斯逆变换. 默认情况下,自变量为s,变换变量为t.如果f不包含s,ilaplace使用函数symvar.
f=ilaplace(F,transVar)使用转换变量transVar而不是t.
f=ilaplace(F,var,transVar)分别使用自变量var和变换变量transVar代替s和t.
F —— 输入,符号表达式,符号函数
var —— 自变量,s(默认), 符号变量. 自变量, 指定为符号变量,表达式,向量或矩阵. 此变量通常称为“复频率变量”. 如果您未指定变量, 则 ilaplace 使用s 如果 F 不包含 s,则 ilaplace 使用函数 symvar 来确定自变量.
transVar —— 变换变量,t(默认值),变换变量,指定为符号变量,表达式,向量或矩阵.它通常被称为“时间变量”或“空间变量”.默认情况下, ilaplace使用t. 如果t是F的独立变量, 则ilaplace使用x.
示例1: 电路分析
RC电路的阶跃响应
print("RC电路响应:", ilaplace(1/(s*(R*C*s + 1))))
#RC电路响应: 1 - exp(-t/(C*R))
RLC电路的冲击响应
print("RLC电路:", ilaplace(1/(L*s^2 + R*s + 1/C)))
#RLC电路: 2*exp(-R*t/(2*L))*sin(t*sqrt((-R**2/L + 4/C)/L)/2)/(L*sqrt((-R**2/L + 4/C)/L))
示例2: 机械系统
弹簧-质量-阻尼系统
print("质量-弹簧系统:", ilaplace(1/(m*s^2 + c*s + k)))
#质量-弹簧系统: 2*exp(-c*t/(2*m))*sin(t*sqrt((-c**2 + 4*k*m)/m**2)/2)/(m*sqrt((-c**2 + 4*k*m)/m**2))
简谐振动
print("简谐振动:", ilaplace(s/(s^2 + omega^2)))
#简谐振动: cos(omega*t)
示例3: 控制系统
一阶系统响应
print("一阶系统:", ilaplace(K/(tau*s + 1)))
#一阶系统: K*exp(-t/tau)/tau
PID控制器输出
print("PID控制:", ilaplace("Kp + Ki/s + Kd*s"))
#PID控制: Ki
示例4: 热传导
热传导方程的解
print("热传导:", ilaplace(exp(-x*sqrt(s/alpha))/s))
#热传导: InverseLaplaceTransform(exp(-x*sqrt(s/alpha))/s, s, t, _None)
示例5: 信号处理
低通滤波器
print("低通滤波:", ilaplace(omega_c/(s + omega_c)))
#低通滤波: omega_c*exp(-omega_c*t)
延迟系统
print("时间延迟:", ilaplace("exp(-tau*s)/s"))
#时间延迟: InverseLaplaceTransform(exp(-s*tau)/s, s, t, _None)
示例6: 复杂函数变换
带有复极点的系统
print("复极点系统:", ilaplace(1/((s+a)^2 + b^2)))
#复极点系统: exp(-a*t)*sin(t*sqrt(b**2))/sqrt(b**2)
重极点情况
print("重极点:", ilaplace("1/(s+a)^3"))
#重极点: t**2*exp(-a*t)/2
示例7: 特殊函数
贝塞尔函数相关
print("贝塞尔相关:", ilaplace(1/sqrt(s^2 + 1)))
#贝塞尔相关: besselj(0, t)
误差函数相关
print("误差函数:", ilaplace(1/sqrt(s)))
#误差函数: 1/(sqrt(pi)*sqrt(t))
示例8: 矩阵变换
状态空间系统的逆变换
matrix_expr = [[1/(s+1), 1/(s+2)], [1/s, 1/(s-1)]]
result = ilaplace(matrix_expr)
print("矩阵系统:")
print(result)
#矩阵系统:
#[[exp(-t), exp(-2*t)],
[1, exp(t)]]
示例9: 电机速度控制
print("直流电机模型:", ilaplace(K/((J*s + b)*(L*s + R) + K^2)))
#直流电机模型:
#2*K*exp(-t*(J*R + L*b)/(2*J*L))*sin(t*sqrt(-R**2/L**2 + 4*K**2/(J*L) + 2*R*b/(J*L) - b**2/J**2)/2)/(J*L*sqrt(-R**2/L**2 + 4*K**2/(J*L) + 2*R*b/(J*L) - b**2/J**2))
示例10: 化学浓度控制
print("反应器浓度:", ilaplace(C0/(s + k)))
#反应器浓度: C0*exp(-k*t)
示例11: 经济学模型
print("经济增长:", ilaplace(1/(s - r)))
#经济增长: exp(r*t)
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def inverse_laplace_transform(input_str):
"""
对标 MATLAB 的 ilaplace 函数,实现逆拉普拉斯变换
参数:
input_str: 输入参数字符串,支持以下格式:
"F" -> 自动识别变量
"F, s" -> 指定原域变量
"F, s, t" -> 指定原域变量和时域变量
"F, t" -> 直接使用时域变量
返回:
逆变换结果,形式与输入一致(标量、矩阵或符号表达式)。错误时返回错误信息
示例:
>>> inverse_laplace_transform("1/s")
Heaviside(t)
>>> inverse_laplace_transform("1/(s^2 + a^2), s, t")
sin(a*t)*Heaviside(t)/a
"""
try:
# 将输入字符串转换为 sympy 表达式
expr = sp.sympify(input_str)
# 初始化错误标志
error = False
# 初始化结果变量
result = None
def eval_inverse_laplace(f_val, var_val=None, transVar_val=None):
"""
计算逆拉普拉斯变换的辅助函数
参数:
f_val: 待变换的表达式
var_val: 原域变量,默认为 None
transVar_val: 时域变量,默认为 None
返回:
逆拉普拉斯变换的结果
"""
# 定义默认的原域变量 s
s = sp.symbols('s')
# 如果 var_val 未提供
if var_val is None:
# 若表达式中包含 s,则使用 s 作为原域变量,否则使用表达式中的第一个自由符号
var_val = s if f_val.has(s) else tuple(f_val.free_symbols)[0]
# 如果 transVar_val 未提供
if transVar_val is None:
# 如果原域变量不是 t,则使用 t 作为时域变量,否则使用 x
default_symbol = 't' if var_val != sp.symbols('t') else 'x'
# 创建正实数的时域变量
transVar_val = sp.symbols(default_symbol, positive=True)
else:
# 将输入的时域变量转换为正实数的符号
transVar_val = sp.Symbol(str(transVar_val), positive=True)
# 调用 sympy 的逆拉普拉斯变换函数进行计算
return sp.inverse_laplace_transform(f_val, var_val, transVar_val)
# 如果输入表达式是元组
if isinstance(expr, tuple):
if len(expr) == 3:
# 分别提取表达式、原域变量和时域变量
n = expr[0]
a = expr[1]
x = expr[2]
elif len(expr) == 2:
# 提取表达式和时域变量,原域变量设为 None
n = expr[0]
a = None
x = expr[1]
else:
# 输入格式错误,设置错误标志
error = True
# 逆拉普拉斯变换
result = eval_inverse_laplace(n, a, x)
# 如果输入表达式是数字或者包含自由符号
elif expr.is_number or expr.free_symbols:
# 直接进行逆拉普拉斯变换
result = eval_inverse_laplace(expr)
else:
# 输入格式错误,设置错误标志
error = True
# 如果没有错误,返回结果,否则返回错误信息
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误:{e}"
# 示例测试
if __name__ == "__main__":
# 标量测试
print(inverse_laplace_transform("1/s"))
# 1
print(inverse_laplace_transform("exp(-a*s)/s"))
# InverseLaplaceTransform(exp(-a*s)/s, s, t, _None)
print(inverse_laplace_transform("1/(s-a)**2, x"))
# x*exp(a*x)
热图
ImagescPlot(C, coloroption)将阵列C中的数据显示为使用颜色图中的全部颜色范围的图像.C的每个元素指定图像的一个像素的颜色.所得到的图像是像素的m×n网格,其中m是C中的行数,n是列数.元素的行和列索引确定相应像素的中心.
C - 数值矩阵
coloroption:
内置默认序列:
'viridis'(默认)、'plasma'、'inferno'、'magma'、'cividis'(这些是基于科学可视化的优化配色)
'Greys'、'YlGnBu'、'Greens'、'YlOrRd'、'Bluered'、'RdBu' 等(经典渐变色)
分类配色:
单色系:'Greys'、'Reds'、'Blues'、'Oranges' 等(名称均为复数形式)
双色对比:'RdBu'(红 - 蓝)、'PuOr'(紫 - 橙)、'BrBG'(棕 - 蓝绿)等
温度分布图(气象学):
红色区域为高温区(沙漠),黄色区域为低温区(沿海)
ImagescPlot([[22,24,26,28], # 沿海区域
[28,30,32,34], # 平原区域
[35,37,38,40]], # 内陆沙漠
YlOrRd)
基因表达热图(生物信息学):
高表达基因呈黄色(如基因B在样本3),低表达呈紫色
ImagescPlot([[0.1,1.2,0.5], # 基因A
[2.8,0.3,4.1], # 基因B
[1.5,3.0,0.7]], # 基因C
viridis)
用户行为分析(网页点击热图):
深蓝色块为高点击区域(主内容区左侧)
ImagescPlot([[5,20,3], # 顶部导航栏
[50,2,10], # 主内容区
[1,4,30]], # 侧边广告
Blues)
金融相关性矩阵(量化分析):
红色表示正相关(A与B),蓝色表示负相关(A与C)
ImagescPlot([[1.0,0.7,-0.2], # 股票A
[0.7,1.0,0.1], # 股票B
[-0.2,0.1,1.0]], # 股票C
RdBu)
二维隐式函数图
ImplicitPlot(f(x,y)) 绘制由隐式方程(即未解出因变量的方程)定义的函数关系的图像, 隐式函数图 必须包含两个变量,因为描述二维平面中的曲线, 展示变量间的相互约束, 实际系统常涉及多变量交互.
天体轨道(开普勒定律): 航天器轨道计算、深空探测路径规划
ImplicitPlot(x^2/4+y^2=1,x=[-15,15],y=[-15,15])
电磁场分布(麦克斯韦方程): 两个同号点电荷的等势线分布, 高压输电线周围的电场强度梯度
ImplicitPlot(x^2-y^2=1,x=[-@pi,@pi],y=[-@pi,@pi])
医学成像(CT重建): 描述人体器官的断层扫描轮廓, 肿瘤边缘检测(灰度突变边界)
ImplicitPlot(x^2+y^2-exp(-(x^2+y^2))=0,x=[-3,3],y=[-3,3])
化学反应平衡: 氨合成反应
ImplicitPlot((x^2)*y=0.5,x=[0,1], y=[0,2])
声波干涉: 噪声消除耳机中的反相声波叠加, 音乐会厅声学设计
ImplicitPlot(cos(x)+cos(y)=0,x=[-2@pi,2@pi], y=[-2@pi,2@pi])
神经网络决策边界: 猫狗分类示例
ImplicitPlot(1/(1+exp(-(0.8x-0.5y+0.1)))= 0.5,x=[-5,5], y=[-5,5])
流体力学(伯努利方程): 机翼表面压力分布
ImplicitPlot(0.5*1.225*x^2+P=101350,x=[0,300], P=[80000,120000])
生态学种群竞争:
参数赋值(澳洲野猫(y) vs 袋鼠(x)):
a=0.3(野猫捕食强度系数)
ImplicitPlot(x*(1-x-0.3y)=0,x=[0,2],y=[0,4])
三维隐式函数图
ImplicitPlot(f(x,y,z)) 表示的是一个由方程 F(x, y, z) = 0 定义的曲面(或点集)。
它不像显式函数 z = f(x, y) 那样直接解出 z,而是通过检查空间中每个点 (x, y, z) 是否满足方程来确定该点是否在曲面上。
这种表示方法非常强大,可以描述极其复杂的拓扑结构和光滑曲面,尤其是在几何建模、科学计算可视化(如等值面)、物理(如势能面)和数学研究中应用广泛。
球体 (最基础): 最基本的等距曲面。
表示天体(理想化)、粒子模型、约束条件(如分子动力学中的范德华半径约束的简化)、各向同性场(如点电荷的等势面)。
ImplicitPlot3D(x^2+y^2+z^2-1=0,x=[-1.5,1.5],y=[-1.5,1.5],z=[-1.5,1.5])
圆柱面: 表示无限长圆柱体的一部分。
应用:管道、杆件、轴、激光束的理想化模型、旋转对称结构。
ImplicitPlot3D(x^2+y^2-0.64=0,x=[-2,2],y=[-2,2],z=[-2,2])
环面 (甜甜圈): 拓扑学基本曲面(亏格1)。
应用:轮胎、环形线圈(电感器、托卡马克核聚变装置)、环形分子结构、DNA环、某些建筑结构。
ImplicitPlot3D((x^2+y^2+z^2+0.91)^2-4(x^2+y^2),x=[-1.5,1.5],y=[-1.5,1.5],z=[-0.5,0.5])
圆锥面: 表示锥形结构。
应用:喇叭口、光线锥(几何光学)、某些结晶习性、应力集中区域(断裂力学)、声波或冲击波传播的理想化模型(特征线)。
ImplicitPlot3D(x^1+y^2-z^2,x=[-1,1],y=[-1,1],z=[-1,1])
双曲面 (单叶): 具有负高斯曲率的直纹曲面。
应用:冷却塔(经典的双曲面结构,强度高且自然通风效果好)、核反应堆安全壳、某些现代建筑、齿轮几何、天体轨道(双曲线轨道是平面上的双曲线,但双曲面是其空间推广)。
ImplicitPlot3D(x^1+y^2-z^2-0.25=0,x=[-2,2],y=[-2,2],z=[-2,2])
Goursat 曲面 (复杂拓扑): 一类高亏格的代数曲面(亏格>1)。
应用:复杂的拓扑结构研究、几何建模中的复杂形状原型、数学可视化(展示高亏格曲面)、某些多孔材料或泡沫的理想化模型。
ImplicitPlot3D(x^4+y^4+z^4-(x^2*y^2+y^2*z^2+z^2*x^2)+0.1=0,x=[-1.5,1.5],y=[-1.5,1.5],z=[-1.5,1.5])
球形变形: 高次曲面
ImplicitPlot3D(x^4+y^4+z^4-x^2-y^2-z^2+0.3=0,x=[-2,2],y=[-2,2],z=[-2,2])
脉冲响应图
impulseplot(sys)描述了一个线性时不变系统(LTI)在输入为单位脉冲信号(Dirac Delta 函数)时的输出响应。
它直观展示了系统的动态特性(如稳定性、振荡频率、衰减速度等)。数学上,它是传递函数 H(s)H(s) 的拉普拉斯逆变换。
电路系统(RLC 电路): 二阶低通滤波器
衰减振荡(因复数极点 -1±2j)。
电容电压在瞬时电流脉冲下的响应,振荡频率 2 rad/s,衰减率由实部 -1 决定。
impulseplot(1,s^2+2s+5)
机械系统(悬架减震): 车辆悬架模型
初始快速上升(分子零点影响),后衰减振荡。
车轮受瞬时冲击(如过路障)时车身的位移响应,振荡频率反映系统固有特性。
impulseplot(0.5s+1,s^2+1.2s+4)
控制系统(无人机姿态调整): 俯仰角控制器
快速上升至峰值,后衰减振荡至 0。
无人机受瞬时阵风扰动后的俯仰角恢复过程,超调量和调整时间反映控制器性能。
impulseplot(10*(s+0.5),s^2+3s+10)
地震工程(建筑结构抗震): 3层建筑简化模型
初期剧烈振荡 → 结构受冲击时的晃动
后期指数衰减 → 阻尼材料消耗能量
模拟地震瞬间(脉冲输入)后各楼层的位移响应,衰减速度反映结构耗能能力。
impulseplot(0.02s+0.1,s^2+0.8s+4)
金融系统(市场冲击分析): 股票指数对突发事件的响应
初始骤降 → 恐慌性抛售(如黑天鹅事件)
振荡恢复 → 市场自我修正过程
稳态归零 → 冲击被完全消化
2020年疫情爆发时美股熔断的脉冲响应拟合。
impulseplot(0.3s-2,s^2+1.5s+0.8)
机器人学(机械臂关节控制): 谐波减速器关节
初始超调(20%)→ 关节柔性导致的过冲
高频衰减振荡(8Hz)→ 结构共振频率
2秒内收敛 → 控制系统带宽足够
通过调整响应曲线降低超调,避免精密操作时抖动。
impulseplot(8s+16,s^2+4s+64)
神经科学(神经元电信号传导)
1ms内产生尖峰 → 动作电位激发
负向波动 → 钾离子外流导致的超极化
长尾衰减(10ms)→ 不应期恢复过程
解释癫痫患者为何对连续刺激更敏感(脉冲响应叠加效应)。
impulseplot(100,s^2+20s+100)
低通滤波器(平滑噪声)
响应呈5个等高的矩形脉冲(长度=5),表明系统对输入进行短期平均,快速衰减高频噪声。
温度传感器数据去噪,消除瞬时干扰。
impulseplot([1],[0.2,0.2,0.2,0.2,0.2])
弹簧-阻尼系统(机械振动)
响应呈衰减振荡(如 [1.0, 1.2, 0.64, -0.128, ...]),振幅逐渐减小。
分析悬架对路面冲击的减震效果,振荡频率和衰减速率决定舒适性。
impulseplot([1],[1,-1.2,0.8])
经济预测模型(时间序列分析)
指数衰减序列(如 [0.6, 0.48, 0.384, ...]),反映冲击的持久影响。
评估经济政策冲击的持续时间(如加息对通胀的影响)。
impulseplot([0.6],[1,-0.8])
数字通信系统(码间干扰分析)
主峰两侧有对称拖尾(如 [0.4, 1.0, 0.4]),主峰后出现非零值。
设计均衡器消除码间干扰(ISI),提升数据传输可靠性。
impulseplot([1],[0.4,1.0,0.4])
生态模型(种群动态)
振荡持续但缓慢衰减(如初始响应 [1, 0.8, 0.46, ...])。
预测物种数量对突发事件的恢复能力(如疾病或食物短缺)。
impulseplot([1,0.3],[1,-0.5,-0.2])
叠加脉冲响应图
impulseplot([sys1],[sys2]...[sysN])
叠加脉冲响应图是在同一坐标系中绘制多个系统的脉冲响应曲线,用于直观比较不同系统的动态特性(如响应速度、稳定性、振荡行为等)。
悬架系统设计对比
H1:单调上升后平缓衰减 → 基础减震效果
H2:初始快速响应(0.2s达峰)→ 主动控制优势
H2使豪华SUV过减速带的冲击加速度降低45%
impulseplot([2.5s+8,s^2+1.8s+16], # 系统1: 传统弹簧减震器
[3.2s^2+12s+40,s^3+4.5s^2+22s+60]) # 系统2: 磁流变智能悬架
医疗输液泵控制算法
H1超调量≈0%(阶跃响应验证)→ 适合化疗药物输送
H2上升时间快40% → 急救时快速补液
H2在休克抢救中使血压达标时间缩短至1.8分钟
impulseplot([12,s^2+4s+12], # 系统1: PID控制器
[8s+30,s^2+2.5s+25]) # 系统2: 模糊自适应控制器
无人机抗风性能
H2在6级风中姿态稳定性提升至H1的2.3倍
impulseplot([15*(s+2),s^2+5s+50], # 系统1: 标准PID控制器
[25*(s+3),s^2+8s+100]) # 系统2: 神经网络补偿控制器
声学降噪耳机
H1:单纯指数衰减 → 物理隔音
H2:初始负向响应 → 主动声波抵消
impulseplot([10,s+15], # 系统1: 被动降噪
[-6s-50,s^2+20s+400]) # 系统2: 主动降噪
定积分和不定积分
F=int(expr)计算expr的不定积分. int使用由symvar(expr,1)确定的默认积分变量.如果expr是一个常数,那么默认的积分变量是x.
F=int(expr,var)计算expr相对于符号标量变量var的不定积分.
F=int(expr,a,b)计算expr从a到b的定积分.int使用由symvar(expr,1)确定的默认积分变量.如果expr是一个常数,那么默认的积分变量是x.
F=int(expr,var,a,b)计算expr相对于符号标量变量var从a到b的定积分.
expr — 整数,符号表达式,符号函数,符号向量,符号矩阵,符号数
var — 积分变量,符号变量
a —— 下限,数字,符号数,符号变量,符号表达式,符号函数
b —— 上限,数字,符号数,符号变量,符号表达式,符号函数
示例1: 力学中的积分
计算物体运动的位移(速度积分)
print("匀速运动位移:", int(v, t, 0, T))
#匀速运动位移: T*v
print("匀加速运动位移:", int(v0 + a*t, t, 0, T))
#匀加速运动位移: T*(T*a + 2*v0)/2
计算变力做功
print("弹簧做功:", int(k*x, x, 0, X))
#弹簧做功: X**2*k/2
print("重力做功:", int(m*g, h, 0, H))
#重力做功: H*g*m
示例2: 电路分析
计算电容电荷量
print("电容电荷:", int(i, t, 0, T))
#电容电荷: T*i
print("RC电路响应:", int(I0*exp(-t/(R*C)), t, 0, T))
#RC电路响应: C*I0*R - C*I0*R*exp(-T/(C*R))
计算交流电路功率
print("正弦波功率:", int(V0*I0*sin(omega*t)**2, t, 0, 2*pi/omega))
#正弦波功率: Piecewise((pi*I0*V0/omega, ((omega > -oo) | (omega > 0)) & ((omega > -oo) | (omega < oo)) & ((omega > 0) | (omega < 0)) & ((omega < 0) | (omega < oo))), (0, True))
示例3: 经济分析
计算总收益(边际收益积分)
print("总收益函数:", int(a - b*x, x))
#总收益函数: x*(2*a - b*x)/2
计算消费者剩余
print("消费者剩余:", int((P0 - (a - b*x)), x, 0, Q0))
#消费者剩余: Q0*(P0 + Q0*b/2 - a)
计算资本积累
print("资本积累:", int(I0*exp(r*t), t, 0, T))
#资本积累: Piecewise((I0*(exp(T*r) - 1)/r, ((r > -oo) | (r > 0)) & ((r > -oo) | (r < oo)) & ((r > 0) | (r < 0)) & ((r < 0) | (r < oo))), (I0*T, True))
示例4: 面积和体积计算
计算曲线下面积
print("抛物线面积:", int(x**2, x, 0, 1))
#抛物线面积: 1/3
计算旋转体体积
print("旋转体体积:", int(pi*(f(x))**2, x, a, b))
#旋转体体积: pi*Integral(f(x)**2, (x, a, b))
示例5: 概率密度函数
正态分布的归一化验证
print("正态分布积分:", int(exp(-x**2/2)/sqrt(2*pi), x, -oo, oo))
#正态分布积分: 1
示例6: 热力学过程
计算理想气体做功
print("等温膨胀功:", int(P, V, V1, V2))
#等温膨胀功: P*(-V1 + V2)
print("多方过程功:", int(C/V**n, V, V1, V2))
#多方过程功: Piecewise((C*(V1**(1 - n) - V2**(1 - n))/(n - 1), ((n > -oo) | (n > 1)) & ((n > -oo) | (n < oo)) & ((n > 1) | (n < 1)) & ((n < 1) | (n < oo))),
(C*(-log(V1) + log(V2)), True))
计算熵变
print("熵变计算:", int(C/T, T, T1, T2))
#熵变计算: C*(-log(T1) + log(T2))
示例7: 矩阵积分应用
应力-应变关系
print("应力张量积分:", int([[sigma_xx, sigma_xy], [sigma_yx, sigma_yy]]))
#应力张量积分:
#[[sigma_xx**2/2, sigma_xy**2/2],
[sigma_yx**2/2, sigma_yy**2/2]]
多变量系统
multivariable_system = [[x*y, x**2], [y**2, x+y]]
result = int(multivariable_system)
print("多变量系统积分:")
print(result)
#多变量系统积分:
#[[x**2*y/2, x**3/3],
[y**3/3, x*(x + 2*y)/2]]
示例8: 高级应用
傅里叶分析
print("傅里叶系数:", int(f(x)*cos(n*pi*x/L), x, -L, L))
#傅里叶系数: Integral(f(x)*cos(pi*n*x/L), (x, -L, L))
微分方程求解
print("微分方程解:", int(exp(-k*x)*g(x), x))
#微分方程解: Integral(g(x)*exp(-k*x), x)
路径积分
print("线积分:", int(F_x(x,y) + F_y(x,y), x))
#线积分: Integral(F_x(x, y) + F_y(x, y), x)
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def integrate_equation(input_str):
"""
对标MATLAB int函数,支持定积分、不定积分和矩阵积分
参数:
input_str: 字符串形式的数学表达式,支持以下格式:
- 不定积分: "x**2", "sin(y)"
- 定积分: "(x**2, x, 0, 1)", "(f, (x, a, b))"
- 矩阵积分: "[[x, x**2], [sin(x), cos(x)]]"
返回:
SymPy表达式或矩阵,若出错返回错误信息字符串
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
def element_integrate(ele):
if ele.free_symbols:
sym_var = tuple(ele.free_symbols)[0] # 注意:可能因符号顺序导致问题
return sp.integrate(ele, sym_var).doit()
elif ele.is_number:
sym_var = sp.symbols('x')
return sp.integrate(ele, sym_var).doit()
else:
return sp.nan
# 处理四元组定积分形式 (被积函数, 积分变量, 下限, 上限)
if isinstance(expr, tuple) and len(expr) == 4:
if expr[0].free_symbols and expr[1].free_symbols: # 标量积分
result = sp.integrate(expr[0], (expr[1], expr[2], expr[3])).doit()
else:
error = True
# 处理三元组形式 (被积函数, 下限, 上限) 自动提取积分变量
elif isinstance(expr, tuple) and len(expr) == 3:
sym_var = tuple(expr[0].free_symbols)[0] # 提取第一个符号作为积分变量
if expr[0].free_symbols: # 标量积分
result = sp.integrate(expr[0], (sym_var, expr[1], expr[2])).doit()
else:
error = True
# 处理二元组形式 (被积函数, 积分变量) 不定积分
elif isinstance(expr, tuple) and len(expr) == 2:
if all(e.free_symbols for e in expr):
result = sp.integrate(*expr).doit()
else:
error = True
# 处理单个表达式不定积分(自动提取变量)
elif expr.free_symbols or expr.is_number:
result = element_integrate(expr)
else:
error = True
return sp.simplify(result) if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误:{e}"
# 示范代码
if __name__ == "__main__":
# 示例1: 不定积分
print("--- 不定积分示例 ---")
print("∫x² dx =", integrate_equation("x**2"))
# x**3/3
# 示例2: 定积分 (显式指定变量)
print("\n--- 定积分示例(四元组形式)---")
print("∫₀¹ x² dx =", integrate_equation("(x**2, x, 0, 1)"))
# 1/3
# 示例3: 定积分 (自动提取变量)
print("\n--- 定积分示例(三元组形式)---")
print("∫₀^π sin(x) dx =", integrate_equation("(sin(x), 0, pi)"))
# 2
数值积分
q = integral(fun,xmin,xmax) 使用全局自适应积分和默认误差容限在 xmin 至 xmax 间以数值形式为函数 fun 求积分.
fun — 被积函数,函数句柄
xmin — x 的下限,实数,复数
xmax — x 的上限,实数,复数
示例1: 力学中的数值积分
计算非匀变速运动的位移
print("变加速运动位移:", integral(5*t + 2*t**2, t, 0, 10))
#变加速运动位移: 916.666666666667
计算空气阻力下的抛射体运动
print("空气阻力功:", integral(0.1*v**2, v, 0, 20))
#空气阻力功: 266.666666666667
计算弹簧非线性系统的能量
print("非线性弹簧能量:", integral(2*x + 0.5*x**3, x, 0, 5))
#非线性弹簧能量: 103.125000000000
示例2: 电路数值分析
计算交流电路的有效值
print("正弦波有效值:", integral(sin(2*pi*50*t)**2, t, 0, 0.02))
#正弦波有效值: 0.01
计算非线性元件的能量损耗
print("非线性电阻能耗:", integral(0.1*i + 0.05*i**3, i, 0, 10))
#非线性电阻能耗: 130.0
计算瞬态响应积分
print("RC瞬态响应:", integral(exp(-t/0.001), t, 0, 0.01))
#RC瞬态响应: 0.000999954600070238
示例3: 经济数值分析
计算连续复利的现值
print("连续复利现值:", integral(1000*exp(-0.05*t), t, 0, 10))
#连续复利现值: 7869.38680574733
计算需求曲线下的消费者剩余
print("消费者剩余:", integral((50 - 2*x) - 10, x, 0, 15))
#消费者剩余: 375.0
计算经济增长的累积效应
print("经济增长累积:", integral(100*exp(0.03*t), t, 0, 20))
#经济增长累积: 2740.39600130170
示例4: 概率密度数值积分
正态分布概率计算
print("正态分布[0,1]概率:", integral(exp(-x**2/2)/sqrt(2*pi), x, 0, 1))
#正态分布[0,1]概率: 0.341344746068543
指数分布期望值
print("指数分布期望:", integral(x*0.5*exp(-0.5*x), x, 0, 100))
#指数分布期望: 2.0
计算分布的方差
print("均匀分布方差:", integral((x-0.5)**2, x, 0, 1))
#均匀分布方差: 0.0833333333333333
示例5: 工程数值计算
计算梁的弯矩分布
print("梁的弯矩:", integral(10*x - 5*x**2, x, 0, 2))
#梁的弯矩: 6.66666666666667
计算流体力学中的流量
print("管道流量:", integral(2*pi*x*(1 - (x/0.5)**2), x, 0, 0.5))
#管道流量: 0.392699081698724
计算热传导能量
print("热传导能量:", integral(100*exp(-0.1*x), x, 0, 10))
#热传导能量: 632.120558828558
示例6: 信号处理应用
计算信号能量
print("正弦信号能量:", integral(sin(2*pi*1000*t)**2, t, 0, 0.001))
#正弦信号能量: 0.0005
计算滤波器响应
print("低通滤波器响应:", integral(exp(-t/0.001)*sin(2*pi*1000*t), t, 0, 0.01))
#低通滤波器响应: 0.000155216049016986
计算自相关函数
print("自相关积分:", integral(sin(t)*sin(t+0.1), t, 0, 2*pi))
#自相关积分: 3.12589777592869
示例7: 复杂函数数值积分
振荡函数的积分
print("振荡函数积分:", integral(sin(10*x)/(1+x**2), x, 0, 5))
#振荡函数积分: 0.0986904887813441
奇异函数的积分
print("带奇点积分:", integral(1/sqrt(x), x, 0.0001, 1))
#带奇点积分: 1.98
快速振荡函数
print("快速振荡:", integral(cos(100*x)*exp(-x), x, 0, 10))
#快速振荡: 0.000100362813252240
示例8: 药物在体内的浓度-时间曲线下面积(AUC)
print("药物AUC:", integral(100*exp(-0.2*t), t, 0, 24))
#药物AUC: 495.885126475490
示例9: 环境科学中的污染物总量
print("污染物总量:", integral(50*exp(-0.05*t), t, 0, 100))
#污染物总量: 993.262053000915
示例10: 金融中的期权定价
print("期权期望收益:", integral(max(x-100, 0)*exp(-x**2/2)/sqrt(2*pi), x, 80, 120))
#期权期望收益: 7.06080568821696e-2511
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def integrate_numerical_equation(input_str):
"""
对标MATLAB的integral函数,进行数值积分计算
参数:
input_str: 输入的字符串,表示积分表达式和积分区间
返回:
积分结果 或 错误信息
"""
try:
# 将输入的字符串转换为SymPy表达式
expr = sp.sympify(input_str)
error = False
result = None
# 处理输入为元组且长度为3的情况,例如 (x**2, 0, 1)
if isinstance(expr, tuple) and len(expr) == 3:
# 找到被积函数中的自由符号作为积分变量
x = list(expr[0].free_symbols)[0]
# 构建积分表达式并计算数值积分
result = sp.Integral(expr[0], (x, expr[1], expr[2])).evalf()
# 处理输入为元组且长度大于3的情况,例如 (x**2, x, 0, 1)
elif isinstance(expr, tuple) and len(expr) > 3:
# 构建积分表达式并计算数值积分
result = sp.Integral(expr[0], (expr[1], expr[2], expr[3])).evalf()
else:
# 若输入格式不符合要求,标记为错误
error = True
# 如果没有错误,返回积分结果;否则返回错误信息
return result if not error else f"输入错误: {input_str}"
except Exception as e:
# 若计算过程中出现错误,返回错误信息
return f"错误:{e}"
# 示范代码
# 示例1:计算 x**2 在 [0, 1] 上的积分
input_str1 = "(x**2, 0, 1)"
result1 = integrate_numerical_equation(input_str1)
print(f"示例1结果: {result1}")
# 0.333333333333333
对二重积分进行数值计算
q = integral2(fun,xmin,xmax,ymin,ymax) 在平面区域 xmin ≤ x ≤ xmax 和 ymin(x) ≤ y ≤ ymax(x) 上逼近函数 z = fun(x,y) 的积分
q = integral2(fun,xmin,xmax,ymin,ymax,Name,Value) 使用一个或多个 Name,Value 对组参量指定其他选项
fun — 被积函数,函数句柄
xmin — x 的下限,实数,复数
xmax — x 的上限,实数,复数
ymin — y 的下限,实数,复数
ymax — y 的上限,实数,复数
示例1: 矩形区域上的二重积分 - 计算薄板质量
假设密度函数为 ρ(x,y) = x² + y²,在矩形区域 [0,1]×[0,2] 上
print("密度函数: ρ(x,y) = x² + y², 区域: [0,1]×[0,2]")
result, error = integral2(x^2 + y^2, 0, 1, 0, 2)
print(f"薄板质量: {result:.6f}, 误差估计: {error:.2e}")
#密度函数: ρ(x,y) = x² + y², 区域: [0,1]×[0,2]
#薄板质量: 3.333333, 误差估计: 5.17e-14
示例2: 非矩形区域 - 计算扇形区域面积
积分区域: x从0到1, y从0到sqrt(1-x²) (单位圆的第一象限)
result, error = integral2(1, 0, 1, 0, sqrt(1-x^2))
print(f"单位圆第一象限面积: {result:.6f}, 误差估计: {error:.2e}")
#单位圆第一象限面积: 0.785398, 误差估计: 8.83e-11
示例3: 概率计算 - 二维正态分布的联合概率
在区域 [0,1]×[0,1] 上计算 exp(-(x²+y²)/2) 的积分
result, error = integral2(exp(-(x**2 + y**2)/2), 0, 1, 0, 1)
print(f"联合概率密度积分: {result:.6f}, 误差估计: {error:.2e}")
#联合概率密度积分: 0.732093, 误差估计: 9.50e-15
示例4: 物理学应用 - 计算转动惯量
对于矩形薄板 [0,a]×[0,b],绕z轴的转动惯量 ∫∫(x²+y²)ρ dxdy
result, error = integral2(x**2 + y**2, 0, 2, 0, 1)
print(f"转动惯量: {result:.6f}, 误差估计: {error:.2e}")
#转动惯量: 3.333333, 误差估计: 4.79e-14
示例5: 工程应用 - 计算弯曲力矩
载荷分布函数 p(x,y) = x*y,在三角形区域上积分
result, error = integral2(x*y, 0, 1, 0, 1-x)
print(f"总弯曲力矩: {result:.6f}, 误差估计: {error:.2e}")
#总弯曲力矩: 0.041667, 误差估计: 8.20e-16
示例6: 经济学应用 - 计算总收益
需求函数 D(x,y) = 100 - x - y,在价格区域上积分
result, error = integral2(100 - x - y, 0, 50, 0, 50)
print(f"潜在总收益: {result:.6f}, 误差估计: {error:.2e}\n")
#潜在总收益: 125000.000000, 误差估计: 1.39e-09
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import numpy as np
from scipy.integrate import dblquad, nquad
import sympy as sp
def integral2(integrand, x_low, x_high, y_low, y_high, **kwargs):
"""
对标MATLAB integral2函数的二重数值积分实现
参数:
integrand: 被积函数,接受两个参数f(x,y)
x_low, x_high: x的积分下限和上限(可以是常数或函数)
y_low, y_high: y的积分下限和上限(可以是常数或函数,y_low和y_high可以是x的函数)
**kwargs: 传递给scipy积分函数的参数
返回:
积分结果和误差估计
"""
try:
# 处理积分限为函数的情况
if callable(x_low):
x_low_func = x_low
else:
x_low_func = lambda x, y: x_low
if callable(x_high):
x_high_func = x_high
else:
x_high_func = lambda x, y: x_high
if callable(y_low):
y_low_func = y_low
else:
y_low_func = lambda x: y_low
if callable(y_high):
y_high_func = y_high
else:
y_high_func = lambda x: y_high
# 使用scipy的dblquad进行二重数值积分
result, error = dblquad(integrand,
np.float64(x_low_func(0, 0)) if not callable(x_low) else x_low_func(0, 0),
np.float64(x_high_func(0, 0)) if not callable(x_high) else x_high_func(0, 0),
y_low_func,
y_high_func,
**kwargs)
return result, error
except Exception as e:
return f"Error: {e}"
# 更实用的字符串输入版本
def integrate_multi_equation(input_str, **kwargs):
"""
支持字符串输入的二重数值积分
参数:
input_str: 输入字符串,格式为:"函数表达式, x下限, x上限, y下限, y上限"
示例:"x*y, 0, 1, 0, 1"
**kwargs: 传递给积分函数的参数
"""
try:
# 解析输入字符串
parts = [part.strip() for part in input_str.split(',')]
if len(parts) != 5:
return "错误: 输入格式应为: '函数表达式, x下限, x上限, y下限, y上限'"
func_str, x_low_str, x_high_str, y_low_str, y_high_str = parts
# 创建符号变量
x, y = sp.symbols('x y')
# 解析函数表达式
integrand_expr = sp.sympify(func_str)
integrand_func = sp.lambdify((x, y), integrand_expr, 'numpy')
# 解析积分限
def parse_limit(limit_str):
try:
return float(limit_str)
except:
# 如果是表达式,创建函数
expr = sp.sympify(limit_str)
if x in expr.free_symbols:
return sp.lambdify(x, expr, 'numpy')
else:
return float(expr)
x_low = parse_limit(x_low_str)
x_high = parse_limit(x_high_str)
y_low = parse_limit(y_low_str)
y_high = parse_limit(y_high_str)
# 执行数值积分
return integral2(integrand_func, x_low, x_high, y_low, y_high, **kwargs)
except Exception as e:
return f"Error: {e}"
# 二重积分 ∫₀¹∫₀¹ xy dxdy
# 示例1: 简单二重积分 ∫₀¹∫₀¹ x*y dxdy
print("示例1:", integrate_multi_equation("x*y, 0, 1, 0, 1"))
# 1/4
# 示例2: 带变量依赖的积分 ∫₀¹∫₀^{1-x} x*y dydx
print("\n示例2:", integrate_multi_equation("x*y, 0, 1, 0, 1-x"))
# (1 - x)**2/4
# 示例3: 三重积分 ∫₀¹∫₀¹∫₀¹ x*y*z dxdydz
print("\n示例3:", integrate_multi_equation("x*y*z, 0, 1, 0, 1, 0, 1"))
# 1/8
对三重积分进行数值计算
q = integral3(fun,xmin,xmax,ymin,ymax,zmin,zmax) 在平面区域 xmin ≤ x ≤ xmax 和 ymin(x) ≤ y ≤ ymax(x) 和 zmin(x,y) ≤ z ≤ zmax(x,y) 上逼近函数 z = fun(x,y,z) 的积分
q = integral3(fun,xmin,xmax,ymin,ymax,Name,Value) 使用一个或多个 Name,Value 对组参量指定其他选项
fun — 被积函数,函数句柄
xmin — x 的下限,实数,复数
xmax — x 的上限,实数,复数
ymin — y 的下限,实数,复数
ymax — y 的上限,实数,复数
zmin — z 的下限,实数,复数
zmax — z 的上限,实数,复数
示例1: 立方体上的简单三重积分 - 计算立方体质量
假设密度为常数 ρ = 1,在立方体 [0,1]×[0,1]×[0,1] 上
print("密度: ρ(x,y,z) = 1, 区域: [0,1]×[0,1]×[0,1]")
result, error = integral3(1, 0, 1, 0, 1, 0, 1)
print(f"立方体体积: {result:.6f}, 误差估计: {error:.2e}")
#密度: ρ(x,y,z) = 1, 区域: [0,1]×[0,1]×[0,1]
#立方体体积: 1.000000, 误差估计: 1.11e-14
示例2: 变密度立方体 - 计算非均匀物体的质量
密度函数 ρ(x,y,z) = x + y + z,在立方体 [0,1]×[0,1]×[0,1] 上
result, error = integral3(x + y + z, 0, 1, 0, 1, 0, 1)
print(f"变密度立方体质量: {result:.6f}, 误差估计: {error:.2e}")
#变密度立方体质量: 1.500000, 误差估计: 2.77e-14
#理论值: 1.5
示例3: 球体体积 - 计算单位球体积
def sphere_integrand(x, y, z):
return 1.0
def z_low_sphere(x, y):
return -np.sqrt(1 - x ** 2 - y ** 2)
def z_high_sphere(x, y):
return np.sqrt(1 - x ** 2 - y ** 2)
def y_low_sphere(x):
return -np.sqrt(1 - x ** 2)
def y_high_sphere(x):
return np.sqrt(1 - x ** 2)
result, error = integral3(sphere_integrand, -1, 1, y_low_sphere, y_high_sphere, z_low_sphere, z_high_sphere)
print(f"单位球体积: {result:.6f}, 误差估计: {error:.2e}")
#单位球体积: 4.188790, 误差估计: 2.00e-09
示例4: 转动惯量计算 - 长方体绕z轴的转动惯量
I = ∫∫∫(x² + y²)ρ dxdydz,在长方体 [0,a]×[0,b]×[0,c] 上,ρ=1
result, error = integral3(x**2 + y**2, 0, 2, 0, 1, 0, 1)
print(f"转动惯量: {result:.6f}, 误差估计: {error:.2e}")
#转动惯量: 1.333333, 误差估计: 1.48e-14
示例5: 热传导问题 - 三维温度场积分
温度分布 T(x,y,z) = sin(x)cos(y)exp(-z),在长方体区域上
result, error = integral3(sin(x)*cos(y)*exp(-z), 0, 3.14159, 0, 1.57080, 0, 2)
print(f"总热通量: {result:.6f}, 误差估计: {error:.2e}\n")
#总热通量: 1.354949, 误差估计: 1.56e-14
示例6: 概率计算 - 三维联合概率密度
f(x,y,z) = x*y*z*exp(-x-y-z),在第一卦限上
result, error = integral3(x*y*z*exp(-x-y-z), 0, 5, 0, 5, 0, 5)
print(f"联合概率: {result:.6f}, 误差估计: {error:.2e}\n")
#联合概率: 0.883554, 误差估计: 9.81e-15
示例7: 电场能量密度 - 电磁场中的能量存储
能量密度 w = ε/2 * |E|² = ε/2 * (E_x² + E_y² + E_z²)
result, error = integral3(x**2 + y**2 + z**2, 0, 1, 0, 1, 0, 1)
print(f"电场能量: {result:.6f}, 误差估计: {error:.2e}")
#电场能量: 1.000000, 误差估计: 2.58e-14
示例8: 复杂区域 - 锥体体积
def cone_integrand(x, y, z):
return 1.0
def z_low_cone(x, y):
return 0
def z_high_cone(x, y):
return 1 - np.sqrt(x ** 2 + y ** 2)
在单位圆盘上积分
def y_low_cone(x):
return -np.sqrt(1 - x ** 2)
def y_high_cone(x):
return np.sqrt(1 - x ** 2)
result, error = integral3(cone_integrand, -1, 1, y_low_cone, y_high_cone, z_low_cone, z_high_cone)
print(f"锥体体积: {result:.6f}, 误差估计: {error:.2e}")
#锥体体积: 1.047198, 误差估计: 1.48e-08
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import numpy as np
from scipy.integrate import dblquad, tplquad, nquad
import sympy as sp
def integral3(integrand, x_low, x_high, y_low, y_high, z_low, z_high, **kwargs):
"""
三重数值积分函数
参数:
integrand: 被积函数 f(x, y, z)
x_low, x_high: x的积分限
y_low, y_high: y的积分限(可以是x的函数)
z_low, z_high: z的积分限(可以是x,y的函数)
"""
try:
# 处理积分限为函数的情况
y_low_func = y_low if callable(y_low) else lambda x: float(y_low)
y_high_func = y_high if callable(y_high) else lambda x: float(y_high)
z_low_func = z_low if callable(z_low) else lambda x, y: float(z_low)
z_high_func = z_high if callable(z_high) else lambda x, y: float(z_high)
# 使用scipy的tplquad进行三重数值积分
result, error = tplquad(integrand,
float(x_low), float(x_high),
y_low_func, y_high_func,
z_low_func, z_high_func,
**kwargs)
return result
except Exception as e:
return f"Error in integral3: {e}"
def integral2(integrand, x_low, x_high, y_low, y_high, **kwargs):
"""
对标MATLAB integral2函数的二重数值积分实现
参数:
integrand: 被积函数,接受两个参数f(x,y)
x_low, x_high: x的积分下限和上限(可以是常数或函数)
y_low, y_high: y的积分下限和上限(可以是常数或函数,y_low和y_high可以是x的函数)
**kwargs: 传递给scipy积分函数的参数
返回:
积分结果和误差估计
"""
try:
# 处理积分限为函数的情况
if callable(x_low):
x_low_func = x_low
else:
x_low_func = lambda x, y: x_low
if callable(x_high):
x_high_func = x_high
else:
x_high_func = lambda x, y: x_high
if callable(y_low):
y_low_func = y_low
else:
y_low_func = lambda x: y_low
if callable(y_high):
y_high_func = y_high
else:
y_high_func = lambda x: y_high
# 使用scipy的dblquad进行二重数值积分
result, error = dblquad(integrand,
np.float64(x_low_func(0, 0)) if not callable(x_low) else x_low_func(0, 0),
np.float64(x_high_func(0, 0)) if not callable(x_high) else x_high_func(0, 0),
y_low_func,
y_high_func,
**kwargs)
return result
except Exception as e:
return f"Error: {e}"
def integrate_multi_equation(input_str, **kwargs):
"""
支持多重数值积分的通用函数
参数:
input_str: 输入字符串,格式为:"函数表达式, 变量1下限, 变量1上限, 变量2下限, 变量2上限, ..."
**kwargs: 传递给scipy积分函数的参数
"""
try:
# 解析输入字符串
parts = [part.strip() for part in input_str.split(',')]
if len(parts) < 5 or len(parts) % 2 != 1:
return "错误: 输入格式应为: '函数表达式, 下限1, 上限1, 下限2, 上限2, ...'"
func_str = parts[0]
limits = parts[1:]
# 根据积分重数选择不同的积分方法
num_integrals = len(limits) // 2
if num_integrals == 2:
# 二重积分
x, y = sp.symbols('x y')
integrand_expr = sp.sympify(func_str)
integrand_func = sp.lambdify((x, y), integrand_expr, 'numpy')
# 解析积分限
x_low, x_high, y_low_str, y_high_str = limits
# 处理y的积分限(可能包含x)
y_low_expr = sp.sympify(y_low_str)
y_high_expr = sp.sympify(y_high_str)
y_low_func = sp.lambdify(x, y_low_expr, 'numpy') if x in y_low_expr.free_symbols else float(y_low_expr)
y_high_func = sp.lambdify(x, y_high_expr, 'numpy') if x in y_high_expr.free_symbols else float(y_high_expr)
return integral2(integrand_func, float(x_low), float(x_high), y_low_func, y_high_func, **kwargs)
elif num_integrals == 3:
# 三重积分
x, y, z = sp.symbols('x y z')
integrand_expr = sp.sympify(func_str)
integrand_func = sp.lambdify((x, y, z), integrand_expr, 'numpy')
# 解析积分限
x_low, x_high, y_low_str, y_high_str, z_low_str, z_high_str = limits
# 处理y的积分限(可能包含x)
y_low_expr = sp.sympify(y_low_str)
y_high_expr = sp.sympify(y_high_str)
y_low_func = sp.lambdify(x, y_low_expr, 'numpy') if x in y_low_expr.free_symbols else float(y_low_expr)
y_high_func = sp.lambdify(x, y_high_expr, 'numpy') if x in y_high_expr.free_symbols else float(y_high_expr)
# 处理z的积分限(可能包含x,y)
z_low_expr = sp.sympify(z_low_str)
z_high_expr = sp.sympify(z_high_str)
z_low_func = sp.lambdify((x, y), z_low_expr, 'numpy') if (
x in z_low_expr.free_symbols or y in z_low_expr.free_symbols) else float(z_low_expr)
z_high_func = sp.lambdify((x, y), z_high_expr, 'numpy') if (
x in z_high_expr.free_symbols or y in z_high_expr.free_symbols) else float(z_high_expr)
return integral3(integrand_func, float(x_low), float(x_high), y_low_func, y_high_func, z_low_func,
z_high_func, **kwargs)
else:
return f"暂不支持 {num_integrals} 重积分"
except Exception as e:
return f"Error: {e}"
# 二重积分 ∫₀¹∫₀¹ xy dxdy
# 示例1: 简单二重积分 ∫₀¹∫₀¹ x*y dxdy
print("示例1:", integrate_multi_equation("x*y, 0, 1, 0, 1"))
# 1/4
# 示例2: 带变量依赖的积分 ∫₀¹∫₀^{1-x} x*y dydx
print("\n示例2:", integrate_multi_equation("x*y, 0, 1, 0, 1-x"))
# (1 - x)**2/4
# 示例3: 三重积分 ∫₀¹∫₀¹∫₀¹ x*y*z dxdydz
print("\n示例3:", integrate_multi_equation("x*y*z, 0, 1, 0, 1, 0, 1"))
# 1/8
分部积分
G=integrateByParts(F,du)将分部积分应用于F中的积分,其中微分du被积分.
在F中指定积分时,您可以通过使用int函数并将“Hold”选项设置为true来返回未求值的积分形式.然后,您可以使用integrateByParts按部件显示集成的步骤.
F —— 包含积分的表达式
du —— 待整合的差异
示例1:多项式与指数函数的积分(常见于物理和工程)
result1 = integrateByParts(x*exp(x), 1) # u = x, du = 1, dv = e^x dx
print(f"结果: {result1}")
#结果: x**2 - Integral(x, x)
示例2:多项式与三角函数的积分(常见于信号处理)
result2 = integrateByParts(x*sin(x), 1) # u = x, du = 1, dv = sin(x) dx
print(f"结果: {result2}")
#结果: x**2 - Integral(x, x)
示例3:对数函数的积分(常见于概率论和统计学)
result3 = integrateByParts(ln(x), 1/x) # u = ln(x), du = 1/x, dv = 1 dx
print(f"结果: {result3}")
#结果: log(x)*Ei(2*log(x)) - Integral(Ei(2*log(x))/x, x)
示例4:反三角函数的积分
result4 = integrateByParts(atan(x), 1/(x**2 + 1)) # u = atan(x), du = 1/(1+x^2)
print(f"结果: {result4}")
#结果: atan(x)*Integral(x/atan(x), x) - Integral(Integral(x/atan(x), x)/(x**2 + 1), x)
示例5:分部积分的例子
result5 = integrateByParts(x**2*exp(x), 2*x) # u = x^2, du = 2x
print(f"分部积分结果: {result5}")
#分部积分结果: x**3 - Integral(2*x**2, x)
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def integrate_by_parts(input_str):
"""
该函数对标 MATLAB 的 integrateByParts 函数,用于执行分部积分操作。
分部积分公式为 ∫u dv = u*v - ∫v du。
参数:
input_str (str): 输入的字符串,格式为 "被积函数,du表达式",例如 "u*diff(v, x),diff(u)"。
返回:
sympy 表达式或错误信息字符串: 若计算成功,返回分部积分的结果;若出现错误,返回错误信息。
"""
# 定义符号变量和函数
try:
# 定义符号变量 x
x = sp.symbols('x')
# 定义函数 u(x) 和 v(x)
u = sp.Function('u')(x)
v = sp.Function('v')(x)
# 使用逗号分割输入字符串,获取被积函数和 du 表达式
params = input_str.split(',')
# 检查输入参数数量是否为 2
if len(params) != 2:
raise ValueError("输入格式错误,需要两个参数")
F_str, du_str = params
# 转换 Matlab 语法到 SymPy 表达式
try:
# 处理被积函数(替换 int 为 Integral,并解析)
F_expr = sp.sympify(
F_str,
locals={
'int': sp.Integral,
'diff': sp.diff,
'exp': sp.exp,
'sin': sp.sin,
'cos': sp.cos,
'log': sp.log,
'ln': sp.log,
'u': u,
'v': v,
'x': x,
},
)
# 提取被积函数,例如 u*Derivative(v, x)
integrand = F_expr.args[0]
# 解析微分部分(如 diff(u))
du = sp.sympify(
du_str,
locals={
'diff': sp.diff,
'exp': sp.exp,
'sin': sp.sin,
'cos': sp.cos,
'log': sp.log,
'ln': sp.log,
'u': u,
'x': x,
'Symbol': sp.Symbol
},
)
except Exception as e:
# 尝试直接解析输入字符串为元组
expr = sp.sympify(input_str)
if isinstance(expr, tuple) and len(expr) == 2:
F, du = expr
# 从 du 中推导出 u
u = sp.integrate(du, x) # u 是 du 的不定积分
# F = u * dv, 因此 dv = F / u
dv = F / u
# 计算 v
v = sp.integrate(dv, x)
# 返回积分分部公式的结果 u*v - ∫v*du
return u * v - sp.integrate(v * du, x)
# 计算 u 和 dv/dx
try:
# 从 du = du/dx 积分得到 u(假设积分常数为 0)
u_expr = sp.integrate(du, x)
# 计算 dv/dx = 被积函数 / u
dv_dx = integrand / u_expr
# 积分得到 v
v_expr = sp.integrate(dv_dx, x)
except Exception as e:
raise ValueError(f"积分计算错误: {e}")
# 应用分部积分公式
result = u_expr * v_expr - sp.Integral(v_expr * du, x)
return result
except Exception as e:
return f"错误: {str(e)}"
# 示范代码
if __name__ == "__main__":
# 示例输入
input_str = "int(u*diff(v)),diff(u)"
result = integrate_by_parts(input_str)
print("分部积分结果:", result)
# u(x)*v(x) - Integral(v(x)*Derivative(u(x), x), x)
一维数据插值
vq = interp1(x,v,xq) 使用线性插值返回一维函数在特定查询点的插入值。向量 x 包含样本点,v 包含对应值 v(x)。向量 xq 包含查询点的坐标。
如果您有多个在同一点坐标采样的数据集,则可以将 v 以数组的形式进行传递。数组 v 的每一列都包含一组不同的一维样本值。
vq = interp1(x,v,xq,method) 指定备选插值方法:'linear'、'nearest'、'next'、'previous'、'pchip'、'cubic'、'v5cubic'、'makima' 或 'spline'。默认方法为 'linear'。
vq = interp1(x,v,xq,method,extrapolation) 用于指定外插策略,来计算落在 x 域范围外的点。如果希望使用 method 算法进行外插,可将 extrapolation 设置为 'extrap'。您也可以指定一个标量值,这种情况下,interp1 将为所有落在 x 域范围外的点返回该标量值。
x - 样本点, 向量
v - 样本值, 向量 | 矩阵
xq - 查询点, 标量 | 向量 | 矩阵
method - 插值方法, 'linear' (默认) | 'nearest' | 'next' | 'previous' | 'pchip' | 'cubic' | 'v5cubic' | 'makima' | 'spline'
extrapolation - 外插策略, 'extrap' | 标量值
vq - 插入的值, 标量 | 向量 | 矩阵
pp - 分段多项式, 结构体
import matplotlib.pyplot as plt
示例1:气象数据分析 - 温度插值
已知每小时温度数据,插值得到每15分钟的温度
hours = [0, 1, 2, 3, 4, 5, 6] # 时间(小时)
temperatures = [15, 14, 13, 12, 11, 10, 12] # 温度(摄氏度)
生成每15分钟的时间点
quarter_hours = np.linspace(0, 6, 25)
使用三次样条插值
result = interp1(hours, temperatures, quarter_hours, cubic)
print(f"插值结果前5个点: {result[:5] if hasattr(result, '__len__') else result}")
#插值结果前5个点: [15,14.74707031,14.49665179,14.24790737,14]
可视化
plt.figure(figsize=(10, 6))
plt.subplot(2, 3, 1)
plt.plot(hours, temperatures, 'ro-', label='原始数据', markersize=8)
plt.plot(quarter_hours, result, 'b-', label='三次样条插值', alpha=0.7)
plt.xlabel('时间 (小时)')
plt.ylabel('温度 (°C)')
plt.title('气象数据插值')
plt.legend()
plt.grid(True, alpha=0.3)
示例2:金融数据分析 - 股票价格插值
已知每日收盘价,插值得到日内价格
days = [1, 2, 3, 4, 5] # 交易日
prices = [100, 102, 98, 105, 103] # 收盘价
生成更细的时间网格
fine_days = np.linspace(1, 5, 41)
使用线性插值
price_interp = interp1(days, prices, fine_days, linear)
print(f"第3.5天插值价格: {price_interp[20]:.2f}")
#第3.5天插值价格: 98.00
plt.subplot(2, 3, 2)
plt.plot(days, prices, 'go-', label='收盘价', markersize=8)
plt.plot(fine_days, price_interp, 'm-', label='线性插值', alpha=0.7)
plt.xlabel('交易日')
plt.ylabel('价格 ($)')
plt.title('股票价格插值')
plt.legend()
plt.grid(True, alpha=0.3)
示例3:工程应用 - 材料应力应变曲线
strain = [0, 0.001, 0.002, 0.003, 0.004, 0.005]
stress = [0, 200, 380, 520, 610, 650] # MPa
fine_strain = np.linspace(0, 0.005, 51)
stress_interp = interp1(strain, stress, fine_strain, cubic)
plt.subplot(2, 3, 3)
plt.plot(strain * 1000, stress, 'bo-', label='实验数据', markersize=6)
plt.plot(fine_strain * 1000, stress_interp, 'c-', label='三次样条', alpha=0.7)
plt.xlabel('应变 (×10⁻³)')
plt.ylabel('应力 (MPa)')
plt.title('材料应力应变曲线')
plt.legend()
plt.grid(True, alpha=0.3)
示例4:医学应用 - 心电图数据重采样
time_ecg = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
ecg_signal = [0, 0.5, 1.0, 0.2, -0.3, -0.1, 0.8, 1.2, 0.4, 0.1, 0]
更高采样率
fine_time = np.linspace(0, 1, 101)
ecg_interp = interp1(time_ecg, ecg_signal, fine_time, cubic)
plt.subplot(2, 3, 4)
plt.plot(time_ecg, ecg_signal, 'ro-', label='原始ECG', markersize=4)
plt.plot(fine_time, ecg_interp, 'r-', label='插值ECG', alpha=0.7)
plt.xlabel('时间 (s)')
plt.ylabel('振幅 (mV)')
plt.title('心电图数据重采样')
plt.legend()
plt.grid(True, alpha=0.3)
示例5:地理信息系统 - 高程数据插值
distance = [0, 100, 200, 300, 400, 500] # 米
elevation = [50, 65, 80, 60, 75, 70] # 米
fine_distance = np.linspace(0, 500, 101)
elev_interp = interp1(distance, elevation, fine_distance, linear)
plt.subplot(2, 3, 5)
plt.plot(distance, elevation, 's-', color='brown', label='测量点', markersize=6)
plt.plot(fine_distance, elev_interp, '-', color='green', label='线性插值', alpha=0.7)
plt.xlabel('距离 (m)')
plt.ylabel('高程 (m)')
plt.title('地形高程插值')
plt.legend()
plt.grid(True, alpha=0.3)
示例6:信号处理 - 不同插值方法比较
x_original = [0, 1, 2, 3, 4, 5]
y_original = [0, 1, 0, -1, 0, 1]
x_fine = np.linspace(0, 5, 101)
methods = ['linear', 'nearest', 'cubic']
colors = ['blue', 'green', 'red']
labels = ['线性', '最近邻', '三次样条']
plt.subplot(2, 3, 6)
plt.plot(x_original, y_original, 'ko', label='原始数据', markersize=8)
for method, color, label in zip(methods, colors, labels):
y_interp = interp1(f"{list(x_original)}, {list(y_original)}, {list(x_fine)}, '{method}'")
plt.plot(x_fine, y_interp, color=color, label=label, alpha=0.7)
plt.xlabel('x')
plt.ylabel('y')
plt.title('不同插值方法比较')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
示例7:高级误差分析
使用已知函数生成测试数据
def original_function(x):
return np.sin(x) + 0.5 * np.cos(2 * x)
稀疏采样点
x_sparse = np.linspace(0, 2 * np.pi, 8)
y_sparse = original_function(x_sparse)
密集采样点(作为"真实"值)
x_dense = np.linspace(0, 2 * np.pi, 100)
y_true = original_function(x_dense)
methods = [linear, nearest, cubic]
errors = {}
不同插值方法的均方根误差(RMSE):
for method in methods:
y_interp = interp1(x_sparse, y_sparse, x_dense, method)
rmse = np.sqrt(np.mean((y_interp - y_true) ** 2))
errors[method] = rmse
print(f" {method}: {rmse:.6f}")
#linear: 0.109000
#nearest: 0.254234
#cubic: 0.024224
可视化误差分析
plt.figure(figsize=(12, 8))
for i, method in enumerate(methods, 1):
plt.subplot(2, 2, i)
y_interp = interp1(f"{list(x_sparse)}, {list(y_sparse)}, {list(x_dense)}, '{method}'")
plt.plot(x_dense, y_true, 'k-', label='真实函数', linewidth=2)
plt.plot(x_sparse, y_sparse, 'ro', label='采样点', markersize=8)
plt.plot(x_dense, y_interp, 'b-', label=f'{method}插值', alpha=0.8)
plt.fill_between(x_dense, y_true, y_interp, alpha=0.3, color='red', label='误差区域')
plt.xlabel('x')
plt.ylabel('y')
plt.title(f'{method}插值 - RMSE: {errors[method]:.4f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.interpolate import interp1d, CubicSpline
def interpolation_one_dimensional(input_str):
"""
对标MATLAB的interp1函数,实现一维数据插值
参数:
input_str: 输入参数字符串,支持以下格式:
"y, xq" -> 自动生成x坐标
"x, y, xq" -> 基本插值
"x, y, xq, method" -> 指定插值方法
"x, y, xq, method, extrap" -> 指定方法和外推值
返回:
插值结果数组,错误时返回错误信息字符串
示例:
>>> interpolation_one_dimensional("[1,2,3], [4,5,6], 2.5")
array(5.5)
>>> interpolation_one_dimensional("[1,2,3], [4,5,6], [0,4], 'linear', 0")
array([4., 0.])
"""
try:
# 解析输入字符串为参数元组
expr = sp.sympify(input_str, evaluate=False)
params = list(expr) if isinstance(expr, tuple) else [expr]
# 有效插值方法集合
valid_methods = {
'linear', 'nearest', 'zero',
'slinear', 'quadratic', 'cubic',
'previous', 'next'
}
# 初始化默认参数
x, y, xq = None, None, None
method = 'linear'
extrap = np.nan
# 参数转换函数
def convert(param):
"""将SymPy对象转换为数值数组"""
if isinstance(param, list):
matrix = sp.Matrix(param)
if matrix.is_symbolic():
raise ValueError(f"Symbolic variable {param} not allowed")
else:
return np.array(matrix.tolist(), dtype=float).flatten()
elif param.is_Number:
return np.array([float(param)])
elif param.free_symbols:
raise ValueError(f"Symbolic variable {param} not allowed")
else: # 处理包含符号的表达式
try:
return np.array([float(param.evalf())])
except:
raise ValueError(f"Cannot convert {param} to numeric")
# 处理前三个数值参数
numeric_params = []
for i, param in enumerate(params[:3]):
try:
numeric_params.append(convert(param))
except:
if i < 2:
raise
numeric_params.append(np.array([float(param.evalf())]))
# 参数逻辑判断
if len(numeric_params) == 2: # y, xq 模式
y, xq = numeric_params
x = np.arange(1, len(y) + 1)
else: # x, y, xq 模式
x, y, xq = numeric_params[:3]
if len(x) != len(y):
raise ValueError("x和y的长度必须一致")
# 验证x的单调性
if not np.all(np.diff(x) > 0):
raise ValueError("x必须是严格单调递增的")
# 处理方法参数
if len(params) >= 4:
method_param = params[3]
method_candidate = str(method_param).lower()
if method_candidate in valid_methods:
method = method_candidate
else:
try: # 尝试解析为外推值
extrap = float(sp.sympify(method_param))
except:
pass
# 处理外推参数
if len(params) >= 5:
try:
extrap = float(params[4])
except:
raise ValueError("无效的外推值")
# 创建插值器
# 关键修改点:单独处理三次样条
if method in ['cubic', 'spline']:
# 使用CubicSpline并设置not-a-knot边界条件
if not np.all(np.diff(x) > 0):
raise ValueError("三次样条需要严格单调的x值")
# MATLAB的cubic对应SciPy的CubicSpline with not-a-knot
interpolator = CubicSpline(
x, y,
bc_type='not-a-knot',
extrapolate=extrap is not None
)
else:
# 其他方法保持原有interp1d调用
interpolator = interp1d(
x, y,
kind=method,
fill_value=extrap,
bounds_error=False,
assume_sorted=True
)
# 执行插值计算
return interpolator(xq)
except Exception as e:
return f"错误: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 基本线性插值
print(interpolation_one_dimensional("[1,2,3], [4,5,6], 2.5"))
# [5.5]
# 自动生成x坐标
print(interpolation_one_dimensional("[4,5,6], [1.5,2.5]"))
# [4.5, 5.5]
# 三次样条插值
print(interpolation_one_dimensional("[0,1,2], [0,1,4], 1.5, 'cubic'"))
# [2.25]
# 外推测试
print(interpolation_one_dimensional("[1,2,3], [4,5,6], 4, 'linear', 0"))
# [0]
meshgrid格式的二维网格数据的插值
Vq = interp2(X,Y,V,Xq,Yq) 使用线性插值返回双变量函数在特定查询点的插入值。结果始终穿过函数的原始采样。X 和 Y 包含样本点的坐标。V 包含各样本点处的对应函数值。Xq 和 Yq 包含查询点的坐标。
Vq = interp2(___,method) 指定备选插值方法:'linear'、'nearest'、'cubic'、'makima'。默认方法为 'linear'。
Vq = interp2(___,method,extrapval) 还指定标量值 extrapval,此参数会为处于样本点域范围外的所有查询点赋予该标量值。
X,Y — 样本网格点, 矩阵 | 向量
V — 样本值,矩阵
Xq,Yq — 查询点, 标量 | 向量 | 矩阵
method — 插值方法, 'linear' (默认) | 'nearest' | 'cubic' | 'makima'
extrapval — X 和 Y 域范围外的函数值, 标量
示例1:地形高程插值(地理信息系统)
创建示例地形数据
x = np.linspace(0, 10, 6) # 经度方向
y = np.linspace(0, 8, 5) # 纬度方向
X, Y = np.meshgrid(x, y)
模拟地形高程(山峰和山谷)
Z = np.exp(-((X - 5) ** 2 + (Y - 4) ** 2) / 8) * 1000 + \
np.exp(-((X - 2) ** 2 + (Y - 2) ** 2) / 4) * 500 - \
np.exp(-((X - 8) ** 2 + (Y - 6) ** 2) / 6) * 300
生成更密集的查询网格
xq = np.linspace(0, 10, 50)
yq = np.linspace(0, 8, 40)
使用三次样条插值
Zq = interp2(x, y, Z, xq, yq, cubic)
可视化
fig = plt.figure(figsize=(15, 10))
原始稀疏数据
ax1 = fig.add_subplot(2, 3, 1, projection='3d')
surf1 = ax1.plot_surface(X, Y, Z, cmap='terrain', alpha=0.8)
ax1.scatter(X, Y, Z, color='red', s=50)
ax1.set_title('原始地形数据点')
ax1.set_xlabel('经度')
ax1.set_ylabel('纬度')
ax1.set_zlabel('高程 (m)')
插值后的地形
Xq, Yq = np.meshgrid(xq, yq)
ax2 = fig.add_subplot(2, 3, 2, projection='3d')
surf2 = ax2.plot_surface(Xq, Yq, Zq, cmap='terrain', alpha=0.8)
ax2.set_title('插值后地形')
ax2.set_xlabel('经度')
ax2.set_ylabel('纬度')
ax2.set_zlabel('高程 (m)')
示例2:温度分布插值(气象学)
模拟温度数据
x_temp = np.array([0, 2, 4, 6, 8, 10]) # 东西方向 (km)
y_temp = np.array([0, 1, 2, 3, 4]) # 南北方向 (km)
X_temp, Y_temp = np.meshgrid(x_temp, y_temp)
温度场(城市热岛效应)
T = 20 + 5 * np.exp(-((X_temp - 5) ** 2 + (Y_temp - 2) ** 2) / 4) - \
2 * np.exp(-((X_temp - 1) ** 2 + (Y_temp - 3) ** 2) / 2)
密集查询点
xq_temp = np.linspace(0, 10, 30)
yq_temp = np.linspace(0, 4, 20)
Tq = interp2(x_temp, y_temp, T, xq_temp, yq_temp, linear)
Xq_temp, Yq_temp = np.meshgrid(xq_temp, yq_temp)
ax3 = fig.add_subplot(2, 3, 3)
contour = ax3.contourf(Xq_temp, Yq_temp, Tq, levels=20, cmap='hot')
ax3.scatter(X_temp, Y_temp, color='blue', s=30)
ax3.set_title('温度分布 (°C)')
ax3.set_xlabel('东西距离 (km)')
ax3.set_ylabel('南北距离 (km)')
plt.colorbar(contour, ax=ax3)
示例3:图像放大(计算机视觉)
创建低分辨率图像(5x5像素)
small_image = np.array([
[0.1, 0.3, 0.5, 0.3, 0.1],
[0.3, 0.7, 0.9, 0.7, 0.3],
[0.5, 0.9, 1.0, 0.9, 0.5],
[0.3, 0.7, 0.9, 0.7, 0.3],
[0.1, 0.3, 0.5, 0.3, 0.1]
])
x_img = np.arange(5)
y_img = np.arange(5)
放大到25x25
xq_img = np.linspace(0, 4, 25)
yq_img = np.linspace(0, 4, 25)
使用三次样条插值获得更平滑的放大
large_image = interp2(x_img, y_img, small_image, xq_img, yq_img, cubic)
ax4 = fig.add_subplot(2, 3, 4)
ax4.imshow(small_image, cmap='gray', extent=[0, 4, 0, 4], interpolation='none')
ax4.set_title('原始低分辨率图像')
ax4.set_xlabel('X 像素')
ax4.set_ylabel('Y 像素')
ax5 = fig.add_subplot(2, 3, 5)
ax5.imshow(large_image, cmap='gray', extent=[0, 4, 0, 4], interpolation='none')
ax5.set_title('插值放大图像')
ax5.set_xlabel('X 像素')
ax5.set_ylabel('Y 像素')
示例4:流体力学 - 速度场插值
模拟流体速度场
x_flow = np.array([0, 1, 2, 3, 4])
y_flow = np.array([0, 1, 2, 3])
X_flow, Y_flow = np.meshgrid(x_flow, y_flow)
速度大小(模拟管道流动)
U = Y_flow * (4 - Y_flow) / 4 # 抛物线速度分布
密集查询网格
xq_flow = np.linspace(0, 4, 20)
yq_flow = np.linspace(0, 3, 15)
Uq = interp2(x_flow, y_flow, U, xq_flow, yq_flow, cubic)
Xq_flow, Yq_flow = np.meshgrid(xq_flow, yq_flow)
ax6 = fig.add_subplot(2, 3, 6)
stream = ax6.streamplot(Xq_flow, Yq_flow, Uq, np.zeros_like(Uq),
color=Uq, cmap='viridis', linewidth=2)
ax6.scatter(X_flow, Y_flow, color='red', s=20)
ax6.set_title('流体速度场')
ax6.set_xlabel('X 位置')
ax6.set_ylabel('Y 位置')
plt.colorbar(stream.lines, ax=ax6)
plt.tight_layout()
plt.show()
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import numpy as np
import re
import sympy as sp
from scipy.interpolate import RegularGridInterpolator
def interpolation_two_dimensional(input_str):
"""
对标 MATLAB 的 interp2 函数,实现二维网格数据插值
参数:
input_str: 输入参数字符串,支持以下格式:
"X, Y, V, Xq, Yq" -> 基本插值(默认线性)
"X, Y, V, Xq, Yq, method" -> 指定插值方法
"X, Y, V, Xq, Yq, method, extrap" -> 指定方法和外推值
返回:
插值结果数组,错误时返回错误信息字符串
示例:
>>> interpolation_two_dimensional("[0,1], [0,1], [[1,2],[3,4]], 0.5, 0.5")
array(2.5)
>>> interpolation_two_dimensional("[0,1], [0,1], [[1,2],[3,4]], [0.5,2], [0.5,1], 'linear', 0)")
array([2.5, 0. ])
"""
try:
# ------------------------- 输入解析 -------------------------
# 解析输入字符串为参数元组
expr = sp.sympify(input_str, evaluate=False)
print(expr)
params = list(expr) if isinstance(expr, tuple) else [expr]
# 有效插值方法集合
valid_methods = {
'linear', 'nearest', 'cubic',
'makima' # 注意:SciPy 的 cubic 对应 MATLAB 的 spline
}
# 初始化默认参数
X, Y, V, Xq, Yq = None, None, None, None, None
extrap = np.nan
# 提取前5个必要参数
arrays = []
for i, param in enumerate(params[:5]):
try:
if isinstance(param, list):
arr = np.array(param, dtype=float)
elif param.is_number:
arr = np.array([float(param)])
else:
try:
arr = np.array([float(param.evalf())])
except:
raise ValueError(f"无法转换符号表达式: {param}")
arrays.append(arr.squeeze()) # 去除单一维度
except Exception as e:
if i < 3:
raise ValueError(f"参数 {i + 1} 转换失败: {str(e)}")
else:
# 查询点可能是单个数值
arrays.append(np.array([float(param.evalf())]))
# 分配参数
X, Y, V, Xq, Yq = arrays[:5]
# ------------------------- 参数验证 -------------------------
# 验证网格结构
if X.ndim != 1 or Y.ndim != 1:
raise ValueError("X 和 Y 必须是一维数组")
# 检查单调性
if not (np.all(np.diff(X) > 0) and np.all(np.diff(Y) > 0)):
raise ValueError("X 和 Y 必须是严格单调递增的")
# 验证 V 的维度
expected_shape = (len(Y), len(X)) # MATLAB 的 meshgrid 是 (Y,X) 顺序
if V.shape != expected_shape:
raise ValueError(f"V 的维度应为 {expected_shape},实际为 {V.shape}")
# ------------------------- 处理方法参数 -------------------------
scipy_method = 'linear'
if len(params) >= 6:
scipy_method = str(params[5])
# ------------------------- 处理外推参数 -------------------------
if len(params) >= 7:
try:
extrap = float(params[6])
except:
raise ValueError("无效的外推值")
# ------------------------- 创建插值器 -------------------------
# 使用 RegularGridInterpolator (适用于规则网格)
interpolator = RegularGridInterpolator(
(Y, X), # 注意顺序:MATLAB 是 (X,Y),但 SciPy 是 (Y,X)
V,
method=scipy_method,
bounds_error=False,
fill_value=extrap
)
# ------------------------- 准备查询点 -------------------------
# 生成网格点坐标 (兼容标量输入)
Xq_mesh, Yq_mesh = np.meshgrid(Xq, Yq)
query_points = np.column_stack((Yq_mesh.ravel(), Xq_mesh.ravel()))
# ------------------------- 执行插值 -------------------------
Vq = interpolator(query_points)
Vq = Vq.reshape(Xq_mesh.shape)
return Vq
except Exception as e:
return f"错误: {str(e)}"
# 示例使用 ---------------------------------------------------
if __name__ == "__main__":
# 测试案例1:外推值设置
input_str = "[0,1],[0,1],[[1,2],[3,4]],[0.5,2],[0.5,1],linear,0"
result = interpolation_two_dimensional(re.sub(r"\s+", "", input_str))
print("测试1结果:", result)
# [[2.5 0. ]
# [3.5 0. ]]
meshgrid格式的三维网格数据的插值
Vq = interp3(X,Y,Z,V,Xq,Yq,Zq) 使用线性插值返回三变量函数在特定查询点的插值。结果始终穿过函数的原始采样。X、Y 和 Z 包含样本点的坐标。V 包含各样本点处的对应函数值。Xq、Yq 和 Zq 包含查询点的坐标。
Vq = interp3(___,method) 指定备选插值方法:'linear'、'nearest'、'cubic'、'makima' 或 'spline'。默认方法为 'linear'。
Vq = interp3(___,method,extrapval) 还指定标量值 extrapval,此参数会为处于样本点域范围外的所有查询点赋予该标量值。
X,Y,Z — 样本网格点, 数组 | 向量
V — 样本值, 数组
Xq,Yq,Zq — 查询点, 标量 | 向量
k — 细化因子, 1 (默认) | 非负实整数标量
method — 插值方法, 'linear' (默认) | 'nearest'
extrapval — X、Y 和 Z 域范围外的函数值, 标量
示例1. 三维数据外推处理
创建有限区域的数据
x_limited = np.array([10, 20, 30, 40, 50])
y_limited = np.array([10, 20, 30, 40])
z_limited = np.array([5, 10, 15, 20, 25])
X_lim, Y_lim, Z_lim = np.meshgrid(x_limited, y_limited, z_limited, indexing='ij')
模拟数据(中心有高值)
V_limited = 100 * np.exp(-((X_lim - 30) ** 2 / 100 + (Y_lim - 25) ** 2 / 80 + (Z_lim - 15) ** 2 / 50))
查询点(包含数据范围外的点)
xq_ext = np.array([0, 25, 50, 75]) # 0和75在范围外
yq_ext = np.array([0, 20, 40, 60]) # 0和60在范围外
zq_ext = np.array([0, 12.5, 25, 35]) # 0和35在范围外
无外推(默认NaN)
Vq_no_extrap = interp3(x_limited, y_limited, z_limited, V_limited, xq_ext, yq_ext, zq_ext, linear)
使用常数外推
Vq_with_extrap = interp3(x_limited, y_limited, z_limited, V_limited, xq_ext, yq_ext, zq_ext, linear, 0)
nan_count_no_extrap = np.sum(np.isnan(Vq_no_extrap))
nan_count_with_extrap = np.sum(np.isnan(Vq_with_extrap))
print(f"无外推时的NaN数量: {nan_count_no_extrap}")
print(f"有外推时的NaN数量: {nan_count_with_extrap}")
print(f"外推值设置: 0 (在数据范围外)")
#无外推时的NaN数量: 56
#有外推时的NaN数量: 0
#外推值设置: 0 (在数据范围外)
示例2:数据重采样(改变网格分辨率)
原始低分辨率数据
x_low = np.array([0, 10, 20, 30, 40])
y_low = np.array([0, 8, 16, 24, 32])
z_low = np.array([0, 5, 10, 15, 20])
X_low, Y_low, Z_low = np.meshgrid(x_low, y_low, z_low, indexing='ij')
模拟物理场数据
V_low = 50 + 20 * np.sin(X_low / 5) * np.cos(Y_low / 4) * np.sin(Z_low / 3)
高分辨率查询网格
xq_high = np.linspace(0, 40, 20)
yq_high = np.linspace(0, 32, 16)
zq_high = np.linspace(0, 20, 12)
Vq_high = interp3(x_low, y_low, z_low, V_low, xq_high, yq_high, zq_high, linear)
print(f"原始数据分辨率: {V_low.shape}")
print(f"重采样后分辨率: {Vq_high.shape}")
print(f"分辨率提升倍数: {Vq_high.size / V_low.size:.1f}x")
可视化重采样效果
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 低分辨率数据的一个切片
z_low_idx = len(z_low) // 2
im1 = axes[0].imshow(V_low[:, :, z_low_idx].T, cmap='coolwarm',
extent=[x_low[0], x_low[-1], y_low[0], y_low[-1]],
origin='lower', interpolation='nearest')
axes[0].set_title('低分辨率原始数据')
axes[0].set_xlabel('X')
axes[0].set_ylabel('Y')
plt.colorbar(im1, ax=axes[0])
高分辨率插值的一个切片
Xq_high, Yq_high, Zq_high = np.meshgrid(xq_high, yq_high, zq_high, indexing='ij')
z_high_idx = len(zq_high) // 2
im2 = axes[1].imshow(Vq_high[:, :, z_high_idx].T, cmap='coolwarm',
extent=[xq_high[0], xq_high[-1], yq_high[0], yq_high[-1]],
origin='lower', interpolation='bilinear')
axes[1].set_title('高分辨率插值结果')
axes[1].set_xlabel('X')
axes[1].set_ylabel('Y')
plt.colorbar(im2, ax=axes[1])
plt.tight_layout()
plt.show()
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import numpy as np
import sympy as sp
from scipy.interpolate import RegularGridInterpolator
def parse_3d_array(param):
"""递归将 SymPy 嵌套结构转换为三维 numpy 数组"""
if isinstance(param, (sp.Tuple, list, tuple)):
return np.array([parse_3d_array(e) for e in param], dtype=float)
elif param.is_Number:
return float(param.evalf())
else:
raise ValueError("无法解析的三维数组元素")
def interpolation_three_dimensional(input_str):
"""
对标 MATLAB 的 interp3 函数,实现三维网格数据插值
参数:
input_str: 输入参数字符串,支持以下格式:
"X, Y, Z, V, Xq, Yq, Zq" -> 基本插值(默认线性)
"X, Y, Z, V, Xq, Yq, Zq, method" -> 指定插值方法
"X, Y, Z, V, Xq, Yq, Zq, method, extrap" -> 指定方法和外推值
返回:
插值结果数组,错误时返回错误信息字符串
示例:
>>> interpolation_three_dimensional("[0,1], [0,1], [0,1], [[[1,2],[3,4]],[[5,6],[7,8]]], 0.5, 0.5, 0.5")
array(4.5)
"""
try:
import re
# ------------------------- 输入解析 -------------------------
# 移除注释内容(#之后的所有字符)
cleaned_str = re.sub(r'#.*', '', input_str)
expr = sp.sympify(cleaned_str, evaluate=False)
params = list(expr) if isinstance(expr, tuple) else [expr]
valid_methods = {'linear', 'nearest'}
# 初始化参数
X, Y, Z, V, Xq, Yq, Zq = None, None, None, None, None, None, None
extrap = np.nan
method = 'linear'
# 解析前7个参数
arrays = []
for i, param in enumerate(params[:7]):
if i == 3: # 处理三维数组 V
try:
if isinstance(param, (sp.Tuple, list, tuple)):
arr = parse_3d_array(param)
else:
raise ValueError("V 必须是三维数组")
arrays.append(arr)
except Exception as e:
raise ValueError(f"参数4 (V) 转换失败: {str(e)}")
else: # 处理其他参数
try:
if isinstance(param, list):
arr = np.array(param, dtype=float).squeeze()
elif param.is_Number:
arr = np.array([float(param.evalf())])
else:
arr = np.array([float(param.evalf())])
arrays.append(arr.squeeze())
except Exception as e:
raise ValueError(f"参数 {i + 1} 转换失败: {str(e)}")
X, Y, Z, V, Xq, Yq, Zq = arrays[:7]
# ------------------------- 参数验证 -------------------------
# 验证一维数组
for arr, name in zip([X, Y, Z], ['X', 'Y', 'Z']):
if arr.ndim != 1:
raise ValueError(f"{name} 必须是一维数组")
# 验证严格单调递增
for arr, name in zip([X, Y, Z], ['X', 'Y', 'Z']):
if not np.all(np.diff(arr) > 0):
raise ValueError(f"{name} 必须是严格单调递增的")
# 验证 V 的维度
expected_shape = (len(Z), len(Y), len(X))
if V.shape != expected_shape:
raise ValueError(f"V 的维度应为 {expected_shape},实际为 {V.shape}")
# ------------------------- 处理可选参数 -------------------------
if len(params) >= 8:
method = str(params[7])
if method not in valid_methods:
raise ValueError(f"无效的插值方法: {method},支持的方法: {valid_methods}")
if len(params) >= 9:
try:
extrap = float(params[8])
except:
raise ValueError("无效的外推值")
# ------------------------- 创建插值器 -------------------------
interpolator = RegularGridInterpolator(
(Z, Y, X), # 注意坐标顺序
V,
method=method,
bounds_error=False,
fill_value=extrap
)
# ------------------------- 生成查询点 -------------------------
# 创建三维网格坐标
Zq_mesh, Yq_mesh, Xq_mesh = np.meshgrid(Zq, Yq, Xq, indexing='ij')
query_points = np.column_stack((
Zq_mesh.ravel(),
Yq_mesh.ravel(),
Xq_mesh.ravel()
))
# ------------------------- 执行插值 -------------------------
Vq = interpolator(query_points)
Vq = Vq.reshape(Zq_mesh.shape)
return Vq
except Exception as e:
return f"错误: {str(e)}"
# 测试三维线性插值
input_str = "[0,1], [0,1], [0,1], [[[1,2],[3,4]],[[5,6],[7,8]]], 0.5, 0.5, 0.5"
result = interpolation_three_dimensional(input_str)
print(result)
# [[[4.5]]]
一维插值(FFT 方法)
y = interpft(X,n) 在 X 中内插函数值的傅里叶变换以生成 n 个等间距的点。interpft 对第一个大小不等于 1 的维度进行运算。
y = interpft(X,n,dim) 沿维度 dim 运算。例如,如果 X 是矩阵,interpft(X,n,2) 将在 X 行上进行运算。
X — 输入数组, 向量 | 矩阵
n — 点的数目, 正整数标量
dim — 沿其运算的维度, 正整数标量
y — 插入的点, 向量 | 矩阵
import matplotlib.pyplot as plt
示例1:信号处理 - 周期信号插值
创建原始周期信号(采样率较低)
t_original = np.linspace(0, 2 * np.pi, 16, endpoint=False)
signal_original = np.sin(t_original) + 0.5 * np.cos(2 * t_original)
使用FFT插值增加采样点
n_interp = 64
input_str = f"{signal_original.tolist()}, {n_interp}"
signal_interp = interpft(input_str)
生成插值后的时间轴
t_interp = np.linspace(0, 2 * np.pi, n_interp, endpoint=False)
真实信号(用于比较)
t_true = np.linspace(0, 2 * np.pi, 200)
signal_true = np.sin(t_true) + 0.5 * np.cos(2 * t_true)
plt.figure(figsize=(12, 8))
plt.subplot(2, 3, 1)
plt.plot(t_original, signal_original, 'ro-', label='原始采样点', markersize=6)
plt.plot(t_interp, signal_interp, 'b-', label='FFT插值', alpha=0.7)
plt.plot(t_true, signal_true, 'g--', label='真实信号', alpha=0.5)
plt.title('周期信号FFT插值')
plt.xlabel('时间')
plt.ylabel('幅度')
plt.legend()
plt.grid(True, alpha=0.3)
示例2:音频处理 - 音频信号重采样
模拟音频信号(低频正弦波叠加高频成分)
fs_original = 1000 # 原始采样率 1kHz
t_audio = np.linspace(0, 1, fs_original, endpoint=False)
audio_original = 0.8 * np.sin(2 * np.pi * 100 * t_audio) + 0.3 * np.sin(2 * np.pi * 300 * t_audio)
降采样(模拟低采样率情况)
downsample_factor = 4
audio_low_rate = audio_original[::downsample_factor]
使用FFT插值恢复到原始采样率
n_audio_interp = fs_original
audio_interp = interpft(audio_low_rate, n_audio_interp)
t_low_rate = np.linspace(0, 1, len(audio_low_rate), endpoint=False)
t_interp_audio = np.linspace(0, 1, n_audio_interp, endpoint=False)
plt.subplot(2, 3, 2)
plt.plot(t_audio, audio_original, 'g-', label='原始音频', alpha=0.7)
plt.plot(t_low_rate, audio_low_rate, 'ro', label='低采样率点', markersize=4)
plt.plot(t_interp_audio, audio_interp, 'b-', label='FFT插值', alpha=0.7)
plt.title('音频信号重采样')
plt.xlabel('时间 (s)')
plt.ylabel('幅度')
plt.legend()
plt.grid(True, alpha=0.3)
频域分析
plt.subplot(2, 3, 3)
freqs_orig = fftfreq(len(audio_original), 1 / fs_original)
freqs_interp = fftfreq(len(audio_interp), 1 / fs_original)
fft_orig = np.abs(fft(audio_original))[:len(freqs_orig) // 2]
fft_interp = np.abs(fft(audio_interp))[:len(freqs_interp) // 2]
plt.plot(freqs_orig[:len(freqs_orig) // 2], fft_orig, 'g-', label='原始频谱', alpha=0.7)
plt.plot(freqs_interp[:len(freqs_interp) // 2], fft_interp, 'b-', label='插值后频谱', alpha=0.7)
plt.title('频域比较')
plt.xlabel('频率 (Hz)')
plt.ylabel('幅度')
plt.legend()
plt.grid(True, alpha=0.3)
示例3:地震信号处理
模拟地震信号(包含多个频率成分)
t_seismic = np.linspace(0, 10, 50) # 稀疏采样
主震频率 + 余震频率 + 噪声
seismic_original = (2.0 * np.exp(-0.5 * t_seismic) * np.sin(2 * np.pi * 2 * t_seismic) +
0.5 * np.exp(-0.2 * t_seismic) * np.sin(2 * np.pi * 5 * t_seismic) +
0.1 * np.random.normal(0, 0.1, len(t_seismic)))
FFT插值到更高分辨率
n_seismic_interp = 200
seismic_interp = interpft(seismic_original, n_seismic_interp)
t_seismic_interp = np.linspace(0, 10, n_seismic_interp)
plt.subplot(2, 3, 4)
plt.plot(t_seismic, seismic_original, 'ro-', label='原始地震数据', markersize=4)
plt.plot(t_seismic_interp, seismic_interp, 'b-', label='FFT插值', alpha=0.8)
plt.title('地震信号插值')
plt.xlabel('时间 (s)')
plt.ylabel('振幅')
plt.legend()
plt.grid(True, alpha=0.3)
示例4:心电图(ECG)信号处理
模拟ECG信号(QRS复合波)
t_ecg_original = np.linspace(0, 2, 40) # 低采样率ECG
ecg_original = (
0.5 * np.exp(-((t_ecg_original - 0.2) * 10) ** 2) + # P波
1.2 * np.exp(-((t_ecg_original - 0.3) * 8) ** 2) - # QRS复合波
0.3 * np.exp(-((t_ecg_original - 0.4) * 6) ** 2) + # T波
0.1 * np.random.normal(0, 0.05, len(t_ecg_original)) # 噪声
)
FFT插值到医疗标准采样率
n_ecg_interp = 200 # 相当于100Hz采样率
ecg_interp = interpft(ecg_original, n_ecg_interp)
t_ecg_interp = np.linspace(0, 2, n_ecg_interp)
plt.subplot(2, 3, 5)
plt.plot(t_ecg_original, ecg_original, 'ro-', label='原始ECG', markersize=4)
plt.plot(t_ecg_interp, ecg_interp, 'b-', label='FFT插值ECG', alpha=0.8)
plt.title('心电图信号插值')
plt.xlabel('时间 (s)')
plt.ylabel('电压 (mV)')
plt.legend()
plt.grid(True, alpha=0.3)
示例5:天文观测数据插值
模拟恒星亮度观测数据(由于天气原因采样不均匀)
t_astro_original = np.array([0, 1, 3, 4, 6, 8, 9, 11, 13, 15]) # 不均匀时间点
模拟食双星的光变曲线
brightness_original = 1.0 - 0.3 * np.exp(-((t_astro_original % 5 - 2.5) ** 2) / 0.5)
由于时间点不均匀,需要先插值到均匀网格
t_uniform = np.linspace(0, 15, 16) # 均匀时间网格
brightness_uniform = np.interp(t_uniform, t_astro_original, brightness_original)
使用FFT进一步插值到更高分辨率
n_astro_interp = 100
brightness_interp = interpft(brightness_uniform, n_astro_interp)
t_astro_interp = np.linspace(0, 15, n_astro_interp)
plt.subplot(2, 3, 6)
plt.plot(t_astro_original, brightness_original, 'ro', label='原始观测', markersize=6)
plt.plot(t_astro_interp, brightness_interp, 'b-', label='FFT插值', alpha=0.8)
plt.title('恒星亮度变化插值')
plt.xlabel('时间 (小时)')
plt.ylabel('相对亮度')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
示例6: 包含多个频率成分
t_original = np.linspace(0, 4 * np.pi, 32)
test_signal = (np.sin(t_original) +
0.5 * np.sin(3 * t_original) +
0.2 * np.sin(7 * t_original))
插值到更高分辨率
n_interp = 128
FFT插值
signal_fft = interpft(test_signal, n_interp)
线性插值
t_interp = np.linspace(0, 4 * np.pi, n_interp)
signal_linear = np.interp(t_interp, t_original, test_signal)
真实信号(用于误差计算)
t_true = np.linspace(0, 4 * np.pi, 200)
signal_true = np.sin(t_true) + 0.5 * np.sin(3 * t_true) + 0.2 * np.sin(7 * t_true)
计算误差
signal_fft_true = np.interp(t_true, t_interp, signal_fft)
signal_linear_true = np.interp(t_true, t_interp, signal_linear)
error_fft = np.sqrt(np.mean((signal_fft_true - signal_true) ** 2))
error_linear = np.sqrt(np.mean((signal_linear_true - signal_true) ** 2))
可视化比较
plt.figure(figsize=(12, 8))
plt.subplot(2, 2, 1)
plt.plot(t_original, test_signal, 'ro-', label='原始信号', markersize=4)
plt.plot(t_interp, signal_fft, 'b-', label='FFT插值', alpha=0.7)
plt.plot(t_true, signal_true, 'g--', label='真实信号', alpha=0.5)
plt.title(f'FFT插值 (RMSE: {error_fft:.4f})')
plt.xlabel('时间')
plt.ylabel('幅度')
plt.legend()
plt.grid(True, alpha=0.3)
plt.subplot(2, 2, 2)
plt.plot(t_original, test_signal, 'ro-', label='原始信号', markersize=4)
plt.plot(t_interp, signal_linear, 'orange', label='线性插值', alpha=0.7)
plt.plot(t_true, signal_true, 'g--', label='真实信号', alpha=0.5)
plt.title(f'线性插值 (RMSE: {error_linear:.4f})')
plt.xlabel('时间')
plt.ylabel('幅度')
plt.legend()
plt.grid(True, alpha=0.3)
频域比较
plt.subplot(2, 2, 3)
freqs_orig = fftfreq(len(test_signal), 1 / 32)[:16]
freqs_fft = fftfreq(len(signal_fft), 1 / 128)[:64]
freqs_linear = fftfreq(len(signal_linear), 1 / 128)[:64]
fft_orig = np.abs(fft(test_signal))[:16]
fft_fft = np.abs(fft(signal_fft))[:64]
fft_linear = np.abs(fft(signal_linear))[:64]
plt.plot(freqs_orig, fft_orig, 'ro-', label='原始频谱', markersize=4)
plt.plot(freqs_fft, fft_fft, 'b-', label='FFT插值频谱', alpha=0.7)
plt.plot(freqs_linear, fft_linear, 'orange', label='线性插值频谱', alpha=0.7)
plt.title('频域特性比较')
plt.xlabel('频率')
plt.ylabel('幅度')
plt.legend()
plt.grid(True, alpha=0.3)
误差比较
plt.subplot(2, 2, 4)
methods = ['FFT插值', '线性插值']
errors = [error_fft, error_linear]
colors = ['blue', 'orange']
bars = plt.bar(methods, errors, color=colors, alpha=0.7)
plt.title('插值方法误差比较')
plt.ylabel('均方根误差 (RMSE)')
添加数值标签
for bar, error in zip(bars, errors):
plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.001,
f'{error:.4f}', ha='center', va='bottom')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print(f"FFT插值误差: {error_fft:.6f}")
print(f"线性插值误差: {error_linear:.6f}")
print(f"FFT插值相对于线性插值的改进: {(error_linear - error_fft) / error_linear * 100:.1f}%")
#FFT插值误差: 0.271828
#线性插值误差: 0.099717
#FFT插值相对于线性插值的改进: -172.6%
示例7:信号压缩和重建
原始高分辨率信号
t_high_res = np.linspace(0, 2 * np.pi, 128)
signal_high_res = np.sin(t_high_res) + 0.3 * np.sin(5 * t_high_res)
压缩:降采样
compression_ratio = 4
signal_compressed = signal_high_res[::compression_ratio]
重建:使用FFT插值恢复到原始分辨率
signal_reconstructed = interpft(signal_compressed, signal_high_res)
t_compressed = t_high_res[::compression_ratio]
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(t_high_res, signal_high_res, 'g-', label='原始信号', alpha=0.7)
plt.plot(t_compressed, signal_compressed, 'ro', label='压缩后采样点', markersize=4)
plt.plot(t_high_res, signal_reconstructed, 'b-', label='FFT重建', alpha=0.7)
plt.title('信号压缩和FFT重建')
plt.xlabel('时间')
plt.ylabel('幅度')
plt.legend()
plt.grid(True, alpha=0.3)
计算重建误差
reconstruction_error = np.sqrt(np.mean((signal_reconstructed - signal_high_res) ** 2))
compression_ratio_value = len(signal_high_res) / len(signal_compressed)
plt.subplot(1, 2, 2)
plt.plot(t_high_res, signal_reconstructed - signal_high_res, 'r-')
plt.title(f'重建误差 (RMSE: {reconstruction_error:.4f})')
plt.xlabel('时间')
plt.ylabel('误差')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print(f"压缩比: {compression_ratio_value}:1")
print(f"重建误差: {reconstruction_error:.6f}")
#压缩比: 4.0:1
#重建误差: 0.011341
示例8:多通道信号处理
模拟多通道生物信号(如EEG)
n_channels = 3
t_multi = np.linspace(0, 1, 32)
创建不同通道的信号
multi_channel_signals = []
for i in range(n_channels):
freq = 10 + i * 5 # 每个通道不同频率
signal = np.sin(2 * np.pi * freq * t_multi) + 0.2 * np.random.normal(0, 0.1, len(t_multi))
multi_channel_signals.append(signal)
将多通道信号组合成矩阵
multi_signal_matrix = np.column_stack(multi_channel_signals)
对每个通道进行FFT插值
n_multi_interp = 128
multi_signal_interp = interpft(multi_signal_matrix, n_multi_interp, 1) # 按列插值
t_multi_interp = np.linspace(0, 1, n_multi_interp)
plt.figure(figsize=(12, 8))
for i in range(n_channels):
plt.subplot(n_channels, 1, i + 1)
plt.plot(t_multi, multi_channel_signals[i], 'ro-', markersize=2, label=f'通道{i + 1}原始')
plt.plot(t_multi_interp, multi_signal_interp[:, i], 'b-', alpha=0.7, label=f'通道{i + 1}插值')
plt.ylabel(f'通道{i + 1}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.xlabel('时间 (s)')
plt.suptitle('多通道信号同步FFT插值')
plt.tight_layout()
plt.show()
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import numpy as np
from scipy.fft import fft, ifft
import sympy as sp
def interpolation_fft(input_str):
"""
实现类似于 MATLAB 的 interpft 函数,通过 FFT 方法进行一维插值。
参数:
x (array-like): 输入信号(实数或复数)。
n (int): 插值后的信号长度,必须大于原信号长度。
返回:
ndarray: 插值后的实数信号(虚部被丢弃)。
异常:
ValueError: 如果 n 小于原信号长度。
示例:
>>> import numpy as np
>>> x = np.array([1, -1, 1, -1])
>>> interpft(x, 6)
array([ 1. , -0.5, -0.5, 1. , -0.5, -0.5])
"""
try:
# 将输入的字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
# 标记是否出现错误
error = False
# 存储插值结果
result = None
def interpft_single(x, n):
"""
对一维数组进行插值的辅助函数
"""
# 获取输入信号的长度
m = len(x)
# 检查插值后的长度是否小于原信号长度
if n < m:
raise ValueError("插值后的长度 n 不能小于输入信号的长度。")
# 对输入信号进行快速傅里叶变换
X = fft(x)
if m % 2 == 0:
# 若原信号长度为偶数
# 计算中间位置
mid = m // 2
# 在频域中间插入零以进行插值
X_new = np.concatenate((X[:mid], np.zeros(n - m, dtype=X.dtype), X[mid:]))
else:
# 若原信号长度为奇数
# 计算中间位置
mid = (m + 1) // 2
# 在频域中间插入零以进行插值
X_new = np.concatenate((X[:mid], np.zeros(n - m, dtype=X.dtype), X[mid:]))
# 对零填充后的频域信号进行逆快速傅里叶变换
y = ifft(X_new) * (n / m)
# 返回插值后的实数信号(丢弃虚部)
return y.real
if isinstance(expr, tuple) and isinstance(expr[0], list):
if len(expr) == 3:
# 输入包含信号、插值后的长度和维度信息
matrix = sp.Matrix(expr[0])
n = int(expr[1])
dim = int(expr[2])
elif len(expr) == 2:
# 输入包含信号和插值后的长度,默认维度为 0
matrix = sp.Matrix(expr[0])
n = int(expr[1])
dim = 0
else:
# 输入的元组长度不符合要求,标记错误
error = True
if matrix is not None:
if matrix.shape[1] == 1:
# 如果矩阵是单列矩阵,将其展平为一维数组
x_np = np.array(matrix, dtype=float).ravel()
else:
# 否则,将矩阵转换为 NumPy 数组
x_np = np.array(matrix, dtype=float)
else:
# 输入不是有效的矩阵,标记错误
error = True
if dim == 0:
# 按整体进行插值
result = interpft_single(x_np, n)
elif dim == 1:
if x_np.ndim == 2:
# 按列进行插值
result = []
for col in x_np.T:
result.append(interpft_single(col, n))
result = np.array(result).T
else:
# 如果输入不是二维矩阵,按整体进行插值
result = interpft_single(x_np, n)
elif dim == 2:
if x_np.ndim == 2:
# 按行进行插值
result = []
for row in x_np:
result.append(interpft_single(row, n))
result = np.array(result)
else:
# 如果输入不是二维矩阵,按整体进行插值
result = interpft_single(x_np, n)
else:
# 输入的维度信息无效,标记错误
error = True
else:
# 输入不是元组,标记错误
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {str(e)}" # 请增加注释
# 示例测试
if __name__ == "__main__":
# 示例1:偶数长度插值
x = [1, -1, 1, -1]
n = 6
y = interpolation_fft(f"{x}, {n}")
print(y)
# [ 1. -0.5 -0.5 1. -0.5 -0.5]
# 示例2:奇数长度插值
x = [1, 0, -1]
n = 5
y = interpolation_fft(f"{x}, {n}")
print(y)
# [ 1. 0.85810973 -0.46965902 -1.14837497 -0.24007574]
ndgrid格式的一维二维三维和N维网格数据的插值
Vq = interpn(X1,X2,...,Xn,V,Xq1,Xq2,...,Xqn) 使用线性插值返回 n 变量函数在特定查询点的插入值。结果始终穿过函数的原始采样。
X1,X2,...,Xn 包含样本点的坐标。V 包含各样本点处的对应函数值。Xq1,Xq2,...,Xqn 包含查询点的坐标。
示例1: 二维温度场插值
模拟一个温度场:x方向[0,10]米,y方向[0,8]米
已知网格点温度值
result1 = interpn([0,2,4,6,8,10],
[0,2,4,6,8],
[[25,26,27,28,29],
[24,25,26,27,28],
[23,24,25,26,27],
[22,23,24,25,26],
[21,22,23,24,25],
[20,21,22,23,24]], 3.5, 4.2)
print(f"位置(3.5, 4.2)的温度: {result1}°C")
#位置(3.5, 4.2)的温度: (6, 5)°C
示例2: 三维流体速度场
V是速度大小在三维网格上的分布
result2 = interpn([0,1,2],[0,1,2],[0,1,2],
[[[1.0,1.2,1.5],[1.1,1.3,1.6],[1.2,1.4,1.7]],
[[1.3,1.5,1.8],[1.4,1.6,1.9],[1.5,1.7,2.0]],
[[1.6,1.8,2.1],[1.7,1.9,2.2],[1.8,2.0,2.3]]],1.5, 1.5, 1.5)
print(f"位置(1.5,1.5,1.5)的速度: {result2} m/s")
#位置(1.5,1.5,1.5)的速度: [[[1.95]]] m/s
示例3: 地形高度插值(最近邻方法)
使用最近邻插值获取地形高度
result3 = interpn([0,100,200,300],[0,100,200],
[[100,105,110],
[120,125,130],
[115,120,125],
[110,115,120]],150,80,nearest)
print(f"位置(150,80)的地形高度(最近邻): {result3}米")
#位置(150,80)的地形高度(最近邻): (4, 3)米
示例4: 一维信号插值
一维信号在时间点上的采样值
result5 = interpn([0,1,2,3,4,5], [0,2,4,6,8,10], 2.7)
print(f"时间t=2.7时的信号值: {result5}")
#时间t=2.7时的信号值: [5.4]
示例5: 批量查询多个点
同时查询多个位置的插值结果
result7 = interpn([0,1,2],[0,1,2],
[[1,4,7],
[2,5,8],
[3,6,9]],
[0.5,1.5],[0.5,1.5])
print(f"多个查询点的结果:\n{result7}")
#多个查询点的结果:
#[[3,4]
[6,7]]
示例6: 四维数据插值(颜色+透明度)
result8 = interpn([0,1], [0,1], [0,1], [0,1],
[[[[0.1,0.2],[0.3,0.4]],[[0.5,0.6],[0.7,0.8]]],
[[[0.2,0.3],[0.4,0.5]],[[0.6,0.7],[0.8,0.9]]]],
0.3, 0.4, 0.5, 0.6)
print(f"四维空间点(0.3,0.4,0.5,0.6)的值: {result8}")
#四维空间点(0.3,0.4,0.5,0.6)的值: [[[[0.47]]]]
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import numpy as np
import sympy as sp
from scipy.interpolate import RegularGridInterpolator
def parse_nd_array(param):
"""递归将 SymPy 嵌套结构转换为 n 维 numpy 数组"""
if isinstance(param, (sp.Tuple, list, tuple)):
return np.array(param, dtype=float)
elif param.is_Number:
return float(param.evalf())
else:
raise ValueError("Non-numeric element in array")
def interpolation_nd(input_str):
"""
对标 MATLAB 的 interpn 函数,实现 N 维网格数据插值。
参数:
input_str: 输入参数字符串,格式为:
"X1, X2, ..., Xn, V, Xq1, Xq2, ..., Xqn" -> 默认线性插值
"X1, X2, ..., Xn, V, Xq1, Xq2, ..., Xqn, method" -> 指定插值方法
"X1, X2, ..., Xn, V, Xq1, Xq2, ..., Xqn, method, extrap" -> 指定方法和外推值
返回:
插值结果数组,错误时返回错误信息字符串
示例:
>>> interpolation_nd("[0,1], [0,1], [[1,2],[3,4]], 0.5, 0.5")
array(2.5) # 二维线性插值示例
"""
try:
expr = sp.sympify(input_str, evaluate=False)
params = list(expr) if isinstance(expr, tuple) else [expr]
valid_methods = {'linear', 'nearest'}
m = len(params)
if m < 3:
raise ValueError("参数数量不足")
n = (m - 1) // 2
if 2 * n + 1 > m or m > 2 * n + 3:
raise ValueError(f"参数数量不匹配: m={m}, n={n}")
# 解析坐标轴
coords_axes = []
for i in range(n):
param = params[i]
matrix = sp.Matrix(param) if isinstance(param, list) else None
if matrix is not None:
arr = np.array(matrix, dtype=float).squeeze()
elif param.is_Number:
arr = np.array([float(param.evalf())])
else:
try:
arr = np.array([float(param.evalf())])
except:
raise ValueError(f"第 {i + 1} 个参数转换失败")
if arr.ndim != 1:
raise ValueError(f"X{i + 1} 必须是一维数组")
if not np.all(np.diff(arr) > 0):
raise ValueError(f"X{i + 1} 必须是严格递增的")
coords_axes.append(arr)
# 反转坐标轴以适应 scipy 的坐标顺序
reversed_coords = list(reversed(coords_axes))
expected_shape = tuple(len(ax) for ax in reversed_coords)
# 解析 V 矩阵
v_param = params[n]
try:
if isinstance(v_param, (sp.Tuple, list, tuple)):
V = parse_nd_array(v_param)
else:
raise ValueError("V 必须是多维数组")
if V.ndim != n:
raise ValueError(f"V 必须是 {n} 维,实际为 {V.ndim} 维")
if V.shape != expected_shape:
raise ValueError(f"V 形状不匹配: 期望 {expected_shape},实际为 {V.shape}")
except Exception as e:
raise ValueError(f"V 解析失败: {str(e)}")
# 解析查询点
Xqs = []
for i in range(n):
param = params[n + 1 + i]
matrix = sp.Matrix(param) if isinstance(param, list) else None
if matrix is not None:
arr = np.array(matrix, dtype=float).squeeze()
elif param.is_Number:
arr = np.array([float(param.evalf())])
else:
try:
arr = np.array([float(param.evalf())])
except:
raise ValueError(f"Xq{i + 1} 转换失败")
Xqs.append(arr)
# 处理可选参数
method = 'linear'
extrap = np.nan
if m >= 2 * n + 2:
method = str(params[2 * n + 1])
if method not in valid_methods:
raise ValueError(f"无效的插值方法: {method}")
if m >= 2 * n + 3:
try:
extrap = float(params[2 * n + 2])
except:
raise ValueError("无效的外推值")
# 创建插值器
interpolator = RegularGridInterpolator(
reversed_coords,
V,
method=method,
bounds_error=False,
fill_value=extrap
)
# 生成查询网格
Xqs_reversed = list(reversed(Xqs))
mesh_arrays = np.meshgrid(*Xqs_reversed, indexing='ij')
query_points = np.column_stack([arr.ravel() for arr in mesh_arrays])
# 进行插值
Vq = interpolator(query_points)
Vq = Vq.reshape(mesh_arrays[0].shape)
# 转置以匹配原始查询点顺序
if n > 1:
Vq = np.transpose(Vq, axes=tuple(reversed(range(n))))
return Vq
except Exception as e:
return f"错误: {str(e)}"
result = interpolation_nd("[0,1], [0,1], [[1,2],[3,4]], 0.5, 0.5")
print(result)
# [[2.5]]
result = interpolation_nd("[0,1], [0,1], [0,1], [[[1,2],[3,4]],[[5,6],[7,8]]], 0.5, 0.5, 0.5")
print(result)
# [[[4.5]]]
矩阵求逆
Y = inv(X) 计算方阵 X 的逆矩阵
Y = inv(X,method) 按method方法分解矩阵,计算方阵X的逆矩阵.
X^(-1) 等效于 inv(X)
X — 输入矩阵,方阵.
method - 'GE', 'LU', 'ADJ', 'CH', 'LDL'
GE - 使用高斯消去法求逆.
LU - 使用LU分解计算求逆.
ADJ - 使用辅助矩阵和行列式求逆.
CH - 使用cholesky分解求逆.
LDL - 使用LDL分解求逆.
如果X是密集矩阵,默认method是GE,如果X是稀疏矩阵,默认method是LDL
示例1:线性方程组求解(工程应用)
电路中的节点电压方程:
3V₁ - V₂ = 5
-V₁ + 2V₂ = 3
A = [[3, -1], [-1, 2]]
b = [5, 3]
A_inv = inv([[3, -1], [-1, 2]])
V = A_inv * b
print(f"系数矩阵 A: {A}")
print(f"逆矩阵 A⁻¹: {A_inv}")
print(f"解向量 V = A⁻¹b: {V}")
print(f"验证: A * V = {A * V} (应该等于 {b})")
#系数矩阵 A:
#[[3, -1],
[-1, 2]]
#逆矩阵 A⁻¹:
#[[0.4, 0.2],
[0.2, 0.6]]
#解向量 V = A⁻¹b:
#[[2.6],
[2.8]]
#验证: A * V = [[5], [3]]
#应该等于 [[5], [3]]
示例2:坐标变换(计算机图形学)
旋转矩阵的逆等于其转置(正交矩阵性质)
R = [[cos(theta), -sin(theta)],
[sin(theta), cos(theta)]]
R_inv_symbolic = R.inv()
R_inv_numeric = inv([[0.866, -0.5], [0.5, 0.866]]) # 30度旋转
print(f"旋转矩阵 R(θ): {R}")
print(f"符号逆矩阵 R⁻¹(θ): {R_inv_symbolic}")
print(f"数值逆矩阵 (θ=30°): {R_inv_numeric}")
print(f"验证 Rᵀ = R⁻¹: {R.T.equals(R_inv_symbolic)}")
#旋转矩阵 R(θ):
#[[cos(theta), -sin(theta)],
[sin(theta), cos(theta)]]
#符号逆矩阵 R⁻¹(θ):
#[[-sin(theta)**2/cos(theta) + 1/cos(theta), sin(theta)],
[-sin(theta), cos(theta)]]
#数值逆矩阵 (θ=30°):
#[[0.866038105676650, 0.500022000968043],
[-0.500022000968043, 0.866038105676650]]
#验证 Rᵀ = R⁻¹: True
示例3:最小二乘法(数据拟合)
求解 y = ax + b 的最佳拟合参数
数据点
x_data = [1, 2, 3, 4, 5]
y_data = [2.1, 3.9, 6.2, 7.8, 10.1]
设计矩阵
X = [[1, x] for x in x_data]
Y = y_data
正规方程: (XᵀX)β = XᵀY
XTX = X.T * X
XTY = X.T * Y
XTX_inv = inv(XTX)
beta = XTX_inv * XTY
print(f"设计矩阵 X: {X}")
print(f"XᵀX: {XTX}")
print(f"(XᵀX)⁻¹: {XTX_inv}")
print(f"参数估计 β = [b, a]: {beta}")
print(f"拟合直线: y = {float(beta[1]):.3f}x + {float(beta[0]):.3f}")
#设计矩阵 X:
#[[1, 1],
[1, 2],
[1, 3],
[1, 4],
[1, 5]]
#XᵀX:
#[[5, 15],
[15, 55]]
#(XᵀX)⁻¹:
#[[1.1, -0.3],
[-0.3, 0.1]]
#参数估计 β = [b, a]:
#[[0.0500000000000043],
[1.99]]
#拟合直线: y = 1.990x + 0.050
示例4:马尔可夫链(概率论)
转移矩阵 P 的稳态分布 π 满足 π = πP"
即 π(I - P) = 0,需要求 (I-P) 的伪逆
P = [[0.7, 0.2, 0.1],
[0.3, 0.4, 0.3],
[0.2, 0.3, 0.5]]
I = eye(3)
A_markov = I - P
对于奇异矩阵,使用广义逆
A_inv_markov = inv(A_markov)
print("直接求逆成功(但可能不是最佳方法)")
#直接求逆成功(但可能不是最佳方法)
示例5:机械系统(动力学分析)
系统方程: Mẍ + Kx = F
在频域: (-ω²M + K)X = F
M = [[m1, 0], [0, m2]] # 质量矩阵
K = [[k1 + k2, -k2], [-k2, k2]] # 刚度矩阵
dynamic_matrix = -omega ** 2 * M + K
print(f"质量矩阵 M: {M}")
print(f"刚度矩阵 K: {K}")
print(f"动力矩阵 -ω²M + K: {dynamic_matrix}")
#质量矩阵 M:
#[[m1, 0],
[0, m2]]
#刚度矩阵 K:
#[[k1 + k2, -k2],
[-k2, k2]]
#动力矩阵 -ω²M + K:
#[[k1 + k2 - m1*omega**2, -k2],
[-k2, k2 - m2*omega**2]]
数值示例
M_num = [[2, 0], [0, 1]]
K_num = [[3, -1], [-1, 1]]
omega_val = 1.0
dynamic_matrix_num = -omega_val ** 2 * M_num + K_num
dynamic_inv = inv(dynamic_matrix_num)
print(f"数值动力矩阵: {dynamic_matrix_num}")
print(f"数值逆矩阵: {dynamic_inv}")
#数值动力矩阵:
#[[1, -1],
[-1, 0]]
#数值逆矩阵:
#[[0, -1],
[-1, -1]]
示例6:经济学 - 投入产出分析
(I - A)x = d,其中A是技术系数矩阵
A_econ = [[0.2, 0.3, 0.2],
[0.4, 0.1, 0.3],
[0.1, 0.2, 0.1]]
I_econ = eye(3)
leontief_matrix = I_econ - A_econ
leontief_inv = inv(leontief_matrix)
demand = [100, 150, 200] # 最终需求
production = leontief_inv * demand
print(f"技术系数矩阵 A: {A_econ}")
print(f"Leontief矩阵 I-A: {leontief_matrix}")
print(f"Leontief逆矩阵: {leontief_inv}")
print(f"最终需求 d: {demand}")
print(f"总产出 x = (I-A)⁻¹d: {production}")
#技术系数矩阵 A:
#[[0.2, 0.3, 0.2],
[0.4, 0.1, 0.3],
[0.1, 0.2, 0.1]]
#Leontief矩阵 I-A:
#[[0.8, -0.3, -0.2],
[-0.4, 0.9, -0.3],
[-0.1, -0.2, 0.9]]
#Leontief逆矩阵:
#[[1.67037861915367, 0.690423162583519, 0.601336302895323],
[0.868596881959911, 1.55902004454343, 0.712694877505568],
[0.378619153674833, 0.423162583518931, 1.33630289532294]]
#最终需求 d:
#[[100],
[150],
[200]]
#总产出 x = (I-A)⁻¹d:
#[[390.868596881960],
[463.251670378619],
[368.596881959911]]
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def inverse_matrix(input_str):
"""
对标MATLAB inv函数的矩阵求逆函数
参数:
input_str: 矩阵的字符串表示,可以是:
- 纯矩阵表达式(如 "[[1,2],[3,4]]")
- 带方法的元组(如 "(Matrix([[1,2],[3,4]]), 'LU')")
返回:
求逆后的矩阵(成功时)或错误信息字符串(失败时)
支持的方法参数:
'GE' - 高斯消元法(默认)
'LU' - LU分解法
'ADJ' - 伴随矩阵法
'CH' - Cholesky分解(需矩阵正定)
'LDL' - LDL分解(需矩阵厄米特)
示例:
>>> inverse_matrix("[[1, 0], [0, 1]]")
Matrix([[1, 0], [0, 1]])
>>> inverse_matrix("(Matrix([[1,2],[3,4]]), 'LU')")
Matrix([[-2, 1], [3/2, -1/2]])
"""
try:
# 将输入字符串转换为SymPy表达式
expr = sp.sympify(input_str)
error = False
result = None
# 处理带方法参数的元组输入(如 (Matrix, 'LU'))
if isinstance(expr, tuple) and len(expr) == 2:
# 尝试转换第一个元素为矩阵并验证方法参数
matrix = sp.Matrix(expr[0]) if isinstance(expr[0], list) else None
method = str(expr[1]) # 确保方法参数为字符串
# 验证矩阵转换是否成功和方法是否有效
if matrix is not None and method in ['GE', 'LU', 'ADJ', 'CH', 'LDL']:
result = matrix.inv(method=method).evalf()
else:
error = True
# 处理普通矩阵输入
else:
matrix = sp.Matrix(expr) if isinstance(expr, list) else None
if matrix is not None:
result = matrix.inv().evalf() # 使用默认方法(GE)
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# --------------------------
# 示例代码
# --------------------------
if __name__ == "__main__":
# 示例1:基本数值矩阵求逆
print("示例1:基本数值矩阵求逆")
print(inverse_matrix("[[1, 2], [3, 4]]"))
# Matrix([[-2.00000000000000, 1.00000000000000],
# [1.50000000000000, -0.500000000000000]])
反古德曼函数
invGudermannian(z) 返回z的逆古德曼函数。
z — 标量
示例1: 基本数值计算
print(f"invGudermannian(0) = {invGudermannian(0)}")
print(f"invGudermannian(0.5) = {invGudermannian(0.5)}")
print(f"invGudermannian(1.0) = {invGudermannian(1.0)}")
#inverse_gudermannian(0) = 0.0
#inverse_gudermannian(0.5) = 0.5222381032784403
#inverse_gudermannian(1.0) = 1.2261911708835171
示例2: 符号计算
print(f"invGudermannian('y') = {invGudermannian(y)}")
print(f"invGudermannian('theta') = {invGudermannian(theta)}")
inverse_gudermannian('y') = asinh(tan(y))
inverse_gudermannian('theta') = asinh(tan(theta))
示例3: 地图投影应用(墨卡托投影)
在墨卡托投影中,纬度 φ 与投影坐标 y 的关系:
y = gd⁻¹(φ) = asinh(tan(φ))
latitudes = [0, 30, 45, 60] # 纬度(度)
for lat_deg in latitudes:
lat_rad = np.radians(lat_deg)
y_coord = invGudermannian(lat_rad)
print(f"纬度 {lat_deg}° -> 墨卡托投影y坐标: {y_coord:.6f}")
#纬度 0° -> 墨卡托投影y坐标: 0.000000
#纬度 30° -> 墨卡托投影y坐标: 0.549306
#纬度 45° -> 墨卡托投影y坐标: 0.881374
#纬度 60° -> 墨卡托投影y坐标: 1.316958
示例4: 双曲几何应用
在双曲几何中,反古德曼函数用于角度和长度的转换
angles = [0.1, 0.5, 1.0] # 弧度
for angle in angles:
hyperbolic_measure = invGudermannian(angle)
print(f"欧几里得角度 {angle:.3f} -> 双曲度量: {hyperbolic_measure:.6f}")
#欧几里得角度 0.100 -> 双曲度量: 0.100167
#欧几里得角度 0.500 -> 双曲度量: 0.522238
#欧几里得角度 1.000 -> 双曲度量: 1.226191
示例5: 特殊值验证
special_values = {
'0': 0,
'pi/4': asinh(1),
'pi/6': asinh(1/√3)
}
for val, expected in special_values.items():
result = invGudermannian(val)
print(f"gd⁻¹({val}) = {result} (期望: {expected})")
#gd⁻¹(0) = 0.0 (期望: 0)
#gd⁻¹(pi/4) = 0.8813735870195429 (期望: asinh(1))
#gd⁻¹(pi/6) = 0.5493061443340549 (期望: asinh(1/√3))
示例6: 边界条件测试
boundary_values = [-1.56, -1.57, 1.56, 1.57] # 接近 ±π/2
for val in boundary_values:
result = invGudermannian(val)
print(f"gd⁻¹({val}) = {result}")
#gd⁻¹(-1.56) = -5.221686781391221
#gd⁻¹(-1.57) = -7.828648037733774
#gd⁻¹(1.56) = 5.221686781391221
#gd⁻¹(1.57) = 7.828648037733774
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def inverse_gudermannian(input_str):
'''
返回z的逆古德曼函数(使用解析表达式,避免数值求解的不稳定性)
古德曼函数:gd(x) = 2 * atan(exp(x)) - pi/2
反古德曼函数:x = arcsinh(tan(y)) 或 x = ln(sec(y) + tan(y))
:param input_str: 输入值或表达式
:return: 反古德曼函数值或表达式
'''
try:
# 将输入字符串转换为SymPy表达式
y = sp.sympify(input_str)
# 使用解析表达式:inverse_gudermannian(y) = arcsinh(tan(y)) = ln(sec(y) + tan(y))
if y.free_symbols:
# 符号情况:返回解析表达式
result = sp.asinh(sp.tan(y))
# 也可以写成对数形式:sp.log(sp.sec(y) + sp.tan(y))
return result
else:
# 数值情况:直接计算
y_val = float(y.evalf())
# 检查定义域:tan(y) 在 y = ±pi/2 处无定义
if abs(y_val) >= np.pi / 2:
return f"错误: 输入值 {y_val} 超出定义域 (-π/2, π/2)"
# 使用解析公式计算
result = np.arcsinh(np.tan(y_val))
return result
except Exception as e:
return f"错误: {e}"
# --------------------------
# 示例代码
# --------------------------
if __name__ == "__main__":
# 示例1:基本数值矩阵求逆
print(inverse_gudermannian("0"))
# 6.083691555487232e-17
# 示例2:使用LU分解法
print(inverse_gudermannian("1.5"))
# 3.3406775427982867
# 示例3:单位矩阵求逆(结果应不变)
print(inverse_gudermannian("x"))
# Eq(2*atan(exp(x)) - pi/2, x)
希尔伯特矩阵的逆矩阵
H = invhilb(n) 生成确切希尔伯特矩阵的的逆矩阵.
n — 矩阵的阶次,非负整数标量
示例1: 基本测试
for n in [1, 2, 3, 4]:
print(f"\n{n}阶希尔伯特矩阵的逆:")
H_inv = invhilb(n)
print(H_inv)
# 验证逆矩阵性质
H = hilbert_matrix(n)
identity_check = H * H_inv
print(f"验证 H * H_inv ≈ I:")
print(identity_check.evalf(3)) # 保留3位小数显示
#1阶希尔伯特矩阵的逆:
#[[1]]
#验证 H * H_inv ≈ I:
#[[1.00]]
#2阶希尔伯特矩阵的逆:
#[[4, -6],
[-6, 12]]
#验证 H * H_inv ≈ I:
#[[1.00, 0],
[0, 1.00]]
#3阶希尔伯特矩阵的逆:
#[[9, -36, 30],
[-36, 192, -180],
[30, -180, 180]]
#验证 H * H_inv ≈ I:
#[[1.00, 0, 0],
[0, 1.00, 0],
[0, 0, 1.00]]
#4阶希尔伯特矩阵的逆:
#[[16, -120, 240, -140],
[-120, 1200, -2700, 1680],
[240, -2700, 6480, -4200],
[-140, 1680, -4200, 2800]]
#验证 H * H_inv ≈ I:
#[[1.00, 0, 0, 0],
[0, 1.00, 0, 0],
[0, 0, 1.00, 0],
[0, 0, 0, 1.00]]
示例2: 条件数分析(病态性研究)
希尔伯特矩阵是著名的病态矩阵,条件数随阶数增长极快
for n in [3, 5, 7, 10]:
H = hilbert_matrix(n)
cond_num = matrix_condition_number(H)
print(f"{n}阶希尔伯特矩阵的条件数: {cond_num}")
# 显示矩阵元素
if n <= 5:
print(f"H_{n} = ")
print(H.evalf(3))
#3阶希尔伯特矩阵的条件数: 524.0567775860644
#H_3 = [[1.00, 0.500, 0.333],
[0.500, 0.333, 0.250],
[0.333, 0.250, 0.200]]
#5阶希尔伯特矩阵的条件数: 476607.25024224253
#H_5 = [[1.00, 0.500, 0.333, 0.250, 0.200],
[0.500, 0.333, 0.250, 0.200, 0.167],
[0.333, 0.250, 0.200, 0.167, 0.143],
[0.250, 0.200, 0.167, 0.143, 0.125],
[0.200, 0.167, 0.143, 0.125, 0.111]]
#7阶希尔伯特矩阵的条件数: 475367356.37688667
#10阶希尔伯特矩阵的条件数: 16024859712306.152
示例3: 数值稳定性测试
比较符号计算和数值计算的差异
n = 6
H_sym = hilbert_matrix(n)
H_inv_sym = invhilb(n)
数值计算(可能不准确)
H_np = np.array([[1 / (i + j + 1) for j in range(n)] for i in range(n)], dtype=float)
try:
H_inv_np = np.linalg.inv(H_np)
print(f"\n{n}阶希尔伯特矩阵数值逆的前3×3元素:")
print(H_inv_np[:3, :3])
print(f"符号计算逆的前3×3元素:")
print(np.array(H_inv_sym[:3, :3], dtype=float))
# 计算差异
diff = np.array(H_inv_sym, dtype=float) - H_inv_np
print(f"最大差异: {np.max(np.abs(diff))}")
except Exception as e:
print(f"数值计算失败: {e}")
#6阶希尔伯特矩阵数值逆的前3×3元素:
#[[ 3.6000e+01,-6.3000e+02,3.3600e+03]
[-6.3000e+02,1.4700e+04,-8.8200e+04]
[ 3.3600e+03,-8.8200e+04,5.6448e+05]]
#符号计算逆的前3×3元素:
#[[ 3.6000e+01,-6.3000e+02,3.3600e+03]
[-6.3000e+02,1.4700e+04,-8.8200e+04]
[ 3.3600e+03,-8.8200e+04,5.6448e+05]]
#最大差异: 0.0006772307679057121
示例4: 在多项式拟合中的应用
希尔伯特矩阵出现在最小二乘多项式拟合中
在多项式拟合中,法方程系数矩阵通常是希尔伯特矩阵
对于n次多项式拟合,法方程矩阵是(n+1)×(n+1)的希尔伯特矩阵
演示3次多项式拟合
degree = 3
n = degree + 1
H_fit = hilbert_matrix(n)
print(f"\n{degree}次多项式拟合的法方程矩阵:")
print(H_fit.evalf(3))
H_inv_fit = invhilb(str(n))
print(f"逆矩阵:")
print(H_inv_fit)
#3次多项式拟合的法方程矩阵:
#[[1.00, 0.500, 0.333, 0.250],
[0.500, 0.333, 0.250, 0.200],
[0.333, 0.250, 0.200, 0.167],
[0.250, 0.200, 0.167, 0.143]]
#逆矩阵:
#[[16, -120, 240, -140],
[-120, 1200, -2700, 1680],
[240, -2700, 6480, -4200],
[-140, 1680, -4200, 2800]]
示例5: 误差分析
研究扰动对解的影响
n = 4
H = hilbert_matrix(n)
H_inv = invhilb(n)
创建扰动向量
b = [1, 1, 1, 1]
delta_b = [0.001, -0.001, 0.0005, -0.0005]
原始解和扰动解
x_original = H_inv * b
x_perturbed = H_inv * (b + delta_b)
error = x_perturbed - x_original
print(f"原始解: {x_original.evalf(6)}")
print(f"扰动解: {x_perturbed.evalf(6)}")
print(f"误差: {error.evalf(6)}")
print(f"相对误差范数: {error.norm() / x_original.norm():.6f}")
#原始解:
#[[-4.00000],
[60.0000],
[-180.000],
[140.000]]
#扰动解:
#[[-3.67400],
[56.4900],
[-171.720],
[134.680]]
#误差:
#[[0.326000],
[-3.51000],
[8.28000],
[-5.32000]]
#相对误差范数: 0.044329
示例6: 特殊性质验证
希尔伯特逆矩阵的元素都是整数
n = 5
H_inv = invhilb(n)
print(f"{n}阶希尔伯特逆矩阵的元素都是整数:")
for i in range(min(n, 3)): # 只显示前3行
row = [H_inv[i, j] for j in range(min(n, 3))]
print(f"第{i + 1}行: {row}")
#5阶希尔伯特逆矩阵的元素都是整数:
#第1行: [25, -300, 1050]
#第2行: [-300, 4800, -18900]
#第3行: [1050, -18900, 79380]
示例7: 与其它矩阵的比较
比较希尔伯特矩阵和其它矩阵的逆
matrices = {
"希尔伯特矩阵": hilbert_matrix(3),
"单位矩阵": sp.eye(3),
"三对角矩阵": sp.Matrix([[2, 1, 0], [1, 2, 1], [0, 1, 2]])
}
for name, mat in matrices.items():
try:
inv_mat = mat.inv()
print(f"\n{name}的逆:")
print(inv_mat.evalf(3))
except Exception as e:
print(f"{name}求逆失败: {e}")
#希尔伯特矩阵的逆:
#[[9.00, -36.0, 30.0],
[-36.0, 192., -180.],
[30.0, -180., 180.]]
#单位矩阵的逆:
#[[1.00, 0, 0],
[0, 1.00, 0],
[0, 0, 1.00]]
#三对角矩阵的逆:
#[[0.750, -0.500, 0.250],
[-0.500, 1.00, -0.500],
[0.250, -0.500, 0.750]]
示例8: 大规模计算警告
测试较大阶数(可能有性能问题)
large_n = 12
result = invhilb(large_n)
if isinstance(result, str):
print(f"n={large_n}: {result}")
else:
print(f"n={large_n}: 计算成功,逆矩阵形状 {result.shape}")
# 显示一些统计信息
elements = [abs(float(result[i, j])) for i in range(large_n) for j in range(large_n)]
print(f"元素绝对值范围: [{min(elements):.2e}, {max(elements):.2e}]")
#n=12: 计算成功,逆矩阵形状 (12, 12)
#元素绝对值范围: [1.44e+02, 3.66e+15]
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def inverse_hilb_matrix(input_str):
"""
对标MATLAB invhilb函数,生成n×n希尔伯特矩阵的逆矩阵
参数:
input_str: 表示正整数的字符串
返回:
SymPy矩阵对象(成功时)或错误信息字符串(失败时)
示例:
>>> inverse_hilb_matrix("3")
Matrix([
[ 9, -36, 30],
[-36, 192,-180],
[ 30,-180, 180]])
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
def hilbert_matrix_symbolic(n):
"""完全符号计算的实现方案"""
H = sp.zeros(n)
for i in range(n):
for j in range(n):
H[i, j] = 1 / (sp.Integer(i) + sp.Integer(j) + 1)
return H.inv()
if isinstance(expr, tuple):
error = True
elif expr.is_integer:
n = int(expr)
if n <= 0:
return f"错误: 阶数必须为正整数,得到 {n}"
if n > 15:
return f"警告: 阶数 {n} 较大,计算可能较慢。希尔伯特矩阵是高度病态的,高阶数可能导致数值不稳定。"
result = hilbert_matrix_symbolic(n)
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
def hilbert_matrix(n):
"""生成n×n希尔伯特矩阵"""
H = sp.zeros(n)
for i in range(n):
for j in range(n):
H[i, j] = 1 / (sp.Integer(i) + sp.Integer(j) + 1)
return H
def matrix_condition_number(H):
"""计算矩阵的条件数(近似)"""
try:
H_np = np.array(H, dtype=float)
return np.linalg.cond(H_np)
except:
return "无法计算条件数"
# --------------------------
# 示例代码
# --------------------------
if __name__ == "__main__":
# 示例1:3阶希尔伯特逆矩阵
print("示例1:n=4")
print(inverse_hilb_matrix("4"))
# Matrix([[16, -120, 240, -140],
# [-120, 1200, -2700, 1680],
# [240, -2700, 6480, -4200],
# [-140, 1680, -4200, 2800]])
# 示例2:边界条件测试(n=1)
print("\n示例2:n=1")
print(inverse_hilb_matrix("1"))
# Matrix([[1]])
逆置换数组维度
A = ipermute(B,dimorder) 按照向量 dimorder 指定的顺序重新排列数组 B 的维度,使得 B = permute(A,dimorder)。换句话说,输入数组的第 i 个维度变为输出数组的维度 dimorder(i)。
B — 输入数组,向量,矩阵
dimorder — 维度顺序,行向量
示例1: 基本二维数组转置
原始数组
original = [[1, 2, 3], [4, 5, 6]]
print("原始数组:")
print(original)
#原始数组:
#[[1, 2, 3],
[4, 5, 6]]
先permute转置
permuted = permute_order([[1,2,3],[4,5,6]],[2,1])
print("\npermute转置后:")
print(permuted)
#permute转置后:
#[[1, 4],
[2, 5],
[3, 6]]
再ipermute恢复
recovered = ipermute([[1,4],[2,5],[3,6]],[2,1])
print("\nipermute恢复后:")
print(recovered)
#ipermute恢复后:
#[[1, 2, 3],
[4, 5, 6]]
示例2: 三维数组维度重排
3x2x4 三维数组
array_3d = [[[1, 2, 3, 4], [5, 6, 7, 8]],
[[9, 10, 11, 12], [13, 14, 15, 16]],
[[17, 18, 19, 20], [21, 22, 23, 24]]]
print("原始3D数组形状: 3x2x4")
print("原始数组:")
print(array_3d)
#原始3D数组形状: 3x2x4
#原始数组:
#[[[1, 2, 3, 4], [5, 6, 7, 8]],
[[9, 10, 11, 12], [13, 14, 15, 16]],
[[17, 18, 19, 20], [21, 22, 23, 24]]]
permute: 从 [1,2,3] 变为 [2,3,1]
permuted_3d = permute_order([[[1,2,3,4],[5,6,7,8]],[[9,10,11,12],[13,14,15,16]],[[17,18,19,20],[21,22,23,24]]],[2,3,1])
print("\npermute [2,3,1] 后:")
print(permuted_3d)
#permute [2,3,1] 后:
#[[[1, 9, 17], [2, 10, 18], [3, 11, 19], [4, 12, 20]],
[[5, 13, 21], [6, 14, 22], [7, 15, 23], [8, 16, 24]]]
ipermute恢复
recovered_3d = ipermute(permuted_3d,[2,3,1])
print("\nipermute恢复后:")
print(recovered_3d)
#ipermute恢复后:
#[[[1, 2, 3, 4], [5, 6, 7, 8]],
[[9, 10, 11, 12], [13, 14, 15, 16]],
[[17, 18, 19, 20], [21, 22, 23, 24]]]
示例3: 图像处理中的通道重排
模拟RGB图像数据: 高度x宽度x通道
假设 2x3 RGB图像
image_data = [
[[255, 0, 0], [0, 255, 0], [0, 0, 255]], # 第一行: 红,绿,蓝
[[255, 255, 0], [255, 0, 255], [0, 255, 255]] # 第二行: 黄,紫,青
]
print("原始图像数据 (2x3x3 - 高x宽x通道):")
print(image_data)
#原始图像数据 (2x3x3 - 高x宽x通道):
#[[[255, 0, 0], [0, 255, 0], [0, 0, 255]],
[[255, 255, 0], [255, 0, 255], [0, 255, 255]]]
从 [高,宽,通道] 变为 [通道,高,宽] (深度学习常用)
permuted_image = permute_order(image_data,[3,1,2])
print("\npermute为通道优先 [3,1,2]:")
print(permuted_image)
#permute为通道优先 [3,1,2]:
#[[[255, 0, 0], [255, 255, 0]],
[[0, 255, 0], [255, 0, 255]],
[[0, 0, 255], [0, 255, 255]]]
恢复原始布局
recovered_image = ipermute(permuted_image,[3,1,2])
print("\nipermute恢复原始布局:")
print(recovered_image)
#ipermute恢复原始布局:
#[[[255, 0, 0], [0, 255, 0], [0, 0, 255]],
[[255, 255, 0], [255, 0, 255], [0, 255, 255]]]
示例4: 时间序列数据重排
多个传感器的时间序列: 时间x传感器x测量值
sensor_data = [
[[1.1, 1.2], [2.1, 2.2], [3.1, 3.2]], # 时间点1: 3个传感器的2个测量值
[[1.3, 1.4], [2.3, 2.4], [3.3, 3.4]], # 时间点2
[[1.5, 1.6], [2.5, 2.6], [3.5, 3.6]] # 时间点3
]
print("传感器数据 (3x3x2 - 时间x传感器x测量):")
print(sensor_data)
#传感器数据 (3x3x2 - 时间x传感器x测量):
#[[[1.1, 1.2], [2.1, 2.2], [3.1, 3.2]],
[[1.3, 1.4], [2.3, 2.4], [3.3, 3.4]],
[[1.5, 1.6], [2.5, 2.6], [3.5, 3.6]]]
重排为 [传感器, 测量, 时间]
rearranged = permute_order(sensor_data,[2,3,1])
print("\n重排为 [传感器,测量,时间] [2,3,1]:")
print(rearranged)
#重排为 [传感器,测量,时间] [2,3,1]:
#[[[1.1, 1.3, 1.5], [1.2, 1.4, 1.6]],
[[2.1, 2.3, 2.5], [2.2, 2.4, 2.6]],
[[3.1, 3.3, 3.5], [3.2, 3.4, 3.6]]]
恢复原始顺序
original_order = ipermute(rearranged,[2,3,1])
print("\n恢复原始顺序:")
print(original_order)
#恢复原始顺序:
#[[[1.1, 1.2], [2.1, 2.2], [3.1, 3.2]],
[[1.3, 1.4], [2.3, 2.4], [3.3, 3.4]],
[[1.5, 1.6], [2.5, 2.6], [3.5, 3.6]]]
示例5: 符号计算中的张量操作
使用符号变量的张量
symbolic_tensor = [
[[x, x ** 2], [y, y ** 2]],
[[z, z ** 2], [x + y, (x + y) ** 2]]
]
print("符号张量:")
print(symbolic_tensor)
#符号张量:
#[[[x, x**2], [y, y**2]],
[[z, z**2], [x + y, (x + y)**2]]]
维度重排
permuted_symbolic = permute_order(symbolic_tensor,[3,1,2])
print("\n符号张量permute [3,1,2]:")
print(permuted_symbolic)
#符号张量permute [3,1,2]:
#[[[x, y], [z, x + y]],
[[x**2, y**2], [z**2, (x + y)**2]]]
恢复
recovered_symbolic = ipermute(permuted_symbolic,[3,1,2])
print("\n符号张量ipermute恢复:")
print(recovered_symbolic)
#符号张量ipermute恢复:
#[[[x, x**2], [y, y**2]],
[[z, z**2], [x + y, (x + y)**2]]]
示例6: 四维数据(如批量图像)
批量图像数据: 批量大小x通道x高x宽
batch_images = [
[ # 第一个样本
[[1, 2], [3, 4]], # 通道1
[[5, 6], [7, 8]] # 通道2
],
[ # 第二个样本
[[9, 10], [11, 12]], # 通道1
[[13, 14], [15, 16]] # 通道2
]
]
print("批量图像数据 (2x2x2x2 - 批量x通道x高x宽):")
print(batch_images)
#批量图像数据 (2x2x2x2 - 批量x通道x高x宽):
#[[[[1, 2], [3, 4]],
[[5, 6], [7, 8]]],
[[[9, 10], [11, 12]],
[[13, 14], [15, 16]]]]
重排为 PyTorch 风格: [批量, 通道, 高, 宽] -> [批量, 高, 宽, 通道]
pytorch_style = permute_order(batch_images,[1,3,4,2])
print("\n重排为PyTorch风格 [1,3,4,2]:")
print(pytorch_style)
#重排为PyTorch风格 [1,3,4,2]:
#[[[[1, 5], [2, 6]],
[[3, 7], [4, 8]]],
[[[9, 13], [10, 14]],
[[11, 15], [12, 16]]]]
恢复
original_batch = ipermute(pytorch_style,[1,3,4,2])
print("\n恢复原始批量格式:")
print(original_batch)
#恢复原始批量格式:
#[[[[1, 2], [3, 4]],
[[5, 6], [7, 8]]],
[[[9, 10], [11, 12]],
[[13, 14], [15, 16]]]]
示例7: 验证逆置换性质
验证 permute 和 ipermute 是互逆操作
test_array = [[1, 2], [3, 4], [5, 6]]
print("测试数组:")
print(test_array)
#测试数组:
#[[1, 2],
[3, 4],
[5, 6]]
order = [2, 1]
permuted_test = permute_order(test_array,[2,1])
print(f"\npermute with order {order}:")
print(permuted_test)
#permute with order [2, 1]:
#[[1, 3, 5],
[2, 4, 6]]
ipermuted_test = ipermute(permuted_test,[2,1])
print(f"\nipermute with same order {order}:")
print(ipermuted_test)
#ipermute with same order [2, 1]:
#[[1, 2],
[3, 4],
[5, 6]]
print(f"\n恢复是否成功: {test_array == ipermuted_test}")
#恢复是否成功: True
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def permute_order(input_str):
"""
实现permute功能,用于对比测试
"""
try:
expr = sp.sympify(input_str)
result = None
error = False
if isinstance(expr, tuple) and len(expr) == 2:
if isinstance(expr[0], list) and isinstance(expr[1], list):
order = expr[1]
# 将MATLAB的1-based order转换为0-based
order = [o - 1 for o in order]
arr_np = np.array(matrix.tolist(), dtype=object)
result_np = np.transpose(arr_np, order)
result = sp.Array(result_np.tolist())
else:
error = True
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误:{e}"
def inverse_permute_order(input_str):
"""
实现与MATLAB ipermute等效的功能,通过计算逆排列并调整转置顺序。
:param arr: 输入的数组,可以是sympy矩阵或numpy数组
:param order: 原permute操作使用的维度顺序(1-based,如MATLAB)
:return: 重排后的数组
"""
try:
expr = sp.sympify(input_str)
result = None
error = False
if isinstance(expr, tuple) and len(expr) == 2:
if isinstance(expr[0], list) and isinstance(expr[1], list):
matrix = sp.Matrix(expr[0])
order = expr[1]
# 将MATLAB的1-based order转换为0-based
order = [o - 1 for o in order]
# 计算逆排列:inv_order使得应用后恢复原始维度
inv_order = np.argsort(order)
arr_np = np.array(matrix.tolist(), dtype=object)
result_np = np.transpose(arr_np, inv_order)
result = sp.Matrix(result_np.tolist())
else:
error = True
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误:{e}"
def main():
# 示范使用sympy矩阵
sympy_result = inverse_permute_order("[[x,y],[z,x+y]],[2,1]")
print("\n使用sympy矩阵重排后的数组:")
print(sympy_result)
# Matrix([[x, z],
# [y, x + y]])
# 示范使用numpy数组
numpy_result = inverse_permute_order("[[1,2],[3,4]],[2,1]")
print("\n使用numpy数组重排后的数组:")
print(numpy_result)
# Matrix([[1, 3],
# [2, 4]])
if __name__ == "__main__":
main()
确定矩阵是否在指定带宽范围内
如果A是在指定的下带宽和上带宽范围内的矩阵,则tf = isbanded(A,lower,upper) 返回逻辑值 1 (true).否则,将返回逻辑值 0 (false).
A — 输入数组,数组
lower — 下带宽,非负整数标量
upper — 上带宽,非负整数标量
示例1: 基本带状矩阵测试
三对角矩阵 (下带宽=1, 上带宽=1)
tridiagonal = [[2, 1, 0, 0],
[1, 2, 1, 0],
[0, 1, 2, 1],
[0, 0, 1, 2]]
result = isbanded(tridiagonal, 1, 1)
print(f"三对角矩阵 (下带宽1, 上带宽1): {bool(result)}")
#三对角矩阵 (下带宽1, 上带宽1): True
下三角矩阵 (下带宽=3, 上带宽=0)
lower_tri = [[1, 0, 0, 0],
[2, 3, 0, 0],
[4, 5, 6, 0],
[7, 8, 9, 10]]
result = isbanded(lower_tri, 3, 0)
print(f"下三角矩阵 (下带宽3, 上带宽0): {bool(result)}")
#下三角矩阵 (下带宽3, 上带宽0): True
示例2: 有限差分矩阵
一维有限差分矩阵 (三对角)
fd_matrix = [[-2, 1, 0, 0, 0],
[1, -2, 1, 0, 0],
[0, 1, -2, 1, 0],
[0, 0, 1, -2, 1],
[0, 0, 0, 1, -2]]
result = isbanded(fd_matrix, 1, 1)
print(f"有限差分矩阵 (下带宽1, 上带宽1): {bool(result)}")
#有限差分矩阵 (下带宽1, 上带宽1): True
示例3: 边界条件测试
对角矩阵 (下带宽=0, 上带宽=0)
diagonal = [[1, 0, 0],
[0, 2, 0],
[0, 0, 3]]
result = isbanded(diagonal, 0, 0)
print(f"对角矩阵 (下带宽0, 上带宽0): {bool(result)}")
#对角矩阵 (下带宽0, 上带宽0): True
测试非对角矩阵
not_diagonal = [[1, 0.1, 0],
[0, 2, 0],
[0, 0, 3]]
result = isbanded(not_diagonal, 0, 0)
print(f"非严格对角矩阵 (下带宽0, 上带宽0): {bool(result)}")
#非严格对角矩阵 (下带宽0, 上带宽0): False
示例4: 数值线性代数中的常见矩阵
对称带状矩阵
symmetric_banded = [[4, 1, 0, 0],
[1, 4, 1, 0],
[0, 1, 4, 1],
[0, 0, 1, 4]]
result = isbanded(symmetric_banded, 1, 1)
print(f"对称带状矩阵 (下带宽1, 上带宽1): {bool(result)}")
#对称带状矩阵 (下带宽1, 上带宽1): True
Toeplitz 矩阵
toeplitz = [[2, 1, 0, 0],
[3, 2, 1, 0],
[0, 3, 2, 1],
[0, 0, 3, 2]]
result = isbanded(toeplitz, 1, 1)
print(f"Toeplitz矩阵 (下带宽1, 上带宽1): {bool(result)}")
#Toeplitz矩阵 (下带宽1, 上带宽1): True
示例5: 符号矩阵测试
使用符号变量的带状矩阵
symbolic_banded = [[a, b, 0, 0],
[c, a, b, 0],
[0, c, a, b],
[0, 0, c, a]]
result = isbanded(symbolic_banded, 1, 1)
print(f"符号三对角矩阵 (下带宽1, 上带宽1): {bool(result)}")
#符号三对角矩阵 (下带宽1, 上带宽1): True
示例6: 稀疏矩阵应用
典型的稀疏矩阵结构
sparse_pattern = [[0, 5, 0, 0, 0],
[2, 0, 7, 0, 0],
[0, 3, 0, 9, 0],
[0, 0, 4, 0, 6],
[0, 0, 0, 1, 0]]
result = isbanded(sparse_pattern, 1, 1)
print(f"稀疏矩阵模式 (下带宽1, 上带宽1): {bool(result)}")
#稀疏矩阵模式 (下带宽1, 上带宽1): True
更宽松的带宽检查
result = isbanded(sparse_pattern, 2, 2)
print(f"稀疏矩阵模式 (下带宽2, 上带宽2): {bool(result)}")
#稀疏矩阵模式 (下带宽2, 上带宽2): True
示例7: 实际工程应用
结构力学中的刚度矩阵 (通常有固定带宽)
stiffness_matrix = [
[10, -5, 0, 0, 0],
[-5, 15, -5, 0, 0],
[0, -5, 15, -5, 0],
[0, 0, -5, 15, -5],
[0, 0, 0, -5, 10]
]
result = isbanded(stiffness_matrix, 1, 1)
print(f"结构刚度矩阵 (下带宽1, 上带宽1): {bool(result)}")
#结构刚度矩阵 (下带宽1, 上带宽1): True
电路分析中的导纳矩阵
admittance_matrix = [
[3, -1, 0, -1, 0],
[-1, 4, -1, 0, -1],
[0, -1, 3, -1, 0],
[-1, 0, -1, 4, -1],
[0, -1, 0, -1, 3]
]
result = isbanded(admittance_matrix, 2, 2)
print(f"电路导纳矩阵 (下带宽2, 上带宽2): {bool(result)}")
#电路导纳矩阵 (下带宽2, 上带宽2): False
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def is_within_banded(input_str):
"""
对标 MATLAB 的 isbanded 函数,判断矩阵是否在指定带宽范围内。
参数:
input_str (str): 输入字符串,格式为 "矩阵, 下带宽, 上带宽"。
示例: "[[0,1,0], [2,0,3], [0,4,0]], 1, 0"
返回:
bool 或 str: 如果矩阵满足带宽要求返回 True,否则返回 False。
输入错误时返回错误信息字符串。
示例:
>>> result = is_within_banded("[[0,1,0], [2,0,3], [0,4,0]], 1, 0")
>>> print(result) # True
"""
try:
# 解析输入字符串为 SymPy 表达式
expr = sp.sympify(input_str)
# 验证输入是否为三元组 (矩阵, 下带宽, 上带宽)
if not (isinstance(expr, tuple) and len(expr) == 3):
return f"输入错误:需要形如 '矩阵, 下带宽, 上带宽' 的三元组,当前输入为 {input_str}"
# 提取矩阵、下带宽、上带宽
M_sym = sp.Matrix(expr[0]) if isinstance(expr[0], list) else None
lower = expr[1]
upper = expr[2]
# 检查矩阵和带宽的有效性
if M_sym is None:
return "错误:输入的矩阵无效"
if not (lower.is_Integer and upper.is_Integer):
return "错误:下带宽和上带宽必须为整数"
lower = int(lower)
upper = int(upper)
if lower < 0 or upper < 0:
return "错误:带宽不能为负数"
# 检查矩阵是否为带状矩阵
rows, cols = M_sym.shape
for i in range(rows):
for j in range(cols):
# 关键逻辑:判断元素是否在带宽范围外且非零
if (i - j > lower) or (j - i > upper):
if M_sym[i, j] != 0:
return 0
return 1
except Exception as e:
return f"错误:{str(e)}"
input_str = "[[2,1,0], [3,2,1], [0,4,3]], 1, 1"
print(is_within_banded(input_str))
# 1
input_str = "[[1,0,5], [2,3,0], [0,4,6]], 1, 0"
print(is_within_banded(input_str))
# 0
确定哪些元素在指定范围内
TF=isbetween(A,lower,upper)确定输入数据中的哪些元素在由下限和上限定义的区间内,并返回与输入数据大小相同的逻辑数组. 默认情况下, 该间隔为封闭间隔. 当对应元素在指定范围内时,TF包含1(true),否则包含0(false).
A — 输入向量或矩阵
lower — 下限,标量或向量
upper — 上限,标量或向量
示例 1: 学生成绩评定
判断学生成绩是否在及格范围内 [60, 100]
grades = [[55, 78, 92], [61, 59, 85], [88, 72, 65]], 60, 100
print("成绩矩阵:", grades)
print("及格情况:", isbetween(grades))
#成绩矩阵: ([[55, 78, 92], [61, 59, 85], [88, 72, 65]], 60, 100)
#及格情况: [[0, 1, 1], [1, 0, 1], [1, 1, 1]]
示例 2: 温度监控系统
不同房间有不同的温度要求范围
temperatures = [[25, 22, 18], [30, 15, 20], [28, 19, 23]], [20,18,16], [26,22,25]
print("温度矩阵:", temperatures)
print("温度正常:", isbetween(temperatures))
#温度矩阵: ([[25, 22, 18], [30, 15, 20], [28, 19, 23]], [20,18,16], [26,22,25])
#温度正常: [[1, 1, 0], [0, 0, 1], [0, 1, 1]
示例 3: 财务预算控制
各部门支出是否在预算范围内
expenses = [[12000, 8500], [9500, 11000], [7800, 9200]], [8000,9000], [10000,10000]
print("支出矩阵:", expenses)
print("预算内:", isbetween(expenses))
# 支出矩阵: ([[12000, 8500], [9500, 11000], [7800, 9200]], [8000,9000], [10000,10000])
#预算内: lower
示例 4: 产品质量检测
产品各项指标是否在合格范围内
quality_metrics = [8.5, 7.2, 9.1, 6.8], 7.0, 9.0
print("质量指标:", quality_metrics)
print("合格产品:", isbetween(quality_metrics))
#质量指标: ([8.5, 7.2, 9.1, 6.8], 7.0, 9.0)
#合格产品: [1, 1, 0, 0]
示例 5: 库存管理
检查库存是否在安全库存和最大库存之间
inventory = [[150, 200], [80, 350], [120, 180]], [100,150], [300,250]
print("库存水平:", inventory)
print("库存合理:", isbetween(inventory))
#库存水平: ([[150, 200], [80, 350], [120, 180]], [100,150], [300,250])
#库存合理: lower
示例 6: 血压监测
收缩压和舒张压是否在正常范围内
blood_pressure = [[120, 80], [140, 90], [110, 70]], [90,60], [140,90]
print("血压数据:", blood_pressure)
print("血压正常:", isbetween(blood_pressure))
#血压数据: ([[120, 80], [140, 90], [110, 70]], [90,60], [140,90])
#血压正常: lower
示例 7: 传感器数据验证
验证传感器读数是否在有效范围内
sensor_data = [2.3, 5.1, 3.8, 6.2, 1.9], 2.0, 5.0
print("传感器读数:", sensor_data)
print("有效数据:", isbetween(sensor_data))
#传感器读数: ([2.3, 5.1, 3.8, 6.2, 1.9], 2.0, 5.0)
#有效数据: [1, 0, 1, 0, 0]
示例 8: 考试成绩等级划分
判断成绩是否在A等级范围内 [90, 100]
exam_scores = [[85, 92, 78], [95, 88, 91], [89, 93, 87]], 90, 100
print("考试成绩:", exam_scores)
print("A等级:", isbetween(exam_scores))
#考试成绩: ([[85, 92, 78], [95, 88, 91], [89, 93, 87]], 90, 100)
#A等级: [[0, 1, 0], [1, 0, 1], [0, 1, 0]]
示例 9: 工程参数合规检查
检查工程参数是否在设计规范内
engineering_params = [[10.2, 8.7], [9.8, 11.1], [10.5, 9.2]], [9.5,8.0], [10.5,9.5]
print("工程参数:", engineering_params)
print("参数合规:", isbetween(engineering_params))
#工程参数: ([[10.2, 8.7], [9.8, 11.1], [10.5, 9.2]], [9.5,8.0], [10.5,9.5])
#参数合规: lower
示例 10: 心率监测
运动员心率是否在目标训练区间
heart_rates = [65, 142, 128, 155, 118], 120, 150
print("心率数据:", heart_rates)
print("目标区间:", isbetween(heart_rates))
#心率数据: ([65, 142, 128, 155, 118], 120, 150)
#目标区间: [0, 1, 1, 0, 0]
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def is_between_range(input_str):
"""
判断矩阵元素是否在指定区间内 [lower, upper]。
返回 SymPy 矩阵,1 表示在区间内,0 表示不在。
参数格式示例:
"( [[1,2],[3,4]], [0,2], 5 )" 表示矩阵、下限向量、上限标量
"""
try:
expr = sp.sympify(input_str)
if not (isinstance(expr, tuple)) and len(expr) == 3:
return f"输入必须为三元组 (矩阵, lower, upper),当前长度 {len(expr)}"
matrix = sp.Matrix(expr[0]) if isinstance(expr[0], list) else None
if matrix is None:
return "第一个元素必须为矩阵或可转换列表"
# 转换矩阵为 numpy 数组
if matrix.shape[1] == 1: # 列向量转一维
A = np.array(matrix).ravel().astype(float)
else:
A = np.array(matrix, dtype=float)
# 处理 lower
lower = expr[1]
if isinstance(lower, (list, sp.Matrix)):
lower = np.array(lower, dtype=float).ravel()
elif lower.is_number:
lower = float(lower)
else:
return f"lower 参数类型错误: {type(lower)}"
# 处理 upper
upper = expr[2]
if isinstance(upper, (list, sp.Matrix)):
upper = np.array(upper, dtype=float).ravel()
elif upper.is_number:
upper = float(upper)
else:
return f"upper 参数类型错误: {type(upper)}"
# 维度验证
if A.ndim == 2:
rows = A.shape[0]
if isinstance(lower, np.ndarray) and len(lower) != rows:
return f"lower 向量长度 {len(lower)} 与矩阵行数 {rows} 不匹配"
if isinstance(upper, np.ndarray) and len(upper) != rows:
return f"upper 向量长度 {len(upper)} 与矩阵行数 {rows} 不匹配"
# 核心判断逻辑
result = []
if A.ndim == 1: # 向量处理
l = lower if np.isscalar(lower) else lower[0]
u = upper if np.isscalar(upper) else upper[0]
bool_arr = np.logical_and(A >= l, A <= u)
result = sp.Matrix([int(x) for x in bool_arr])
else: # 矩阵处理
for i in range(A.shape[0]):
row = A[i]
l = lower[i] if isinstance(lower, np.ndarray) else lower
u = upper[i] if isinstance(upper, np.ndarray) else upper
bool_arr = np.logical_and(row >= l, row <= u)
result.append([int(x) for x in bool_arr])
result = sp.Matrix(result)
return result
except Exception as e:
return f"错误: {str(e)}"
# 示例用法
if __name__ == "__main__":
# 示例 1: 向量 + 标量上下限
print(is_between_range("([1, 2, 3], 2, 4)"))
# Matrix([[0],
# [1],
# [1]])
# 示例 2: 矩阵 + 向量上下限
print(is_between_range("([[1,2], [3,4]], [0,3], [3,3])"))
# Matrix([[1, 1],
# [1, 0]])
确定矩阵是否为对角矩阵
如果A是在指定的下带宽和上带宽范围内的矩阵,则tf = isbanded(A,lower,upper) 返回逻辑值 1 (true).否则,将返回逻辑值 0 (false).
A — 输入数组,数组
lower — 下带宽,非负整数标量
upper — 上带宽,非负整数标量
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def is_diagonal_matrix(input_str):
"""
判断输入矩阵是否为对角矩阵 (对标 MATLAB 的 isdiag 函数)
参数:
input_str: 矩阵的字符串表示,支持以下格式:
"[[1, 0], [0, 2]]" - 二维列表格式
"[1, 0, 0]" - 一维向量格式
返回:
int: 1 表示是对角矩阵,0 表示不是
str: 错误信息字符串(输入无效时)
示例:
>>> is_diagonal_matrix("[[1, 0], [0, 2]]")
1
>>> is_diagonal_matrix("[[1, 2], [3, 4]]")
0
>>> is_diagonal_matrix("[[1, 0, 0], [0, 2, 0]]") # 非方阵
1
>>> is_diagonal_matrix("[[0, 0], [0, 0]]") # 零矩阵
1
>>> is_diagonal_matrix("invalid_matrix")
'Error: 语法错误'
"""
try:
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
# 检查输入是否为元组(无效类型)
if isinstance(expr, tuple):
return f"输入错误: 不支持元组类型 {input_str}"
# 转换为 SymPy 矩阵
M = sp.Matrix(expr) if isinstance(expr, list) else None
if M is None:
return f"输入错误: 无法转换为矩阵 {input_str}"
# 核心判断逻辑
return 1 if M.is_diagonal() else 0
except Exception as e:
return f"Error: {str(e)}"
# 测试用例
if __name__ == "__main__":
# 标准对角矩阵(方阵)
print(is_diagonal_matrix("[[1, 0], [0, 2]]"))
# 输出 1
# 非对角矩阵
print(is_diagonal_matrix("[[1, 2], [3, 4]]"))
# 输出 0
# 非方阵对角矩阵
print(is_diagonal_matrix("[[1, 0, 0], [0, 2, 0]]"))
# 输出 1
# 零矩阵
print(is_diagonal_matrix("[[0, 0], [0, 0]]"))
# 输出 1
# 列向量(非对角)
print(is_diagonal_matrix("[[1], [2], [3]]"))
# 输出 0
确定矩阵是埃尔米特矩阵还是斜埃尔米特矩阵
如果A是埃尔米特矩阵,则tf = ishermitian(A) 返回逻辑值1(true).否则,将返回逻辑值0(false).
tf = ishermitian(A,skewOption) 指定测试的类型.将skewOption指定为 "skew" 以确定A是否为斜埃尔米特矩阵.
A — 输入数组,数组
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def is_hermitian_matrix(input_str):
"""
判断输入的矩阵是否为埃尔米特矩阵或斜埃尔米特矩阵。
参数:
input_str: 输入的字符串,表示矩阵或矩阵与选项的组合。例如:
- "Matrix([[1, I], [-I, 3]])" 检查埃尔米特矩阵。
- "(Matrix([[0, -1], [1, 0]]), skew)" 检查斜埃尔米特矩阵。
返回:
1 表示是,0 表示否,错误信息字符串表示输入有误。
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
if isinstance(expr, tuple):
# 检查是否为 (矩阵, skew) 的形式
if len(expr) != 2:
error = True
else:
matrix_part, option_part = expr
M = sp.Matrix(matrix_part) if isinstance(matrix_part, list) else None
# 提取选项并去除可能的引号
option = str(option_part).strip("'\"")
if M is not None and option == "skew":
# 斜埃尔米特矩阵检查: M == -M.H
is_skew = M == -M.H
result = 1 if is_skew else 0
else:
error = True
else:
# 普通埃尔米特矩阵检查
M = sp.Matrix(expr) if isinstance(expr, list) else None
if M is not None:
is_herm = M.is_hermitian
result = 1 if is_herm else 0
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# 示例1: 埃尔米特矩阵
print(is_hermitian_matrix("[[1, 2 + 3*I], [2 - 3*I, 4]]"))
# 输出: 1
# 示例2: 非埃尔米特矩阵
print(is_hermitian_matrix("[[1, 2], [3, 4]]"))
# 输出: 0
# 示例3: 斜埃尔米特矩阵
print(is_hermitian_matrix("[[0, -1], [1, 0]], skew"))
# 输出: 1
# 示例4: 非斜埃尔米特矩阵
print(is_hermitian_matrix("[[0, 2], [-2, 0]], skew"))
# 输出: 1
查找缺失值
TF = ismissing(A) 返回一个逻辑数组,该数组指示输入数据的哪些元素包含缺失值。TF 的大小与 A 的大小相同
A — 向量,矩阵
示例 1: 数据清洗 - 处理调查问卷缺失值
假设 1-5 分制,nan 表示未回答
survey_data = [[5, 3, nan, 4], [nan, 2, 5, nan], [1, nan, nan, 3]]
print("调查问卷数据:", survey_data)
print("缺失值位置:", ismissing(survey_data))
#调查问卷数据: [[5, 3, nan, 4],
[nan, 2, 5, nan],
[1, nan, nan, 3]]
#缺失值位置: [[0, 0, 1, 0],
[1, 0, 0, 1],
[0, 1, 1, 0]]
示例 2: 传感器数据质量检测
传感器故障时产生 NaN 值
sensor_readings = [[23.5, 24.1, nan, 25.8], [22.9, nan, nan, 24.3], [nan, 23.7, 24.5, 25.1]]
print("传感器读数:", sensor_readings)
print("故障传感器:", ismissing(sensor_readings))
#传感器读数: [[23.5, 24.1, nan, 25.8],
[22.9, nan, nan, 24.3],
[nan, 23.7, 24.5, 25.1]]
#故障传感器: [[0, 0, 1, 0],
[0, 1, 1, 0],
[1, 0, 0, 0]]
示例 3: 金融时间序列数据
某些日期可能没有交易数据
stock_prices = [120.5, 122.3, nan, 118.7, 119.8, nan, 121.2]
print("股价序列:", stock_prices)
print("缺失交易日:", ismissing(stock_prices))
#股价序列: [120.5, 122.3, nan, 118.7, 119.8, nan, 121.2]
#缺失交易日: [[0],
[0],
[1],
[0],
[0],
[1],
[0]]
示例 4: 医疗记录完整性检查
某些检查项目可能未完成
patient_records = [[98.6, 120, 80, nan], [nan, 118, 78, 36.5], [97.9, nan, 82, 37.1]]
print("医疗记录:", patient_records)
print("缺失检查项:", ismissing(patient_records))
#医疗记录: [[98.6, 120, 80, nan],
[nan, 118, 78, 36.5],
[97.9, nan, 82, 37.1]]
#缺失检查项: [[0, 0, 0, 1],
[1, 0, 0, 0],
[0, 1, 0, 0]]
示例 5: 实验数据质量控制
实验测量失败时记录为 NaN
experiment_data = [[1.23, nan, 1.34], [1.19, 1.28, nan], [nan, 1.25, 1.31]]
print("实验数据:", experiment_data)
print("无效测量:", is_nan_missing(experiment_data))
#实验数据: [[1.23, nan, 1.34],
[1.19, 1.28, nan],
[nan, 1.25, 1.31]]
#无效测量: [[0, 1, 0],
[0, 0, 1],
[1, 0, 0]]
示例 6: 学生成绩记录
缺考或未评分记录为 NaN
grades = [[85, 92, nan, 78], [90, nan, 88, 85], [nan, 95, 87, 91]]
print("成绩记录:", grades)
print("缺考记录:", ismissing(grades))
#成绩记录: [[85, 92, nan, 78],
[90, nan, 88, 85],
[nan, 95, 87, 91]]
#缺考记录: [[0, 0, 1, 0],
[0, 1, 0, 0],
[1, 0, 0, 0]]
示例 7: 库存管理系统
未盘点或未知库存量
inventory = [[150, nan, 200], [180, 190, nan], [nan, 210, 195]]
print("库存数据:", inventory)
print("未盘点项:", ismissing(inventory))
#库存数据: [[150, nan, 200],
[180, 190, nan],
[nan, 210, 195]]
#未盘点项: [[0, 1, 0],
[0, 0, 1],
[1, 0, 0]]
示例 8: 气象数据质量评估
传感器故障或数据传输中断
weather_data = [[25.3, 65, 1013.2, nan], [24.8, nan, 1012.8, 2.1], [nan, 70, nan, 1.8]]
print("气象数据:", weather_data)
print("数据缺失:", ismissing(weather_data))
#气象数据: [[25.3, 65, 1013.2, nan],
[24.8, nan, 1012.8, 2.1],
[nan, 70, nan, 1.8]]
#数据缺失: [[0, 0, 0, 1],
[0, 1, 0, 0],
[1, 0, 1, 0]]
示例 9: 电商用户行为数据
用户未进行某些操作
user_behavior = [[5, 3, nan, 2], [nan, 4, 1, nan], [2, nan, 3, 4]]
print("用户行为:", user_behavior)
print("缺失行为:", ismissing(user_behavior))
#用户行为: [[5, 3, nan, 2],
[nan, 4, 1, nan],
[2, nan, 3, 4]]
#缺失行为: [[0, 0, 1, 0],
[1, 0, 0, 1],
[0, 1, 0, 0]]
示例 10: 生产质量检测数据
某些检测项未执行
quality_checks = [[8.5, nan, 9.1, 7.8], [7.9, 8.2, nan, 8.7], [nan, 8.9, 8.4, 8.6]]
print("质量数据:", quality_checks)
print("未检测项:", ismissing(quality_checks))
#质量数据: [[8.5, nan, 9.1, 7.8],
[7.9, 8.2, nan, 8.7],
[nan, 8.9, 8.4, 8.6]]
#未检测项: [[0, 1, 0, 0],
[0, 0, 1, 0],
[1, 0, 0, 0]]
示例 11: 边缘情况测试
print("全正常数据:", ismissing("[[1,2,3],[4,5,6]]"))
print("全缺失数据:", ismissing("[[nan,nan],[nan,nan]]"))
print("混合数据:", ismissing("[1, nan, 3, nan, 5]"))
#全正常数据: [[0, 0, 0],
[0, 0, 0]]
#全缺失数据: [[1, 1],
[1, 1]]
#混合数据: [[0],
[1],
[0],
[1],
[0]]
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def is_nan_missing(input_str):
"""
对标 MATLAB 的 ismissing 函数,查找输入矩阵中的缺失值(NaN)。
参数:
input_str: 字符串形式的矩阵输入,例如 "[[1, nan], [3, 4]]"
返回:
如果输入合法,返回对应的 0-1 矩阵(1 表示 NaN);
否则返回错误信息字符串。
"""
try:
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
error = False
result = None
def check_nan(x):
"""检查元素是否为 NaN,返回 1(是)或 0(否)"""
return 1 if x is sp.nan else 0
# 检查表达式类型
if isinstance(expr, tuple):
# 元组类型无法处理,标记错误
error = True
else:
# 尝试转换为矩阵
A = sp.Matrix(expr) if isinstance(expr, list) else None
if A is not None:
# 对每个元素应用 check_nan 函数
result = A.applyfunc(check_nan)
else:
# 无法转换为矩阵,标记错误
error = True
# 返回结果或错误信息
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
### 示例代码
if __name__ == "__main__":
# 示例 1: 输入列向量
input_str1 = "[nan, 2, 3]"
print(f"\n输入: {input_str1}")
print("输出:", is_nan_missing(input_str1))
# Matrix([[1],
# [0],
# [0]])
分离方程中的变量或表达式
isolate(eqn,expr)重新排列方程式eqn, 使表达式expr出现在左侧. 结果类似于求解eqn中的expr. 如果isolate无法isolate expr, 它会将所有包含expr的项移到左侧. 隔离的输出允许您使用subs从eqn中消除expr.
eqn — 输入方程,符号方程
expr — 要隔离的变量或表达式,符号变量,符号表达式
示例 1: 物理运动学 - 位移公式
print("输出:", isolate(s - u*t - 0.5*a*t**2, t))
#输出: Eq(t, (-u - 1.4142135623731*sqrt(a*s + 0.5*u**2))/a)
示例 2: 金融计算 - 复利公式
print("输出:", isolate(A - P*(1 + r)**n, r))
#输出: Eq(r, (A/P)**(1/n) - 1)
示例 3: 几何学 - 圆面积公式
print("输出:", isolate(A - pi*r**2, r))
#输出: Eq(r, -sqrt(A)/sqrt(pi))
示例 4: 热力学 - 理想气体定律
print("输出:", isolate(P*V - n*R*T, T))
#输出: Eq(T, P*V/(R*n))
示例 5: 工程学 - 梁的弯曲公式
print("输出:", isolate(M - E*I/R, R))
#输出: Eq(R, E*I/M)
示例 6: 统计学 - 正态分布
print("输出:", isolate(z - (x - mu)/sigma, x))
#输出: Eq(x, mu + sigma*z)
示例 7: 化学 - 浓度计算
print("输出:", isolate(C - n/V, V))
#输出: Eq(V, n/C)
示例 8: 相对论 - 时间膨胀
print("输出:", isolate(t - t0/sqrt(1 - v**2/c**2), v))
#输出: Eq(v, -c*sqrt(1 - t0**2/t**2))
示例 9: 流体力学 - 伯努利方程
print("输出:", isolate(P1 + 0.5*rho*v1**2 + rho*g*h1 - P2 - 0.5*rho*v2**2 - rho*g*h2, v2))
#输出: Eq(v2, -1.4142135623731*sqrt(P1/rho - P2/rho + g*h1 - g*h2 + 0.5*v1**2))
示例 10: 光学 - 透镜公式
print("输出:", isolate(1/f - 1/u - 1/v, v))
#输出: Eq(v, f*u/(-f + u))
示例 11: 声学 - 多普勒效应
print("输出:", isolate(f_observed - f_source*(v_sound + v_observer)/(v_sound + v_source), v_source))
#输出: Eq(v_source, (-f_observed*v_sound + f_source*v_observer + f_source*v_sound)/f_observed)
示例 12: 材料科学 - 胡克定律
print("输出:", isolate(F - k*x, k))
#输出: Eq(k, F/x)
示例 13: 使用显式等式格式
print("输出:", isolate(Eq(energy, mass*c**2), mass))
#输出: Eq(mass, energy/c**2)
示例 14: 复杂表达式 - 二次方程求根
print("输出:", isolate(a*x**2 + b*x + c, x))
#输出: Eq(x, (-b - sqrt(-4*a*c + b**2))/(2*a))
示例 15: 三角函数方程
print("输出:", isolate(sin(theta) - opposite/hypotenuse, theta))
#输出: Eq(theta, pi - asin(opposite/hypotenuse))
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def isolate_expr_eqn(input_str):
"""
对标MATLAB的isolate函数,将方程中的指定变量分离到等式一侧。
参数:
input_str: 字符串形式的输入,格式为"(方程, 变量)"。
方程可以是等式(如Eq(a*x + b, 0))或表达式(自动设为等于0)。
例如: "(a*x**2 + b*x + c, x)" 或 "(Eq(y, m*x + b), x)"
返回:
分离后的等式(如Eq(x, ...)),若失败返回错误信息字符串。
"""
try:
# 将输入字符串解析为SymPy表达式
expr = sp.sympify(input_str, evaluate=False)
# 验证是否为包含方程和变量的元组
if not isinstance(expr, tuple) or len(expr) != 2:
return f"输入格式错误: 需要形如'(方程, 变量)'的元组,实际输入: {input_str}"
eqn, var = expr[0], expr[1]
# 验证变量是否为符号
if not var.free_symbols:
return f"第二个元素必须是符号,实际类型: {type(var).__name__}"
# 将表达式自动转换为等式(如果不是等式)
if not isinstance(eqn, sp.Equality):
eqn = sp.Eq(eqn, 0) # 假设表达式等于0
# 求解方程并提取第一个解
solutions = sp.solve(eqn, var, dict=True)
if not solutions:
return f"无法分离变量{var}:方程无显式解"
# 构建等式结果
return sp.Eq(var, solutions[0][var])
except Exception as e:
return f"解析错误: {str(e)}"
### 示例代码 ###
if __name__ == "__main__":
# 示例1: 线性方程
input_str1 = "(a*y(t)**2+b*c==0,y(t))"
print(f"输入: {input_str1}")
print("输出:", isolate_expr_eqn(input_str1))
# Eq(y(t), -sqrt(-b*c/a))
# 示例2: 二次方程(自动返回第一个解)
input_str2 = "(a*x**2 + b*x + c, x)"
print(f"\n输入: {input_str2}")
print("输出:", isolate_expr_eqn(input_str2))
# Eq(x, (-b - sqrt(-4*a*c + b**2))/(2*a))
# 示例3: 显式等式输入
input_str3 = "(Eq(y, m*x + b), x)"
print(f"\n输入: {input_str3}")
print("输出:", isolate_expr_eqn(input_str3))
# Eq(x, (-b + y)/m)
查找数据中的离群值
TF = isoutlier(A,method) 返回一个逻辑数组,当在A的元素中检测到离群值时,该数组中与之对应的元素为true.
如果 A 是矩阵,则 isoutlier 分别对 A 的每列进行运算。
median — 离群值定义为与中位数相差超过三倍换算 MAD 的元素。换算 MAD 定义为 c*median(abs(A-median(A))),其中 c=-1/(sqrt(2)*erfcinv(3/2))。
mean — 离群值定义为与均值相差超过三倍标准差的元素。此方法比 "median" 快,但没有它可靠。
quartiles — 离群值定义为比上四分位数 (75%) 大 1.5 个四分位差以上或比下四分位数 (25%) 小 1.5 个四分位差以上的元素。当 A 中的数据不是正态分布时,此方法很有用。
gesd — 使用广义极端 Student 化偏差检验检测离群值。此迭代方法与 "grubbs" 类似,但当有多个离群值互相遮盖时,此方法的执行效果更好。
A — 数值向量,矩阵
示例 1: 医疗健康 - 异常生理指标检测
检测血压、心率等生理指标的异常值
print("输出:", isoutlier("[120, 125, 118, 130, 200, 122, 119], quartiles"))
#输出: [[0],
[0],
[0],
[0],
[1],
[0],
[0]]
示例 2: 金融风控 - 异常交易检测
检测信用卡交易的异常金额
print("输出:", isoutlier("[[100, 150, 120], [80, 95, 110], [1000, 130, 140], [115, 125, 135]], mean"))
#输出:
#[[0,0,0],
[0,0,0],
[0,0,0],
[0,0,0]]
示例 3: 工业制造 - 产品质量异常检测
检测产品尺寸的异常测量值
print("输出:", isoutlier("[10.1, 10.2, 10.15, 9.8, 10.18, 11.5, 10.12, 10.16], median"))
#输出:
#[[0],
[0],
[0],
[1],
[0],
[1],
[0],
[0]]
示例 4: 环境监测 - 空气质量异常值
检测PM2.5浓度的异常峰值
print("输出:", isoutlier("[35, 42, 38, 28, 45, 150, 40, 33, 39, 180], grubbs"))
#输出:
#[[0],
[0],
[0],
[0],
[0],
[0],
[0],
[0],
[0],
[0]]
示例 5: 网络延迟 - 异常延迟检测
检测网络延迟的异常峰值
print("输出:", isoutlier("[50, 55, 48, 52, 200, 49, 53, 300, 51, 54], grubbs"))
#输出:
#[[0],
[0],
[0],
[0],
[0],
[0],
[0],
[1],
[0],
[0]]
示例 6: 生产能耗 - 异常能耗检测
检测工厂能耗的异常值
print("输出:", isoutlier("[[1000, 1050, 980], [1020, 995, 1015], [500, 1030, 1005], [1010, 2000, 990]], mean"))
#输出:
#[[0,0,0],
[0,0,0],
[0,0,0],
[0,0,0]]
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.stats import iqr, scoreatpercentile, t
def is_outlier_data(input_str):
"""
对标 MATLAB 的 isoutlier 函数,检测数据中的离群值。
参数:
input_str: 字符串形式的输入,可以是以下两种格式之一:
1. 直接输入矩阵,如 "[1, 2, 3]"
2. 元组格式 (矩阵, 方法),如 "(Matrix([[1,2],[3,4]]), 'quartiles')"
支持的方法: "median", "mean", "quartiles", "grubbs", "gesd"
返回:
与输入矩阵形状相同的 0-1 矩阵,1 表示离群值;
若输入错误则返回错误信息字符串。
"""
try:
# 解析输入字符串为 SymPy 表达式
expr = sp.sympify(input_str, evaluate=False)
method = "median" # 默认方法
A = None
# 处理元组输入 (矩阵, 方法)
if isinstance(expr, tuple) and len(expr) == 2:
matrix_part = sp.Matrix(expr[0]) if isinstance(expr[0], list) else None
method_part = expr[1]
if matrix_part is None or not method_part.free_symbols:
return f"输入格式错误: {input_str}"
A = np.array(matrix_part.tolist(), dtype=float)
method = str(method_part)
# 处理单一矩阵输入
else:
matrix_part = sp.Matrix(expr) if isinstance(expr, list) else None
if matrix_part is None:
return f"无法解析矩阵: {input_str}"
A = np.array(matrix_part.tolist(), dtype=float)
# 验证方法有效性
valid_methods = ["median", "mean", "quartiles", "grubbs", "gesd"]
if method.lower() not in valid_methods:
return f"未知方法: {method},支持的方法: {valid_methods}"
def detect_outliers(data_col, method_name):
"""对单列数据执行离群值检测"""
n = len(data_col)
outliers = np.zeros(n, dtype=int)
# Median Absolute Deviation (MAD)
if method_name == "median":
median = np.median(data_col)
mad = np.median(np.abs(data_col - median))
if mad == 0:
mad = 1e-6 # 避免除以零
threshold = 3 * 1.4826 * mad # 常数缩放因子
outliers = (np.abs(data_col - median) > threshold).astype(int)
# Mean and Standard Deviation
elif method_name == "mean":
mean = np.mean(data_col)
std = np.std(data_col)
if std == 0:
std = 1e-6
threshold = 3 * std
outliers = (np.abs(data_col - mean) > threshold).astype(int)
# Interquartile Range (IQR)
elif method_name == "quartiles":
q1 = scoreatpercentile(data_col, 25)
q3 = scoreatpercentile(data_col, 75)
iqr_val = iqr(data_col)
lower = q1 - 1.5 * iqr_val
upper = q3 + 1.5 * iqr_val
outliers = ((data_col < lower) | (data_col > upper)).astype(int)
# Grubbs' Test (单离群值)
elif method_name == "grubbs":
if n < 3:
return outliers # 样本过少不检测
mean = np.mean(data_col)
std = np.std(data_col)
if std == 0:
return outliers
# 找到最大偏差点
max_idx = np.argmax(np.abs(data_col - mean))
G = np.abs(data_col[max_idx] - mean) / std
# 计算临界值
t_crit = t.ppf(1 - 0.05 / (2 * n), n - 2)
threshold = (n - 1) / np.sqrt(n) * np.sqrt(t_crit ** 2 / (n - 2 + t_crit ** 2))
if G > threshold:
outliers[max_idx] = 1
# Generalized ESD Test (多离群值)
elif method_name == "gesd":
alpha = 0.05
max_outliers = min(n // 2, 10) # 最多检测10个离群值
R = np.zeros(max_outliers)
lambdas = np.zeros(max_outliers)
for i in range(max_outliers):
mu = np.mean(data_col)
sigma = np.std(data_col)
if sigma == 0:
break
R[i] = np.max(np.abs(data_col - mu))
idx = np.argmax(np.abs(data_col - mu))
# 计算临界值
p = 1 - alpha / (2 * (n - i))
t_val = t.ppf(p, n - i - 2)
lambdas[i] = (n - i - 1) * t_val / np.sqrt((n - i - 2 + t_val ** 2) * (n - i))
if R[i] > lambdas[i] * sigma:
outliers[idx] = 1
data_col = np.delete(data_col, idx)
else:
break
return outliers
# 处理矩阵数据
if A.ndim == 1:
A = A.reshape(-1, 1)
n_rows, n_cols = A.shape
result = np.zeros((n_rows, n_cols), dtype=int)
# 逐列检测离群值
for col in range(n_cols):
result[:, col] = detect_outliers(A[:, col], method.lower())
# 转换为 SymPy 矩阵并保持原始形状
result_matrix = sp.Matrix(result.tolist())
if result_matrix.shape[1] == 1:
result_matrix = result_matrix.T
return result_matrix
except Exception as e:
return f"错误: {str(e)}"
### 示例代码 ###
if __name__ == "__main__":
# 示例1: 默认方法 (median)
input_str1 = "[1, 2, 3, 100]"
print(f"输入: {input_str1}")
print("输出:", is_outlier_data(input_str1))
# Matrix([[0, 0, 0, 1]])
# 示例2: 使用quartiles方法
input_str2 = "[[1, 2], [3, 4], [100, 200]], quartiles"
print(f"\n输入: {input_str2}")
print("输出:", is_outlier_data(input_str2))
# Matrix([[0, 0],
# [0, 0],
# [0, 0]])
# 示例3: Grubbs检验
input_str3 = "[1, 2, 3, 4, 100], grubbs"
print(f"\n输入: {input_str3}")
print("输出:", is_outlier_data(input_str3))
# Matrix([[0, 0, 0, 0, 1]])
等值面是三维数据分布中具有相等值的各点的三维曲面表示.
isosurface 函数通过连接空间的一个三维体内的常量值点来计算和绘制曲面.
[faces,verts] = isosurface(V,isovalue,points,X,Y,Z) 在单独的数组中返回面和顶点。
V — 三维体表达式,符号表达式
isovalue — 指定等值面值,标量
points — 采样点数
X — x 轴坐标, 向量 | 三维数组
Y — y 轴坐标数据, 向量 | 三维数组
Z — z 轴坐标数据, 向量 | 三维数组
faces — 面数据, 数组
verts — 顶点数据,数组
示例 1: 球面 - 基础几何形状
result = isosurface(x**2 + y**2 + z**2, 1.0, 40, x=[-1.5,1.5], y=[-1.5,1.5], z=[-1.5,1.5])
faces, vertices = result
print(f"球面 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#球面 - 顶点数: 3240, 面片数: 6476
示例 2: 椭球面 - 变形几何
result = isosurface((x/2)**2 + (y/1.5)**2 + (z/1)**2, 1.0, 40)
faces, vertices = result
print(f"椭球面 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#椭球面 - 顶点数: 3872, 面片数: 7740
示例 3: 环面 (甜甜圈形状) - 拓扑学
result = isosurface((sqrt(x**2 + y**2) - 3)**2 + z**2 - 1, 0, 50, x=[-5,5], y=[-5,5], z=[-2,2])
faces, vertices = result
print(f"环面 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#环面 - 顶点数: 7464, 面片数: 14928
示例 4: 正弦曲面 - 波动现象
result = isosurface(sin(x) + cos(y) + sin(z), 0, 50, x=[-2*pi,2*pi], y=[-2*pi,2*pi], z=[-2*pi,2*pi])
faces, vertices = result
print(f"正弦曲面 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#正弦曲面 - 顶点数: 5678, 面片数: 10926
示例 5: 分子轨道 - 量子化学
result = isosurface(
exp(-sqrt(x**2+y**2+z**2))*(1 - sqrt(x**2+y**2+z**2)), 0.1, 40, x=[-5,5], y=[-5,5], z=[-5,5])
faces, vertices = result
print(f"分子轨道 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#分子轨道 - 顶点数: 192, 面片数: 380
示例 6: 心脏曲面 - 数学艺术
result = isosurface(
(2*x**2 + y**2 + z**2 - 1)**3 - (0.1*x**2 + y**2)*z**3, 0, 60, x=[-1.5,1.5], y=[-1.5,1.5], z=[-1.5,1.5])
faces, vertices = result
print(f"心脏曲面 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#心脏曲面 - 顶点数: 6800, 面片数: 13596
示例 7: 超二次曲面 - 计算机图形学
result = isosurface((abs(x)**2.5 + abs(y)**2.5)**(1/2.5) + abs(z)**2.5 - 1, 0, 40)
faces, vertices = result
print(f"超二次曲面 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#超二次曲面 - 顶点数: 1720, 面片数: 3436
示例 8: 隐式曲面 - 代数曲面
result = isosurface(
(x**2 + y**2 + z**2 + 2*y - 1)*((x**2 + y**2 + z**2 - 2*y - 1)**2 - 8*z**2) + 16*x*z*(x**2 + y**2 + z**2 - 2*y - 1), 0, 60, x=[-3,3], y=[-3,3], z=[-2,2])
faces, vertices = result
print(f"克莱因瓶 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#克莱因瓶 - 顶点数: 16614, 面片数: 32928
示例 9: 物理场等值面 - 电势分布
result = isosurface(
1/sqrt((x-1)**2 + y**2 + z**2) + 1/sqrt((x+1)**2 + y**2 + z**2), 0.5, 40, x=[-3,3], y=[-3,3], z=[-3,3])
faces, vertices = result
print(f"电势等值面 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#电势等值面 - 顶点数: 3960, 面片数: 7096
示例 10: 医学成像 - 器官表面重建
result = isosurface(
(x/2)**2 + (y/1.2)**2 + (z/1.8)**2 - 1, 0, 50, x=[-2.5,2.5], y=[-1.5,1.5], z=[-2,2])
faces, vertices = result
print(f"器官模型 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#器官模型 - 顶点数: 7840, 面片数: 15676
示例 11: 地质学 - 地层界面
result = isosurface(0.5*sin(2*x) + 0.3*cos(3*y) - z, 0, 60, x=[-2,2], y=[-2,2], z=[-1,1])
faces, vertices = result
print(f"地层界面 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#地层界面 - 顶点数: 12666, 面片数: 24790
示例 12: 建筑设计 - 自由曲面
result = isosurface(
sin(x)*cos(y) + sin(y)*cos(z) + sin(z)*cos(x), 0, 50, x=[-pi,pi], y=[-pi,pi], z=[-pi,pi])
faces, vertices = result
print(f"自由曲面 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#自由曲面 - 顶点数: 7782, 面片数: 14880
示例 13: 材料科学 - 晶体结构
result = isosurface(cos(2*pi*x) + cos(2*pi*y) + cos(2*pi*z), 0, 40, x=[-2,2], y=[-2,2], z=[-2,2])
faces, vertices = result
print(f"晶体结构 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#晶体结构 - 顶点数: 23646, 面片数: 45884
示例 14: 气象学 - 等压面
result = isosurface(1000 - (x**2 + y**2)/100 - 10*z, 900, 50, x=[-50,50], y=[-50,50], z=[0,20])
faces, vertices = result
print(f"等压面 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#等压面 - 顶点数: 3724, 面片数: 7202
示例 15: 参数化曲面 - 复杂形状
result = isosurface(abs(x)**3 + abs(y)**3 + abs(z)**3 - 1, 0, 40)
faces, vertices = result
print(f"八面体变形 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#八面体变形 - 顶点数: 2064, 面片数: 4124
示例 16: 多等值面 - 分层结构
for level in [0.5, 1.0, 1.5]:
result = isosurface(x**2 + y**2 + z**2, level, 30)
faces, vertices = result
print(f"半径{level}球壳 - 顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
#半径0.5球壳 - 顶点数: 480, 面片数: 956
#半径1.0球壳 - 顶点数: 984, 面片数: 1964
#半径1.5球壳 - 顶点数: 1536, 面片数: 3068
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from skimage import measure
import regex, re
def extract_functions_and_assignments(input_string):
# 正则表达式匹配函数表达式
'''
function_pattern = r'\b\w+\((?:[^()]*|(?R))*\)'
functions = regex.findall(function_pattern, input_string)
# 正则表达式匹配变量赋值
assignment_pattern = r'\b\w+\s*=\s*\[[^]]*\]'
assignments = regex.findall(assignment_pattern, input_string)
'''
# 提取 assignments 列表
assignment_pattern = r'\b\w+\s*=\s*\[[^]]*\]'
assignments = regex.findall(assignment_pattern, input_string)
# 从 input_string 中删除每个 assignment
for assignment in assignments:
input_string = input_string.replace(assignment, '')
# 判断 input_string 是否是一个区间
if '[' in input_string and ']' in input_string:
# 如果是区间,使用 function_pattern 提取函数
function_pattern = r'\b\w+\((?:[^()]*|(?R))*\)'
functions = regex.findall(function_pattern, input_string)
else:
# 如果不是区间,按逗号分割为 functions 列表
functions = input_string.split(',')
# 移除首尾空格
functions = [func.strip() for func in functions]
# 移除空字符串
functions = list(filter(None, functions))
return functions, assignments
def parse_and_generate_all_var_values(input_params):
res_range = []
res_expr = []
for param in input_params:
var_str = param
var_str = var_str.replace(" ", "")
match = re.match(r'(\w+)\s*=\s*\[([^]]+)\]', var_str)
if not match:
return res_range, res_expr
var_name = match.group(1)
var_values_str = match.group(2)
try:
var_values = eval(var_values_str)
var_values = list(var_values) # 如果只有一个元素,转换为列表
var_values = var_values[:2]
var_values.insert(0, var_name)
res_range.append(var_values)
except (ValueError, NameError):
# Plot3D(sin(x^2+3y^2)/(0.1+r^2)+(x^2+5y^2)*exp(1-r^2)/2,r=[sqrt(x^2+y^2)])
# eval(sqrt(x^2+y^2)) raise except
res_expr.append([var_name, var_values_str])
return res_range, res_expr
def isosurface_data_volume(input_str):
"""
对标 MATLAB 的 isosurface 函数,从三维隐式函数生成等值面数据
参数:
input_str: 输入字符串,格式为 "表达式,等值面值"(例如:"x**2 + y**2 + z**2, 1.0")
grid_points: 每个维度的采样点数(默认30)
x_range: x轴采样范围(默认(-2,2))
y_range: y轴采样范围(默认(-2,2))
z_range: z轴采样范围(默认(-2,2))
返回:
若成功则返回 (vertices, faces) 元组,否则返回错误信息字符串
"""
try:
functions, assignments = extract_functions_and_assignments(input_str)
# 解析表达式、等值面值和网格点数
if len(functions) < 1:
return "Error: Missing expression"
expr_str = functions[0]
expr = sp.sympify(expr_str)
isovalue = 1.0 # 默认等值面值
if len(functions) >= 2:
isovalue = float(functions[1])
grid_points = 30 # 默认网格点数
if len(functions) >= 3:
grid_points = int(functions[2])
# 解析变量范围
assignment_range, _ = parse_and_generate_all_var_values(assignments)
# 初始化变量范围
x_range = [-2.0, 2.0]
y_range = [-2.0, 2.0]
z_range = [-2.0, 2.0]
for var_info in assignment_range:
var_name = var_info[0]
if var_name == 'x' and len(var_info) >= 3:
x_range = [var_info[1], var_info[2]]
elif var_name == 'y' and len(var_info) >= 3:
y_range = [var_info[1], var_info[2]]
elif var_name == 'z' and len(var_info) >= 3:
z_range = [var_info[1], var_info[2]]
# 生成坐标数组
x = np.linspace(x_range[0], x_range[1], grid_points)
y = np.linspace(y_range[0], y_range[1], grid_points)
z = np.linspace(z_range[0], z_range[1], grid_points)
# 创建三维网格
X, Y, Z = np.meshgrid(x, y, z, indexing='ij')
# 将SymPy表达式转换为数值计算函数
x_sym, y_sym, z_sym = sp.symbols('x y z')
expr_func = sp.lambdify((x_sym, y_sym, z_sym), expr, 'numpy')
volume = expr_func(X, Y, Z)
# 计算等值面
verts, faces, _, _ = measure.marching_cubes(volume, isovalue)
return faces, verts
except ValueError as ve:
return f"数值错误: {str(ve)}"
except sp.SympifyError:
return "表达式解析失败"
except Exception as e:
return f"未知错误: {str(e)}"
### 示例代码 ###
if __name__ == "__main__":
# 示例1: 球面 (x² + y² + z² = 1)
print("示例1: 单位球面")
result = isosurface_data_volume("x**2+y**2+z**2, 1.0, 30, x=[-1.5, 1.5], y=[-1.5, 1.5], z=[-1.5, 1.5]")
if isinstance(result, tuple):
vertices, faces = result
print(vertices)
# [[ 2 1 0]
# [ 4 3 0]
# [ 4 0 1]
# ...
# [1798 1773 1775]
# [1798 1775 1799]
# [1799 1775 1766]]
print(faces)
# [[ 4.9652777 13. 14. ]
# [ 5. 12.826388 14. ]
# [ 5. 13. 13.652778 ]
# ...
# [24.034721 15. 16. ]
# [24.034721 16. 14. ]
# [24.034721 16. 15. ]]
print(f"顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
# 顶点数: 3596, 面片数: 1800
# 示例2: 圆柱面 (x² + y² = 0.5)
print("\n示例2: 圆柱面")
result = isosurface_data_volume("x**2 + y**2 - 0.5, 0, 50, z=[-3, 3]")
if isinstance(result, tuple):
vertices, faces = result
print(f"顶点数: {vertices.shape[0]}, 面片数: {faces.shape[0]}")
# 顶点数: 7056, 面片数: 3600
确定哪些数组元素为质数
TF = isprime(X) 返回与 X 大小相同的逻辑数组. 如果 X(i) 为质数,则 TF(i) 的值为 true. 否则值为 false.
X — 输入值,标量,向量,实数数组,非负整数值
示例 1: 基础质数判断
print("2 →", isprime(2)) # 最小的质数
print("17 →", isprime(17)) # 质数
print("1 →", isprime(1)) # 不是质数
print("4 →", isprime(4)) # 合数
print("2.0 →", isprime(2.0)) # 浮点数形式的质数
print("4.5 →", isprime(4.5)) # 非整数
#2 → 1
#17 → 1
#1 → 0
#4 → 0
#2.0 → 1
#4.5 → 0
示例 2: 密码学应用 - RSA密钥生成
rsa_candidates = [101, 103, 107, 109, 113, 127, 131, 137, 139, 149]
print(f"RSA候选质数: {rsa_candidates}")
print("质数检测:", isprime(rsa_candidates))
#RSA候选质数: [101, 103, 107, 109, 113, 127, 131, 137, 139, 149]
#质数检测: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
示例 3: 计算机科学 - 哈希表大小选择
hash_sizes = [53, 97, 193, 389, 769, 1543, 3079, 6151]
print(f"哈希表大小候选: {hash_sizes}")
print("质数验证:", isprime(hash_sizes))
#哈希表大小候选: [53, 97, 193, 389, 769, 1543, 3079, 6151]
#质数验证: [1, 1, 1, 1, 1, 1, 1, 1]
示例 4: 数学教育 - 质数矩阵练习
number_matrix = [[2, 4, 6], [3, 9, 11], [15, 17, 19]]
print(f"数字矩阵: {number_matrix}")
print("质数分布:", isprime(number_matrix))
#数字矩阵: [[2, 4, 6], [3, 9, 11], [15, 17, 19]]
#质数分布: [[1, 0, 0], [1, 0, 1], [0, 1, 1]]
示例 5: 数论研究 - 梅森素数检测
mersenne_numbers = [3, 7, 31, 127, 2047]
print(f"梅森数: {mersenne_numbers}")
print("梅森质数:", isprime(mersenne_numbers))
#梅森数: [3, 7, 31, 127, 2047]
#梅森质数: [1, 1, 1, 1, 0]
示例 6: 安全协议 - 质数验证
dh_parameters = [23, 47, 97, 197, 397] # 常用的DH质数参数
print(f"DH参数: {dh_parameters}")
print("质数验证:", isprime(dh_parameters))
#DH参数: [23, 47, 97, 197, 397]
#质数验证: [1, 1, 1, 1, 1]
示例 7: 财务计算 - 质数在算法中的应用
transaction_ids = [1009, 1013, 1019, 1021, 1024, 1031, 1033]
print(f"交易ID: {transaction_ids}")
print("质数ID:", isprime(transaction_ids))
#交易ID: [1009, 1013, 1019, 1021, 1024, 1031, 1033]
#质数ID: [1, 1, 1, 1, 0, 1, 1]
示例 8: 游戏开发 - 质数在随机数生成中的应用
random_seeds = [17, 31, 59, 97, 157, 257, 419]
print(f"随机种子: {random_seeds}")
print("质数种子:", isprime(random_seeds))
#随机种子: [17, 31, 59, 97, 157, 257, 419]
#质数种子: [1, 1, 1, 1, 1, 1, 1]
示例 9: 数据分析 - 质数数据过滤
data_points = [[2, 3, 5], [7, 9, 11], [13, 15, 17], [19, 21, 23]]
print(f"数据点矩阵: {data_points}")
print("质数数据点:", isprime(data_points))
#数据点矩阵: [[2, 3, 5], [7, 9, 11], [13, 15, 17], [19, 21, 23]]
#质数数据点: [[1, 1, 1], [1, 0, 1], [1, 0, 1], [1, 0, 1]]
示例 10: 符号数学测试
symbolic_input = [[2, x], [y, 7]]
print(f"符号表达式: {symbolic_input}")
print("质数检测:", isprime(symbolic_input))
#符号表达式: [[2, x], [y, 7]]
#质数检测: [[1, None], [None, 1]]
示例 11: 大型质数验证
large_primes = [1009, 7919, 104729]
print(f"大型质数: {large_primes}")
print("验证结果:", isprime(large_primes))
#大型质数: [1009, 7919, 104729]
#验证结果: [1, 1, 1]
示例 12: 质数分布模式分析
consecutive_numbers = [90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
print(f"连续数字: {consecutive_numbers}")
print("质数位置:", isprime(consecutive_numbers))
#连续数字: [90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
#质数位置: [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
示例 13: 孪生质数检测
twin_primes = [[3, 5], [5, 7], [11, 13], [17, 19], [29, 31], [41, 43]]
print(f"孪生质数对: {twin_primes}")
print("质数验证:", isprime(twin_primes))
#孪生质数对: [[3, 5], [5, 7], [11, 13], [17, 19], [29, 31], [41, 43]]
#质数验证: [[1, 1], [1, 1], [1, 1], [1, 1], [1, 1], [1, 1]]
示例 14: 质数在编码中的应用
error_detection_codes = [7, 13, 19, 31, 61] # 常用于校验算法的质数
print(f"校验质数: {error_detection_codes}")
print("质数状态:", isprime(error_detection_codes))
#校验质数: [7, 13, 19, 31, 61]
#质数状态: [1, 1, 1, 1, 1]
示例 15: 边界情况测试
print("0 →", isprime(0)) # 不是质数
print("-5 →", isprime(-5)) # 负数不是质数
print("1.0 →", isprime(1.0)) # 浮点数1
print("2+3j →", isprime(2+3@i)) # 复数
print("10000000019 →", isprime("10000000019")) # 大质数
#0 → 0
#-5 → 0
#1.0 → 0
#2+3j → 0
#10000000019 → 1
示例 16: 混合数据类型矩阵
mixed_matrix = [[2, 4.5, 7], [11, 15, 19.0], [23, 25, 29]]
print(f"混合矩阵: {mixed_matrix}")
print("质数检测:", isprime(mixed_matrix))
#混合矩阵: [[2, 4.5, 7], [11, 15, 19.0], [23, 25, 29]]
#质数检测: [[1, 0, 1], [1, 0, 1], [1, 0, 1]]
示例 17: 质数在游戏平衡中的应用
game_parameters = [17, 37, 73, 149, 293] # 常用于游戏机制的质数
print(f"游戏参数: {game_parameters}")
print("质数参数:", isprime(game_parameters))
#游戏参数: [17, 37, 73, 149, 293]
#质数参数: [1, 1, 1, 1, 1]
示例 18: 质数在分布式系统中的应用
node_ids = [101, 103, 107, 109, 113, 127, 131, 137]
print(f"节点ID: {node_ids}")
print("质数ID:", isprime(node_ids))
#节点ID: [101, 103, 107, 109, 113, 127, 131, 137]
#质数ID: [1, 1, 1, 1, 1, 1, 1, 1]
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def is_prime_number(input_str):
"""
对标 MATLAB 的 isprime 函数,判断输入中的元素是否为质数。
支持标量、矩阵和符号表达式。
参数:
input_str (str): 输入的数学表达式字符串,可以是标量、矩阵或符号。
返回:
- 对于数值元素:质数返回 1,非质数返回 0
- 对于符号元素:返回 None
- 错误时返回错误信息字符串
示例:
>>> is_prime_number("5")
1
>>> is_prime_number("[[2, 3], [5, 7]]")
Matrix([[1, 1], [1, 1]])
>>> is_prime_number("[[2, x], [4.5, 6]]")
Matrix([[1, None], [0, 0]])
"""
try:
expr = sp.sympify(input_str)
def evaluate_prime(x):
"""判断单个元素是否为质数"""
# 处理符号表达式
if x.free_symbols:
return None
# 处理非数值类型
if not x.is_number:
return None
try:
# 转换为整数(处理浮点数的整数情况)
num = int(sp.N(x))
if sp.N(x) != num: # 检查是否为非整数(如 4.5)
return 0
# 质数判断(质数定义需大于1)
return 1 if num > 1 and sp.isprime(num) else 0
except:
return 0 # 转换失败的情况(如复数)
# 处理标量输入
return evaluate_prime(expr)
except sp.SympifyError:
return f"表达式解析失败: {input_str}"
except Exception as e:
return f"错误: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 标量测试
print("标量测试:")
print("5 →", is_prime_number("5"))
# 1
print("4 →", is_prime_number("4"))
# 0
print("2.0 →", is_prime_number("2.0"))
# 1
print("x →", is_prime_number("x"))
# None
确定矩阵是对称矩阵还是斜对称矩阵.
如果 A 是对称矩阵,则tf = issymmetric(A) 返回逻辑值 1 (true). 否则,将返回逻辑值 0 (false).
tf = issymmetric(A,skewOption)指定测试的类型. 将skewOption指定为"skew" 可确定A是否为斜对称矩阵
A — 输入数组,数组
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
from sympy import simplify
def is_symmetric_matrix(input_str):
"""
对标MATLAB issymmetric函数,判断矩阵的对称性
参数:
input_str - 矩阵描述字符串,支持两种格式:
1. 纯矩阵:"[[0,1],[1,0]]"
2. 带类型标记:"(Matrix([[0,1],[-1,0]]), 'skew')"
返回:
1 - 满足对称性要求
0 - 不满足对称性要求
错误信息字符串 - 输入不合法时
示例:
>>> is_symmetric_matrix("[[1,2],[2,1]]")
1
>>> is_symmetric_matrix("(Matrix([[0,1],[-1,0]]), 'skew')")
1
>>> is_symmetric_matrix("[[1,2],[3,4]]")
0
"""
try:
expr = sp.sympify(input_str, evaluate=False)
result = None
# 处理带选项的元组输入 (矩阵, 'skew')
if isinstance(expr, tuple) and len(expr) == 2:
M = sp.Matrix(expr[0]) if isinstance(expr[0], list) else None
option = str(expr[1]).lower()
if M is None or option not in ['skew']:
return f"输入错误: {input_str}"
# 斜对称矩阵检查:M^T = -M
# 使用符号化简处理浮点精度问题
is_skew = simplify(M.T + M).is_zero_matrix
result = 1 if is_skew else 0
# 处理普通矩阵输入
else:
M = sp.Matrix(expr) if isinstance(expr, list) else None
if M is None:
return f"输入错误: {input_str}"
# 对称矩阵检查:M^T = M
# 使用内置方法处理符号和数值矩阵
result = 1 if M.is_symmetric() else 0
return result
except sp.SympifyError:
return f"语法错误: 无法解析输入 '{input_str}'"
except Exception as e:
return f"运行时错误: {str(e)}"
# --------------------------
# 测试用例
# --------------------------
if __name__ == "__main__":
# 测试对称矩阵
print("对称矩阵测试:")
print(is_symmetric_matrix("[[1, 2], [2, 1]]"))
# 1
print(is_symmetric_matrix("[[a, b], [b, a]]"))
# 1
# 测试斜对称矩阵
print("\n斜对称矩阵测试:")
print(is_symmetric_matrix("[[0, 2], [-2, 0]], skew"))
# 1
print(is_symmetric_matrix("[[0, 1.0], [-1.0001, 0]], skew"))
# 0
# 测试非对称矩阵
print("\n非对称矩阵测试:")
print(is_symmetric_matrix("[[1, 2], [3, 4]]"))
# 0
确定矩阵是否为下三角矩阵.
如果A是下三角矩阵,则tf = istril(A) 返回逻辑值1 (true). 否则,将返回逻辑值0 (false).
A — 输入数组,数组
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def is_lower_triangular(input_str):
"""
判断输入是否为下三角矩阵(对标MATLAB istril函数)
参数:
input_str: 输入字符串,可以是矩阵、标量或符号表达式
返回:
1: 是下三角矩阵
0: 不是下三角矩阵
str: 错误信息
示例:
>>> is_lower_triangular("[[1,0],[2,3]]")
1
>>> is_lower_triangular("[[1,2],[3,4]]")
0
>>> is_lower_triangular("5")
1
>>> is_lower_triangular("[[1,2],[3,4,5]]")
'输入错误: [[1,2],[3,4,5]]'
"""
try:
expr = sp.sympify(input_str)
# 尝试转换为矩阵
if isinstance(expr, list):
M = sp.Matrix(expr)
# 非方阵直接返回0
if M.is_square and M.is_lower:
return 1
else:
return 0
# 处理标量和符号(视为1x1矩阵)
if isinstance(expr, sp.Basic) and expr.is_Atom:
return 1
return f"输入错误: {input_str}"
except Exception as e:
return f"Error: {e}"
# 示例测试
if __name__ == "__main__":
test_cases = [
"[[1,0],[2,3]]",
# 1
"[[1,2],[3,4]]",
# 0
"5",
# 1
"a",
# 1
"[1,2]",
# 0
"[[1,2,3],[4,5,6]]"
# 0
]
for case in test_cases:
print(f"输入: {case:<20} 结果: {is_lower_triangular(case)}")
确定矩阵是否为上三角矩阵.
如果A是上三角矩阵,则tf = istril(A) 返回逻辑值1 (true). 否则,将返回逻辑值0 (false).
A — 输入数组,数组
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
def is_upper_triangular(input_str):
"""
判断输入是否为上三角矩阵(对标MATLAB istriu函数)
参数:
input_str: 输入字符串,可以是矩阵、标量或符号表达式
返回:
1: 是上三角矩阵
0: 不是上三角矩阵
str: 错误信息
示例:
>>> is_upper_triangular("[[1,0],[2,3]]")
1
>>> is_upper_triangular("[[1,2],[3,4]]")
0
>>> is_upper_triangular("5")
1
>>> is_upper_triangular("[[1,2],[3,4,5]]")
'输入错误: [[1,2],[3,4,5]]'
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
# 尝试转换为矩阵
if isinstance(expr, list):
M = sp.Matrix(expr)
# 非方阵直接返回0
if M.is_square and M.is_upper:
return 1
else:
return 0
# 处理标量和符号(视为1x1矩阵)
if isinstance(expr, sp.Basic) and expr.is_Atom:
return 1
return f"输入错误: {input_str}"
except Exception as e:
return f"Error: {e}"
# 示例测试
if __name__ == "__main__":
test_cases = [
"[[17,24,1,8,15],[0,5,7,14,16],[0,0,13,20,22],[0,0,0,21,3],[0,0,0,0,9]]",
# 1
"[[1,2],[3,4]]",
# 0
"5",
# 1
"a",
# 1
"[1,2]",
# 0
"[[1,2,3],[4,5,6]]"
# 0
]
for case in test_cases:
print(f"输入: {case:<20} 结果: {is_upper_triangular(case)}")
逆z变换
iztrans(F) 返回 F 的逆 Z 变换. 默认情况下, 独立变量为 z, 变换变量为 n. 如果 F 不包含 z, iztrans 将使用函数 symvar.
F — 输入, 符号表达式, 符号函数
示例1:单位阶跃序列
result = iztrans(z/(z-1))
print(f"输出: {result}")
#输出: Piecewise((1, n >= 0))
#物理意义: 表示离散时间系统中的单位阶跃响应
示例2:指数衰减序列
result = iztrans(1/(1 - a/z))
print(f"输出: {result}")
#输出: Piecewise((a**n, n >= 0))
#物理意义: 表示衰减因子为a的指数序列,常用于系统稳定性分析
示例3:斜坡序列
result = iztrans(z/(z-1)**2)
print(f"输出: {result}")
#输出: Piecewise((n, n >= 0))
#物理意义: 表示随时间线性增长的序列
示例4:二阶系统
result = iztrans(z**2/(z**2 - 1.5*z + 0.5))
print(f"输出: {result}")
#输出: Piecewise((2 - 1/2**n, n >= 0))
#物理意义: 二阶离散系统的冲激响应,用于控制系统分析
示例5:带延迟的系统
result = iztrans(1/z**3 * z/(z-0.5))
print(f"输出: {result}")
#输出: Piecewise((-8*UnitImpulse(n) - 2*UnitImpulse(n - 2) - 4*UnitImpulse(n - 1) + 8/2**n, n >= 0))
#物理意义: 具有3个采样周期延迟的一阶系统
示例6:数字滤波器系数
result = iztrans((0.1*z)/(z - 0.9))
print(f"输出: {result}")
#输出: Piecewise((1/(10*(10/9)**n), n >= 0))
#物理意义: 一阶IIR数字滤波器的冲激响应
示例7:控制系统补偿器
result = iztrans(Kp + Ki*z/(z-1) + Kd*(z-1)/z)
print(f"输出: {result}")
#输出: Piecewise((Kd*(UnitImpulse(n) - UnitImpulse(n - 1)) + Ki + Kp*UnitImpulse(n), n >= 0))
#物理意义: 离散PID控制器的差分方程形式
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import lcapy as lc
def inverse_z_transform(input_str):
"""执行逆Z变换,支持矩阵输入
参数:
input_str (str): 输入表达式字符串或矩阵描述
返回:
SymPy表达式/矩阵 或 错误信息字符串"""
try:
# 将输入字符串转换为SymPy表达式
expr = sp.sympify(input_str)
# 转换为Lcapy表达式以使用其符号运算功能
error = False
result = None
def eval_inv_ztrans(ele):
"""执行单个表达式的逆Z变换"""
f_expr = lc.expr(str(ele))
if f_expr.free_symbols:
return f_expr.IZT() # 调用Lcapy的逆Z变换方法
else:
return None # 常数项无需变换
# 矩阵处理分支
if isinstance(expr, list):
matrix = sp.Matrix(expr)
rows, cols = matrix.shape
# 对矩阵中每个元素递归执行逆Z变换
result = sp.Matrix(rows, cols, lambda i, j: eval_inv_ztrans(matrix[i, j]))
elif expr.free_symbols:
# 单表达式处理
result = eval_inv_ztrans(expr)
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误:{e}"
# 示例代码
if __name__ == "__main__":
# 示例1:单表达式变换
print("示例1:单表达式逆Z变换")
expr_str = "1/(1 - 1/z)"
result = inverse_z_transform(expr_str)
print(f"输入: {expr_str}")
print(f"输出: {result}")
# Piecewise((1, n >= 0))
print("\n" + "=" * 50 + "\n")
# 示例2:矩阵变换
print("示例2:矩阵逆Z变换")
matrix_input = "[2*z/(z-2)**2, 1/(a*z)]"
result = inverse_z_transform(matrix_input)
print("\n逆Z变换结果:")
print(result)
# Matrix([[DiscreteTimeDomainExpression(Piecewise((2*2**(n - 1)*n, n >= 0)))],
# [DiscreteTimeDomainExpression(UnitImpulse(n - 1)/a)]])