CNC_PYTHON&&CPP联合编程
资料:
- https://pybind11.readthedocs.io/en/stable/advanced/cast/eigen.html
- https://www.cnblogs.com/hyl2018/p/14089299.html
- https://www.yingnd.com/python/105835.html
这篇笔记,记录借助pybind11,python调用eigen库进行KU=F的求解.
准备
- 安装vs2022,选择C++桌面开发;
- 下载eigen源码,https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.zip
- 安装python3.10+,安装numpy,pybind11;
第一步,编写cpp代码
在solve_KUF.cpp
中:
#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <stdexcept>
namespace py = pybind11;
Eigen::VectorXd solveKUF(const Eigen::MatrixXd& A, const Eigen::VectorXd& B) {
// 输入验证
if (A.rows() != A.cols()) {
throw std::invalid_argument("Matrix A must be square");
}
if (A.rows() != B.rows()) {
throw std::invalid_argument("Matrix A and Vector B must have same number of rows");
}
// 转换为稀疏矩阵
Eigen::SparseMatrix<double> sparseA = A.sparseView();
// 使用BiCGSTAB求解器
Eigen::BiCGSTAB<Eigen::SparseMatrix<double>> solver;
solver.compute(sparseA);
if (solver.info() != Eigen::Success) {
throw std::runtime_error("Matrix decomposition failed");
}
Eigen::VectorXd X = solver.solve(B);
if (solver.info() != Eigen::Success) {
throw std::runtime_error("Solving failed");
}
return X;
}
// Pybind11模块定义
PYBIND11_MODULE(solve_KUF, m) {
m.doc() = "Python module for solving sparse linear system AX=B using Eigen";
m.def("solveKUF", &solveKUF,
py::arg("A"), py::arg("B"),
"Solve the linear system AX=B for sparse matrix A and vector B\n"
"Args:\n"
" A: NxN numpy array (sparse matrix in dense format)\n"
" B: Nx1 numpy array\n"
"Returns:\n"
" Solution vector X as numpy array");
}
pybind11支持numpy数组和eigen MatixXd之间的自动转换.
第二步,编写setup.py文件
在setup.py中:
from setuptools import setup, Extension
import pybind11
# 定义扩展模块
ext_modules =Extension(
'solve_KUF',
sources=['solve_KUF.cpp'],
include_dirs=[pybind11.get_include(),
'L:\\EF2D\\includes\\eigen-3.4.0'], # 添加Eigen和pybind11头文件路径
language='c++',
extra_compile_args=['--std=c++17', '--O3'] # 优化标志
)
setup(
name='solve_KUF',
version='0.1',
ext_modules=[ext_modules],
)
第三步,编译
在目录中 执行:
如果出现:build文件夹和solve_KUF.cp310-win_amd64.pyd就 说明编译成功.
第四步,测试
import numpy as np
import solve_KUF
# 创建一个稀疏矩阵的密集表示
N = 5
A = np.zeros((N, N))
np.fill_diagonal(A, 2.0) # 对角线为2
A[0, 1] = 1.0
A[1, 0] = 1.0
# 创建右侧向量
B = np.random.rand(N)
# 求解AX=B
X = solve_KUF.solveKUF(A, B)
print("A:\n", A)
print("\nB:\n", B)
print("\nSolution X:\n", X)
print("\nA @ X (should equal B):\n", A @ X)