锯齿波或三角波
x = sawtooth(t)为时间数组t的元素生成周期为2π的锯齿波. sawtooth类似于正弦函数,但会创建峰值为-1和1的锯齿波.锯齿波定义为在2π的倍数处为-1,而在所有其他时间处以斜率为1/π 随时间呈现线性增加.
x = sawtooth(t,xmax) 生成修正三角波,其每个周期的最大值位置由xmax控制, 默认值1.
t — 时间数组,向量,矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
def sawtooth_wave(input_str):
"""
根据输入生成锯齿波或三角波,对标MATLAB的sawtooth函数。
参数:
input_str: 字符串输入,可以是以下形式:
- 时间变量,如 "t"
- 时间数组,如 "[0, 0.1, 0.2]"
- 元组形式的时间和占空比,如 "(t, 0.5)"(占空比必须在0到1之间)
返回:
tuple: (x_values, y_values) 分别为时间数组和对应的波形值。
错误时返回错误信息字符串。
"""
try:
expr = sp.sympify(input_str)
duty = 1.0 # 默认占空比为1(锯齿波)
x_values = None
# 处理元组输入(时间和占空比)
if isinstance(expr, tuple):
if len(expr) != 2:
raise ValueError("输入元组必须包含两个元素:时间和占空比")
t_expr, duty_expr = expr
# 解析占空比
try:
duty = float(duty_expr.evalf())
if not (0 <= duty <= 1):
raise ValueError("占空比必须在0到1之间")
except:
raise ValueError("无效的占空比")
# 解析时间表达式
matrix = sp.Matrix(t_expr) if isinstance(t_expr, list) else None
if matrix is not None:
x_values = np.array(matrix).astype(float).ravel()
elif isinstance(t_expr, sp.Expr):
# 生成默认时间序列(0到2π,500个点)以匹配MATLAB的周期
var = next(iter(t_expr.free_symbols)) if t_expr.free_symbols else None
t = np.linspace(0, 2 * np.pi, 500, endpoint=False)
x_values = sp.lambdify(var, t_expr, 'numpy')(t)
else:
raise ValueError("无法解析时间表达式")
# 处理非元组输入
else:
matrix = sp.Matrix(expr) if isinstance(expr, list) else None
if matrix is not None:
x_values = np.array(matrix).astype(float).ravel()
elif isinstance(expr, sp.Expr):
# 生成默认时间序列(0到2π,500个点)
var = next(iter(expr.free_symbols)) if expr.free_symbols else None
t = np.linspace(0, 2 * np.pi, 500, endpoint=False)
x_values = sp.lambdify(var, expr, 'numpy')(t)
else:
raise ValueError("无法解析输入表达式")
# 生成波形(不再额外乘以2π)
y_values = signal.sawtooth(x_values, width=duty)
return x_values, y_values
except Exception as e:
return f"错误: {str(e)}"
# 示例代码
if __name__ == "__main__":
# 示例1:基本锯齿波(width=1)
x, y = sawtooth_wave("t")
plt.figure(figsize=(10, 4))
plt.plot(x, y)
plt.title("Sawtooth Wave (duty=1)")
plt.grid(True)
plt.show()
# 示例2:复杂表达式
x, y = sawtooth_wave("t*pi/2*sin(t/5)")
plt.figure(figsize=(10, 4))
plt.plot(x, y)
plt.title("Custom Waveform: t*pi/2*sin(t/5)")
plt.grid(True)
plt.show()
舒尔分解
[U,T] = schur(A,mode) 返回酉矩阵U, 舒尔矩阵T. 并满足 A = U*T*U'.
如果mode为"real", U, T = schur(A,mode)(其中 A 为实矩阵),返回实数拟三角舒尔矩阵T. 如果mode为"complex",则返回复数三角舒尔矩阵.
如果A为复矩阵,则不管mode的值是多少,schur都返回复数舒尔形式.
t — 时间数组,向量,矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.linalg import schur as scipy_schur
def schur_decomposition(input_expr):
"""
执行舒尔分解(Schur Decomposition),对标 MATLAB 的 schur 函数。
参数:
input_expr: 输入可以是以下形式之一:
- SymPy 矩阵
- 列表或嵌套列表表示的矩阵
- 元组 (矩阵, 'real') 或 (矩阵, 'complex') 指定输出类型
返回:
若成功,返回 (Z, T),其中:
Z: 酉矩阵(SymPy 矩阵)
T: 上三角矩阵(SymPy 矩阵)
若失败,返回错误信息字符串。
示例:
>>> schur_decomposition([[1, 2], [3, 4]])
(Matrix(...), Matrix(...))
"""
try:
# 解析输入
if isinstance(input_expr, tuple) and len(input_expr) == 2:
matrix_part, output_type = input_expr
output_type = str(output_type).lower()
if output_type not in ['real', 'complex']:
return "错误: 分解类型必须为 'real' 或 'complex'"
else:
matrix_part = input_expr
output_type = 'real' # 默认实数分解
# 转换为 SymPy 矩阵
A = sp.Matrix(matrix_part) if isinstance(matrix_part, list) else None
if A is None:
return "错误: 输入不是有效矩阵"
# 检查矩阵是否为数值矩阵
if not all(val.is_number for val in A):
return "错误: 矩阵包含符号变量,仅支持数值矩阵"
# 转换为 NumPy 数组进行舒尔分解
A_np = np.array(A, dtype=float)
# 调用 SciPy 的舒尔分解
T_np, Z_np = scipy_schur(A_np, output=output_type)
# 转换回 SymPy 矩阵
Z = sp.Matrix(Z_np)
T = sp.Matrix(T_np)
return (Z, T)
except Exception as e:
return f"错误: {e}"
# --------------------- 示例用法 ---------------------
if __name__ == "__main__":
# 示例 1: 实数分解 (默认)
matrix = [[1, 2], [3, 4]]
Z, T = schur_decomposition(matrix)
print("示例1 实数分解:")
print("Z =\n", Z)
# Matrix([[-0.824564840132394, -0.565767464968992],
# [0.565767464968992, -0.824564840132394]])
print("T =\n", T)
# Matrix([[-0.372281323269014, -1.00000000000000],
# [0, 5.37228132326901]])
print("验证 Z*T*Z.T ≈ A:\n", Z * T * Z.T)
# Matrix([[1.00000000000000, 2.00000000000000],
# [3.00000000000000, 4.00000000000000]])
# 示例 2: 复数分解
input_tuple = ([[0, -1], [1, 0]], 'complex')
Z, T = schur_decomposition(input_tuple)
print("\n示例2 复数分解:")
print("Z =\n", Z)
# Matrix([[-0.707106781186547*I, -0.531446838683691 + 0.466437839002273*I],
# [-0.707106781186547, -0.466437839002273 - 0.531446838683691*I]])
print("T =\n", T)
# Matrix([[1.0*I, -2.2677956401069e-16 + 3.09244860014577e-17*I],
# [0, 2.77555756156289e-17 - 1.0*I]])
角的正割(以弧度为单位)
Y = sec(X) 返回X的元素的正割. sec函数按元素处理数组.该函数同时接受实数和复数输入.
对于X的实数值,sec(X)返回区间 [-∞, - 1] 和 [1, ∞] 内的实数值.
对于X的复数值,sec(X)返回复数值
X — 输入角(以弧度为单位),标量,向量,矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def secant_of_radians(input_str):
"""
计算角的正割(以弧度为单位),对标MATLAB的sec函数
参数:
input_str: 输入字符串,可以是:
- 数值 (如 "0", "pi/3")
- 矩阵 (如 "[[1, 0], [pi/4, pi/6]]")
- 包含符号的表达式 (如 "t", "2*x + pi/2")
返回:
计算结果 (标量/矩阵/符号表达式) 或错误信息字符串
特征:
- 支持符号计算
- 支持矩阵元素级运算
- 自动数值求值
- 完善的错误处理
"""
try:
# 解析输入字符串为SymPy表达式
expr = sp.sympify(input_str)
error = False
result = None
if expr.is_number:
z = complex(expr)
result = 1 / np.cos(z)
elif expr.free_symbols:
# 符号运算后数值求值
result = sp.sec(expr).evalf()
else:
error = True
# 处理无法识别的输入类型
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# 示例代码
if __name__ == "__main__":
# 初始化美化打印
sp.init_printing(use_unicode=True)
# 示例1:基本数值计算
print("示例1:标量计算")
print("sec(0) =", secant_of_radians("0")) #
# (1+0j)
print("sec(pi/3) =", secant_of_radians("pi/3"))
# (2.0000000000000004+0j)
print("sec(pi/2) =", secant_of_radians("pi/2"))
# (1.633123935319537e+16+0j)
# 示例3:符号运算
print("\n示例3:符号表达式")
t = secant_of_radians("t")
print("sec(t) =", t)
# sec(t)
expr = secant_of_radians("2*x + pi/3")
print("复合表达式:", expr)
# sec(2*x + pi/3)
参量的正割(以度为单位)
Y = secd(X)返回X的元素的正割(以度为单位).
X — 以度为单位的角,标量值,向量,矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def secant_degree_radians(input_str):
"""
计算角度的正割(以度为单位),对标MATLAB的secd函数
参数:
input_str: 输入字符串,可以是:
- 数值角度 (如 "30", "45")
- 矩阵 (如 "[[0, 60], [90, 180]]")
- 符号表达式 (如 "theta", "2*x + 45")
返回:
计算结果 (数值/矩阵/符号表达式) 或错误信息字符串
特征:
- 自动将度数转换为弧度
- 支持符号计算
- 支持矩阵元素级运算
- 完善的错误处理
"""
try:
# 解析输入字符串为SymPy表达式
expr = sp.sympify(input_str)
# 定义核心计算函数
def sec_degree_sym(x):
"""实际计算函数,处理单个元素"""
# 转换为弧度:degree * π / 180
x_rad = x * sp.pi / 180
return sp.sec(x_rad).evalf()
def sec_degree_num(x):
"""
计算以度数为单位的角度的正割值(secant)
等效于 MATLAB 的 secd 函数
参数:
x : 角度(度数),可以是标量或NumPy数组
返回:
正割值,当 cos(radians) = 0 时返回无穷大(inf)
"""
# 将角度转换为弧度
x_rad = x * np.pi / 180
# 计算余弦值
cos_vals = np.cos(x_rad)
# 计算正割 = 1 / 余弦,避免除零警告
with np.errstate(divide='ignore', invalid='ignore'):
sec_vals = np.where(np.abs(cos_vals) > np.finfo(float).eps,
1.0 / cos_vals,
np.inf)
return sec_vals
# 处理元组输入的特殊情况
if isinstance(expr, tuple):
raise ValueError("不支持元组输入,请使用数值、矩阵或符号表达式")
# 处理标量或符号表达式
if expr.is_number:
z = complex(expr)
return sec_degree_num(z)
else:
return sec_degree_sym(expr)
# 处理未知类型
except Exception as e:
return f"错误: {str(e)}"
# 示例代码
if __name__ == "__main__":
# 初始化美化打印
sp.init_printing(use_unicode=True)
# 示例1:基本数值计算
print("示例1:标量计算")
print("secd(0) =", secant_degree_radians("0"))
# (1+0j)
print("secd(60) =", secant_degree_radians("60"))
# (1.9999999999999996+0j)
print("secd(90) =", secant_degree_radians("90"))
# (inf+0j)
# 示例3:符号运算
print("\n示例3:符号表达式")
theta = secant_degree_radians("theta")
print("secd(theta) =", theta)
# sec(pi*theta/180)
expr = secant_degree_radians("2*x + 45")
print("复合表达式:", expr)
# sec(pi*(x/90 + 1/4))
双曲正割
Y = sech(X) 返回X的元素的双曲正割.sech函数按元素处理数组.该函数同时接受实数和复数输入.所有的角度都以弧度表示.
X — 输入角(以弧度为单位),标量值,向量,矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def secant_hyperbolic_radians(input_str):
"""
计算双曲正割函数(sech),对标MATLAB的sech函数
参数:
input_str: 输入字符串,可以是:
- 数值 (如 "0", "1")
- 矩阵 (如 "[[0, 1], [2, 3]]")
- 符号表达式 (如 "x", "2*y + 1")
返回:
计算结果 (数值/矩阵/符号表达式) 或错误信息字符串
特征:
- 支持符号计算
- 自动处理矩阵元素级运算
- 数值计算自动转换为浮点数
- 兼容NumPy数组输入
"""
try:
# 解析输入并替换特殊字符
expr = sp.sympify(input_str)
# 检查元组输入类型
if isinstance(expr, tuple):
raise ValueError("不支持元组输入,请使用数值、矩阵或符号表达式")
# 处理标量和符号表达式
if expr.is_number:
# 数值优化处理
z = complex(expr)
return 1 / np.cosh(z)
elif expr.free_symbols:
# 符号运算
return sp.sech(expr).evalf()
# 处理未知类型
raise TypeError("无法识别的输入类型")
except Exception as e:
return f"错误: {str(e)}"
# 示例代码
if __name__ == "__main__":
sp.init_printing(use_unicode=True) # 美化打印
# 示例1:标量计算
print("示例1:标量计算")
print("sech(0) =", secant_hyperbolic_radians("0"))
# (1+0j)
print("sech(1) =", secant_hyperbolic_radians("1"))
# (0.6480542736638855+0j)
# 示例3:符号运算
print("\n示例3:符号表达式")
x = secant_hyperbolic_radians("x")
print("sech(x) =", x)
# sech(x)
expr = secant_hyperbolic_radians("2*y + 1")
print("复合表达式:", expr)
# sech(2*y + 1)
以列表形式返回序列
Sequence(f,x,start,end,step)依据输入字符串构建一个序列,并依据输入的不同参数对序列进行切片操作.
f -- 符号表达式
x -- 符号标量
start, end, step -- 标量, 切片参数
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def squence_list(input_str):
"""
此函数的作用是依据输入字符串构建一个序列,并依据输入的不同参数对序列进行切片操作。
参数:
input_str (str): 包含序列定义和切片参数的字符串。
返回:
list 或者 str: 如果输入无误,返回切片后的序列列表;若输入有误,返回错误信息。
"""
try:
# 把输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
error = False
result = None
# 检查输入表达式的长度是否小于 4,若小于 4 则判定为输入错误
if len(expr) < 4:
error = True
# 若输入表达式长度为 4,构建一个完整的序列
elif len(expr) == 4:
# 构建序列,第一个参数是序列的通项公式,后面三个参数分别是变量、起始值、结束值
s = sp.sequence(expr[0], (expr[1], expr[2], expr[3]))
# 获取序列的所有元素
result = s[:]
# 若输入表达式长度为 5,构建序列并按指定步长切片
elif len(expr) == 5:
s = sp.sequence(expr[0], (expr[1], expr[2], expr[3]))
# 获取步长
step = expr[4]
# 按步长对序列进行切片
result = s[::step]
# 若输入表达式长度为 6,构建序列,按指定步长切片,再从指定起始索引开始取元素
elif len(expr) == 6:
s = sp.sequence(expr[0], (expr[1], expr[2], expr[3]))
step = expr[4]
# 获取起始索引
start_index = expr[5]
my_list = s[::step]
result = my_list[start_index:]
# 若输入表达式长度为 7,构建序列,按指定步长切片,从指定起始索引开始取指定数量的元素
elif len(expr) == 7:
s = sp.sequence(expr[0], (expr[1], expr[2], expr[3]))
step = expr[4]
start_index = expr[5]
# 获取要取的元素数量
num_elements = expr[6]
my_list = s[::step]
if start_index > 0:
result = my_list[start_index:start_index + num_elements]
else:
result = my_list[start_index - num_elements:start_index][::-1]
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# 示范代码
if __name__ == "__main__":
# 测试输入,构建一个从 1 到 10 的整数序列
input1 = "(i, i, 1, 10)"
print(squence_list(input1))
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 测试输入,构建一个从 1 到 10 的整数序列,步长为 2
input2 = "(i, i, 1, 10, 2)"
print(squence_list(input2))
# [1, 3, 5, 7, 9]
# 测试输入,构建一个从 1 到 10 的整数序列,步长为 2,从索引 1 开始取元素
input3 = "(i, i, 1, 10, 2, 1)"
print(squence_list(input3))
# [3, 5, 7, 9]
# 测试输入,构建一个从 1 到 10 的整数序列,步长为 2,从索引 1 开始取 2 个元素
input4 = "(i, i, 1, 10, 2, 1, 2)"
print(squence_list(input4))
# [3, 5]
皮瑟级数
series(f,var)用f的Puiseux级数展开逼近f,直到在点var=0处的五阶.如果不指定var,那么series将使用由f确定默认变量.
f —— 近似输入, 符号表达式,符号函数
var —— 符号变量
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def series_puiseux(input_str):
"""
计算给定表达式在指定变量处的Puiseux级数展开(支持分数指数)。
参数:
input_str (str): 输入的表达式字符串,格式为"表达式, 变量",例如"sqrt(x),x"。
如果未指定变量且表达式只有一个变量,则自动选择该变量。
返回:
sympy.Expr 或 str: 级数展开结果,若出错则返回错误信息字符串。
"""
try:
# 尝试将输入的字符串转换为 sympy 表达式,evaluate=False 表示不进行求值
expr = sp.sympify(input_str, evaluate=False)
# 初始化错误标志
error = False
# 如果表达式是一个元组且长度为 2,说明输入格式为"表达式, 变量"
if isinstance(expr, tuple) and len(expr) == 2:
# 尝试判断第一个元素是否为函数,如果不是则直接使用该元素作为表达式
f = expr[0]
# 第二个元素作为展开变量
variable = expr[1]
# 如果表达式有自由变量
elif expr.free_symbols:
# 直接使用表达式
f = expr
# 获取表达式中的自由变量
variables = f.free_symbols
# 若有自由变量,选择第一个作为展开变量
variable = tuple(variables)[0]
else:
# 若表达式没有自由变量,设置错误标志
error = True
# 默认展开的项数为 5
n = 5
# 生成级数展开并移除无穷小量
series_exp = f.series(variable, n=n).removeO()
# 如果没有错误则返回展开结果,否则返回错误信息
return series_exp if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误:{e}"
# 示例代码
if __name__ == "__main__":
# 示例1:展开sin(x)到5阶
input1 = "sin(x), x"
print(f"输入:{input1}")
print("输出:", series_puiseux(input1))
# -x**3/6 + x
# 示例2:展开sqrt(x)到5阶
input2 = "sqrt(x), x"
print(f"\n输入:{input2}")
print("输出:", series_puiseux(input2))
# sqrt(x)
# 示例3:多变量未指定
input3 = "x*y + y"
print(f"\n输入:{input3}")
print("输出:", series_puiseux(input3))
# x*y + y
移动数组维度
B = shiftdim(A,n) 将数组 A 的维度移动 n 个位置。当 n 为正整数时,shiftdim 向左移动维度;当 n 为负整数时,向右移动维度。
A — 输入数组, 向量 | 矩阵
n — 位置的数量, 整数
B — 输出数组, 向量 | 矩阵
var —— 符号变量
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def shift_arr_dim(input_str):
"""
实现类似 MATLAB shiftdim 函数的功能
:param arr: 输入的数组,可以是 sympy 矩阵或 numpy 数组
:param n: 移位的位数,正数表示向左移位,负数表示向右移位
:return: 移位后的数组
"""
try:
expr = sp.sympify(input_str)
result = None
error = False
if isinstance(expr, tuple) and isinstance(expr[0], list) and expr[1].is_integer:
arr = np.array(expr[0], dtype=object)
n = int(expr[1])
# 处理 n 为正数的情况(循环左移)
if n > 0:
ndim = arr.ndim
if ndim == 0:
pass # 标量无需处理
else:
n_shift = n % ndim # 处理 n 大于维度数的情况
if n_shift != 0:
new_order = list(range(n_shift, ndim)) + list(range(n_shift))
arr = np.transpose(arr, new_order)
# 处理 n 为负数的情况(添加前导单一维度)
elif n < 0:
for _ in range(-n):
arr = np.expand_dims(arr, axis=0)
else:
error = True
if not error:
if arr.ndim == 2:
# 如果输入是 sympy 矩阵且结果为二维,将结果转换回 sympy 矩阵
result = sp.Matrix(arr.tolist())
else:
result = arr
return result
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误:{e}"
# 示例使用
# 创建一个符号数组
# 向左移位 1 位
shifted_left = shift_arr_dim("[[x, y],[z,x+y]],1")
print("\n向左移位 1 位后的数组:")
print(shifted_left)
# Matrix([[x, z],
# [y, x + y]])
# 向左移位 1 位
shifted_left = shift_arr_dim("[[3, 4],[5,6]],1")
print("\n向左移位 1 位后的数组:")
print(shifted_left)
# Matrix([[3, 5],
# [4, 6]])
# 向右移位 1 位
shifted_right = shift_arr_dim("[[x, y],[z,x+y]],-1")
print("\n向右移位 1 位后的数组:")
print(shifted_right)
# [[[x y]
# [z x + y]]]
对数组执行符号函数
Y=sign(x)返回一个与x大小相同的数组Y,其中Y的每个元素为:
如果x的对应元素大于0,则为1.
如果x的相应元素等于0,则为0.
如果x的对应元素小于0,则为1.
如果x是复数, 返回x/abs(x).
a — 输入数组,标量,向量,矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def sign_function(input_str):
"""
符号函数计算,对标 MATLAB 的 sign 函数
定义:
对于实数 x:
sign(x) = 1 if x > 0
0 if x = 0
-1 if x < 0
对于复数 z = a + bi:
sign(z) = z / |z| (当 z ≠ 0 时)
0 (当 z = 0 时)
参数:
input_str (str): 输入表达式,可以是:
- 数值 (如 "2.5", "-3")
- 复数 (如 "1+2j")
- 符号表达式 (如 "x", "y**2")
- 矩阵 (如 "[[1, -2], [0, 3+4j]]")
返回:
[类型] 数值/符号表达式/矩阵 或 错误信息字符串
示例:
>>> sign_function("5")
1.0
>>> sign_function("-x")
-sign(x)
"""
try:
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
# 情况2:处理数值和符号输入
if expr.is_number or expr.free_symbols:
# 数值类型转换
# 符号表达式保持符号形式
return sp.sign(expr).evalf()
# 其他无法处理的情况
return f"输入错误: 不支持的类型 {type(expr)}"
except Exception as e:
return f"计算错误: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 示例1:实数计算
print("示例1 实数计算:")
print(sign_function("5"))
# 1.00000000000000
print(sign_function("-3.2"))
# -1.00000000000000
print(sign_function("0"))
# 0
# 示例2:复数计算
print("\n示例2 复数计算:")
print(sign_function("3+4j"))
# 0.6 + 0.8*I
print(sign_function("0+0j"))
# 0
# 示例3:符号运算
print("\n示例3 符号运算:")
print(sign_function("x"))
# sign(x)
print(sign_function("-y**2"))
# -sign(y**2)
双曲正弦积分
如果x是浮点数,则sinhint(x)返回浮点结果.
Y = sinhint(x)返回算术表达式
x是标量,符号变量,表达式,向量,矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.special import shichi
def shi_hyper_sine_integral(input_str):
"""
计算双曲正弦积分函数 Shi(z),对标 MATLAB 的 sinhint 函数
定义:
Shi(z) = ∫₀ᶻ (sinh(t)/t) dt
参数:
input_str (str): 输入表达式,可以是:
- 数值 (如 "0", "3.14")
- 符号表达式 (如 "x", "2*t+1")
- 矩阵 (如 "[[0, 1], [2, 3]]")
返回:
[类型] 数值/符号表达式/矩阵 或 错误信息字符串
示例:
>>> shi_hyper_sine_integral("0")
0.0
>>> shi_hyper_sine_integral("x")
Shi(x)
"""
try:
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
# 处理数值和符号输入
if expr.is_number:
z = complex(expr)
sin_arr, cos_arr = shichi(z)
return sin_arr
elif expr.free_symbols:
return sp.Shi(expr).evalf()
return f"输入错误: 无法处理类型 {type(expr)}"
except Exception as e:
return f"计算错误: {str(e)}"
if __name__ == "__main__":
# 示例 1:数值输入
print("示例1 数值计算:")
print(shi_hyper_sine_integral("0"))
# 0j
print(shi_hyper_sine_integral("1.0"))
# (1.0572508753757286+0j)
# 示例 2:符号计算
print("\n示例2 符号运算:")
print(shi_hyper_sine_integral("x"))
# Shi(x)
print(shi_hyper_sine_integral("2*t + 1"))
# Shi(2*t + 1)
正弦积分
sinint(X)返回X的正弦积分函数.
根据其参数,sinint返回浮点或精确的符号结果.
X是指定为符号数,变量,表达式或函数,或指定为符号,变量,公式或函数的矢量或矩阵.
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
from scipy.special import sici
def si_sine_integral(input_str):
"""
计算正弦积分函数 Si(z),对标 MATLAB 的 sinint 函数
定义:
Si(z) = ∫₀ᶻ (sin(t)/t) dt
参数:
input_str (str): 输入表达式,可以是:
- 数值 (如 "0", "3.14")
- 符号表达式 (如 "x", "2*t+1")
- 矩阵 (如 "[[0, 1], [2, 3]]")
返回:
[类型] 数值/符号表达式/矩阵 或 错误信息字符串
示例:
>>> si_sine_integral("0")
0.0
>>> si_sine_integral("x")
Si(x)
"""
try:
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
result = None
error = False
# 处理元组输入
if isinstance(expr, tuple):
error = True
# 处理数值和符号输入
if expr.is_number:
z = complex(expr)
result = sici(z)[0]
elif expr.free_symbols:
result = sp.Si(expr.evalf())
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"计算错误: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 示例 1:数值输入
print("示例1 数值计算:")
print(si_sine_integral("0"))
# 0j
print(si_sine_integral("1.0"))
# (0.946083070367183-0j)
# 示例 2:符号计算
print("\n示例2 符号运算:")
print(si_sine_integral("x"))
# Si(x)
print(si_sine_integral("2*t + 1"))
# Si(2.0*t + 1.0)
代数简化
S=simplify(expr)执行expr的代数简化. 如果expr是符号向量或矩阵,则此函数简化了expr的每个元素.
expr — 输入表达式, 符号表达式, 符号函数, 符号向量, 符号矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def simplify_function(input_str):
"""
简化输入的数学表达式或矩阵中的每个元素,对标Matlab的simplify函数。
参数:
input_str (str): 输入的数学表达式或矩阵的字符串表示。
返回:
SymPy对象或错误信息字符串: 简化后的表达式或矩阵,若出错则返回错误信息。
示例:
>>> simplify_function("x + x + 2*y - y")
2*x + y
>>> simplify_function("[[x + x, 2*y], [sin(pi/2), sqrt(4)]]")
Matrix([[2*x, 2*y], [1, 2]])
>>> simplify_function("3 + 4")
7
>>> simplify_function("(1, 2)")
'输入错误: (1, 2)'
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
def eval_expression(expr_item):
"""内部函数,用于简化单个表达式元素。"""
return sp.simplify(expr_item)
# 检查输入是否为元组(视为无效输入)
if isinstance(expr, tuple):
error = True
else:
# 处理普通标量或符号表达式
result = eval_expression(expr)
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误:{e}"
# 简化符号表达式
print(simplify_function("x + x + y - y/2"))
# 2*x + y/2
# 简化数值表达式
print(simplify_function("sqrt(9) + cos(pi)")) # 2
简化符号有理表达式
simplifyFraction(expr)简化有理表达式expr,使得分子和分母没有共同的除数.
simplifyFraction(expr,'Expand',true)将所得简化分数的分子和分母展开为无需分解的多项式.
expr — 输入数字,向量,矩阵,数组,符号数,符号变量,符号数组,符号函数,符号表达式
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def simplify_fraction(input_str):
"""
简化符号有理表达式,对标Matlab的simplifyFraction函数,支持矩阵输入。
参数:
input_str (str): 输入的有理表达式或矩阵的字符串表示。
返回:
SymPy对象或str: 简化后的表达式或矩阵,错误时返回错误信息。
示例:
>>> simplify_fraction("(x^2 - 1)/(x - 1)")
x + 1
>>> simplify_fraction("[[(x^2 - 1)/(x - 1), 6/3], [2*y/(y+y), (a+b)^2/(a+b)]]")
Matrix([[x + 1, 2], [1, a + b]])
>>> simplify_fraction("4/2 + 6/3")
4
>>> simplify_fraction("invalid expr")
错误:...
"""
try:
# 将输入字符串转换为SymPy表达式
expr = sp.sympify(input_str)
return sp.cancel(expr)
except Exception as e:
return f"错误:{e}"
print(simplify_fraction("((y+1)^2*(x^2-1))/((x+1)*(x-1)^2)"))
# (y**2 + 2*y + 1)/(x - 1)
以弧度为单位的参量的正弦.
Y = sin(X)返回X的每个元素的余弦.sin函数按元素处理数组.该函数同时接受实数和复数输入.
对于X的实数值,sin(X)返回区间[-1, 1]内的实数值.
对于X的复数值,sin(X)返回复数值.
X是标量,向量,数组,矩阵.
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def sine_trig_function(input_str):
"""
对标 MATLAB 的 sin 函数,计算以弧度为单位的正弦值
参数:
input_str: 输入的数学表达式字符串,可以是数值、符号、矩阵等
返回:
计算结果(数值、符号表达式或矩阵),若输入不合法则返回错误信息
"""
try:
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
error = False
result = None
# 处理元组输入(视为非法)
if isinstance(expr, tuple):
error = True
elif expr.is_number or expr.free_symbols:
result = sp.sin(expr).evalf()
# 其他无法处理的类型
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:", sine_trig_function("0"))
# 0
print("示例 1:", sine_trig_function("pi/2"))
# 1.00000000000000
# 示例 2: 符号输入
x = sp.symbols('x')
print("示例 2:", sine_trig_function("x"))
# sin(x)
print("示例 2:", sine_trig_function("x + pi"))
# -sin(x)
辛格函数
y = sinc(x) 返回数组 y,其元素是输入 x 的元素的 sinc。输出 y 与 x 的大小相同.
x是标量值,向量,矩阵或多维数组.
y是标量值,向量,矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def sinc_sampling_function(input_str):
"""
计算输入表达式的 sinc 采样函数值,对标 MATLAB 的 sinc 函数。
MATLAB 定义:sinc(x) = sin(πx)/(πx),且在 x=0 时值为 1
参数:
input_str (str): 输入表达式字符串,可以是:
- 数值(如 "0")
- 符号表达式(如 "x")
- 矩阵(如 "[[0, 1], [2, 3]]")
返回:
sympy 表达式/矩阵/浮点数 或 str: 计算结果或错误信息
"""
try:
# 将输入字符串转换为 SymPy 对象
expr = sp.sympify(input_str)
def sinc_numpy_style(x):
if x == 0:
return 1
else:
return sp.sin(sp.pi * x) / (sp.pi * x)
# 情况 2:处理数值输入
if expr.is_number:
z = complex(expr)
return np.sinc(z)
# 情况 3:处理符号表达式
elif expr.free_symbols:
return sinc_numpy_style(expr).evalf()
# 其他无法处理的情况
else:
return f"输入错误: 不支持的类型 {type(expr)}"
except Exception as e:
return f"错误: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 示例 1:数值输入
print("示例 1:")
print(sinc_sampling_function("0"))
# (1+0j)
print(sinc_sampling_function("1.0"))
# (3.8981718325193755e-17-0j)
# 示例 2:符号输入
print("\n示例 2:")
x = sp.symbols('x')
print(sinc_sampling_function("x"))
# 0.318309886183791*sin(pi*x)/x
print(sinc_sampling_function("2*x + 1"))
# 0.318309886183791*sin(pi*(2*x + 1))/(2.0*x + 1.0)
以度为单位的参量的正弦.
Y = sind(X)返回X的每个元素的余弦.sind函数按元素处理数组.该函数同时接受实数和复数输入.
X是标量,向量,数组,矩阵.
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def sind_sine_degree(input_str):
try:
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
error = False
result = None
# 定义度数转弧度的正弦计算函数
def sine_deg(x_val):
return sp.sin(x_val * sp.pi / 180).evalf()
# 处理数值或符号表达式
if expr.is_number:
z = complex(expr)
result = np.sin(z * np.pi / 180)
elif expr.free_symbols:
result = sine_deg(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:", sind_sine_degree("30"))
# (0.49999999999999994+0j)
# 示例 2: 符号输入
x = sp.symbols('x')
print("示例 2:", sind_sine_degree("x"))
# sin(pi*x/180)
正弦拟合
p = sinfit(x,y,n) 返回次数为n的正弦拟合 p(x) 的系数
x是查询点,指定为一个向量.
y是查询点位置的拟合值,指定为向量.
n是正弦拟合的次数, 正整数标量.
Y = a1*sin(b1*x+c1)
Y = a1*sin(b1*x+c1)+a2*sin(b2*x+c2)
Y = a1*sin(b1*x+c1)+...+a3*sin(b3*x+c3)
Y = a1*sin(b1*x+c1)+...+a8*sin(b8*x+c8)
以此类推,最大到 sin8
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.optimize import curve_fit
def sin_fit_nonlinear(input_str):
"""
使用非线性最小二乘法进行正弦曲线拟合,支持1到8阶正弦项。
参数:
x_data (array_like): 自变量数据数组
y_data (array_like): 因变量数据数组
n (int): 正弦项的数量(1到8)
maxfev (int): 最大函数评估次数
返回:
sympy.Expr: 拟合的正弦表达式
str: 错误信息(如果发生错误)
示例:
x = np.linspace(0, 10, 100)
y = 2.5 * np.sin(3 * x + 1) + 0.5 * np.sin(5 * x - 2)
expr = sin_fit_nonlinear(x, y, n=2)
print(expr) # 输出类似 2.5000*sin(3.0000*x + 1.0000) + 0.5000*sin(5.0000*x - 2.0000)
"""
try:
expr = sp.sympify(input_str)
error = False
maxfev = 100000
# 定义正旋拟合函数,从一阶到八阶
if isinstance(expr, tuple):
if len(expr) == 3:
x, y, n = expr[0], expr[1], int(expr[2])
elif len(expr) == 2:
x, y = expr
n = 1
else:
error = True
if isinstance(x, list):
x_data = np.array(x, dtype=float).ravel()
if isinstance(y, list):
y_data = np.array(y, dtype=float).ravel()
# 输入验证
if n < 1 or n > 8:
return None, "阶数n必须在1到8之间"
if len(x_data) != len(y_data):
return None, "x_data和y_data长度不一致"
else:
error = True
# 定义各阶正弦函数
func_dict = {
1: lambda x, *p: p[0] * np.sin(p[1] * x + p[2]),
2: lambda x, *p: sum(p[i * 3] * np.sin(p[i * 3 + 1] * x + p[i * 3 + 2]) for i in range(2)),
# ... 类似定义到n=8
}
# 生成初始猜测
a_guess = (np.max(y_data) - np.min(y_data)) / 2
b_guess = 2 * np.pi / (np.max(x_data) - np.min(x_data))
initial_guess = [a_guess, b_guess, 0] * n
params, _ = curve_fit(func_dict[n], x_data, y_data,
p0=initial_guess, maxfev=maxfev,
bounds=(0, [np.inf, np.inf, 2 * np.pi] * n))
# 构建表达式
terms = []
for i in range(n):
a, b, c = params[i * 3: (i + 1) * 3]
terms.append(f"{a:.4f}*sin({b:.4f}*x + {c:.4f})")
return sp.sympify("+".join(terms))
except Exception as e:
return f"错误:{e}"
# 生成测试数据
x = [1, 2, 3, 4, 5, 6, 7, 8]
y = [9, 10, 11, 12, 13, 14, 15, 16]
# 进行拟合
expr = sin_fit_nonlinear(f"{x},{y},2")
if expr:
print("拟合表达式:", expr)
# 5.1845*sin(1.0957*x)
else:
print("错误:")
双曲正弦
Y = sinh(X)返回X的每个元素的双曲正弦.sinh函数按元素处理数组.该函数同时接受实数和复数输入.
所有的角度都以弧度表示.
X是标量,向量,数组,矩阵.
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def sin_hyperbolic_sine(input_str):
"""
计算输入的双曲正弦值(对标MATLAB sinh函数)
参数:
expr: 输入数据,支持以下类型:
- 数值(int/float)
- SymPy符号表达式
- SymPy矩阵
- 嵌套列表(自动转换为SymPy矩阵)
返回:
SymPy对象(数值/矩阵/表达式)或错误信息字符串
示例:
1. 标量计算
>>> sin_hyperbolic_sine(0)
0
2. 符号计算
>>> x = sp.Symbol('x')
>>> sin_hyperbolic_sine(x)
sinh(x)
3. 矩阵计算
>>> sin_hyperbolic_sine([[0, 1], [2, 3]])
Matrix([
[0, sinh(1)],
[sinh(2), sinh(3)]])
4. 错误处理
>>> sin_hyperbolic_sine("invalid")
"错误: 不支持的类型: "
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
# 处理标量或符号表达式输入
if expr.is_number:
z = complex(expr)
result = np.sinh(z)
elif expr.free_symbols:
result = sp.sinh(expr).evalf()
# 其他类型错误
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# 以下是测试用例
if __name__ == "__main__":
# 标量测试
print("标量测试:", sin_hyperbolic_sine(0))
# 0j
# 符号测试
x = sp.Symbol('x')
print("符号测试:", sin_hyperbolic_sine(x))
# sinh(x)
准确计算sin(x*pi)
Y = sinpi(X).该函数同时接受实数和复数输入.
X是标量,向量,数组,矩阵.
对于奇数,sinpi(n/2) 为+1或-1.
对于整数,sinpi(n) 为零
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def sin_pi_sine(input_str):
"""
准确计算 sin(X*π) 的符号表达式和数值计算
对标MATLAB sinpi函数特性:
1. 精确处理符号表达式 (如 sin(pi*x))
2. 数值计算时不直接展开π,避免浮点误差
3. 支持矩阵元素级计算
参数:
input_str (str): 输入表达式,可以是:
- 数值 (如 "0.5")
- 符号表达式 (如 "x")
- 矩阵 (如 "[[1, 2], [x, 1/2]]")
返回:
float: 数值计算结果
MutableDenseMatrix: 矩阵计算结果
sp.Expr: 符号表达式结果
str: 错误信息
示例:
>>> sin_pi_sine("0.5")
1.0
>>> sin_pi_sine("x")
sin(pi*x)
>>> sin_pi_sine("[[1/2, 0], [x, 1/6]]")
Matrix([[1.0, 0], [sin(pi*x), 0.5]])
"""
try:
# 符号化输入(自动识别矩阵和表达式)
expr = sp.sympify(input_str)
# 处理标量数值/符号
if expr.is_number:
z = complex(expr)
result = np.sin(np.pi * z)
elif expr.free_symbols:
result = sp.sin(sp.pi * expr)
return result
except Exception as e:
return f"计算错误: {str(e)}"
# ----------------------------
# 测试案例
# ----------------------------
if __name__ == "__main__":
# 案例1: 数值计算
print(sin_pi_sine("0.5"))
# (1+0j)
print(sin_pi_sine("1/6"))
# (0.49999999999999994+0j)
# 案例2: 符号计算
print(sin_pi_sine("x"))
# sin(pi*x)
# 案例4: 复合表达式
print(sin_pi_sine("x + 1/2"))
# sin(pi*(x + 1/2))
求解优化问题或方程问题
sol = solve(prob) 求解优化问题或方程问题prob
prob — 优化问题或方程问题, 线性或非线性方程组,包括等式方程及不等式方程
sol — 解
将球面坐标转换为笛卡尔坐标
[x,y,z] = sph2cart(azimuth,elevation,r) 将球面坐标数组 azimuth,elevation和r的对应元素转换为笛卡尔坐标,即 xyz 坐标
azimuth — 方位角,标量,向量,矩阵
elevation — 仰角,标量,向量,矩阵
r — 半径,标量,向量,矩阵
x,y,z — 笛卡尔坐标,数组
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def spherical_to_cartesian(input_str):
"""
球坐标转笛卡尔坐标 (对标 MATLAB sph2cart 函数)
参数:
input_str: 字符串形式的输入,支持三种格式:
1. 单独方位角 (az):返回 (x, y) 平面坐标
2. 方位角 (az) 和仰角 (el):假定 r=1
3. 方位角 (az), 仰角 (el), 半径 (r)
返回:
(x, y, z) 元组,元素类型与输入保持一致(标量/矩阵)
实现特性:
- 支持符号计算
- 自动广播标量到矩阵维度
- 输入验证和错误处理
"""
try:
# 解析输入表达式
expr = sp.sympify(input_str)
error = False
result = None
# 定义转换函数
def compute_coords(az_val, el_val, r_val):
x = r_val * sp.cos(el_val) * sp.cos(az_val)
y = r_val * sp.cos(el_val) * sp.sin(az_val)
z = r_val * sp.sin(el_val)
return x, y, z
def spherical_to_cartesian(az, el, r):
"""
将球面坐标转换为笛卡尔坐标,支持标量、向量和多维数组输入。
参数:
az: 方位角(弧度),可以是标量或NumPy数组
el: 仰角(弧度),可以是标量或NumPy数组
r: 半径,可以是标量或NumPy数组
返回:
x, y, z: 笛卡尔坐标,与输入具有相同的维度
"""
# 将输入转换为NumPy数组以支持广播
az = np.asarray(az)
el = np.asarray(el)
r = np.asarray(r)
# 执行坐标转换
x = r * np.cos(el) * np.cos(az)
y = r * np.cos(el) * np.sin(az)
z = r * np.sin(el)
return x, y, z
if isinstance(expr, tuple) and len(expr) == 3:
if all(e.is_number for e in expr):
params = tuple(float(e) for e in expr)
result = spherical_to_cartesian(*params)
elif any(e.free_symbols for e in expr):
result = compute_coords(*expr)
else:
error = True
return result if not error else f"输入错误:{input_str}"
except Exception as e:
return f"错误: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 示例1: 标量输入
print("示例1 输入: (pi/4, pi/6, 2)")
print("输出:", spherical_to_cartesian("(pi/4, pi/6, 2)"))
# (1.2247448713915892, 1.224744871391589, 1.0)
# 示例2: 符号输入
a, e = sp.symbols('a e')
print("\n示例2 输入: (a, e, 1)")
print("输出:", spherical_to_cartesian(f"({a}, {e}, 1)"))
# (cos(a)*cos(e), sin(a)*cos(e), sin(e))
球面坐标3D绘图.
球面坐标θ和φ的半径绘制函数.
SphericalPlot3D(L,r1,r2,options)
L是具有两个变量的过程或表达式,或三个此类过程或表达式的列表
r1,r2是表达式变量的范围.
1. 地球形状近似(轴对称椭球):
描述地球的 两极扁平化(赤道半径 > 极半径)
赤道(θ=π/2)膨胀约 21.3 km
SphericalPlot3D(6371*(1+0.003*(1.5cos(theta)^2-0.5)), theta=[0,@pi])
2. 声学指向性模式(扬声器设计):
优化扬声器阵列的声波覆盖
抑制特定方向干扰(如舞台反馈啸叫)
输出特征:主瓣沿 z 轴 + 4个侧瓣
SphericalPlot3D(abs(sinc(3*sin(theta)*cos(phi))), theta=[0,@pi], phi=[0,2@pi])
3. 等离子体湍流(核聚变研究):
模拟托卡马克装置中磁流体不稳定性
预测等离子体破裂位置
输出特征:螺旋波纹结构(类似扭曲模)
SphericalPlot3D(1+0.1*(sin(theta+2phi)+sin(2theta+2phi)+sin(3theta+2phi)),theta=[0,@pi], phi=[0,2@pi])
4. 天线辐射方向图(通信工程):
设计 5G 基站天线覆盖范围
优化卫星通信链路
输出特征: 轮胎状辐射模式(最大增益在赤道面)
SphericalPlot3D(abs(cos((@pi/2)*cos(theta))/sin(theta)),theta=[0,@pi])
5. 液滴振动模式(轴对称基础模态):
赤道膨胀 + 两极扁平化的振荡
SphericalPlot3D(1+0.2*(1.5*cos(theta)^2-0.5),theta=[0,@pi])
6. 核物质分布(球形原子核):
沿旋转轴压缩的椭球形状
SphericalPlot3D(1.2*(1-0.05*(1.5*cos(theta)^2-0.5)),theta=[0,@pi])
多曲面球面坐标3D图
内球提供基准形状,外曲面突出相对变形,清晰显示表面与内部的对应
1. 行星大气环流模型:
内球:地球固体表面
外曲面:大气温度异常分布
5个经向波动 + 10个纬向波动表示大气环流模式
角度限制聚焦北半球中高纬度区域
SphericalPlot3D(6371,6371+8*sin(5phi)*sin(10theta), theta=[0,0.7@pi],phi=[0,1.8@pi])
2. 核聚变装置等离子体约束
内球:真空室边界
外曲面:等离子体密度分布
sin(5ϕ)sin(10θ) 模拟磁流体不稳定性
角度限制避免极区复杂物理现象
SphericalPlot3D(1,1.5+0.2*sin(@phi)*sin(10theta), theta=[0,0.7@pi],phi=[0,1.8@pi])
3. 脑皮层神经活动映射:
内球:基准脑皮层表面
外曲面:神经活动强度
5×10 振荡模式模拟不同功能区域
角度限制对应可观测的脑区
SphericalPlot3D(0.9,1+0.15*sin(5phi)*sin(10theta), theta=[0.2@pi,0.7@pi],phi=[0.1@pi,1.8@pi])
4. 多波束天线方向图
内球:参考单位增益
外曲面:实际辐射强度
5个方位角波束 + 10个仰角波束
φ范围限制表示天线机械旋转范围
SphericalPlot3D(1,1.5+0.3*sin(5phi)*sin(10theta), theta=[0,0.7@pi],phi=[0,1.8@pi])
5. 地幔对流模型
内球:地核-地幔边界
外曲面:地幔对流速度
5个经向对流单元 + 10个纬向结构
θ限制表示上地幔区域(深0-670km)
SphericalPlot3D(0.9,1+0.25*sin(5phi)*sin(10theta), theta=[0,0.7@pi],phi=[0,1.8@pi])
6. 蛋白质分子表面
内球:分子核心
外曲面:范德华表面
5×10 波动模拟结合口袋结构
角度限制聚焦功能活性区域
SphericalPlot3D(0.8,1+0.4*sin(5phi)*sin(10theta), theta=[0.1,0.6@pi],phi=[0.2,1.6@pi])
SpotPlot(list1, list2)
通过笛卡尔坐标系展示两个变量之间关系的图表。每个数据点由横坐标(X轴)和纵坐标(Y轴)的值共同定位,直观反映变量间的关联性、分布模式或趋势。
电商运营:价格与销量关系
确定最优定价区间(如$20时销量180件,总收入$3600 vs $30时销量150件,总收入$4500)
发现异常点:若$40时突然销量200件,可能需排查数据错误或促销活动影响
SpotPlot([10,20,30,40,50],[200,180,150,120,80])
医疗研究:药物剂量与疗效
确定安全剂量窗口(100–150mg)
警示毒性风险:>150mg时疗效骤降
SpotPlot([0,50,100,150,200],[10,40,75,80,30])
气候科学:CO₂浓度与温度
量化碳排放对变暖的影响(如CO₂每升50ppm,温度+0.8℃)
支持气候政策制定(如控制CO₂<450ppm以维持温度增幅<2℃)
SpotPlot([300,350,400,450],[14.0,14.5,15.2,15.8])
教育评估:学习时间与成绩
建议最佳学习时长(15-20小时)
识别低效学生:如投入25小时成绩仅82分,需学习方法干预
SpotPlot([5,10,15,20,25],[60,75,85,88,82])
工业制造:设备温度与故障率
设置温度报警阈值(80℃)
预测设备寿命:100℃时故障率15次/月,需提前更换
SpotPlot([60,70,80,90,100],[1,2,3,8,15])
金融分析:广告投入与ROI
优化预算:>30万时边际收益递减
止损点:40万后ROI<150%,应削减投入
SpotPlot([10,20,30,40,50],[120,150,170,160,140])
结构秩
r = sprank(A) 计算稀疏矩阵 A 的结构秩.
A — 输入矩阵,稀疏矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import maximum_bipartite_matching
def sparse_rank_matrix(input_str):
"""
计算稀疏矩阵的结构秩,对标 MATLAB 的 sprank 函数
参数:
input_str: 字符串形式的矩阵输入,例如 "[[1, 0], [0, 1]]"
返回:
结构秩数值(整数)或错误信息字符串
实现原理:
1. 通过二分图匹配计算最大匹配数
2. 使用 SciPy 的 maximum_bipartite_matching 算法
3. 结构秩 = 最大匹配数
注意:
- 不支持符号矩阵
- 自动忽略复数元素
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
# 检查转换结果是否有效(sympify 转换失败返回元组)
if isinstance(expr, tuple):
error = True
else:
# 转换为 SymPy 矩阵
a = sp.Matrix(expr) if isinstance(expr, list) else None
if a is not None:
# 检查是否包含符号或复数
contains_symbols = any(element.free_symbols for element in a)
contains_complex = any(element.has(sp.I) for element in a)
if contains_symbols or contains_complex:
error = True
else:
# 转换为 SciPy 稀疏矩阵
A = csr_matrix(np.array(a, dtype=float))
try:
# 正确调用方式(SciPy≥1.4.0)
matching = maximum_bipartite_matching(A)
# 修正:直接统计匹配结果中不等于-1的元素个数
return int(np.sum(matching != -1))
except Exception as e:
result = sp.Matrix(A.toarray()).rank()
return result
else:
error = True # 非矩阵输入
# 生成错误信息
if error:
if contains_symbols:
return f"错误: 不支持符号矩阵输入"
elif contains_complex:
return f"错误: 不支持复数矩阵输入"
else:
return f"输入错误: {input_str}"
return result
except Exception as e:
return f"错误: {e}"
# 示例代码
if __name__ == "__main__":
# 示例1: 满秩对角矩阵
m1 = "[[1,0,2,0],[2,0,4,0]]"
print(f"示例1 输入: {m1}")
print(f"示例1 输出: {sparse_rank_matrix(m1)}\n")
# 2
# 示例2: 秩亏缺但结构满秩
m2 = "[[1, 1], [1, 1]]"
print(f"示例2 输入: {m2}")
print(f"示例2 输出: {sparse_rank_matrix(m2)}\n")
# 2
# 示例3: 结构秩小于数值秩
m3 = "[[0, 1], [1, 0]]"
print(f"示例3 输入: {m3}")
print(f"示例3 输出: {sparse_rank_matrix(m3)}\n")
# 2
# 示例4: 非方阵
m4 = "[[1, 0, 0], [0, 1, 0]]"
print(f"示例4 输入: {m4}")
print(f"示例4 输出: {sparse_rank_matrix(m4)}\n")
# 2
创建稀疏矩阵
r = sprank(A) 计算稀疏矩阵 A 的结构秩.
S = sparse(A) 通过挤出任何零元素将满矩阵转换为稀疏格式. 如果矩阵包含许多零, 将矩阵转换为稀疏存储空间可以节省内存.
S = sparse(m,n) 生成 m×n 全零稀疏矩阵.
S = sparse(i,j,v) 根据 i、j 和 v 三元组生成稀疏矩阵 S, 以便 S(i(k),j(k)) = v(k). max(i)×max(j) 输出矩阵为 length(v) 个非零值元素分配了空间. 如果输入 i, j 和 v 为向量或矩阵, 则它们必须具有相同数量的元素. 参量 v 和/或 i 或 j 其中一个参量可以使标量
A — 输入矩阵, 满矩阵, 稀疏矩阵
i,j — 下标对组(指定为单独的参量), 标量, 向量, 矩阵
v — 值, 标量, 向量, 矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.sparse import csr_matrix
def sparse_matrix(input_str):
"""
对标 MATLAB 的 sparse 函数,创建稀疏矩阵
支持的输入格式:
1. 三数组格式: (行索引列表, 列索引列表, 值列表) 例如: "([0,1], [0,1], [1,2])"
2. 全矩阵转换: 嵌套列表或 SymPy 矩阵 例如: "[[1,0], [0,2]]"
3. 指定维度空矩阵: (行数, 列数) 例如: "(2,3)"
参数:
input_str: 输入字符串,描述矩阵的格式
返回:
SymPy 矩阵对象或错误信息字符串
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
# 情况1:处理三数组格式 (i, j, v)
if isinstance(expr, tuple):
if len(expr) >= 3 and all(isinstance(item, list) for item in expr[:3]):
# 提取前三个元素作为行索引、列索引和值
i = np.array(expr[0], dtype=int)
j = np.array(expr[1], dtype=int)
v = np.array(expr[2], dtype=float)
# 创建稀疏矩阵(自动处理重复索引的求和)
sparse_mat = csr_matrix((v, (i, j)))
result = sparse_mat.toarray()
# 情况2:处理指定维度的空矩阵 (m, n)
elif len(expr) == 2 and all(e.is_integer for e in expr):
rows, cols = map(int, expr)
sparse_mat = csr_matrix((rows, cols))
result = sparse_mat.toarray()
else:
error = True
# 情况3:处理全矩阵转换
elif isinstance(expr, list):
# 将 SymPy 矩阵转换为 NumPy 数组
dense_array = np.array(expr, dtype=float)
# 转换为稀疏格式后再转回密集数组(用于验证)
sparse_mat = csr_matrix(dense_array)
result = sparse_mat.toarray()
else:
error = True
# 返回 SymPy 矩阵或错误信息
return sp.Matrix(result) if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# 示例代码
if __name__ == "__main__":
# 示例1:三数组格式创建对角矩阵
print("示例1:")
print(sparse_matrix("([0, 1], [0, 1], [1, 2])"))
# Matrix([[1.00000000000000, 0],
# [0, 2.00000000000000]])
# 示例2:全矩阵转换
print("\n示例2:")
print(sparse_matrix("[[1, 0], [0, 2]]"))
# Matrix([[1.00000000000000, 0],
# [0, 2.00000000000000]])
# 示例3:创建 2x3 空矩阵
print("\n示例3:")
print(sparse_matrix("(2, 3)"))
# Matrix([[0, 0, 0],
# [0, 0, 0]])
# 示例4:重复索引自动求和
print("\n示例4:")
print(sparse_matrix("([0, 0], [0, 0], [1, 2])"))
# Matrix([[3.00000000000000]])
三次方样条数据插值
s = spline(x,y,xq) 返回与 xq 中的查询点对应的插值 s 的向量。s 的值由 x 和 y 的三次样条插值确定。
pp = spline(x,y) 返回一个分段多项式结构体以用于 ppval 和样条实用工具 unmkpp。
x - x 坐标, 向量
y - x 坐标处的函数值, 向量 | 矩阵
xq - 查询点, 标量 | 向量 | 矩阵
s - 查询点位置的插值, 标量 | 向量 | 矩阵
pp - 分段多项式,结构体
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.interpolate import CubicSpline
def spline_cubic(input_str):
"""
对标MATLAB的spline函数,实现三次样条插值
参数:
input_str: 输入参数字符串,格式示例:
"x, y" -> 返回样条函数
"y" -> 自动生成x坐标并返回样条函数
"x, y, xq" -> 返回xq处的插值结果
"y, xq" -> 自动生成x坐标并返回xq处插值结果
返回:
样条函数对象或插值结果数组,错误时返回字符串信息
示例:
>>> spline_cubic("[1,2,3], [4,5,6]")
>>> spline_cubic("[1,2,3], [4,5,6], 2.5")
array(5.0)
"""
try:
# 符号解析与类型转换 ------------------------------------------------
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")
# 解析输入字符串
expr = sp.sympify(input_str, evaluate=False) # 强制转换为元组
params = [convert(p) for p in expr] if isinstance(expr, tuple) else [convert(expr)]
# 参数处理与插值计算 ------------------------------------------------
def validate_length(a, b):
if len(a) != len(b):
raise ValueError(f"Length mismatch: {len(a)} vs {len(b)}")
# 处理不同参数数量
if len(params) == 1: # spline(y)
y = params[0]
x = np.arange(len(y))
return CubicSpline(x, y, bc_type='not-a-knot')
elif len(params) == 2: # spline(x,y) 或 spline(y,xq)
a, b = params
if len(a) == len(b): # x,y模式
return CubicSpline(a, b, bc_type='not-a-knot')
else: # y,xq模式
y, xq = a, b
x = np.arange(len(y))
return CubicSpline(x, y)(xq)
elif len(params) == 3: # spline(x,y,xq)
x, y, xq = params
validate_length(x, y)
return CubicSpline(x, y, bc_type='not-a-knot')(xq)
else:
raise ValueError("Invalid number of parameters (1-3 required)")
except Exception as e:
return f"Error: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 标准插值测试
print(spline_cubic("[1,2,3], [4,5,6], 2"))
# [5.]
print(spline_cubic("[0,1,2], [0,1,4], 1.5"))
# [2.25]
# 自动生成x坐标测试
print(spline_cubic("[3,1,4], [0.5, 1.5]"))
# [1.375 1.875]
平方根
B=sqrt(X)返回数组X中每个元素的平方根.对于X中为负或复数的元素,sqrt(X)会产生复数结果.
X —— 输入数组,标量,向量,矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def square_root(input_str):
"""
计算元素的平方根,对标 MATLAB 的 sqrt 函数。
参数:
input_str: 字符串形式的输入,可以是标量或矩阵,例如 "4" 或 "[[1, 4], [9, 16]]"
返回:
计算结果(SymPy 矩阵或数值),错误时返回字符串描述错误信息
示例:
>>> square_root("4")
2.0
>>> square_root("[[1, 4], [9, 16]]")
Matrix([
[1.0, 2.0],
[3.0, 4.0]])
>>> square_root("[[a, 4], [9, b]]")
Matrix([
[sqrt(a), 2.0],
[ 3.0, sqrt(b)]])
"""
try:
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
error = False
result = None
# 检查转换结果是否有效(sympify 转换失败返回元组)
if isinstance(expr, tuple):
error = True
else:
# 标量处理:直接计算平方根并数值化
result = sp.sqrt(expr).evalf()
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# 示例代码
if __name__ == "__main__":
# 示例 1: 标量输入
print("示例1 输入: '4'")
print("示例1 输出:", square_root("4"), end="\n\n")
# 2.00000000000000
# 示例 2: 复数结果
print("示例2 输入: '-1'")
print("示例2 输出:", square_root("-1"), end="\n\n")
# 1.0*I
矩阵平方根
X = sqrtm(A)返回矩阵A的主平方根,即X*X=A.
X是每个特征值都有非负实部的唯一平方根.如果A有任何具有负实部的特征值,则会产生复结果.
如果A是单数,那么A可能没有平方根.
A —— 输入矩阵,方阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy import linalg as dense_linalg
def square_root_matrix(input_str):
"""
计算矩阵的平方根,对标 MATLAB 的 sqrtm 函数。
参数:
input_str: 字符串形式的矩阵输入,例如 "[[1, 0], [0, 4]]"。
返回:
如果输入合法且为方阵,返回 SymPy 矩阵;否则返回错误信息字符串。
"""
try:
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
error = False
result = None
# 检查转换后的表达式是否有效(如果转换失败,sympify 可能返回元组)
if isinstance(expr, tuple):
error = True
else:
# 转换为 SymPy 矩阵
A = sp.Matrix(expr) if isinstance(expr, list) else None
if A is not None:
# 检查矩阵是否包含符号或虚数单位 I
contains_symbols = A.is_symbolic() or any(element.has(sp.I) for element in A)
# 仅处理方阵
if A.is_square:
if contains_symbols:
# 符号矩阵:使用 SymPy 的矩阵幂运算
result = A ** sp.Rational(1, 2)
else:
# 数值矩阵:转换为 NumPy 数组并用 SciPy 计算平方根
N_A = np.array(A, dtype=float)
scipy_result = dense_linalg.sqrtm(N_A)
# 将结果转换回 SymPy 矩阵并四舍五入到合理精度
result = sp.Matrix(scipy_result.round(10))
else:
error = True # 非方阵报错
else:
error = True # 非矩阵类型报错
# 返回结果或错误信息
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# 示例代码
if __name__ == "__main__":
# 示例 1: 数值方阵
matrix1 = "[[1, 0], [0, 4]]"
print("示例1 输入:", matrix1)
print("示例1 输出:", square_root_matrix(matrix1))
# Matrix([[1.00000000000000, 0],
# [0, 2.00000000000000]])
# 示例 2: 符号矩阵
a, b = sp.symbols('a b')
matrix2 = f"[[{a}, 0], [0, {b}]]"
print("\n示例3 输入:", matrix2)
print("示例3 输出:", square_root_matrix(matrix2))
# Matrix([[sqrt(a), 0],
# [0, sqrt(b)]])
# 示例 3: 复数矩阵
matrix3 = "[[-1, 0], [0, -1]]"
print("\n示例4 输入:", matrix3)
print("示例4 输出:", square_root_matrix(matrix3))
# Matrix([[1.0*I, 0],
# [0, 1.0*I]])
格式化距离矩阵
ZOut = squareform(yIn) 将yIn(m个观测值的长度为m(m–1)/2的成对距离向量)转换为ZOut(对角线上有零的m乘m对称矩阵)
yIn是数值向量,逻辑向量.
ZOut是数值矩阵,逻辑矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.spatial import distance
def distance_square_form(input_str):
"""
对标MATLAB的squareform函数,实现压缩向量与距离方阵的相互转换。
参数:
input_str (str): 输入字符串,可以是以下两种形式:
1. 压缩距离向量:如 "[0.5, 1.2, 2.3]"
2. 对称距离方阵:如 "[[0, 0.5, 1.2], [0.5, 0, 2.3], [1.2, 2.3, 0]]"
返回:
sympy.Matrix: 根据输入类型自动转换:
- 输入为向量时返回对称方阵
- 输入为方阵时返回压缩向量
如果输入格式错误,返回描述性错误信息
示例:
>>> distance_square_form("[1, 2, 3]")
Matrix([
[0, 1, 2],
[1, 0, 3],
[2, 3, 0]])
>>> distance_square_form("[[0, 1, 2], [1, 0, 3], [2, 3, 0]]")
Matrix([1.0, 2.0, 3.0])
"""
try:
# 将输入字符串解析为SymPy对象
expr = sp.sympify(input_str)
error = False
result = None
# 处理列表输入
if isinstance(expr, list):
arr = np.array(expr, dtype=float).ravel()
else:
error = True
# 检查数组维度有效性
if arr.ndim not in (1, 2):
raise ValueError("输入必须是向量(1D)或矩阵(2D)")
# 使用scipy进行格式转换
result = distance.squareform(arr)
# 转换为SymPy矩阵返回
return sp.Matrix(result) if not error else f"输入错误: {input_str}"
except ValueError as ve:
return f"数值错误: {str(ve)}"
except sp.SympifyError:
return "格式错误: 无法解析输入字符串"
except Exception as e:
return f"处理错误: {str(e)}"
input_str = "[1, 2, 3, 4, 5, 6]"
print(distance_square_form(input_str))
# Matrix([[0, 1.00000000000000, 2.00000000000000, 3.00000000000000],
# [1.00000000000000, 0, 4.00000000000000, 5.00000000000000],
# [2.00000000000000, 4.00000000000000, 0, 6.00000000000000],
# [3.00000000000000, 5.00000000000000, 6.00000000000000, 0]])
方波
x = square(t) 为时间数组t的元素生成周期为2π的方波.square类似于正弦函数,但会创建值为-1和1的方波.
x = square(t,duty) 生成指定占空比为duty的方波.占空比是方波为正的信号周期的百分比.
t — 时间数组,向量,矩阵
duty — 占空比,0到1之间
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy import signal
def square_wave(input_str):
"""
生成方波信号,对标MATLAB square函数
参数:
input_expr: 输入表达式,支持以下形式:
- 时间向量 (数值数组/矩阵)
- 符号表达式 (如 't',需包含单个符号变量)
- 元组 (时间向量, 占空比)
duty (可选): 占空比 (0到1之间,默认0.5)
freq (可选): 信号频率 (单位Hz,默认1)
sample_points (可选): 符号表达式采样点数 (默认500)
返回:
tuple: (时间向量, 方波信号) 或 错误信息字符串
示例:
>>> # 数值输入
>>> t = [0, 0.1, 0.2, 0.3]
>>> square_wave(t)
(array([0. , 0.1, 0.2, 0.3]), array([ 1., 1., 1., -1.]))
>>> # 符号表达式输入
>>> square_wave('t', duty=0.3)
(array([0. , 0.002,...,1.0]), array([1, 1,...,-1]))
>>> # 矩阵输入
>>> square_wave([[0, 0.5], [1, 1.5]])
(array([0. , 0.5, 1. , 1.5]), array([ 1., 1., -1., -1.]))
"""
try:
# 统一输入处理
expr = sp.sympify(input_str)
error = False
duty = 0.5
freq = 1
sample_points = 500
# 处理元组输入 (时间向量, 占空比)
if isinstance(expr, tuple) and len(expr) == 2:
t, custom_duty = expr
duty = float(custom_duty)
# 参数校验
if not 0 <= duty <= 1:
raise ValueError("占空比必须在0到1之间")
expr = t
# 矩阵/数组处理
if isinstance(expr, list):
t_values = np.array(expr).astype(float).ravel()
# 符号表达式处理
elif expr.free_symbols:
symbols = expr.free_symbols
if len(symbols) != 1:
raise ValueError("符号表达式必须包含单个变量")
var = symbols.pop()
t_values = np.linspace(0, 1 / freq, sample_points)
expr_func = sp.lambdify(var, expr, 'numpy')
t_values = expr_func(t_values)
# 数值处理
elif expr.is_number:
t_values = np.array(expr, dtype=float)
else:
error = True
# 生成方波 (MATLAB的2π周期对应频率f=1/(2π))
y_values = signal.square(2 * np.pi * freq * t_values, duty=duty)
return t_values, y_values if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {str(e)}"
# 处理各种输入类型
print(square_wave("[[0,0.5],[1,1.5]]"))
# (array([0. , 0.5, 1. , 1.5]),
# array([ 1., -1., 1., -1.]))
删除长度为 1 的维度
B = squeeze(A) 返回一个数组,其元素与输入数组 A 相同,但删除了长度为 1 的维度。例如,如果 A 是 3×1×2 数组,则 squeeze(A) 返回 3×2 矩阵。
如果 A 是行向量、列向量、标量或没有长度为 1 的维度的数组,则 squeeze 返回输入 A。
A — 输入数组,多维数组
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def squeeze_arr_dim(input_str):
"""
该函数的主要功能是将输入的字符串转换为数组,然后去除数组中长度为 1 的维度。
如果输入不是有效的矩阵格式,或者在处理过程中出现异常,会返回相应的错误信息。
参数:
input_str (str): 输入的字符串,预期为表示矩阵的字符串
返回:
numpy.ndarray 或 str: 如果处理成功,返回去除长度为 1 的维度后的数组;如果出现错误,返回错误信息字符串
"""
try:
# 这个函数可能用于处理字符串中的一些格式问题,使其符合后续处理的要求
# 使用 sympy 的 sympify 函数将修正后的字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
# 初始化结果变量,用于存储最终处理后的数组
result = None
# 初始化错误标志,用于标记是否出现错误
error = False
# 如果是矩阵,该函数会返回矩阵对象;否则返回 None
# 使用海象运算符(Python 3.8 及以上版本支持)将结果赋值给 matrix 变量
if isinstance(expr,list):
# 如果是矩阵,将矩阵对象转换为 NumPy 数组,数据类型为 object
arr = np.array(expr, dtype=object)
# 使用 NumPy 的 squeeze 函数去除数组中长度为 1 的维度
result = np.squeeze(arr)
else:
# 如果输入不是矩阵,将错误标志设置为 True
error = True
# 如果没有出现错误,返回处理后的数组;否则返回错误信息
return result if not error else f"输入错误: {input_str}"
except Exception as e:
# 如果在处理过程中出现异常,捕获异常并返回错误信息
return f"错误:{e}"
print(squeeze_arr_dim("[[[1,2]]]"))
# [1 2]
print(squeeze_arr_dim("[[[x,y]]]"))
# [x y]
状态空间模型
A,B,C,D,dt = ss(sys) 将线性系统转换为空间系统形式。始终创建一个新系统,即使sys已经是一个状态空间系统.
A - 装态数, 状态数是矩阵A的行(或列)数. 如果矩阵A是一个4×4的矩阵,因此有四个状态.
B - 输入数:输入数是矩阵B的列数. 比如矩阵B是一个4×2的矩阵,因此有两个输入.
C - 输出数:输出数是矩阵C的行数. 比如矩阵C是一个3×4的矩阵,因此有三个输出.
D - 矩阵D代表直接传递矩阵(Direct transmission matrix),也称为前馈矩阵(feedforward matrix).它描述了系统输入对系统输出的直接影响,而不经过系统的状态.
dt - 采样时间
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
import control.matlab as ct
def convert_to_numpy_or_float(expr):
"""
将表达式转换为 NumPy 数组或浮点数。
:param expr: 输入的表达式
:return: 转换后的 NumPy 数组或浮点数
"""
if isinstance(expr, list):
return np.array(expr, dtype=float)
elif expr.is_number:
return float(expr)
else:
# 如果既不是列表也不是数字,抛出类型错误
raise TypeError(f"不支持的类型: {type(expr).__name__}")
def state_space_system(input_str):
"""构建状态空间系统
参数格式示例:
- 连续系统: "[[-1,-2],[3,-4]],[[5],[7]],[[6, 8]],[[9]]"
- 离散系统: "[[-1.5,-2],[1,0]],[[0.5],[0]],[0,1],0,0.2"
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
# 检查表达式是否为元组
if not isinstance(expr, tuple):
return f"输入错误: 期望输入为元组,但得到 {type(expr).__name__}"
# 检查元组长度是否至少为 4
if len(expr) < 4:
return f"输入错误: 元组长度至少为 4,但得到 {len(expr)}"
# 提取 A, B, C, D 矩阵
A = convert_to_numpy_or_float(expr[0])
B = convert_to_numpy_or_float(expr[1])
C = convert_to_numpy_or_float(expr[2])
D = convert_to_numpy_or_float(expr[3])
# 检查是否有采样时间
if len(expr) > 4:
try:
dt = float(expr[4])
except ValueError:
return f"输入错误: 采样时间必须是数字,但得到 {expr[4]}"
# 创建连续时间状态空间系统
sys1 = ct.ss(A, B, C, D, dt)
result = sp.Matrix(sys1.A), sp.Matrix(sys1.B), sp.Matrix(sys1.C), sp.Matrix(sys1.D), sys1.dt
else:
# 创建离散时间状态空间系统
sys1 = ct.ss(A, B, C, D)
result = sp.Matrix(sys1.A), sp.Matrix(sys1.B), sp.Matrix(sys1.C), sp.Matrix(sys1.D)
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误:{e}"
# 测试案例
if __name__ == "__main__":
test_cases = [
"([[-1,-2],[3,-4]],[[5],[7]],[[6, 8]],[[9]])",
# A: Matrix([[-1.00000000000000, -2.00000000000000], [3.00000000000000, -4.00000000000000]])
# B: Matrix([[5.00000000000000], [7.00000000000000]])
# C: Matrix([[6.00000000000000, 8.00000000000000]])
# D: Matrix([[9.00000000000000]])
"([[-1.5,-2],[1,0]],[[0.5],[0]],[0,1],0,0.2)",
# A: Matrix([[-1.50000000000000, -2.00000000000000], [1.00000000000000, 0]])
# B: Matrix([[0.500000000000000], [0]])
# C: Matrix([[0, 1.00000000000000]])
# D: Matrix([[0]])
]
for case in test_cases:
print(f"测试输入: {case}")
result = state_space_system(case)
if isinstance(result, tuple):
if len(result) == 4:
A, B, C, D = result
else:
A, B, C, D, _ = result
print("A:", A)
print("B:", B)
print("C:", C)
print("D:", D)
else:
print("错误信息:", result)
print("─" * 50)
移位正弦积分
ssinint(X)返回移位后的正弦积分函数. ssiint(X)=sinint(X)-pi/2.
X —— 输入,符号数,符号变量,符号表达式,符号函数,符号向量,符号矩阵.
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
from sympy import Si, pi
import numpy as np
from scipy.special import sici
def shifted_sine_integral(input_str):
"""
对标 MATLAB 的 ssinint 函数,计算位移正弦积分 Si(x) - π/2。
参数:
input_str: 输入的字符串,可以表示数值、符号表达式或矩阵。
返回:
- 对于数值输入,返回浮点数结果。
- 对于符号输入,返回符号表达式。
- 对于矩阵输入,返回各元素对应的位移正弦积分结果的 SymPy 矩阵。
- 错误时返回错误消息字符串。
示例:
>>> shifted_sine_integral('2')
-0.110538260536646 # 示例值,实际结果可能不同
>>> shifted_sine_integral('x')
Si(x) - pi/2
>>> shifted_sine_integral('[[1, x], [2, y]]')
Matrix([
[Si(1) - pi/2, Si(x) - pi/2],
[Si(2) - pi/2, Si(y) - pi/2]])
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
# 处理单个数值或符号
if expr.is_number:
z = complex(expr)
"""计算位移正弦积分 Si(x) - π/2,仅处理数值标量输入。"""
si, _ = sici(z) # 仅取正弦积分部分
result = si - np.pi / 2
elif expr.free_symbols:
"""计算位移正弦积分 Si(x) - π/2,根据输入类型返回数值或符号表达式。"""
result = Si(expr) - pi / 2
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# 示例测试
if __name__ == "__main__":
# 数值输入
print(shifted_sine_integral('2'))
# (0.03461665000779801-0j)
# 符号输入
print(shifted_sine_integral('x'))
# Si(x) - pi/2
stairs(Y) 绘制 Y 中元素的阶梯图.
如果Y为矩阵,则stairs为每个矩阵列绘制一个线条
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.interpolate import interp1d
def stair_wave(input_str):
"""
对标 MATLAB 的 stairs 函数,生成阶梯图数据。
参数:
input_str: 输入的字符串,可以表示:
- 数值矩阵(视为 Y 值,X 自动生成)
- 符号表达式(如 'sin(x)',需配合 x_range 使用)
x_range: 符号表达式时 X 的取值范围,格式为 (start, stop, num_points)
返回:
- 成功时返回 (x_out, y_out) 的 NumPy 数组
- 错误时返回错误消息字符串
示例:
>>> x, y = stair_wave('[[1, 2, 3], [4, 5, 6]]') # 输入二维矩阵
>>> x, y = stair_wave('sin(x)', x_range=(0, 2*np.pi, 100)) # 符号表达式
"""
try:
# 尝试将输入解析为 SymPy 表达式或矩阵
expr = sp.sympify(input_str)
x_out, y_out = None, None
error = False
# Continuous data
NUM = 1000 # modify the number of points you want
if isinstance(expr, list):
# 如果 expr 是一个矩阵,则将其转换为 NumPy 数组并展平
x = np.array(expr, dtype=float).ravel()
# 这里 y 的计算暂时写为 np.sin(x),实际使用时 y 需要根据具体需求输入,例如 0.5*cos(x)
y = np.sin(x)
# 对 y 进行累加操作
y = np.cumsum(y)
# 初始化 x=0 时的 y 值
y0 = np.array([0])
# 通过插值计算 y=0 时对应的 x 值
x0 = np.interp([0], y, x)
# 将 x0 与原 x 数组拼接
x = np.concatenate([x0, x])
# 将 y0 与原 y 数组拼接
y = np.concatenate([y0, y])
# 使用 'next' 方式进行插值,创建插值函数
funct = interp1d(x, y, kind='next')
# 生成连续的 x 值
x_cont = np.linspace(x[0], x[-1], NUM)
# 通过插值函数计算对应的连续 y 值
y_cont = funct(x_cont)
elif expr.free_symbols:
# 如果输入是符号表达式,默认生成 0 到 4π 之间的 50 个 x 值
x_values = np.linspace(0, 4 * np.pi, 50)
# 如果 expr 是一个 SymPy 表达式,则执行相应的操作
if variables := expr.free_symbols:
# 将 SymPy 表达式转换为可以在 NumPy 中计算的函数
expression_func = sp.lambdify(tuple(variables), expr, modules=['numpy'])
# 计算 y
y = expression_func(x_values)
else:
# 如果没有自由变量,直接将 expr 作为 y
y = expr
# 对 y 进行累加操作
y = np.cumsum(y)
# 初始化 x=0 时的 y 值
y0 = np.array([0])
# 通过插值计算 y=0 时对应的 x 值
x0 = np.interp([0], y, x_values)
# 将 x0 与原 x 数组拼接
x_values = np.concatenate([x0, x_values])
# 将 y0 与原 y 数组拼接
y = np.concatenate([y0, y])
# 使用 'next' 方式进行插值,创建插值函数
funct = interp1d(x_values, y, kind='next')
# 生成连续的 x 值
x_cont = np.linspace(x_values[0], x_values[-1], NUM)
# 通过插值函数计算对应的连续 y 值
y_cont = funct(x_cont)
else:
# 如果 expr 不是矩阵也不是 SymPy 表达式,则抛出错误或者执行其他操作
error = True
return x_cont, y_cont if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# 示例测试
if __name__ == "__main__":
# 示例 : 符号表达式输入
x, y = stair_wave('sin(x)')
print("符号表达式采样:", x[:5], y[:5])
# [0. 0.01257895 0.0251579 0.03773685 0.0503158 ]
# [0. 0.25365458 0.25365458 0.25365458 0.25365458]
插入标准缺失值
B = standardizeMissing(A,indicator) 用 A 中的标准缺失值替换 indicator 中指定的值,并返回一个标准化数组
A — 输入数据,向量,矩阵
indicator — 非标准缺失值指示符,标量
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from ast import literal_eval # 用于安全解析元组
def standardize_missing(input_str):
"""
对标 MATLAB 的 standardizeMissing 函数,将指定值替换为标准缺失值 NaN
参数:
input_str: 输入的字符串,格式应为 "(matrix, indicator)",其中:
- matrix: 数值矩阵(支持嵌套列表或 SymPy 矩阵)
- indicator: 要替换的值(数值或列表)
返回:
SymPy 矩阵 或 错误信息字符串
示例:
>>> standardize_missing("([[1, 0], [3, -999]], -999)")
Matrix([[1, 0], [3, nan]])
>>> standardize_missing("([5, 2, 888, 4], [2, 888])")
Matrix([[5, nan, nan, 4]])
"""
try:
# 安全解析输入字符串为Python对象
parsed = literal_eval(input_str.strip())
# 验证输入格式是否为 (matrix, indicator)
if not (isinstance(parsed, tuple) and len(parsed) == 2):
return "输入错误: 必须为 (matrix, indicator) 格式的元组"
matrix, indicator = parsed
# 转换输入矩阵为SymPy矩阵
sp_matrix = sp.Matrix(matrix) if isinstance(matrix, list) else None
if sp_matrix is None:
return "输入错误: 无法解析矩阵数据"
# 验证矩阵是否为纯数值型
if sp_matrix.is_symbolic():
return "错误: 矩阵包含符号元素,仅支持数值矩阵"
# 转换指示符为NumPy数组形式
indicators = np.array([indicator]).flatten() if np.isscalar(indicator) else np.array(indicator)
# 转换为NumPy数组进行操作
np_matrix = np.array(sp_matrix.tolist(), dtype=float)
# 创建掩码矩阵(True表示需要替换的位置)
mask = np.isin(np_matrix, indicators)
# 替换目标值为NaN
np_matrix[mask] = np.nan
# 转换回SymPy矩阵
if sp_matrix.shape[1] == 1:
return sp.Matrix(np_matrix).T
else:
return sp.Matrix(np_matrix)
except SyntaxError:
return "语法错误: 输入格式应为有效的Python元组表达式"
except ValueError as ve:
return f"数值转换错误: {ve}"
except Exception as e:
return f"未处理的异常: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 测试用例1:替换单个值
test1 = "([[1, 0], [3, -999]], -999)"
print(f"测试1输入: {test1}")
print("测试1输出:", standardize_missing(test1))
# Matrix([[1.00000000000000, 0],
# [3.00000000000000, nan]])
# 测试用例2:替换多个值
test2 = "([5, 2, 888, 4], [2, 888])"
print(f"\n测试2输入: {test2}")
print("测试2输出:", standardize_missing(test2))
# Matrix([[5.00000000000000, nan, nan, 4.00000000000000]])
标准差
S = std(A) 返回数组元素的标准偏差,即分布范围的度量.默认情况下,标准偏差是为展开的阵列计算的,否则是在指定的轴上计算的.
S = std(A,dim). 计算标准偏差的一个或多个轴.默认情况是计算展平阵列的标准偏差.
dim=0,计算以列为单位的标准差.
dim=1,计算以行为单位的标准差.
A - 输入数组,向量,矩阵
dim - 沿其运算的维度
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
def standard_deviation_array(input_str, ddof=1):
"""
对标 MATLAB 的 std 函数,精确处理向量和矩阵输入
参数:
input_str: 输入字符串,格式支持:
- "matrix" : 直接输入矩阵
- "(matrix, dim)" : 矩阵+维度(1=列方向,2=行方向)
ddof: 自由度调整(默认1对应无偏估计)
返回:
- 标量(向量输入或整体计算)
- 列表(矩阵按列/行计算)
- 错误信息字符串
示例:
>>> standard_deviation_array("[1, 2, 3, 4]") # 向量输入
1.118033988749895
>>> standard_deviation_array("[[1,2],[3,4]]") # 矩阵默认按列
[1.0, 1.0]
>>> standard_deviation_array("([[1,2],[3,4]], 2)") # 按行计算
[0.7071, 0.7071]
"""
try:
# 解析输入
parsed = sp.sympify(input_str)
matrix_data, dim = (parsed if isinstance(parsed, tuple)
else (parsed, None))
# 验证矩阵有效性
sp_matrix = sp.Matrix(matrix_data) if isinstance(matrix_data, list) else None
if not sp_matrix or sp_matrix.is_symbolic():
return "无效矩阵输入" if not sp_matrix else "仅支持数值矩阵"
# 转换为 NumPy 数组
np_matrix = np.array(sp_matrix.tolist(), dtype=float)
original_shape = np_matrix.shape
# 自动识别向量并展平
if np_matrix.ndim == 2 and min(np_matrix.shape) == 1:
np_matrix = np_matrix.ravel()
# 计算维度处理
if dim is None:
# 智能维度判断
if np_matrix.ndim == 1:
axis = None # 向量计算整体
else:
axis = 0 # 矩阵默认按列
else:
axis = int(dim) - 1 # MATLAB 转 NumPy 轴
# 执行标准差计算
result = np.std(np_matrix, axis=axis, ddof=ddof)
# 标准化输出格式
if isinstance(result, np.ndarray):
return np.around(result.tolist(), 4) if result.ndim == 1 else result.tolist()
else:
return float(np.around(result, 4))
except Exception as e:
return f"错误: {str(e)}"
# 验证测试
if __name__ == "__main__":
# 测试1: 行向量输入
print(standard_deviation_array("[[1, 2, 3, 4]]"))
# 1.291
# 测试2: 列向量输入
print(standard_deviation_array("[[1], [2], [3], [4]]"))
# 1.291
# 测试3: 4x3矩阵按列
test_data = "[[1,5,9], [2,6,10], [3,7,11], [4,8,12]]"
print(standard_deviation_array(test_data))
# [1.291 1.291 1.291]
# 测试4: 同上矩阵按行
print(standard_deviation_array(f"({test_data}, 2)"))
# [4. 4. 4. 4.]
阶跃响应图
stepplot(sys) 可视化系统对单位阶跃输入(Unit Step Input)的动态响应.
单位阶跃输入在时间 t = 0时从 0 突然跳变到 1(例如,一个开关的瞬时开启)。
阶跃响应图显示了系统输出随时间的变化,帮助我们分析系统的稳定性、速度、准确性等性能指标。
一阶系统(无振荡):
类似 RC 电路充电过程(如电容器电压响应)
阶跃响应特性:
无超调(单调上升)
上升时间:约 1.15 秒(从 10% 到 90% 稳态值)
调节时间:约 4 秒(±2% 准则)
稳态值:2.5(因为 G(0) = 5/2 = 2.5G(0)=5/2=2.5)
stepplot(5,s+2)
二阶欠阻尼系统(有振荡):
弹簧-质量-阻尼系统的振荡响应(如汽车悬架)
阶跃响应特性:
超调量:约 16.3%(因阻尼比 \zeta = 0.316ζ=0.316)
上升时间:约 0.55 秒
峰值时间:约 1.05 秒
调节时间:约 4 秒(±2% 准则)
稳态值:1(因为 G(0) = 10/10 = 1G(0)=10/10=1)
stepplot(10,s^2+2s+10)
二阶临界阻尼系统(最快无振荡):
门关闭装置的理想响应(快速且无反弹)
阶跃响应特性:
无超调(单调上升)
上升时间:约 1.17 秒
调节时间:约 2.4 秒(±2% 准则)
稳态值:1(因为 G(0) = 9/9 = 1G(0)=9/9=1)
stepplot(9,s^2+6s+9)
高阶系统(含振荡和延迟效应):
带滤波器的电机位置控制系统
阶跃响应特性:
超调量:约 8%
调节时间:约 8 秒
稳态值:0.4(因为 G(0) = 2/5 = 0.4G(0)=2/5=0.4)
stepplot(s+2,s^3+5s^2+9s+5)
质量-弹簧-阻尼系统(机械工程)
汽车减震器设计、建筑抗震分析。
阶跃响应特性:
输入:突加 1 N 的恒定力(阶跃力)
输出:物体位移
超调量 ≈ 15%(轻微振荡)
调节时间 ≈ 4 秒
stepplot(1,0.5s^2+1.2s+8)
水箱液位控制系统(过程控制)
化工生产中的液位调节,需避免溢出。
阶跃响应特性:
输入:进水流量阶跃增加(如 0→2 m³/s)
输出:液位高度(稳态值 = 1 m)
上升时间 ≈ 11 秒(缓慢上升,无超调)
stepplot(2,5s+1)
直流电机位置控制(机电系统)
机器人关节定位,要求精确无振荡。
阶跃响应特性:
输入:目标角度阶跃(如 0→90°)
输出:实际转子角度
稳态值 = 90°(无稳态误差)
上升时间 ≈ 1.2 秒(单调上升)
stepplot(3,s*(s+4))
RLC带通滤波器(电子工程):
通信系统中提取高频信号。
阶跃响应特性:
输入:电压阶跃(0→1 V)
输出:电阻两端电压
初始峰值 ≈ 0.8 V(快速响应)
稳态值 = 0(高通特性)
stepplot(0.6s,s^2+0.7s+1)
疫情传播模型(流行病学)
预测隔离政策对感染峰值的影响。
阶跃响应特性:
输入:突现 1 名感染者(阶跃输入)
输出:累计感染比例
峰值感染率 ≈ 20%(超调)
稳定时间 ≈ 30 天
stepplot(0.05,s^2+0.3s+0.05)
股票市场反应模型(金融)
量化交易中事件驱动策略的回测。
阶跃响应特性:
输入:消息公布(阶跃事件)
输出:股价变动
初始过冲 ≈ +15%(投机泡沫)
稳态值 = +100%(最终合理估值)
stepplot(-0.2s+1,s^2+0.5s+1)
卫星姿态控制(航空航天):
太空望远镜精密指向控制。
阶跃响应特性:
输入:目标角度阶跃(如 0→10°)
输出:实际俯仰角
稳态误差 = 0(积分作用)
超调 ≈ 35%(需优化阻尼)
stepplot(100,s^2*(s+10))
机械减震系统
观察车身振动的超调量、稳定时间,优化舒适性。
汽车悬架系统,输入为路面阶跃冲击(如突然遇到障碍物),输出为车身垂直位移。
分母 s² + 2s + 5 对应质量-弹簧-阻尼系统
s² 项:质量惯性(m)
2s 项:阻尼系数(c)
5:弹簧刚度(k)
stepplot([1],[1,2,5])
温度控制系统
分析水温上升的延迟和稳态时间,避免过热风险。
电热水壶的加热系统,输入为阶跃电压(突然通电),输出为水温。
分母 3s + 1 表示一阶惯性:
3:热容(C)与热阻(R)的乘积(时间常数 τ = RC)
stepplot([1],[3,1])
直流电机调速
检查转速是否快速跟踪指令(上升时间短),且无振荡(超调小)。
电机转速控制,输入为阶跃电压,输出为转速。
分母 s² + 4s + 8 包含: 电感(L)、电阻(R)、反电动势(K)的耦合效应
stepplot([1],[1,4,8])
化学反应釜浓度控制
评估浓度超调是否导致副产物超标,调整进料策略。
反应物输入流量阶跃增加,输出为产物浓度。
三阶系统(s³项)反映多级混合/反应延迟。
stepplot([1],[1,3,3,1])
生态系统种群模型
预测种群是否稳定或震荡,指导生态干预。
突然引入食物资源(阶跃输入),输出为物种数量(如鱼类)。
低阻尼(0.5s项小)易引发振荡(数量暴涨后崩溃)。
stepplot([1],[1,0.5,0.1])
叠加阶跃响应图
stepplot([sys1],[sys2]...[sysN]) 是在同一坐标系中绘制多个系统对单位阶跃输入的响应曲线,用于直观比较不同系统的动态性能。
不同阻尼比的弹簧系统:
质量相同的弹簧系统,阻尼系数递增。
stepplot([1,s^2+0.5s+1], # ζ=0.25 (欠阻尼)
[1,s^2+s+1], # ζ=0.5 (最佳阻尼)
[1,s^2+2s+1]) # ζ=1.0 (临界阻尼)
电路滤波器性能对比
电子滤波器对电压阶跃的响应
stepplot([1,s+1], # 一阶低通
[s,s^2+s+1], # 带通
[1,0.1s^2+0.3s+1]) # 二阶快速响应
温度控制器增益对比
恒温箱加热系统(时间常数5秒)
stepplot([0.5,5s+1], # 低增益
[1,5s+1], # 中增益
[2,5s+1]) # 高增益
无人机高度控制器
stepplot([4,s^2+0.8s+4], # 标准
[6,s^2+1.2s+6], # 高刚度
[3,s^2+0.4s+3]) # 低阻尼
机械臂关节定位精度
stepplot([1,s^2+3s], # PD控制
[s+1,s^3+3s^2+2s], # PID控制
[0.5,s^2+2s+1]) # 简化模型
流线图
StreamPlot(expression)绘制一系列平滑的、永不交叉的曲线(即“流线”)来描绘二维向量场的图像。
1:流体力学 - 一个点源(水龙头滴下一滴水)
想象在原点有一个水龙头,水均匀地向四面八方流出去。
画图范围:x从-2到2,y从-2到2(注意避开原点x=0, y=0,因为那里分母为零)。
它像什么:所有流线都是从原点(源点)直接向外发射的直线。
StreamPlot(x/(x^2+y^2),y/(x^2+y^2),x=[-2,2],y=[-2,2])
2:流体力学 - 一个涡旋(水池排水时形成的漩涡)
想象原点是一个排水口,水在旋转着流下去。
画图范围:x从-2到2,y从-2到2(同样避开原点)。
它像什么:所有流线都是围绕原点旋转的圆圈,形成一个涡旋。
StreamPlot(x/(x^2+y^2),-y/(x^2+y^2),x=[-2,2],y=[-2,2])
3:电磁学 - 一个偶极子(一个正电荷和一个负电荷靠在一起)
就像一根磁铁或一个电荷对的磁场/电场。
画图范围:x从-2到2,y从-1到1。
它像什么:流线从正电荷(源)出发,弯曲地连接并终止于负电荷(汇)。
StreamPlot((x+0.5)/(((x+0.5)^2+y^2 )^1.5)-(x-0.5)/(((x-0.5)^2+y^2)^1.5),y/(((x+0.5)^2+y^2)^1.5)-y/(((x-0.5)^2+y^2)^1.5),x=[-2,2],y=[-1,1])
4:理论模型 - saddle点(鞍点)
这是一个非常基础但又重要的场结构,像一个山口。
画图范围:x从-2到2,y从-2到2。
它像什么:流线沿着x轴向外散开,沿着y轴向内收拢。原点(0,0)这个点就叫做saddle点(鞍点),它既不是源也不是汇,是不稳定点。
StreamPlot(x,-y,x=[-2,2],y=[-2,2])
5:最简单的函数 F(z) = z
表达式:F(z) = z = x + i*y
对应的向量场:( u, v ) = ( x, y )
流线图分析:
这是一个标准的源(Source)。
所有点的向量都从原点指向外。
离原点越远,向量长度(模)越大。
这类似于一个水龙头向平静的水面滴水形成的流场。
StreamPlot(z,z=[-2-2@i,2+2@i])
6:F(z) = i * z (乘以虚数单位 i)
表达式:F(z) = i * (x + i*y) = -y + i*x
对应的向量场:( u, v ) = ( -y, x )
流线图分析:
这是一个纯粹的涡旋(Vortex)。
所有流线都是围绕原点的同心圆。
向量方向永远垂直于该点与原点的连线。
这类似于水池排水时形成的漩涡。
StreamPlot(z*1@i,z=[-2-2@i,2+2@i])
7:F(z) = z^2
表达式:F(z) = (x + i*y)^2 = (x^2 - y^2) + i*(2*x*y)
对应的向量场:( u, v ) = ( x^2 - y^2, 2*x*y )
流线图分析:
这个场看起来会比前两个复杂。
沿着 x 轴 (y=0) 和 y 轴 (x=0) 看,场的方向很好判断。
你会看到两个“源”或“汇”挤压在一起形成的复杂图案,流线是双曲线形状。它在原点是一个鞍点(Saddle Point)。
StreamPlot(z^2,z=[-2-2@i,2+2@i])
8:F(z) = 1 / z
表达式:F(z) = 1 / (x + i*y) = (x - i*y) / (x^2 + y^2)
对应的向量场:( u, v ) = ( x / (x^2+y^2), -y / (x^2+y^2) )
流线图分析:
这是源和涡旋的叠加!
实部 x/(r^2) 代表一个源。
虚部 -y/(r^2) 代表一个涡旋。
最终的流线是从原点出发,同时向外且旋转的螺旋线。
这在物理上对应着一个偶极子(Dipole)的场,但带有旋转效应。原点 z=0 是奇点。
StreamPlot(1/z,z=[-2-2@i,2+2@i])
9:F(z) = exp(z) (指数函数)
表达式:利用欧拉公式 exp(x + i*y) = exp(x) * (cos(y) + i*sin(y))
对应的向量场:( u, v ) = ( exp(x)*cos(y), exp(x)*sin(y) )
流线图分析:
这个场在 y 方向是周期性的(因为包含 cos(y) 和 sin(y))。
沿着任意一条水平线 (y = constant),场的强度 |F| = exp(x) 随着 x 增大而指数增长。
流线图会呈现出周期性重复的、从左向右发散的图案。
StreamPlot(exp(z),z=[-2-2@i,2+2@i])
根据常见的子表达式重写符号表达式
[r,sigma] = subexpr(expr)根据公共子表达式重写符号表达式expr,用符号变量sigma替换该公共子表达式. 输入表达式expr不能包含变量sigma.
expr —— 包含常见子表达式的长表达式,符号表达,符号功能
r —— 用缩写替换普通子表达式的表达式,符号表达,符号功能
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def subexpression_common_elimination(input_str):
"""
对标 MATLAB 的 subexpr 函数,通过公共子表达式重写符号表达式
Args:
input_str: 可解析为矩阵或符号表达式的字符串
Returns:
成功时返回元组 (替换规则列表, 简化后的表达式)
失败时返回错误描述字符串
Examples:
>>> subexpression_common_elimination("[[x + y, (x + y)**2], [exp(x + y), 1/(x + y)]]")
([(x0, x + y)], Matrix([
[ x0, x0**2],
[exp(x0), 1/x0]]))
>>> subexpression_common_elimination("sin(a) + sqrt(a) + a**2")
([(x0, a)], sin(x0) + sqrt(x0) + x0**2)
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
if expr.free_symbols:
R, sigma = sp.cse(expr)
result = R, sigma
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误:{e}"
# 示例测试
if __name__ == "__main__":
# 矩阵测试用例
test_cases = [
"sin(a) + sqrt(a) + a^2",
# [sqrt(a) + a**2 + sin(a)]
]
for case in test_cases:
print(f"\n输入: {str(case)[:50]}...")
result = subexpression_common_elimination(str(case)) # 统一转换为字符串
if isinstance(result, tuple):
print("替换规则:", result[0])
print("简化表达式:", result[1])
else:
print("错误输出:", result)
两个子空间之间的角度
theta = subspace(A,B) 计算 A 和 B 的列指定的两个子空间之间的角度. 如果 A 和 B 是单位长度的列向量, 则此角度与 acos(abs(A'*B)) 相同
A, B —— 输入矩阵, 向量
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.linalg import svd
def subspace_angle(A, B):
"""
计算两个子空间之间的最大主角度(单位:弧度)
参数:
A, B (np.ndarray): 数值矩阵,每一列代表子空间的基向量
返回:
float: 两个子空间之间的夹角(弧度制)
算法说明:
1. 对两个矩阵进行QR分解获得正交基
2. 计算正交基的乘积矩阵的奇异值
3. 最大主角度由最小奇异值的反余弦确定
"""
# 处理空矩阵情况
if A.size == 0 or B.size == 0:
raise ValueError("输入矩阵不能为空")
# 进行QR分解获得正交基(reduced模式)
Q_A, _ = np.linalg.qr(A, mode='reduced')
Q_B, _ = np.linalg.qr(B, mode='reduced')
# 计算正交基的乘积
C = np.dot(Q_A.T, Q_B)
# 计算奇异值(降序排列)
_, s, _ = svd(C)
# 处理数值误差:将大于1的值截断为1
s = np.clip(s, 0.0, 1.0)
# 最大主角度由最小奇异值确定
return np.arccos(s.min()) if s.size > 0 else np.pi / 2
def subspace_arch_matrix(input_str):
"""
计算两个矩阵列空间之间的最大主角度(对标MATLAB subspace函数)
参数:
input_str (str): 输入字符串,格式应为包含两个矩阵的元组
示例:'([[1,0], [0,1]], [[1,1], [1,1]])'
返回:
float: 子空间夹角(弧度)或错误信息字符串
"""
try:
# 将输入字符串转换为SymPy表达式
expr = sp.sympify(input_str)
# 验证输入格式是否为二元组
if not (isinstance(expr, tuple) and len(expr) == 2):
return f"输入格式错误:需要两个矩阵组成的元组,但收到 {input_str}"
# 转换矩阵
matrix_A = sp.Matrix(expr[0]) if isinstance(expr[0], list) else None
matrix_B = sp.Matrix(expr[1]) if isinstance(expr[1], list) else None
# 验证矩阵有效性
if matrix_A is None or matrix_B is None:
return "输入包含无效矩阵,请检查格式是否正确(例如:[[1,0],[0,1]])"
# 转换为数值矩阵
A = np.array(matrix_A.tolist(), dtype=float)
B = np.array(matrix_B.tolist(), dtype=float)
# 验证矩阵维度
if A.shape[0] != B.shape[0]:
return f"矩阵行数不匹配:矩阵A有{A.shape[0]}行,矩阵B有{B.shape[0]}行"
return subspace_angle(A, B)
except Exception as e:
return f"计算错误:{str(e)}"
# --------------------------
# 示范用例
# --------------------------
if __name__ == "__main__":
# 测试用例1:相同子空间
test_case1 = '([[1,0], [0,1]], [[1,0], [0,1]])'
print(f"测试用例1: {test_case1}")
angle = subspace_arch_matrix(test_case1)
print(f"结果: {angle:.4f} 弧度 ({np.degrees(angle):.1f} 度)\n")
# 0.0000 弧度 (0.0 度)
# 测试用例2:正交子空间
test_case2 = '([[1,0], [0,0]], [[0,0], [0,1]])' # A的列空间是x轴,B的列空间是y轴
print(f"测试用例2: {test_case2}")
angle = subspace_arch_matrix(test_case2)
print(f"结果: {angle:.4f} 弧度 ({np.degrees(angle):.1f} 度)\n")
# .0000 弧度 (0.0 度)
# 测试用例3:45度夹角
test_case3 = '([[1], [0]], [[1], [1]])' # A为x轴,B为y=x线
print(f"测试用例3: {test_case3}")
angle = subspace_arch_matrix(test_case3)
print(f"结果: {angle:.4f} 弧度 ({np.degrees(angle):.1f} 度)\n")
# 0.7854 弧度 (45.0 度)
# 测试用例4:三维空间中的斜交子空间
test_case4 = '([[1,0], [0,1], [0,0]], [[1,1], [1,1], [0,0]])' # 列空间平面与另一平面夹角
print(f"测试用例4: {test_case4}")
angle = subspace_arch_matrix(test_case4)
print(f"结果: {angle:.4f} 弧度 ({np.degrees(angle):.1f} 度)\n")
# 输出: 0.0000 弧度 (0.0 度)
三维曲面法向量
vect1, -vect1 = surfnorm(function,varlist,point) 计算并得到在特定点处的曲面的正负法向量,这些向量表示曲面在该点处的垂直方向,分别朝向曲面内外.
这些向量对于理解曲面的几何性质,绘制曲面的法线图以及进行物理模拟都非常有用.
function -- 曲面函数
varlist -- 曲面函数的变量
point -- 曲面上的特定坐标点
vect1, vect2 -- 向量.
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def surface_normal_expression(input_str):
"""
计算三维曲面在指定点处的法向量表达式
参数:
input_str (str): 输入字符串,应为格式 ('函数', (变量1,变量2,变量3), (点坐标1,点坐标2,点坐标3)) 的合法 SymPy 表达式
示例: '(x**2 + y**2 + z**2, (x,y,z), (1,0,0))'
返回:
tuple: 包含正负两个法向量的元组,格式为 (正向单位法向量, 负向单位法向量)
或返回错误信息字符串
注意:
1. 法向量通过计算函数梯度后归一化得到
2. 梯度向量指向函数增长最快的方向,即曲面的正向法向量
3. 若输入格式错误或计算过程中出现异常,返回错误描述
"""
try:
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
error = False
result = None
# 检查是否为三元组结构 (函数, 变量元组, 点坐标元组)
if isinstance(expr, tuple) and len(expr) == 3:
# 解析表达式各部分
func = expr[0] # 曲面函数表达式
variables = expr[1] # 变量元组 (如 (x,y,z))
point_values = expr[2] # 求值点坐标元组 (如 (1,0,0))
# 创建变量到点值的映射字典
substitution_dict = {var: val for var, val in zip(variables, point_values)}
# 计算各变量的偏导数(梯度分量)
gradient_components = [sp.diff(func, var) for var in variables]
# 在指定点代入求值梯度向量
gradient_vector = sp.Matrix([comp.subs(substitution_dict) for comp in gradient_components])
# 计算梯度向量的模长
gradient_magnitude = gradient_vector.norm()
# 处理零梯度异常情况
if gradient_magnitude == 0:
return "错误:梯度为零向量,无法计算法向量"
# 计算单位法向量(正向)
unit_normal_vector = gradient_vector / gradient_magnitude
# 返回正负两个方向的法向量
result = (unit_normal_vector, -unit_normal_vector)
else:
error = True
return result if not error else f"输入格式错误: 需要 (函数, 变量元组, 点坐标元组) 格式,但收到 {input_str}"
except Exception as e:
return f"计算错误: {str(e)}"
# --------------------------
# 示范用例
# --------------------------
if __name__ == "__main__":
# 测试用例1:标准球面函数
test_case1 = '(x**2 + y**2 + z**2, (x,y,z), (1,0,0))'
print("测试用例1:", test_case1)
print("结果:", surface_normal_expression(test_case1))
# (Matrix([[1],
# [0],
# [0]]),
# Matrix([[-1],
# [ 0],
# [ 0]]))
# 测试用例2:平面函数
test_case2 = '(2*x + 3*y + 4*z, (x,y,z), (5,-2,1))'
print("\n测试用例2:", test_case2)
print("结果:", surface_normal_expression(test_case2))
# (Matrix([[2*sqrt(29)/29],
# [3*sqrt(29)/29],
# [4*sqrt(29)/29]]),
# Matrix([[-2*sqrt(29)/29],
# [-3*sqrt(29)/29],
# [-4*sqrt(29)/29]]))
# 测试用例3:变量与点值数量不匹配
test_case3 = '(x**2 + y**2, (x,y,z), (1,2))'
print("\n测试用例4:", test_case3)
print("结果:", surface_normal_expression(test_case3))
# (Matrix([[ sqrt(5)/5],
# [2*sqrt(5)/5],
# [ 0]]),
# Matrix([[ -sqrt(5)/5],
# [-2*sqrt(5)/5],
# [ 0]]))
奇异值分解
U, S, V = svd(A)
U - 左奇异向量组成的矩阵
S - 奇异值组成的对角矩阵
V - 右奇异向量组成的矩阵
A - 输入, 矩阵.
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.linalg import svd as scipy_svd
def singular_values_matrix(input_str):
"""
执行完整的奇异值分解,对标MATLAB的svd函数
参数:
input_str: 字符串形式的矩阵输入
返回:
当输入为数值矩阵时:
U: 左奇异向量矩阵 (m x m)
S: 奇异值对角矩阵 (m x n)
V: 右奇异向量矩阵 (n x n)
当输入包含符号时返回符号解
错误时返回字符串提示
"""
try:
# 符号解析输入
expr = sp.sympify(input_str)
# 输入有效性验证
if isinstance(expr, tuple):
return "错误:不接受元组输入,请输入单个矩阵"
A = sp.Matrix(expr) if isinstance(expr, list) else None
if A is None:
return "错误:输入不是有效矩阵"
# 符号矩阵的特殊处理
try:
# 尝试符号计算SVD
U, S, V = A.singular_value_decomposition()
return (U.evalf(), sp.diag(*S).evalf(), V.evalf())
except NotImplementedError:
# 符号方法失败时转数值计算
np_A = np.array(A, dtype=float)
U_np, S_np, Vt_np = scipy_svd(np_A, full_matrices=True)
return (sp.Matrix(U_np).evalf(),
sp.Matrix(np.diag(S_np)).evalf(),
sp.Matrix(Vt_np.T).evalf())
except Exception as e:
return f"分解错误: {str(e)}"
# 示范代码
if __name__ == "__main__":
# 示例1:标准数值矩阵
case1 = "[[1, 2], [3, 4], [5, 6]]"
print("案例1 (3x2数值矩阵):")
result1 = singular_values_matrix(case1)
if isinstance(result1, tuple):
print("U:\n", result1[0])
# Matrix([[0.883461017698525, 0.229847696400071],
# [0.240782492132547, 0.524744818760294],
# [-0.401896033433432, 0.819641941120516]])
print("S:\n", result1[1])
# Matrix([[0.514300580658644, 0, 0, 0],
# [0, 0, 0, 0],
# [0, 0, 0, 0],
# [0, 0, 0, 9.52551809156511]])
print("V:\n", result1[2])
# Matrix([[-0.784894453267052, 0.619629483829340],
# [0.619629483829340, 0.784894453267052]])
else:
print(result1)
# 示例2:符号矩阵测试
case2 = "[[x, 0], [0, y]]"
print("\n案例2 (符号矩阵):")
print(singular_values_matrix(case2))
# (Matrix([[x/(x*conjugate(x))**0.5, 0],
# [ 0, y/(y*conjugate(y))**0.5]]),
# Matrix([[(x*conjugate(x))**0.5, 0, 0, 0],
# [ 0, 0, 0, 0],
# [ 0, 0, 0, 0],
# [ 0, 0, 0, (y*conjugate(y))**0.5]]),
# Matrix([[1.0, 0],
# [ 0, 1.0]]))
添加数据后修改SVD
[U1,S1,V1] = svdappend(U,S,V,D),其中A=U*S*V'是一个现有的奇异值分解(SVD),计算[A D]的SVD,而不显式形成A或[A D].结果相等,四舍五入误差
U,S,V —— 现有SVD因素,矩阵
D —— 要追加的新列或行,向量,矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.linalg import svd
def singular_values_append(input_str):
"""
在追加新数据列后更新SVD分解,对标MATLAB的svdappend功能。
参数:
input_str: 字符串形式的元组,包含四个元素:(U, S, V, D),其中:
- U: 原左奇异向量矩阵
- S: 原奇异值对角矩阵
- V: 原右奇异向量矩阵
- D: 要追加的新数据列(必须与原矩阵列数相同)
返回:
更新后的U_new, S_new, V_new(SymPy矩阵)或错误信息。
"""
try:
expr = sp.sympify(input_str)
error_msg = None
# 输入格式验证
if not isinstance(expr, tuple) or len(expr) != 4:
error_msg = "输入必须为四元组 (U, S, V, D)"
else:
U, S, V, D = expr
U = sp.Matrix(U) if isinstance(U, list) else None
S = sp.Matrix(S) if isinstance(S, list) else None
V = sp.Matrix(V) if isinstance(V, list) else None
D = sp.Matrix(D) if isinstance(D, list) else None
if None in (U, S, V, D):
error_msg = "无效的矩阵输入"
else:
# 转换为NumPy数组进行数值计算
U_np = np.array(U, dtype=float)
S_np = np.array(S, dtype=float)
D_np = np.array(D, dtype=float)
V_np = np.array(V, dtype=float)
# 验证维度一致性
m, k = U_np.shape
s_dim = S_np.shape
if s_dim[0] != s_dim[1] or s_dim[0] != k:
error_msg = "S必须是方阵且与U的列数一致"
elif D_np.shape[0] != m:
error_msg = "D的行数必须与U的行数一致"
elif V_np.shape[1] != k:
error_msg = "V的列数必须与U的列数一致"
if error_msg:
return error_msg
# 增量SVD核心算法
# 步骤1:计算新列在现有列空间的投影
proj = U_np.T @ D_np
# 步骤2:计算正交补分量
D_ortho = D_np - U_np @ proj
# 步骤3:对正交分量进行QR分解
Q, R = np.linalg.qr(D_ortho, mode='reduced')
# 步骤4:构造中间矩阵
K = np.block([[S_np, proj],
[np.zeros((R.shape[0], S_np.shape[1])), R]])
# 步骤5:计算中间矩阵的SVD
Uk, Sk, Vkt = svd(K, full_matrices=False)
# 步骤6:构造新的U和S
U_new = np.hstack((U_np, Q)) @ Uk
S_new = np.diag(Sk)
# 步骤7:构造新的V
V_ext = np.eye(V_np.shape[0] + 1) # 扩展单位矩阵
V_ext[:V_np.shape[0], :V_np.shape[1]] = V_np
V_new = V_ext @ Vkt.T
# 转换回SymPy矩阵并格式化
return (
sp.Matrix(U_new).evalf(chop=True),
sp.Matrix(S_new).evalf(chop=True),
sp.Matrix(V_new).evalf(chop=True)
)
except Exception as e:
return f"错误: {str(e)}"
# 示范代码
if __name__ == "__main__":
# 示例1:有效输入
U = [[1, 0], [0, 1], [0, 0]]
S = [[5, 0], [0, 3]]
V = [[1, 0], [0, 1]]
D = [[2], [3], [4]]
input_str = f"({U}, {S}, {V}, {D})"
result = singular_values_append(input_str)
print("示例1结果:")
if isinstance(result, tuple):
print("U_new:\n", result[0])
# Matrix([[0.707608901615485, 0.700874167360754, 0.0898055893633361],
# [0.493471643807718, -0.581132003549788, 0.647125436996504],
# [0.505742403909574, -0.413595207874290, -0.757075706195349]])
print("S_new:\n", result[1])
# Matrix([[6.23714970083448, 0, 0],
# [0, 4.39365160364841, 0],
# [0, 0, 2.18947235541766]])
print("V_new:\n", result[2])
# Matrix([[0.567253421479376, 0.797598706709882, 0.205085004021905],
# [0.237354401037559, -0.396798874358104, 0.886686834015394],
# [0.788597770810977, -0.454298312084543, -0.414399082418255]])
else:
print(result)
奇异值和向量的子集
s = svds(A) 返回一个向量,其中包含矩阵A的六个最大的奇异值.当使用svd计算所有奇异值的计算量很大时(例如对于大型稀疏矩阵而言),可以使用此函数
s = svds(A,k) 返回k个最大奇异值
A — 输入, 矩阵
k — 要计算的奇异值个数,标量
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.sparse import linalg as sparse_linalg
def singular_values_subset(input_str):
"""
计算矩阵的奇异值子集,对标MATLAB的svds函数。
参数:
input_str: 输入的矩阵或元组(矩阵和奇异值数量k)的字符串表示。
返回:
如果输入有效,返回奇异值的SymPy矩阵(按降序排列);否则返回错误信息。
"""
try:
expr = sp.sympify(input_str)
error = False
U, S, Vt = None, None, None
# 处理元组输入(矩阵和k)
if isinstance(expr, tuple) and len(expr) == 2:
A_expr, k_expr = expr[0], expr[1]
A = sp.Matrix(A_expr) if isinstance(A_expr, list) else None
if A is not None and k_expr.is_integer:
k = int(k_expr)
N_A = np.array(A, dtype=float)
m, n = N_A.shape
max_k = min(m, n) - 1
if max_k <= 0:
max_k = 1
k = min(k, max_k)
U, S, Vt = sparse_linalg.svds(N_A, k)
else:
error = True
# 处理单个矩阵输入,自动确定k
else:
A = sp.Matrix(expr) if isinstance(expr, list) else None
if A is not None:
N_A = np.array(A, dtype=float)
m, n = N_A.shape
max_k = min(m, n) - 1
if max_k <= 0:
max_k = 1
k = min(6, max_k)
U, S, Vt = sparse_linalg.svds(N_A, k)
else:
error = True
if error:
return f"输入错误: {input_str}"
else:
# 将奇异值按降序排列
S_sorted = np.sort(S)[::-1]
return sp.Matrix(S_sorted).evalf()
except Exception as e:
return f"错误: {e}"
# 示范代码
if __name__ == "__main__":
# 示例1:输入矩阵和k值
input1 = "(([[1, 2], [3, 4], [5, 6]]), 1)"
result1 = singular_values_subset(input1)
print(f"示例1结果:\n{result1}")
# Matrix([[9.52551809156511]])
# 示例2:输入矩阵,自动确定k
input2 = "[[1, 2], [3, 4]]"
result2 = singular_values_subset(input2)
print(f"示例2结果:\n{result2}")
# Matrix([[5.46498570421904]
计算低秩矩阵草图的SVD
[U,S,V] = svdsketch(A) 返回输入矩阵A的低秩矩阵草图的奇异值分解(SVD).
[U,S,V] = svdsketch(A,tol) 指定矩阵草图的容差。svdsketch 使用 tol 以自适应方式确定矩阵草图逼近的秩。随着容差变大,矩阵草图中使用的 A 的特征越来越少。
矩阵草图是一种低秩逼近,仅反映A的最重要特征(最大容差). 与使用svds相比,它能够更快地计算大型矩阵的部分SVD.
A — 输入, 矩阵, 指定为稀疏矩阵或满矩阵。A 通常为大型稀疏矩阵,但不总是这样。svdsketch 最适合对特征数量相对较少的秩亏矩阵进行操作。
tol — 矩阵草图容差, eps(class(A))^(1/4) (默认) | 实数标量
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from sklearn.utils.extmath import randomized_svd
def sklearn_randomized_svd(input_str):
"""
对标MATLAB的svdsketch函数,计算低秩矩阵近似SVD
参数:
A: 输入矩阵,支持SymPy矩阵/列表/NumPy数组
tol: 近似容差 (默认1e-10)
max_rank: 最大允许秩 (可选)
random_state: 随机种子 (可选)
返回:
U: 左奇异向量矩阵
S: 奇异值对角矩阵
V: 右奇异向量矩阵
rank: 实际使用的秩
示例:
>>> A = np.random.rand(100, 50)
>>> U, S, V, r = svdsketch(A, tol=1e-5)
"""
try:
# 定义容差,用于后续判断奇异值的截断条件
tol = 1e-10
# 最大秩,初始设为 None,后续会根据矩阵情况确定
max_rank = None
# 随机状态,用于随机化过程的可重复性,初始设为 None
random_state = None
# 错误标志,用于标记是否出现错误情况
error = False
# 将输入字符串转换为 SymPy 表达式
expr = sp.sympify(input_str)
# 检查 expr 是否为元组
if isinstance(expr, tuple):
# 如果元组长度为 4,分别将元素赋值给 A, tol, max_rank, random_state
if len(expr) == 4:
A, tol, max_rank, random_state = expr
# 如果元组长度为 3,分别将元素赋值给 A, tol, max_rank
elif len(expr) == 3:
A, tol, max_rank = expr
# 如果元组长度为 2,分别将元素赋值给 A, tol
elif len(expr) == 2:
A, tol = expr
# 若元组长度不符合上述情况,标记错误
else:
error = True
# 若 expr 不是元组,直接将其赋值给 A
else:
A = expr
# 检查 A 是否为有效的矩阵,如果不是则返回 None
sp_A = sp.Matrix(A) if isinstance(A, list) else None
if sp_A is None:
raise ValueError("无效的矩阵输入")
elif sp_A.is_symbolic():
raise ValueError("需要数值矩阵输入")
else:
np_A = np.array(sp_A, dtype=float)
# 矩阵维度检查
if np_A.ndim != 2:
raise ValueError("输入必须是二维矩阵")
# 自动确定目标秩
m, n = np_A.shape
if max_rank is None:
max_rank = min(m, n) - 1
# 使用自适应随机SVD
rank = min(max_rank, min(m, n))
U, S, Vt = randomized_svd(np_A, n_components=rank,
random_state=random_state)
# 根据容差调整实际秩
sigma_norm = np.linalg.norm(S) # 奇异值的F范数
if sigma_norm > 0:
cumulative = np.cumsum(S[::-1] ** 2)[::-1] # 降序累积平方和
for k in range(len(cumulative)):
if np.sqrt(cumulative[k]) <= tol * sigma_norm:
rank = k
break
rank = max(1, min(rank, max_rank))
# 截断到实际秩
U = U[:, :rank]
S = S[:rank]
Vt = Vt[:rank, :]
if not error:
return U, np.diag(S), Vt.T, rank
except Exception as e:
print(f"计算错误: {e}")
return None, None, None, 0
# 示例代码
if __name__ == "__main__":
# 示例3:数值矩阵测试
try:
C = "[[2, 0], [0, 1]]"
print(sklearn_randomized_svd(C))
# (array([[ 1.00000000e+00],
# [-2.16840434e-19]]),
# array([[2.]]),
# array([[1.],
# [0.]]),
# 1)
except Exception as e:
print(f"示例3 错误捕获: {e}")
求解关于X的西尔维斯特方程AX+XB=C
X=sylvester(A,B,C)将解X返回到sylvester方程.
输入A是一个m乘m矩阵,输入B是一个n乘n矩阵,C和X都是m乘n矩阵.
A,B,C — 输入矩阵
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy import linalg as dense_linalg
def solve_sylvester_equation(A, B, C):
"""
解西尔维斯特方程 AX + XB = C。
参数:
A: 方程中的矩阵A,支持 SymPy 矩阵、列表或 NumPy 数组。
B: 方程中的矩阵B,支持类型同上。
C: 方程中的矩阵C,支持类型同上。
返回:
SymPy 矩阵: 解矩阵X(若成功)。
str: 错误信息(若输入无效或计算失败)。
示例:
>>> A = [[1, 0], [0, 2]]
>>> B = [[3, 1], [1, 4]]
>>> C = [[5, 6], [7, 8]]
>>> solve_sylvester_equation(A, B, C)
Matrix([
[ 1.0, 1.0],
[-1.5, 2.0]])
"""
try:
# 转换为 SymPy 矩阵
A_mat = sp.Matrix(A) if isinstance(A, list) else None
B_mat = sp.Matrix(B) if isinstance(B, list) else None
C_mat = sp.Matrix(C) if isinstance(C, list) else None
if None in (A_mat, B_mat, C_mat):
return "错误: 输入无法转换为有效矩阵"
# 符号检查
if A_mat.is_symbolic() or B_mat.is_symbolic() or C_mat.is_symbolic():
return "错误: 暂不支持符号运算"
# 维度验证
if not A_mat.is_square or not B_mat.is_square:
return "错误: A 和 B 必须是方阵"
if C_mat.rows != A_mat.rows or C_mat.cols != B_mat.rows:
return f"错误: C的维度应为({A_mat.rows}, {B_mat.rows}),实际为({C_mat.rows}, {C_mat.cols})"
# 转换为 NumPy 数组
A_np = np.array(A_mat, dtype=float)
B_np = np.array(B_mat, dtype=float)
C_np = np.array(C_mat, dtype=float)
# 解方程
X_np = dense_linalg.solve_sylvester(A_np, B_np, C_np)
return sp.Matrix(X_np)
except ValueError as ve:
return f"数值错误: {ve}"
except Exception as e:
return f"未知错误: {e}"
if __name__ == "__main__":
# 示例 1: 标准数值解
A = [[1, 0], [0, 2]]
B = [[3, 1], [1, 4]]
C = [[5, 6], [7, 8]]
print("示例1解:\n", solve_sylvester_equation(A, B, C))
# Matrix([[1.00000000000000, 1.00000000000000],
# [1.17241379310345, 1.13793103448276]])
对称近似最小度置换
对称近似最小度置换,对于对称正定矩阵A,命令p=symamd(S)返回置换向量p,因此S(p,p)倾向于比S具有更稀疏的乔列斯基因子.
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
import numpy as np
from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import reverse_cuthill_mckee
def symamd_permutation_vector(input_str):
"""
对标 MATLAB 的 symamd 函数(注意:实际使用 RCM 算法实现带宽优化)。
该函数接受矩阵输入,返回行/列置换向量以优化稀疏性模式。
参数:
input_str: 矩阵的字符串表示(如 "[[1, 2], [3, 4]]")或 SymPy 矩阵。
返回:
置换向量 (numpy数组) 或错误信息字符串。
"""
try:
expr = sp.sympify(input_str)
error = False
result = None
if isinstance(expr, list):
matrix = sp.Matrix(expr)
# 检查矩阵是否包含符号
if matrix.is_symbolic():
return "错误: 矩阵包含符号变量,暂不支持符号运算"
# 转换为 numpy 数组并创建稀疏矩阵
try:
np_matrix = np.array(matrix, dtype=float)
graph = csr_matrix(np_matrix)
# 使用反向 Cuthill-McKee 算法获取置换
# 注意:这里实际使用的是 RCM 算法而非精确的 AMD 算法
result = reverse_cuthill_mckee(graph)
except ValueError as ve:
return f"数值转换错误: {ve}"
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {e}"
# 示范代码
if __name__ == "__main__":
# 示例 1: 数值矩阵
matrix_str = "[[1, 0, 4], [0, 2, 5], [4, 5, 3]]"
permutation = symamd_permutation_vector(matrix_str)
print(f"示例1置换向量: {permutation}")
# [1 2 0]
# 示例 2: 非对称矩阵
non_sym_matrix = "[[1, 2], [3, 4]]"
print(symamd_permutation_vector(non_sym_matrix))
# [1 0]
级数的乘积
F = symprod(f,k,a,b) 返回表达式 f 指定的级数的乘积, 该级数取决于符号变量 k. k 的值范围从 a 到 b. 如果您未指定 k,symprod 将使用 symvar 确定的变量. 如果f是常量, 则默认变量为x.
F = symprod(f,k) 返回表达式 f 指定的级数的乘积, 该级数取决于符号变量 k. k 的值从 1 开始, 上限未指定. 乘积 F 以 k 的形式返回, 其中 k 表示上限. 此乘积 F 与不定乘积不同. 如果您未指定 k, symprod 将使用 symvar 确定的变量. 如果 f 是常量, 则默认变量为 x.
f — 定义级数项的表达式, 符号表达式, 符号函数, 符号向量, 符号矩阵
k — 乘积指数,符号变量
a — 乘积指数的下限, 数, 符号数, 符号变量, 符号表达式, 符号函数
b — 乘积指数的上限, 数, 符号数, 符号变量, 符号表达式, 符号函数
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def symvar_product_series(input_str):
"""
计算符号乘积级数,类似 MATLAB 的 symprod 函数
参数:
input_str: 输入字符串,支持以下格式:
- 普通符号表达式 (例如 "k")
- 矩阵的嵌套列表 (例如 "[[k, 1], [2, 3]]")
- 元组格式,可包含:
* (表达式, 变量) (例如 "(k, k)")
* (表达式, 变量, 下限) (例如 "(k, k, 1)")
* (表达式, 变量, 下限, 上限) (例如 "(k, k, 1, 5)")
* (矩阵, 变量, 下限, 上限) (例如 "(Matrix([[k]]), k, 1, n)")
返回:
SymPy 表达式/矩阵 或 错误消息
示例:
>>> symvar_product_series("k")
Product(k, (k, 1, n))
>>> symvar_product_series("(k, k, 1, 5)")
120
>>> symvar_product_series("([[k, 1], [2, 3]], k, 1, n)")
Matrix([
[Product(k, (k, 1, n)), 1],
[ 2**n, 3**n]])
"""
try:
# 尝试解析输入字符串为Python对象
expr = sp.sympify(input_str)
error = False
result = None
def evaluation_product_series(f_expr, k=None, a=None, b=None):
"""
内部函数:计算乘积级数
参数:
f_expr: 乘积表达式
k: 乘积变量
a: 下限,默认为1
b: 上限,默认为符号n
"""
# 自动确定乘积变量
if f_expr.free_symbols and (k is None):
k = list(f_expr.free_symbols)[0] # 默认取第一个符号
elif k is None:
k = sp.symbols('x') # 默认变量
# 设置默认上下限
a = 1 if a is None else a
b = sp.symbols('n') if b is None else b
return sp.product(f_expr, (k, a, b)).evalf()
# 处理元组输入的情况
if isinstance(expr, tuple):
# 矩阵处理分支 (格式: (矩阵, 变量, 下限, 上限))
if len(expr) >= 4 and isinstance(expr[0], list):
F = sp.Matrix(expr[0])
k_var = expr[1]
lower = expr[2]
upper = expr[3]
# 对矩阵每个元素计算乘积
result = sp.Matrix(F.shape[0], F.shape[1],
lambda i, j: evaluation_product_series(
F[i, j], k_var, lower, upper))
# 普通表达式处理分支 (格式: (表达式, 变量, 下限, 上限))
elif len(expr) >= 4 and expr[0].free_symbols:
f_expr = expr[0]
k_var = expr[1]
lower = expr[2]
upper = expr[3]
result = evaluation_product_series(f_expr, k_var, lower, upper)
# 简写格式处理 (例如 (矩阵, 变量))
elif isinstance(expr[0], list):
F = sp.Matrix(expr[0])
k_var = expr[1]
result = sp.Matrix(F.shape[0], F.shape[1],
lambda i, j: evaluation_product_series(F[i, j], k_var))
# 简写格式处理 (例如 (表达式, 变量))
elif expr[0].free_symbols:
f_expr = expr[0]
k_var = expr[1]
result = evaluation_product_series(f_expr, k_var)
else:
error = True
# 处理矩阵输入
elif isinstance(expr, list):
F = sp.Matrix(expr)
result = sp.Matrix(F.shape[0], F.shape[1],
lambda i, j: evaluation_product_series(F[i, j]))
# 处理普通符号表达式
elif expr.free_symbols:
result = evaluation_product_series(expr)
# 处理纯数值输入
elif expr.is_number:
result = evaluation_product_series(expr)
else:
error = True
return result if not error else f"输入错误: {input_str}"
except Exception as e:
return f"错误: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 普通符号乘积
print(symvar_product_series("k"))
# factorial(n)
# 具体数值范围乘积
print(symvar_product_series("(k, k, 1, 5)"))
# 120.000000000000
# 矩阵乘积
mat_expr = symvar_product_series("([[k, 1], [2, 3]], k, 1, n)")
print(mat_expr)
# Matrix([[factorial(n), 1.00000000000000],
# [2.0**n, 3.0**n]])
符号和(有限或无限)
F = symsum(f,k,a,b)从下界a到上界b,返回级数F相对于求和索引k的符号定和.如果不指定k,symsum将使用symvar确定的变量作为求和索引.如果f是常数,那么默认变量是x.
F = symsum(f,k)返回级数F相对于求和索引k的不定和(反差).f自变量定义级数,使得不定和f满足关系式f(k+1)-f(k)=f(k).如果不指定k,symsum将使用symvar确定的变量作为求和索引.如果f是常数,那么默认变量是x。
f —— 定义级数项的表达式,符号表达式,符号函数,符号向量,符号矩阵,符号数
k —— 求和指数,符号变量
a —— 求和指数的下界,数字,符号数,符号变量,符号表达式,符号函数
b —— 求和指数的上界,数字,符号数,符号变量,符号表达式,符号函数
# Copyright 2025 小塔立软件有限公司及其旗下网站:www.qikjik.com
# Licensed under the MIT License.
import sympy as sp
def symsum(input_str):
"""
对标 MATLAB 的 symsum 函数,计算符号级数和
参数:
input_str: 输入字符串,支持以下格式:
- "f" : 自动选择变量,从1到无穷大
- "(f, k)" : 从k=1到无穷大
- "(f, k, a)" : 从k=a到无穷大
- "(f, k, a, b)" : 从k=a到k=b
- "[[f1, f2], [f3, f4]]" : 矩阵输入
返回:
- 符号表达式结果
- SymPy 矩阵(矩阵输入时)
- 错误信息字符串
示例:
>>> symsum("(k, k, 1, 5)") # Σk from 1到5 → 15
>>> symsum("(1/k^2, k, 1, oo)") # π²/6
>>> symsum("[[k, k^2], [k^3, 1]]") # 矩阵各元素求和
"""
try:
# 安全解析输入字符串
expr = sp.sympify(input_str)
def get_summation(f, k=None, a=1, b=sp.oo):
"""
计算符号级数和
:param f: 被求和的表达式
:param k: 求和变量
:param a: 求和下限
:param b: 求和上限
:return: 符号级数和的结果
"""
if k is None:
if f.free_symbols:
k = tuple(f.free_symbols)[0]
else:
k = sp.symbols('x')
return sp.summation(f, (k, a, b))
if isinstance(expr, tuple):
# 处理元组输入
f = expr[0]
k = expr[1] if len(expr) > 1 else None
a = expr[2] if len(expr) > 2 else 1
b = expr[3] if len(expr) > 3 else sp.oo
if isinstance(f, list):
F = sp.Matrix(f)
# 处理矩阵输入
return sp.Matrix(F.shape[0], F.shape[1], lambda i, j: get_summation(F[i, j], k, a, b))
else:
return get_summation(f, k, a, b)
elif isinstance(expr, list):
F = sp.Matrix(expr)
# 处理矩阵输入,默认从1到无穷大
return sp.Matrix(F.shape[0], F.shape[1], lambda i, j: get_summation(F[i, j]))
else:
# 处理普通表达式输入,默认从1到无穷大
return get_summation(expr)
except SyntaxError:
return "语法错误: 输入格式不正确"
except ValueError as ve:
return f"数值错误: {str(ve)}"
except Exception as e:
return f"未处理的错误: {str(e)}"
# 示例测试
if __name__ == "__main__":
# 测试1: 有限求和
print("Σk from 1到5:", symsum("(k, k, 1, 5)"))
# 15
# 测试2: 无限级数
print("Σ1/k² from 1到∞:", symsum("(1/k**2, k, 1, oo)"))
# pi**2/6
# 测试3: 自动变量选择
print("Σm from 1到∞:", symsum("m"))
# oo
# 测试4: 矩阵输入
print("矩阵求和结果:\n", symsum("[[k, k**2], [k**3, 1/k]]"))
# Matrix([[oo, oo],
# [oo, oo]])