Возвращение списка или кортежа массивов из собственного пакета pybind11 - PullRequest
1 голос
/ 24 мая 2019

У меня есть функция c ++, использующая eigen, которая обернута с помощью pybind11, так что я могу вызывать ее из python. Простая версия намеченной функции возвращает тип Eigen::MatrixXd, который pybind успешно преобразует в двумерный массив Numpy.

Мне бы хотелось, чтобы эта функция могла возвращать либо список, либо кортеж таких матриц, либо трехмерный массив NumPy.

Я новичок в c ++, и документация для pybind не дает (насколько я понимаю) какого-либо направления. Пример макета ниже:

test.cpp

#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <Eigen/Dense>

Eigen::MatrixXd test(Eigen::Ref<const Eigen::MatrixXd> x, double a)
{
  Eigen::MatrixXd y;
  y = x * a;
  return y;
}

Eigen::MatrixXd *test2(Eigen::Ref<const Eigen::MatrixXd> x, Eigen::Ref<const Eigen::VectorXd> as)
{
  Eigen::MatrixXd *ys = new Eigen::MatrixXd[as.size()];
  for(unsigned int k = 0; k < as.size(); k++){
    Eigen::MatrixXd& y = ys[k];
    y = x * as[k];
  }
  return ys;
}

namespace py = pybind11;

PYBIND11_MODULE(test, m)
{
  m.doc() = "minimal working example";
  m.def("test", &test);
  m.def("test2", &test2);
}

Я бы хотел, чтобы test2 вернул список или кортеж массивов.

В питоне:

import test
import numpy as np
x = np.random.random((50, 50))
x = np.asfortranarray(x)
a = 0.1
a2 = np.array([1.0, 2.0, 3.0])
y = test.test(x, a)
ys = test.test2(x, a2)

Массив y соответствует ожидаемому, но ys содержит только массив, соответствующий первому коэффициенту a2.

Как мне изменить test2, чтобы правильно возвращать более одного массива? 3D-массив также будет приемлемым.

1 Ответ

0 голосов
/ 25 мая 2019

Я использовал Eigen раньше, но я не эксперт, поэтому другие могут улучшить это решение.

#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <pybind11/stl.h>
#include <Eigen/Dense>

std::vector<Eigen::MatrixXd> 
test2(Eigen::Ref<const Eigen::MatrixXd> x, Eigen::Ref<const Eigen::VectorXd> as){
    std::vector<Eigen::MatrixXd> matrices;
    for(unsigned int k = 0; k < as.size(); k++){
        Eigen::MatrixXd ys = x * as[k];
        matrices.push_back(ys);
    }
    return matrices;
}

namespace py = pybind11;

PYBIND11_MODULE(test, m){
    m.doc() = "minimal working example";
    m.def("test2", &test2);
}

Вектор преобразуется в список пустых массивов с помощью pybind11. Результаты:

In [1]: import numpy as np; x = np.ones((2,2)); a = np.array((2., 3.)); import test

In [2]: test.test2(x, a)
Out[2]: 
[array([[2., 2.],
        [2., 2.]]), array([[3., 3.],
        [3., 3.]])]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...