vectores multiplicar matriz matrices libreria imprimir elementos ejemplos bidimensionales arreglos array agregar python c++ arrays numpy c-api

matriz - multiplicar matrices python numpy



Enviar una matriz C++ a Python y viceversa(Extender C++ con Numpy) (3)

Voy a enviar una matriz c++ a una función python como numpy array y obtener otra numpy array . Después de consultar con la documentación numpy y algunos otros hilos y ajustar el código, finalmente el código está funcionando, pero me gustaría saber si este código está escrito de manera óptima teniendo en cuenta:

  • Copia innecesaria de la matriz entre c++ y numpy (python) .
  • Corregir la desreferenciación de las variables.
  • Enfoque sencillo y directo.

Código C ++:

// python_embed.cpp : Defines the entry point for the console application. // #include "stdafx.h" #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include "Python.h" #include "numpy/arrayobject.h" #include<iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { Py_SetProgramName(argv[0]); Py_Initialize(); import_array() // Build the 2D array PyObject *pArgs, *pReturn, *pModule, *pFunc; PyArrayObject *np_ret, *np_arg; const int SIZE{ 10 }; npy_intp dims[2]{SIZE, SIZE}; const int ND{ 2 }; long double(*c_arr)[SIZE]{ new long double[SIZE][SIZE] }; long double* c_out; for (int i{}; i < SIZE; i++) for (int j{}; j < SIZE; j++) c_arr[i][j] = i * SIZE + j; np_arg = reinterpret_cast<PyArrayObject*>(PyArray_SimpleNewFromData(ND, dims, NPY_LONGDOUBLE, reinterpret_cast<void*>(c_arr))); // Calling array_tutorial from mymodule PyObject *pName = PyUnicode_FromString("mymodule"); pModule = PyImport_Import(pName); Py_DECREF(pName); if (!pModule){ cout << "mymodule can not be imported" << endl; Py_DECREF(np_arg); delete[] c_arr; return 1; } pFunc = PyObject_GetAttrString(pModule, "array_tutorial"); if (!pFunc || !PyCallable_Check(pFunc)){ Py_DECREF(pModule); Py_XDECREF(pFunc); Py_DECREF(np_arg); delete[] c_arr; cout << "array_tutorial is null or not callable" << endl; return 1; } pArgs = PyTuple_New(1); PyTuple_SetItem(pArgs, 0, reinterpret_cast<PyObject*>(np_arg)); pReturn = PyObject_CallObject(pFunc, pArgs); np_ret = reinterpret_cast<PyArrayObject*>(pReturn); if (PyArray_NDIM(np_ret) != ND - 1){ // row[0] is returned cout << "Function returned with wrong dimension" << endl; Py_DECREF(pFunc); Py_DECREF(pModule); Py_DECREF(np_arg); Py_DECREF(np_ret); delete[] c_arr; return 1; } int len{ PyArray_SHAPE(np_ret)[0] }; c_out = reinterpret_cast<long double*>(PyArray_DATA(np_ret)); cout << "Printing output array" << endl; for (int i{}; i < len; i++) cout << c_out[i] << '' ''; cout << endl; // Finalizing Py_DECREF(pFunc); Py_DECREF(pModule); Py_DECREF(np_arg); Py_DECREF(np_ret); delete[] c_arr; Py_Finalize(); return 0; }

En CodeReview, hay una respuesta fantástica: Enlace ...


Desde mi experiencia, eso parece ser bastante eficiente. Para obtener aún más eficiencia, intente esto: http://ubuntuforums.org/showthread.php?t=1266059

Usando el tejido puede alinear el código C / C ++ en Python para que pueda ser útil.

http://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.weave.inline.html

Aquí hay un enlace sobre cómo se puede usar Python para interactuar entre muchos idiomas diferentes junto con ejemplos.

http://docs.scipy.org/doc/numpy/user/c-info.python-as-glue.html

Este es un ejemplo rápido y fácil de cómo pasar matrices numpy a c ++ usando Cython:

http://www.birving.com/blog/2014/05/13/passing-numpy-arrays-between-python-and/


Pruebe xtensor y los enlaces de python xtensor-python .

xtensor es una biblioteca C ++ destinada para el análisis numérico con expresiones de matriz multidimensionales.

xtensor proporciona

  • un sistema de expresión extensible que permite la difusión de estilo numpy (ver la hoja de trucos de numpy a xtensor).
  • una API que sigue los modismos de la biblioteca estándar de C ++.
  • herramientas para manipular expresiones de matriz y construir sobre xtensor.
  • enlaces para Python, pero también R y Julia.

Ejemplo de uso

Inicialice una matriz 2-D y calcule la suma de una de sus filas y una matriz 1-D.

#include <iostream> #include "xtensor/xarray.hpp" #include "xtensor/xio.hpp" xt::xarray<double> arr1 {{1.0, 2.0, 3.0}, {2.0, 5.0, 7.0}, {2.0, 5.0, 7.0}}; xt::xarray<double> arr2 {5.0, 6.0, 7.0}; xt::xarray<double> res = xt::view(arr1, 1) + arr2; std::cout << res;

Salidas

{7, 11, 14}

Creando una función universal de estilo Numpy en C ++.

#include "pybind11/pybind11.h" #include "xtensor-python/pyvectorize.hpp" #include <numeric> #include <cmath> namespace py = pybind11; double scalar_func(double i, double j) { return std::sin(i) - std::cos(j); } PYBIND11_PLUGIN(xtensor_python_test) { py::module m("xtensor_python_test", "Test module for xtensor python bindings"); m.def("vectorized_func", xt::pyvectorize(scalar_func), ""); return m.ptr(); }

Código de Python:

import numpy as np import xtensor_python_test as xt x = np.arange(15).reshape(3, 5) y = [1, 2, 3, 4, 5] z = xt.vectorized_func(x, y) z

Salidas

[[-0.540302, 1.257618, 1.89929 , 0.794764, -1.040465], [-1.499227, 0.136731, 1.646979, 1.643002, 0.128456], [-1.084323, -0.583843, 0.45342 , 1.073811, 0.706945]]


Como una forma adicional, sin tocar directamente la API de Python C, es posible usar pybind11 (biblioteca de solo cabecera):

CPP:

#include <pybind11/embed.h> // everything needed for embedding #include <iostream> #include <Eigen/Dense> #include<pybind11/eigen.h> using Eigen::MatrixXd; namespace py = pybind11; int main() { try { Py_SetProgramName("PYTHON"); py::scoped_interpreter guard{}; py::module py_test = py::module::import("py_test"); MatrixXd m(2,2); m(0,0) = 1; m(1,0) = 2; m(0,1) = 3; m(1,1) = 4; py::object result = py_test.attr("test_mat")(m); MatrixXd res = result.cast<MatrixXd>(); std::cout << "In c++ /n" << m << std::endl; } catch (std::exception ex) { std::cout << "ERROR : " << ex.what() << std::endl; } return 1; }

En py_test.py :

def test_mat(m): print ("Inside python m = /n ",m ) m[0,0] = 10 m[1,1] = 99 return m

Salida:

Inside python m = [[ 1. 3.] [ 2. 4.]] In c++ 10 3 2 99

Ver la documentación oficial .

ps: estoy usando Eigen para la Matriz C ++.