diff options
Diffstat (limited to 'eval/src/tests/tensor')
-rw-r--r-- | eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp | 441 |
1 files changed, 216 insertions, 225 deletions
diff --git a/eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp b/eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp index 8fede7e3d0b..6572ab1ed92 100644 --- a/eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp +++ b/eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp @@ -2,244 +2,235 @@ #include <vespa/vespalib/testkit/test_kit.h> #include <vespa/vespalib/util/stringfmt.h> -#include <vespa/eval/tensor/sparse/sparse_tensor.h> -#include <vespa/eval/tensor/sparse/sparse_tensor_builder.h> -#include <vespa/eval/tensor/dense/dense_tensor.h> -#include <vespa/eval/tensor/dense/dense_tensor_builder.h> -#include <vespa/eval/tensor/types.h> -#include <vespa/eval/tensor/tensor_factory.h> #include <vespa/eval/tensor/tensor_mapper.h> -#include <vespa/eval/tensor/default_tensor.h> -#include <ostream> +#include <vespa/eval/tensor/wrapped_simple_tensor.h> +#include <vespa/eval/tensor/default_tensor_engine.h> +#include <vespa/eval/eval/tensor_spec.h> +#include <vespa/eval/eval/simple_tensor.h> using vespalib::eval::ValueType; +using vespalib::eval::TensorSpec; +using vespalib::eval::SimpleTensor; using namespace vespalib::tensor; -namespace vespalib { -namespace tensor { +void verify_wrapped(const TensorSpec &source, const vespalib::string &type, const TensorSpec &expect) { + auto tensor = std::make_unique<WrappedSimpleTensor>(SimpleTensor::create(source)); + auto mapped = TensorMapper::mapToWrapped(*tensor, ValueType::from_spec(type)); + TensorSpec actual = mapped->toSpec(); + EXPECT_EQUAL(actual, expect); +} + +void verify(const TensorSpec &source, const vespalib::string &type, const TensorSpec &expect) { + auto tensor = DefaultTensorEngine::ref().create(source); + const Tensor *tensor_impl = dynamic_cast<const Tensor *>(tensor.get()); + ASSERT_TRUE(tensor_impl); + TensorMapper mapper(ValueType::from_spec(type)); + auto mapped = mapper.map(*tensor_impl); + TensorSpec actual = mapped->toSpec(); + EXPECT_EQUAL(actual, expect); + TEST_DO(verify_wrapped(source, type, expect)); +} + +TEST("require that sparse tensors can be mapped to sparse type") { + TEST_DO(verify(TensorSpec("tensor(x{},y{})") + .add({{"x","1"},{"y","1"}}, 1) + .add({{"x","2"},{"y","1"}}, 3) + .add({{"x","1"},{"y","2"}}, 5) + .add({{"x","2"},{"y","2"}}, 7), + "tensor(y{})", + TensorSpec("tensor(y{})") + .add({{"y","1"}}, 4) + .add({{"y","2"}}, 12))); + + TEST_DO(verify(TensorSpec("tensor(x{},y{})") + .add({{"x","1"},{"y","1"}}, 1) + .add({{"x","2"},{"y","1"}}, 3) + .add({{"x","1"},{"y","2"}}, 5) + .add({{"x","2"},{"y","2"}}, 7), + "tensor(x{})", + TensorSpec("tensor(x{})") + .add({{"x","1"}}, 6) + .add({{"x","2"}}, 10))); +} + +TEST("require that sparse tensors can be mapped to dense type") { + TEST_DO(verify(TensorSpec("tensor(x{},y{})") + .add({{"x","1"},{"y","0"}}, 1) + .add({{"x","2"},{"y","0"}}, 3) + .add({{"x","1"},{"y","1"}}, 5) + .add({{"x","2"},{"y","1"}}, 7), + "tensor(y[3])", + TensorSpec("tensor(y[3])") + .add({{"y",0}}, 4) + .add({{"y",1}}, 12) + .add({{"y",2}}, 0))); + + TEST_DO(verify(TensorSpec("tensor(x{},y{})") + .add({{"x","1"},{"y","0x"}}, 1) + .add({{"x","2"},{"y",""}}, 3) + .add({{"x","1"},{"y","1"}}, 5) + .add({{"x","2"},{"y","10"}}, 7), + "tensor(y[3])", + TensorSpec("tensor(y[3])") + .add({{"y",0}}, 3) + .add({{"y",1}}, 5) + .add({{"y",2}}, 0))); + + TEST_DO(verify(TensorSpec("tensor(x{},y{})") + .add({{"x","0"},{"y","0"}}, 1) + .add({{"x","1"},{"y","0"}}, 3) + .add({{"x","0"},{"y","1"}}, 5) + .add({{"x","10"},{"y","1"}}, 7), + "tensor(x[2],y[3])", + TensorSpec("tensor(x[2],y[3])") + .add({{"x",0},{"y",0}}, 1) + .add({{"x",0},{"y",1}}, 5) + .add({{"x",0},{"y",2}}, 0) + .add({{"x",1},{"y",0}}, 3) + .add({{"x",1},{"y",1}}, 0) + .add({{"x",1},{"y",2}}, 0))); +} -static bool operator==(const Tensor &lhs, const Tensor &rhs) -{ - return lhs.equals(rhs); +TEST("require that sparse tensors can be mapped to abstract dense type") { + TEST_DO(verify(TensorSpec("tensor(x{},y{})") + .add({{"x","0"},{"y","0"}}, 1) + .add({{"x","1"},{"y","0"}}, 3) + .add({{"x","0"},{"y","1"}}, 5) + .add({{"x","10"},{"y","1"}}, 7), + "tensor(x[2],y[])", + TensorSpec("tensor(x[2],y[2])") + .add({{"x",0},{"y",0}}, 1) + .add({{"x",0},{"y",1}}, 5) + .add({{"x",1},{"y",0}}, 3) + .add({{"x",1},{"y",1}}, 0))); + + TEST_DO(verify(TensorSpec("tensor(x{},y{})") + .add({{"x","0"},{"y","0"}}, 1) + .add({{"x","1"},{"y","0"}}, 3) + .add({{"x","0"},{"y","1"}}, 5) + .add({{"x","2"},{"y","0"}}, 7), + "tensor(x[],y[])", + TensorSpec("tensor(x[3],y[2])") + .add({{"x",0},{"y",0}}, 1) + .add({{"x",0},{"y",1}}, 5) + .add({{"x",1},{"y",0}}, 3) + .add({{"x",1},{"y",1}}, 0) + .add({{"x",2},{"y",0}}, 7) + .add({{"x",2},{"y",1}}, 0))); + + TEST_DO(verify(TensorSpec("tensor(x{},y{})") + .add({{"x","0"},{"y","0"}}, 1) + .add({{"x","1"},{"y","0"}}, 3) + .add({{"x","0"},{"y","1"}}, 5) + .add({{"x","10"},{"y","3"}}, 7), + "tensor(x[],y[3])", + TensorSpec("tensor(x[2],y[3])") + .add({{"x",0},{"y",0}}, 1) + .add({{"x",0},{"y",1}}, 5) + .add({{"x",0},{"y",2}}, 0) + .add({{"x",1},{"y",0}}, 3) + .add({{"x",1},{"y",1}}, 0) + .add({{"x",1},{"y",2}}, 0))); } +TEST("require that dense tensors can be mapped to sparse type") { + TEST_DO(verify(TensorSpec("tensor(x[2],y[2])") + .add({{"x",0},{"y",0}}, 1) + .add({{"x",0},{"y",1}}, 3) + .add({{"x",1},{"y",0}}, 5) + .add({{"x",1},{"y",1}}, 7), + "tensor(x{})", + TensorSpec("tensor(x{})") + .add({{"x","0"}}, 4) + .add({{"x","1"}}, 12))); } + +TEST("require that mixed tensors can be mapped to sparse type") { + TEST_DO(verify(TensorSpec("tensor(x[2],y{})") + .add({{"x",0},{"y","0"}}, 1) + .add({{"x",0},{"y","1"}}, 3) + .add({{"x",1},{"y","0"}}, 5) + .add({{"x",1},{"y","1"}}, 7), + "tensor(x{})", + TensorSpec("tensor(x{})") + .add({{"x","0"}}, 4) + .add({{"x","1"}}, 12))); +} + +TEST("require that mixed tensors can be mapped to dense type") { + TEST_DO(verify(TensorSpec("tensor(x[2],y{})") + .add({{"x",0},{"y","0"}}, 1) + .add({{"x",0},{"y","1"}}, 3) + .add({{"x",1},{"y","0"}}, 5) + .add({{"x",1},{"y","1"}}, 7), + "tensor(y[])", + TensorSpec("tensor(y[2])") + .add({{"y",0}}, 6) + .add({{"y",1}}, 10))); +} + +TEST("require that mixed tensors can be mapped to mixed type") { + TEST_DO(verify(TensorSpec("tensor(x[2],y{})") + .add({{"x",0},{"y","0"}}, 1) + .add({{"x",0},{"y","1"}}, 3) + .add({{"x",1},{"y","0"}}, 5) + .add({{"x",1},{"y","1"}}, 7), + "tensor(x{},y[])", + TensorSpec("tensor(x{},y[2])") + .add({{"x","0"},{"y",0}}, 1) + .add({{"x","0"},{"y",1}}, 3) + .add({{"x","1"},{"y",0}}, 5) + .add({{"x","1"},{"y",1}}, 7))); +} + +TEST("require that dense tensors can be mapped to mixed type") { + TEST_DO(verify(TensorSpec("tensor(x[2],y[2])") + .add({{"x",0},{"y",0}}, 1) + .add({{"x",0},{"y",1}}, 3) + .add({{"x",1},{"y",0}}, 5) + .add({{"x",1},{"y",1}}, 7), + "tensor(x{},y[])", + TensorSpec("tensor(x{},y[2])") + .add({{"x","0"},{"y",0}}, 1) + .add({{"x","0"},{"y",1}}, 3) + .add({{"x","1"},{"y",0}}, 5) + .add({{"x","1"},{"y",1}}, 7))); } -template <typename BuilderType> -bool defaultBuilder() { return false; } - -template <> -bool defaultBuilder<DefaultTensor::builder>() { return true; } - -template <typename BuilderType> -struct TensorTFromBuilder; - -template <> -struct TensorTFromBuilder<SparseTensorBuilder> { - using TensorT = SparseTensor; -}; - -template <typename BuilderType> -using TensorTFromBuilder_t = typename TensorTFromBuilder<BuilderType>::TensorT; - -struct FixtureBase -{ - Tensor::UP createDenseTensor(const DenseTensorCells &cells) { - return TensorFactory::createDense(cells); - } -}; - -template <typename BuilderType> -struct Fixture : public FixtureBase -{ - BuilderType _builder; - using TensorT = TensorTFromBuilder_t<BuilderType>; - Fixture() : FixtureBase(), _builder() {} - - Tensor::UP createTensor(const TensorCells &cells, - const TensorDimensions &dimensions) { - return TensorFactory::create(cells, dimensions, _builder); - } - - void assertSparseMapImpl(const Tensor &exp, - const ValueType &tensorType, - const Tensor &rhs, bool isDefaultBuilder) - { - EXPECT_TRUE(tensorType.is_sparse()); - if (isDefaultBuilder) { - TensorMapper mapper(tensorType); - std::unique_ptr<Tensor> mapped = mapper.map(rhs); - EXPECT_TRUE(!!mapped); - EXPECT_EQUAL(exp, *mapped); - } - std::unique_ptr<Tensor> mapped = - TensorMapper::mapToSparse<TensorT>(rhs, tensorType); - EXPECT_TRUE(!!mapped); - EXPECT_EQUAL(exp, *mapped); - } - - void assertDenseMapImpl(const Tensor &exp, - const ValueType &tensorType, - const Tensor &rhs) - { - EXPECT_TRUE(tensorType.is_dense()); - TensorMapper mapper(tensorType); - std::unique_ptr<Tensor> mapped = mapper.map(rhs); - EXPECT_TRUE(!!mapped); - EXPECT_EQUAL(exp, *mapped); - } - - void - assertSparseMap(const TensorCells &expTensor, - const TensorDimensions &expDimensions, - const vespalib::string &typeSpec, - const TensorCells &rhsTensor, - const TensorDimensions &rhsDimensions) - { - assertSparseMapImpl(*createTensor(expTensor, expDimensions), - ValueType::from_spec(typeSpec), - *createTensor(rhsTensor, rhsDimensions), - defaultBuilder<BuilderType>()); - } - - void - assertDenseMap(const DenseTensorCells &expTensor, - const vespalib::string &typeSpec, - const TensorCells &rhsTensor, - const TensorDimensions &rhsDimensions) - { - assertDenseMapImpl(*createDenseTensor(expTensor), - ValueType::from_spec(typeSpec), - *createTensor(rhsTensor, rhsDimensions)); - } -}; - -using SparseFixture = Fixture<SparseTensorBuilder>; - -template <typename FixtureType> -void -testTensorMapper(FixtureType &f) -{ - TEST_DO(f.assertSparseMap({ - {{{"y","1"}}, 4}, - {{{"y","2"}}, 12} - }, - { "y" }, - "tensor(y{})", - { - {{{"x","1"},{"y","1"}}, 1}, - {{{"x","2"},{"y","1"}}, 3}, - {{{"x","1"},{"y","2"}}, 5}, - {{{"x","2"},{"y","2"}}, 7} - }, - { "x", "y" })); - TEST_DO(f.assertSparseMap({ - {{{"x","1"}}, 6}, - {{{"x","2"}}, 10} - }, - { "x" }, - "tensor(x{})", - { - {{{"x","1"},{"y","1"}}, 1}, - {{{"x","2"},{"y","1"}}, 3}, - {{{"x","1"},{"y","2"}}, 5}, - {{{"x","2"},{"y","2"}}, 7} - }, - { "x", "y" })); - TEST_DO(f.assertDenseMap({ - {{{"y",0}}, 4}, - {{{"y",1}}, 12}, - {{{"y",2}}, 0} - }, - "tensor(y[3])", - { - {{{"x","1"},{"y","0"}}, 1}, - {{{"x","2"},{"y","0"}}, 3}, - {{{"x","1"},{"y","1"}}, 5}, - {{{"x","2"},{"y","1"}}, 7} - }, - { "x", "y" })); - TEST_DO(f.assertDenseMap({ - {{{"y",0}}, 3}, - {{{"y",1}}, 5}, - {{{"y",2}}, 0} - }, - "tensor(y[3])", - { - {{{"x","1"},{"y","0x"}}, 1}, - {{{"x","2"},{"y",""}}, 3}, - {{{"x","1"},{"y","1"}}, 5}, - {{{"x","2"},{"y","10"}}, 7} - }, - { "x", "y" })); - TEST_DO(f.assertDenseMap({ - {{{"x",0},{"y",0}}, 1}, - {{{"x",0},{"y",1}}, 5}, - {{{"x",0},{"y",2}}, 0}, - {{{"x",1},{"y",0}}, 3}, - {{{"x",1},{"y",1}}, 0}, - {{{"x",1},{"y",2}}, 0} - }, - "tensor(x[2], y[3])", - { - {{{"x","0"},{"y","0"}}, 1}, - {{{"x","1"},{"y","0"}}, 3}, - {{{"x","0"},{"y","1"}}, 5}, - {{{"x","10"},{"y","1"}}, 7} - }, - { "x", "y" })); - TEST_DO(f.assertDenseMap({ - {{{"x",0},{"y",0}}, 1}, - {{{"x",0},{"y",1}}, 5}, - {{{"x",1},{"y",0}}, 3}, - {{{"x",1},{"y",1}}, 0} - }, - "tensor(x[2], y[])", - { - {{{"x","0"},{"y","0"}}, 1}, - {{{"x","1"},{"y","0"}}, 3}, - {{{"x","0"},{"y","1"}}, 5}, - {{{"x","10"},{"y","1"}}, 7} - }, - { "x", "y" })); - TEST_DO(f.assertDenseMap({ - {{{"x",0},{"y",0}}, 1}, - {{{"x",0},{"y",1}}, 5}, - {{{"x",1},{"y",0}}, 3}, - {{{"x",1},{"y",1}}, 0}, - {{{"x",2},{"y",0}}, 7}, - {{{"x",2},{"y",1}}, 0} - }, - "tensor(x[], y[])", - { - {{{"x","0"},{"y","0"}}, 1}, - {{{"x","1"},{"y","0"}}, 3}, - {{{"x","0"},{"y","1"}}, 5}, - {{{"x","2"},{"y","0"}}, 7} - }, - { "x", "y" })); - TEST_DO(f.assertDenseMap({ - {{{"x",0},{"y",0}}, 1}, - {{{"x",0},{"y",1}}, 5}, - {{{"x",0},{"y",2}}, 0}, - {{{"x",1},{"y",0}}, 3}, - {{{"x",1},{"y",1}}, 0}, - {{{"x",1},{"y",2}}, 0} - }, - "tensor(x[], y[3])", - { - {{{"x","0"},{"y","0"}}, 1}, - {{{"x","1"},{"y","0"}}, 3}, - {{{"x","0"},{"y","1"}}, 5}, - {{{"x","10"},{"y","3"}}, 7} - }, - { "x", "y" })); +TEST("require that sparse tensors can be mapped to mixed type") { + TEST_DO(verify(TensorSpec("tensor(x{},y{})") + .add({{"x","0"},{"y","0"}}, 1) + .add({{"x","0"},{"y","1"}}, 3) + .add({{"x","1"},{"y","0"}}, 5) + .add({{"x","1"},{"y","1"}}, 7), + "tensor(x[],y{})", + TensorSpec("tensor(x[2],y{})") + .add({{"x",0},{"y","0"}}, 1) + .add({{"x",0},{"y","1"}}, 3) + .add({{"x",1},{"y","0"}}, 5) + .add({{"x",1},{"y","1"}}, 7))); } -TEST_F("test tensor mapper for SparseTensor", SparseFixture) -{ - testTensorMapper(f); +TEST("require that missing dimensions are added appropriately") { + TEST_DO(verify(TensorSpec("tensor(x{})") + .add({{"x","foo"}}, 42), + "tensor(x{},y{})", + TensorSpec("tensor(x{},y{})") + .add({{"x","foo"},{"y",""}}, 42))); + + TEST_DO(verify(TensorSpec("tensor(x[1])") + .add({{"x",0}}, 42), + "tensor(x[1],y[],z[2])", + TensorSpec("tensor(x[1],y[1],z[2])") + .add({{"x",0},{"y",0},{"z",0}}, 42) + .add({{"x",0},{"y",0},{"z",1}}, 0))); + + TEST_DO(verify(TensorSpec("tensor(a{})") + .add({{"a","foo"}}, 42), + "tensor(a{},b[],c{},d[2])", + TensorSpec("tensor(a{},b[1],c{},d[2])") + .add({{"a","foo"},{"b",0},{"c",""},{"d",0}}, 42) + .add({{"a","foo"},{"b",0},{"c",""},{"d",1}}, 0))); } TEST_MAIN() { TEST_RUN_ALL(); } |