autodiff.in.cpp 58.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*******************************************************************************
* Copyright 2017-2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
16 17

#include <algorithm>
18
#include <functional>
19
#include <memory>
20
#include <tuple>
21 22 23 24

#include "gtest/gtest.h"

#include "ngraph/ngraph.hpp"
25
#include "ngraph/runtime/reference/avg_pool.hpp"
26
#include "util/autodiff/backprop_function.hpp"
adstraw's avatar
adstraw committed
27
#include "util/autodiff/numeric_compare.hpp"
28
#include "util/random.hpp"
29
#include "util/test_control.hpp"
30 31 32 33

using namespace std;
using namespace ngraph;

34 35 36
static string s_manifest = "${MANIFEST}";

NGRAPH_TEST(${BACKEND_NAME}, backwards_maxpool_n4_c1_hw4_2x2_max)
37
{
38
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
39

40 41
    Shape shape_a{1, 4, 4, 4}; //in CHWN
    Shape maxpool_shape{1, 4, 3, 3};
42 43 44 45

    auto A = make_shared<op::Parameter>(element::i32, shape_a);
    auto reshape = make_shared<op::Reshape>(
        A, AxisVector{0, 3, 1, 2}, Shape{1, 4, 4, 4}); //convert CHWN to CNHW
46
    Shape window_shape{2, 2};
47 48
    auto window_movement_strides = Strides{1, 1};
    auto maxpool = make_shared<op::MaxPool>(reshape, window_shape, window_movement_strides);
49
    auto f = make_shared<Function>(maxpool, op::ParameterVector{A});
50

51
    shared_ptr<runtime::TensorView> ep = backend->create_tensor(element::i32, maxpool_shape);
52 53
    vector<int> dataEp(shape_size(maxpool_shape), 4);

54 55
    shared_ptr<runtime::TensorView> input = backend->create_tensor(element::i32, shape_a);
    shared_ptr<runtime::TensorView> output = backend->create_tensor(element::i32, shape_a);
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

    vector<int> dataInput{11, 65, 44, 28, 31, 33, 21, 66, 40, 49, 69, 57, 47, 30, 24, 27,
                          13, 56, 46, 60, 61, 41, 25, 42, 48, 53, 51, 43, 59, 58, 29, 71,
                          17, 22, 72, 18, 39, 35, 15, 38, 64, 52, 73, 67, 62, 50, 10, 68,
                          45, 63, 16, 14, 55, 54, 37, 20, 36, 12, 70, 34, 19, 26, 32, 23};

    vector<int> expected{//delta
                         0, 4, 0, 0, 0, 0, 0, 8, 0, 0, 8, 0, 0, 0, 0, 0, 0, 4, 4,  4, 12, 0,
                         0, 0, 0, 8, 0, 0, 4, 8, 0, 8, 0, 0, 8, 0, 0, 0, 0, 4, 16, 4, 16, 8,
                         0, 0, 0, 4, 0, 4, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0};

    copy_data(ep, dataEp);
    copy_data(input, dataInput);

    auto C = make_shared<op::Parameter>(element::i32, maxpool_shape);
    auto df = autodiff::backprop_function(f);
72
    backend->call(df, {output}, {input, ep});
73
    ASSERT_TRUE(read_vector<int>(output) == expected);
74 75
}

76
NGRAPH_TEST(${BACKEND_NAME}, backwards_maxpool_n2_c1_hw5_3x3_str2_max)
77
{
78
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
79

80 81
    Shape shape_a{1, 5, 5, 2}; //in CHWN
    Shape maxpool_shape{1, 2, 2, 2};
82 83 84 85

    auto A = make_shared<op::Parameter>(element::i32, shape_a);
    auto reshape = make_shared<op::Reshape>(
        A, AxisVector{0, 3, 1, 2}, Shape{1, 2, 5, 5}); //convert CHWN to CNHW
86
    Shape window_shape{3, 3};
87 88
    auto window_movement_strides = Strides{2, 2};
    auto maxpool = make_shared<op::MaxPool>(reshape, window_shape, window_movement_strides);
89
    auto f = make_shared<Function>(maxpool, op::ParameterVector{A});
90

91
    shared_ptr<runtime::TensorView> ep = backend->create_tensor(element::i32, maxpool_shape);
92 93
    vector<int> dataEp(shape_size(maxpool_shape), 4);

94 95
    shared_ptr<runtime::TensorView> input = backend->create_tensor(element::i32, shape_a);
    shared_ptr<runtime::TensorView> output = backend->create_tensor(element::i32, shape_a);
96 97 98 99 100 101 102 103 104 105 106 107 108 109

    vector<int> dataInput{58, 15, 51, 35, 18, 47, 31, 32, 52, 21, 36, 38, 57, 54, 25, 45, 23,
                          30, 16, 27, 48, 20, 41, 37, 43, 39, 22, 28, 33, 29, 12, 17, 44, 42,
                          19, 40, 10, 46, 34, 53, 26, 55, 50, 13, 24, 14, 49, 56, 59, 11};

    vector<int> expected{//delta
                         4, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 4, 4, 0};

    copy_data(ep, dataEp);
    copy_data(input, dataInput);

    auto C = make_shared<op::Parameter>(element::i32, maxpool_shape);
    auto df = autodiff::backprop_function(f);
110
    backend->call(df, {output}, {input, ep});
111
    ASSERT_TRUE(read_vector<int>(output) == expected);
112 113
}

114
NGRAPH_TEST(${BACKEND_NAME}, backwards_avgpool_n1_c1_hw2x2)
115
{
116
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
117

118
    Shape padding{1, 1};
119

120 121
    Shape shape_a{1, 1, 2, 2};
    Shape avgpool_shape{1, 1, 2, 2};
122 123

    auto A = make_shared<op::Parameter>(element::i32, shape_a);
124
    Shape window_shape{2, 2};
125 126
    auto window_movement_strides = Strides{2, 2};
    auto avgpool =
127
        make_shared<op::AvgPool>(A, window_shape, window_movement_strides, padding, padding, false);
128
    auto f = make_shared<Function>(avgpool, op::ParameterVector{A});
129

130
    shared_ptr<runtime::TensorView> ep = backend->create_tensor(element::i32, avgpool_shape);
131 132
    vector<int> dataEp(shape_size(avgpool_shape), 4);

133
    shared_ptr<runtime::TensorView> input = backend->create_tensor(element::i32, shape_a);
134

135
    shared_ptr<runtime::TensorView> output = backend->create_tensor(element::i32, shape_a);
136 137 138 139 140 141 142 143 144 145

    vector<int> dataInput{4, 8, 12, 16};

    vector<int> expected{1, 2, 3, 4};

    copy_data(ep, dataEp);
    copy_data(input, dataInput);

    auto C = make_shared<op::Parameter>(element::i32, avgpool_shape);
    auto df = autodiff::backprop_function(f);
146
    backend->call(df, {output}, {input, ep});
147 148 149
    ASSERT_TRUE(read_vector<int>(output) == dataEp);
}

150
NGRAPH_TEST(${BACKEND_NAME}, backwards_avgpool_n1_c1_hw4x4)
151
{
152
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
153

154 155
    Shape shape_a{1, 1, 4, 4};
    Shape avgpool_shape{1, 1, 3, 3};
156 157

    auto A = make_shared<op::Parameter>(element::i32, shape_a);
158
    Shape window_shape{2, 2};
159 160
    auto window_movement_strides = Strides{1, 1};
    auto avgpool = make_shared<op::AvgPool>(A, window_shape, window_movement_strides);
161
    auto f = make_shared<Function>(avgpool, op::ParameterVector{A});
162

163
    shared_ptr<runtime::TensorView> ep = backend->create_tensor(element::i32, avgpool_shape);
164 165
    vector<int> dataEp(shape_size(avgpool_shape), 4);

166
    shared_ptr<runtime::TensorView> input = backend->create_tensor(element::i32, shape_a);
167

168
    shared_ptr<runtime::TensorView> output = backend->create_tensor(element::i32, shape_a);
169 170 171 172 173 174 175 176 177 178

    vector<int> dataInput{1, 3, 1, 3, 1, 3, 1, 3, 3, 5, 3, 5, 3, 5, 3, 5};

    vector<int> expected{1, 2, 2, 1, 2, 4, 4, 2, 2, 4, 4, 2, 1, 2, 2, 1};

    copy_data(ep, dataEp);
    copy_data(input, dataInput);

    auto C = make_shared<op::Parameter>(element::i32, avgpool_shape);
    auto df = autodiff::backprop_function(f);
179
    backend->call(df, {output}, {input, ep});
180 181 182
    ASSERT_TRUE(read_vector<int>(output) == expected);
}

183
NGRAPH_TEST(${BACKEND_NAME}, backwards_avgpool_n2_c2_hw4x4)
184
{
185
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
186

187 188
    Shape shape_a{2, 2, 4, 4};
    Shape avgpool_shape{2, 2, 2, 2};
189 190

    auto A = make_shared<op::Parameter>(element::i32, shape_a);
191
    Shape window_shape{2, 2};
192 193
    auto window_movement_strides = Strides{2, 2};
    auto avgpool = make_shared<op::AvgPool>(A, window_shape, window_movement_strides);
194
    auto f = make_shared<Function>(avgpool, op::ParameterVector{A});
195

196
    shared_ptr<runtime::TensorView> ep = backend->create_tensor(element::i32, avgpool_shape);
197 198
    vector<int> dataEp(shape_size(avgpool_shape), 12);

199
    shared_ptr<runtime::TensorView> input = backend->create_tensor(element::i32, shape_a);
200

201
    shared_ptr<runtime::TensorView> output = backend->create_tensor(element::i32, shape_a);
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277

    vector<int> dataInput{//i1c1
                          1,
                          2,
                          6,
                          7,
                          3,
                          4,
                          4,
                          3,
                          19,
                          1,
                          2,
                          3,
                          18,
                          2,
                          3,
                          2,
                          //i1c2
                          4,
                          1,
                          5,
                          5,
                          1,
                          4,
                          5,
                          5,
                          12,
                          8,
                          2,
                          3,
                          15,
                          5,
                          3,
                          2,
                          //i2c1
                          2,
                          3,
                          7,
                          7,
                          3,
                          2,
                          3,
                          3,
                          13,
                          7,
                          1,
                          2,
                          7,
                          13,
                          3,
                          4,
                          //i2c2
                          1,
                          1,
                          2,
                          2,
                          7,
                          1,
                          2,
                          14,
                          6,
                          16,
                          4,
                          1,
                          14,
                          4,
                          4,
                          1};

    vector<int> expected(shape_size(shape_a), 3);
    copy_data(ep, dataEp);
    copy_data(input, dataInput);

    auto C = make_shared<op::Parameter>(element::i32, avgpool_shape);
    auto df = autodiff::backprop_function(f);
278
    backend->call(df, {output}, {input, ep});
279 280 281
    ASSERT_TRUE(read_vector<int>(output) == expected);
}

282
NGRAPH_TEST(${BACKEND_NAME}, backwards_avgpool_n2_c2_hw4x4_numeric)
283
{
284
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
285
    Shape shape_a{2, 2, 4, 4};
286 287 288 289
    test::Uniform<float> rng(1.0f, 10.0f);

    auto make_graph = [shape_a]() {
        auto A = make_shared<op::Parameter>(element::f32, shape_a);
290
        Shape window_shape{2, 2};
291 292
        auto window_movement_strides = Strides{2, 2};
        auto avgpool = make_shared<op::AvgPool>(A, window_shape, window_movement_strides);
293
        return make_shared<Function>(avgpool, op::ParameterVector{A});
294 295 296

    };

297
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
298
    {
299 300
        auto x = rng.initialize(backend->create_tensor(element::f32, shape_a));
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
301 302 303
    }
}

304
NGRAPH_TEST(${BACKEND_NAME}, backwards_avgpool_n2_c2_hw4x4_win_2x2_str_1x1_numeric)
305
{
306
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
307
    Shape shape_a{2, 2, 4, 4};
308 309 310 311
    test::Uniform<float> rng(1.0f, 10.0f);

    auto make_graph = [shape_a]() {
        auto A = make_shared<op::Parameter>(element::f32, shape_a);
312
        Shape window_shape{2, 2};
313 314
        auto window_movement_strides = Strides{1, 1};
        auto avgpool = make_shared<op::AvgPool>(A, window_shape, window_movement_strides);
315
        return make_shared<Function>(avgpool, op::ParameterVector{A});
316 317 318

    };

319
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
320
    {
321 322
        auto x = rng.initialize(backend->create_tensor(element::f32, shape_a));
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
323 324 325
    }
}

326
NGRAPH_TEST(${BACKEND_NAME}, backwards_avgpool_n2_c2_hw2x2_win_2x2_str_1x1_padding_numeric)
327
{
328
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
329
    Shape shape_a{2, 2, 4, 4};
330 331 332 333
    test::Uniform<float> rng(1.0f, 10.0f);

    auto make_graph = [shape_a]() {
        auto A = make_shared<op::Parameter>(element::f32, shape_a);
334 335
        Shape window_shape{2, 2};
        Shape padding{1, 1};
336
        auto window_movement_strides = Strides{2, 2};
337 338
        auto avgpool = make_shared<op::AvgPool>(
            A, window_shape, window_movement_strides, padding, padding, false);
339
        return make_shared<Function>(avgpool, op::ParameterVector{A});
340 341 342

    };

343
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
344
    {
345 346
        auto x = rng.initialize(backend->create_tensor(element::f32, shape_a));
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
347 348 349
    }
}

350
NGRAPH_TEST(${BACKEND_NAME}, backwards_abs)
351
{
352
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
353 354 355 356 357

    // The numeric derivative and the symbolic one may disagree around 0, so we will dance around
    // that point by skipping (-0.01,0.01).
    test::Uniform<float> rng_neg(-1.0f, -0.01f);
    test::Uniform<float> rng_pos(0.01f, 1.0f);
358
    Shape shape{2, 3};
359 360

    auto make_graph = [shape]() {
361
        auto X = make_shared<op::Parameter>(element::f32, shape);
362 363
        return make_shared<Function>(make_shared<op::Abs>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
364 365
    };

366
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
367
    {
368
        auto x_neg = rng_neg.initialize(backend->create_tensor<float>(shape));
369

370
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_neg}, .01f, .01f));
371

372
        auto x_pos = rng_pos.initialize(backend->create_tensor<float>(shape));
373

374
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_pos}, .01f, .01f));
375
    }
376 377
}

378
NGRAPH_TEST(${BACKEND_NAME}, backwards_acos)
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
{
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    test::Uniform<float> rng(-0.9f, 0.9f);
    Shape shape{2, 3};
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));

    auto make_graph = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Acos>(X0),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
}

394
NGRAPH_TEST(${BACKEND_NAME}, backwards_add)
395
{
396
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
397

398
    test::Uniform<float> rng(-1.0f, 1.0f);
399
    Shape shape{2, 3};
400 401
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape));
Scott Cyphers's avatar
Scott Cyphers committed
402

403
    auto make_graph = [shape]() {
404 405
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
406
        return make_shared<Function>(X0 + X1, std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
407
    };
408
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
409 410
}

411
NGRAPH_TEST(${BACKEND_NAME}, backwards_add_nested)
412
{
413
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
414

415
    test::Uniform<float> rng(-1.0f, 1.0f);
416
    Shape shape{2, 3};
417 418
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape));
419 420

    auto make_graph = [shape]() {
421 422
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
423 424
        return make_shared<Function>((X0 + X1) + (X1 + X0),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
425
    };
426
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
427 428
}

429
NGRAPH_TEST(${BACKEND_NAME}, backwards_asin)
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
{
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    test::Uniform<float> rng(-0.9f, 0.9f);
    Shape shape{2, 3};
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));

    auto make_graph = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Asin>(X0),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
}

445
NGRAPH_TEST(${BACKEND_NAME}, backwards_atan)
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
{
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    test::Uniform<float> rng(-10.0f, 10.0f);
    Shape shape{2, 3};
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));

    auto make_graph = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Atan>(X0),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
}

461
NGRAPH_TEST(${BACKEND_NAME}, backwards_broadcast0)
462
{
463
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
464

465
    test::Uniform<float> rng(-1.0f, 1.0f);
466
    Shape shape{3};
467
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
468 469

    auto make_graph = [shape]() {
470
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
471 472 473
        return make_shared<Function>(make_shared<op::Broadcast>(X0, Shape{2, 3}, AxisSet{0}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
474
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
475 476
}

477
NGRAPH_TEST(${BACKEND_NAME}, backwards_broadcast1)
478
{
479
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
480

481
    test::Uniform<float> rng(-1.0f, 1.0f);
482
    Shape shape{3};
483
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
484 485

    auto make_graph = [shape]() {
486
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
487 488 489
        return make_shared<Function>(make_shared<op::Broadcast>(X0, Shape{3, 2}, AxisSet{1}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
490
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
491 492
}

493
NGRAPH_TEST(${BACKEND_NAME}, backwards_concat_vector)
494
{
495
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
496 497

    test::Uniform<float> rng(-1.0f, 1.0f);
498
    Shape shape_0{3};
499
    auto x0 = rng.initialize(backend->create_tensor(element::f32, shape_0));
500
    Shape shape_1{2};
501
    auto x1 = rng.initialize(backend->create_tensor(element::f32, shape_1));
502
    Shape shape_2{1};
503
    auto x2 = rng.initialize(backend->create_tensor(element::f32, shape_2));
504 505

    auto make_graph = [shape_0, shape_1, shape_2]() {
506 507 508
        auto X0 = make_shared<op::Parameter>(element::f32, shape_0);
        auto X1 = make_shared<op::Parameter>(element::f32, shape_1);
        auto X2 = make_shared<op::Parameter>(element::f32, shape_2);
509
        return make_shared<Function>(make_shared<op::Concat>(NodeVector{X0, X1, X2}, 0),
510 511
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1, X2});
    };
512
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1, x2}, .01f, .01f));
513 514
}

515
NGRAPH_TEST(${BACKEND_NAME}, backwards_concat_axis_0)
516
{
517
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
518 519

    test::Uniform<float> rng(-1.0f, 1.0f);
520
    Shape shape_0{3, 2};
521
    auto x0 = rng.initialize(backend->create_tensor(element::f32, shape_0));
522
    Shape shape_1{2, 2};
523
    auto x1 = rng.initialize(backend->create_tensor(element::f32, shape_1));
524
    Shape shape_2{1, 2};
525
    auto x2 = rng.initialize(backend->create_tensor(element::f32, shape_2));
526 527

    auto make_graph = [shape_0, shape_1, shape_2]() {
528 529 530
        auto X0 = make_shared<op::Parameter>(element::f32, shape_0);
        auto X1 = make_shared<op::Parameter>(element::f32, shape_1);
        auto X2 = make_shared<op::Parameter>(element::f32, shape_2);
531
        return make_shared<Function>(make_shared<op::Concat>(NodeVector{X0, X1, X2}, 0),
532 533
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1, X2});
    };
534
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1, x2}, .01f, .01f));
535 536
}

537
NGRAPH_TEST(${BACKEND_NAME}, backwards_concat_axis_1)
538
{
539
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
540 541

    test::Uniform<float> rng(-1.0f, 1.0f);
542
    Shape shape_0{2, 3};
543
    auto x0 = rng.initialize(backend->create_tensor(element::f32, shape_0));
544
    Shape shape_1{2, 2};
545
    auto x1 = rng.initialize(backend->create_tensor(element::f32, shape_1));
546
    Shape shape_2{2, 1};
547
    auto x2 = rng.initialize(backend->create_tensor(element::f32, shape_2));
548 549

    auto make_graph = [shape_0, shape_1, shape_2]() {
550 551 552
        auto X0 = make_shared<op::Parameter>(element::f32, shape_0);
        auto X1 = make_shared<op::Parameter>(element::f32, shape_1);
        auto X2 = make_shared<op::Parameter>(element::f32, shape_2);
553
        return make_shared<Function>(make_shared<op::Concat>(NodeVector{X0, X1, X2}, 1),
554 555
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1, X2});
    };
556
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1, x2}, .01f, .01f));
557 558
}

559
NGRAPH_TEST(${BACKEND_NAME}, backwards_ceiling)
560
{
561
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
562 563 564 565 566 567

    // The numeric derivative and the symbolic one may disagree near integers, so we will dance around
    // them.
    test::Uniform<float> rng_minusone(-0.95f, -0.05f);
    test::Uniform<float> rng_plusone(0.05f, 0.95f);
    test::Uniform<float> rng_plustwo(1.05f, 1.95f);
568
    Shape shape{2, 3};
569 570

    auto make_graph = [shape]() {
571
        auto X = make_shared<op::Parameter>(element::f32, shape);
572 573
        return make_shared<Function>(make_shared<op::Ceiling>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
574 575
    };

576
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
577
    {
578
        auto x_minusone = rng_minusone.initialize(backend->create_tensor<float>(shape));
579

580
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_minusone}, .01f, .01f));
581

582
        auto x_plusone = rng_plusone.initialize(backend->create_tensor<float>(shape));
583

584
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_plusone}, .01f, .01f));
585

586
        auto x_plustwo = rng_plustwo.initialize(backend->create_tensor<float>(shape));
587

588
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_plustwo}, .01f, .01f));
589 590 591
    }
}

592
NGRAPH_TEST(${BACKEND_NAME}, backwards_cos)
593
{
594
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
595 596

    test::Uniform<float> rng(-10.0f, 10.0f);
597
    Shape shape{2, 3};
598
    auto make_graph = [shape]() {
599
        auto X = make_shared<op::Parameter>(element::f32, shape);
600 601
        return make_shared<Function>(make_shared<op::Cos>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
602 603
    };

604
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
605
    {
606
        auto x = rng.initialize(backend->create_tensor<float>(shape));
607

608
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
609 610 611
    }
}

612
NGRAPH_TEST(${BACKEND_NAME}, backwards_cosh)
613
{
614
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
615 616

    test::Uniform<float> rng(-10.0f, 10.0f);
617
    Shape shape{2, 3};
618
    auto make_graph = [shape]() {
619
        auto X = make_shared<op::Parameter>(element::f32, shape);
620 621
        return make_shared<Function>(make_shared<op::Cosh>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
622 623
    };

624
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
625
    {
626
        auto x = rng.initialize(backend->create_tensor<float>(shape));
627

628
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
629 630 631
    }
}

632
NGRAPH_TEST(${BACKEND_NAME}, backwards_divide)
633
{
634
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
635

636 637 638
    test::Uniform<float> rng(-1.0f, 1.0f);
    test::Uniform<float> rng1(1.0f, 2.0f);
    test::Uniform<float> rng2(-2.0f, -1.0f);
639
    Shape shape{2, 3};
640 641 642
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
    auto x1 = rng1.initialize(backend->create_tensor<float>(shape));
    auto x2 = rng2.initialize(backend->create_tensor<float>(shape));
643

644
    auto make_graph = [shape]() {
645 646
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
647
        return make_shared<Function>(X0 / X1, std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
648
    };
649 650
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x2}, .01f, .01f));
Scott Cyphers's avatar
Scott Cyphers committed
651
}
652

653
NGRAPH_TEST(${BACKEND_NAME}, backwards_dot_scalar_scalar)
654
{
655
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
656

657
    test::Uniform<float> rng(-1.0f, 1.0f);
658 659
    Shape shape0{};
    Shape shape1{};
660 661
    auto x0 = rng.initialize(backend->create_tensor<float>(shape0));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape1));
662 663

    auto make_graph = [shape0, shape1]() {
664 665
        auto X0 = make_shared<op::Parameter>(element::f32, shape0);
        auto X1 = make_shared<op::Parameter>(element::f32, shape1);
666 667 668
        return make_shared<Function>(make_shared<op::Dot>(X0, X1),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
    };
669
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
670 671
}

672
NGRAPH_TEST(${BACKEND_NAME}, backwards_dot_scalar_tensor)
673
{
674
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
675

676
    test::Uniform<float> rng(-1.0f, 1.0f);
677 678
    Shape shape0{};
    Shape shape1{3, 4};
679 680
    auto x0 = rng.initialize(backend->create_tensor<float>(shape0));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape1));
681 682

    auto make_graph = [shape0, shape1]() {
683 684
        auto X0 = make_shared<op::Parameter>(element::f32, shape0);
        auto X1 = make_shared<op::Parameter>(element::f32, shape1);
685 686 687
        return make_shared<Function>(make_shared<op::Dot>(X0, X1),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
    };
688
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
689 690
}

691
NGRAPH_TEST(${BACKEND_NAME}, backwards_dot_tensor_scalar)
692
{
693
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
694

695
    test::Uniform<float> rng(-1.0f, 1.0f);
696 697
    Shape shape0{3, 4};
    Shape shape1{};
698 699
    auto x0 = rng.initialize(backend->create_tensor<float>(shape0));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape1));
700 701

    auto make_graph = [shape0, shape1]() {
702 703
        auto X0 = make_shared<op::Parameter>(element::f32, shape0);
        auto X1 = make_shared<op::Parameter>(element::f32, shape1);
704 705 706
        return make_shared<Function>(make_shared<op::Dot>(X0, X1),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
    };
707
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
708 709
}

710
NGRAPH_TEST(${BACKEND_NAME}, backwards_dot_vector_vector)
711
{
712
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
713

714
    test::Uniform<float> rng(-1.0f, 1.0f);
715 716
    Shape shape0{3};
    Shape shape1{3};
717 718
    auto x0 = rng.initialize(backend->create_tensor<float>(shape0));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape1));
719 720

    auto make_graph = [shape0, shape1]() {
721 722
        auto X0 = make_shared<op::Parameter>(element::f32, shape0);
        auto X1 = make_shared<op::Parameter>(element::f32, shape1);
723 724 725
        return make_shared<Function>(make_shared<op::Dot>(X0, X1),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
    };
726
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
727 728
}

729
NGRAPH_TEST(${BACKEND_NAME}, backwards_dot_tensor_vector)
730
{
731
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
732

733
    test::Uniform<float> rng(-1.0f, 1.0f);
734 735
    Shape shape0{4, 3};
    Shape shape1{3};
736 737
    auto x0 = rng.initialize(backend->create_tensor<float>(shape0));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape1));
738 739

    auto make_graph = [shape0, shape1]() {
740 741
        auto X0 = make_shared<op::Parameter>(element::f32, shape0);
        auto X1 = make_shared<op::Parameter>(element::f32, shape1);
742 743 744
        return make_shared<Function>(make_shared<op::Dot>(X0, X1),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
    };
745
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
746 747
}

748
NGRAPH_TEST(${BACKEND_NAME}, backwards_dot_tensor2_tensor2)
749
{
750
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
751

752
    test::Uniform<float> rng(-1.0f, 1.0f);
753 754
    Shape shape0{4, 3};
    Shape shape1{3, 5};
755 756
    auto x0 = rng.initialize(backend->create_tensor<float>(shape0));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape1));
757 758

    auto make_graph = [shape0, shape1]() {
759 760
        auto X0 = make_shared<op::Parameter>(element::f32, shape0);
        auto X1 = make_shared<op::Parameter>(element::f32, shape1);
761 762
        return make_shared<Function>(make_shared<op::Dot>(X0, X1),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
Adam Procter's avatar
Adam Procter committed
763
    };
764
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
Adam Procter's avatar
Adam Procter committed
765 766
}

767
NGRAPH_TEST(${BACKEND_NAME}, backwards_dot_tensor3_tensor3)
Adam Procter's avatar
Adam Procter committed
768
{
769
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
Adam Procter's avatar
Adam Procter committed
770 771

    test::Uniform<float> rng(-1.0f, 1.0f);
772 773
    Shape shape0{2, 4, 3};
    Shape shape1{4, 3, 3};
774 775
    auto x0 = rng.initialize(backend->create_tensor<float>(shape0));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape1));
Adam Procter's avatar
Adam Procter committed
776 777

    auto make_graph = [shape0, shape1]() {
778 779
        auto X0 = make_shared<op::Parameter>(element::f32, shape0);
        auto X1 = make_shared<op::Parameter>(element::f32, shape1);
Adam Procter's avatar
Adam Procter committed
780 781
        return make_shared<Function>(make_shared<op::Dot>(X0, X1, 2),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
782
    };
783
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
784 785
}

786
NGRAPH_TEST(${BACKEND_NAME}, backwards_exp)
Scott Cyphers's avatar
Scott Cyphers committed
787
{
788
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
Scott Cyphers's avatar
Scott Cyphers committed
789

790
    test::Uniform<float> rng(-1.0f, 1.0f);
791
    Shape shape{2, 3};
792
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
Scott Cyphers's avatar
Scott Cyphers committed
793 794

    auto make_graph = [shape]() {
795
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
796 797
        return make_shared<Function>(make_shared<op::Exp>(X0),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
Scott Cyphers's avatar
Scott Cyphers committed
798
    };
799
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
Scott Cyphers's avatar
Scott Cyphers committed
800 801
}

802
NGRAPH_TEST(${BACKEND_NAME}, backwards_floor)
803
{
804
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
805 806 807 808 809 810

    // The numeric derivative and the symbolic one may disagree near integers, so we will dance around
    // them.
    test::Uniform<float> rng_minusone(-0.95f, -0.05f);
    test::Uniform<float> rng_plusone(0.05f, 0.95f);
    test::Uniform<float> rng_plustwo(1.05f, 1.95f);
811
    Shape shape{2, 3};
812 813

    auto make_graph = [shape]() {
814
        auto X = make_shared<op::Parameter>(element::f32, shape);
815 816
        return make_shared<Function>(make_shared<op::Floor>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
817 818
    };

819
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
820
    {
821
        auto x_minusone = rng_minusone.initialize(backend->create_tensor<float>(shape));
822

823
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_minusone}, .01f, .01f));
824

825
        auto x_plusone = rng_plusone.initialize(backend->create_tensor<float>(shape));
826

827
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_plusone}, .01f, .01f));
828

829
        auto x_plustwo = rng_plustwo.initialize(backend->create_tensor<float>(shape));
830

831
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_plustwo}, .01f, .01f));
832 833 834
    }
}

835
NGRAPH_TEST(${BACKEND_NAME}, backwards_log)
Scott Cyphers's avatar
Scott Cyphers committed
836
{
837
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
Scott Cyphers's avatar
Scott Cyphers committed
838

839
    test::Uniform<float> rng(1.0f, 2.0f);
840
    Shape shape{2, 3};
841
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
Scott Cyphers's avatar
Scott Cyphers committed
842 843

    auto make_graph = [shape]() {
844
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
845 846
        return make_shared<Function>(make_shared<op::Log>(X0),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
Scott Cyphers's avatar
Scott Cyphers committed
847
    };
848
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
849 850
}

851
NGRAPH_TEST(${BACKEND_NAME}, backwards_maximum)
852
{
853
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
854

855
    test::Uniform<float> rng(-1.0f, 1.0f);
856
    Shape shape{2, 3};
857 858
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape));
859 860

    auto make_graph = [shape]() {
861 862
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
863 864 865
        return make_shared<Function>(make_shared<op::Maximum>(X0, X1),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
    };
866
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
867 868
}

869
NGRAPH_TEST(${BACKEND_NAME}, backwards_minimum)
870
{
871
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
872

873
    test::Uniform<float> rng(-1.0f, 1.0f);
874
    Shape shape{2, 3};
875 876
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape));
877 878

    auto make_graph = [shape]() {
879 880
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
881 882 883
        return make_shared<Function>(make_shared<op::Minimum>(X0, X1),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
    };
884
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
885 886
}

887
NGRAPH_TEST(${BACKEND_NAME}, backwards_multiply)
888
{
889
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
890

891
    test::Uniform<float> rng(-1.0f, 1.0f);
892
    Shape shape{2, 3};
893 894
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape));
895

896
    auto make_graph = [shape]() {
897 898
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
899
        return make_shared<Function>(X0 * X1, std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
900
    };
901
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
902
}
Scott Cyphers's avatar
Scott Cyphers committed
903

904
NGRAPH_TEST(${BACKEND_NAME}, backwards_negative)
Scott Cyphers's avatar
Scott Cyphers committed
905
{
906
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
Scott Cyphers's avatar
Scott Cyphers committed
907

908
    test::Uniform<float> rng(-1.0f, 1.0f);
909
    Shape shape{2, 3};
910
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
Scott Cyphers's avatar
Scott Cyphers committed
911 912

    auto make_graph = [shape]() {
913
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
914
        return make_shared<Function>(-X0, std::vector<std::shared_ptr<op::Parameter>>{X0});
Scott Cyphers's avatar
Scott Cyphers committed
915
    };
916
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
Scott Cyphers's avatar
Scott Cyphers committed
917 918
}

919
NGRAPH_TEST(${BACKEND_NAME}, backwards_parameter)
Scott Cyphers's avatar
Scott Cyphers committed
920
{
921
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
Scott Cyphers's avatar
Scott Cyphers committed
922

923
    test::Uniform<float> rng(-1.0f, 1.0f);
924
    Shape shape{2, 3};
925
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
Scott Cyphers's avatar
Scott Cyphers committed
926
    auto make_graph = [shape]() {
927
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
928
        return make_shared<Function>(X0, std::vector<std::shared_ptr<op::Parameter>>{X0});
Scott Cyphers's avatar
Scott Cyphers committed
929
    };
930
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
931 932
}

933
NGRAPH_TEST(${BACKEND_NAME}, backwards_power)
934
{
935
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
936 937 938

    test::Uniform<float> rng_neg(-5.0f, -0.5f);
    test::Uniform<float> rng_pos(0.5f, 5.0f);
939
    Shape shape{2, 3};
940 941

    auto make_graph = [shape]() {
942 943
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
944 945 946 947
        return make_shared<Function>(std::make_shared<op::Power>(X0, X1),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
    };

948 949
    auto x0 = rng_neg.initialize(backend->create_tensor<float>(shape));
    auto x1 = rng_pos.initialize(backend->create_tensor<float>(shape));
950

951
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
952

953 954
    x0 = rng_pos.initialize(backend->create_tensor<float>(shape));
    x1 = rng_neg.initialize(backend->create_tensor<float>(shape));
955

956
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
957

958 959
    x0 = rng_pos.initialize(backend->create_tensor<float>(shape));
    x1 = rng_pos.initialize(backend->create_tensor<float>(shape));
960

961
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
962 963
}

964
NGRAPH_TEST(${BACKEND_NAME}, backwards_relu)
965
{
966
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
967 968 969 970

    test::Uniform<float> rng_neg(-1.0f, -0.01f);
    test::Uniform<float> rng_pos(0.01f, 1.0f);
    Shape shape{2, 3};
971 972
    auto x0 = rng_neg.initialize(backend->create_tensor<float>(shape));
    auto x1 = rng_pos.initialize(backend->create_tensor<float>(shape));
973 974 975 976 977 978 979 980 981

    auto make_graph = [shape]() {
        auto X = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Relu>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
    };

    for (auto i = 0; i < ${TEST_LOOPS}; i++)
    {
982
        auto x_neg = rng_neg.initialize(backend->create_tensor<float>(shape));
983

984
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_neg}, .01f, .01f));
985

986
        auto x_pos = rng_pos.initialize(backend->create_tensor<float>(shape));
987

988
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_pos}, .01f, .01f));
989 990 991
    }
}

992
NGRAPH_TEST(${BACKEND_NAME}, backwards_replace_slice)
993
{
994
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
995 996

    test::Uniform<float> rng(-10.0f, 10.0f);
997 998
    Shape shape_x{5, 5};
    Shape shape_y{2, 2};
999
    auto make_graph = [shape_x, shape_y]() {
1000 1001
        auto X = make_shared<op::Parameter>(element::f32, shape_x);
        auto Y = make_shared<op::Parameter>(element::f32, shape_y);
1002 1003 1004 1005 1006
        return make_shared<Function>(
            make_shared<op::ReplaceSlice>(X, Y, Coordinate{2, 3}, Coordinate{4, 5}),
            std::vector<std::shared_ptr<op::Parameter>>{X, Y});
    };

1007
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
1008
    {
1009 1010
        auto x = rng.initialize(backend->create_tensor<float>(shape_x));
        auto y = rng.initialize(backend->create_tensor<float>(shape_y));
1011

1012
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x, y}, .01f, .01f));
1013 1014 1015
    }
}

1016
NGRAPH_TEST(${BACKEND_NAME}, backwards_reshape)
1017
{
1018
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1019

1020
    test::Uniform<float> rng(-1.0f, 1.0f);
1021
    Shape shape{3, 4};
1022
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
1023 1024

    auto make_graph = [shape]() {
1025
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
1026 1027 1028
        return make_shared<Function>(make_shared<op::Reshape>(X0, AxisVector{1, 0}, Shape{4, 3}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
1029
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
Scott Cyphers's avatar
Scott Cyphers committed
1030 1031
}

1032
NGRAPH_TEST(${BACKEND_NAME}, backwards_select)
1033
{
1034
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1035 1036

    test::Uniform<float> rng(-10.0f, 10.0f);
1037
    Shape shape{2, 3};
1038
    auto make_graph = [shape]() {
1039 1040 1041
        auto X0 = make_shared<op::Parameter>(element::boolean, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
        auto X2 = make_shared<op::Parameter>(element::f32, shape);
1042 1043 1044 1045
        return make_shared<Function>(make_shared<op::Select>(X0, X1, X2),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1, X2});
    };

1046
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
1047
    {
1048
        auto x0 = backend->create_tensor(element::boolean, shape);
1049
        write_vector(x0, vector<char>{0, 1, 0, 1, 0, 1});
1050 1051 1052 1053 1054
        auto x1 = rng.initialize(backend->create_tensor<float>(shape));
        auto x2 = rng.initialize(backend->create_tensor<float>(shape));

        EXPECT_TRUE(autodiff_numeric_compare_selective<float>(
            backend, make_graph, {x0, x1, x2}, .01f, .01f, std::vector<bool>{false, true, true}));
1055 1056 1057
    }
}

1058
NGRAPH_TEST(${BACKEND_NAME}, backwards_select_nested)
1059
{
1060
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1061 1062

    test::Uniform<float> rng(-10.0f, 10.0f);
1063
    Shape shape{2, 3};
1064
    auto make_graph = [shape]() {
1065 1066 1067
        auto X0 = make_shared<op::Parameter>(element::boolean, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
        auto X2 = make_shared<op::Parameter>(element::f32, shape);
1068 1069 1070 1071
        return make_shared<Function>(make_shared<op::Select>(X0, X1 + X2, X2 - X1),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1, X2});
    };

1072
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
1073
    {
1074
        auto x0 = backend->create_tensor(element::boolean, shape);
1075
        write_vector(x0, vector<char>{0, 1, 0, 1, 0, 1});
1076 1077 1078 1079 1080
        auto x1 = rng.initialize(backend->create_tensor<float>(shape));
        auto x2 = rng.initialize(backend->create_tensor<float>(shape));

        EXPECT_TRUE(autodiff_numeric_compare_selective<float>(
            backend, make_graph, {x0, x1, x2}, .01f, .01f, std::vector<bool>{false, true, true}));
1081 1082 1083
    }
}

1084
NGRAPH_TEST(${BACKEND_NAME}, backwards_sign)
1085
{
1086
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1087 1088 1089 1090 1091

    // The numeric derivative and the symbolic one may disagree around 0, so we will dance around
    // that point by skipping (-0.01,0.01).
    test::Uniform<float> rng_neg(-1.0f, -0.01f);
    test::Uniform<float> rng_pos(0.01f, 1.0f);
1092
    Shape shape{2, 3};
1093 1094

    auto make_graph = [shape]() {
1095
        auto X = make_shared<op::Parameter>(element::f32, shape);
1096 1097
        return make_shared<Function>(make_shared<op::Sign>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
1098 1099
    };

1100
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
1101
    {
1102
        auto x_neg = rng_neg.initialize(backend->create_tensor<float>(shape));
1103

1104
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_neg}, .01f, .01f));
1105

1106
        auto x_pos = rng_pos.initialize(backend->create_tensor<float>(shape));
1107

1108
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_pos}, .01f, .01f));
1109 1110 1111
    }
}

1112
NGRAPH_TEST(${BACKEND_NAME}, backwards_sin)
1113
{
1114
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1115 1116

    test::Uniform<float> rng(-10.0f, 10.0f);
1117
    Shape shape{2, 3};
1118
    auto make_graph = [shape]() {
1119
        auto X = make_shared<op::Parameter>(element::f32, shape);
1120 1121
        return make_shared<Function>(make_shared<op::Sin>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
1122 1123
    };

1124
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
1125
    {
1126
        auto x = rng.initialize(backend->create_tensor<float>(shape));
1127

1128
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
1129 1130 1131
    }
}

1132
NGRAPH_TEST(${BACKEND_NAME}, backwards_sinh)
1133
{
1134
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1135 1136

    test::Uniform<float> rng(-10.0f, 10.0f);
1137
    Shape shape{2, 3};
1138
    auto make_graph = [shape]() {
1139
        auto X = make_shared<op::Parameter>(element::f32, shape);
1140 1141
        return make_shared<Function>(make_shared<op::Sinh>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
1142 1143
    };

1144
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
1145
    {
1146
        auto x = rng.initialize(backend->create_tensor<float>(shape));
1147

1148
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
1149 1150 1151
    }
}

1152
NGRAPH_TEST(${BACKEND_NAME}, backwards_slice)
1153
{
1154
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1155
    test::Uniform<float> rng(-10.0f, 10.0f);
1156
    Shape shape{5, 5};
1157
    auto make_graph = [shape]() {
1158
        auto X = make_shared<op::Parameter>(element::f32, shape);
1159 1160 1161 1162
        return make_shared<Function>(make_shared<op::Slice>(X, Coordinate{2, 3}, Coordinate{4, 5}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
    };

1163
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
1164
    {
1165
        auto x = rng.initialize(backend->create_tensor<float>(shape));
1166

1167
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
1168 1169 1170
    }
}

1171
NGRAPH_TEST(${BACKEND_NAME}, backwards_softmax_all)
1172
{
1173
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1174

adstraw's avatar
adstraw committed
1175
    test::Uniform<float> rng(-1.0f, 1.0f);
1176
    Shape shape{2, 3};
1177
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
adstraw's avatar
adstraw committed
1178

1179
    auto make_graph = [shape]() {
adstraw's avatar
adstraw committed
1180 1181 1182
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Softmax>(X0, AxisSet{0, 1}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
1183
    };
1184
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
adstraw's avatar
adstraw committed
1185
}
1186

1187
NGRAPH_TEST(${BACKEND_NAME}, backwards_softmax_axis)
adstraw's avatar
adstraw committed
1188
{
1189
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1190

adstraw's avatar
adstraw committed
1191 1192
    test::Uniform<float> rng(-1.0f, 1.0f);
    Shape shape{2, 3};
1193
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
adstraw's avatar
adstraw committed
1194 1195 1196 1197 1198 1199

    auto make_graph = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Softmax>(X0, AxisSet{1}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
1200
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
adstraw's avatar
adstraw committed
1201 1202
}

1203
NGRAPH_TEST(${BACKEND_NAME}, backwards_softmax_underflow)
adstraw's avatar
adstraw committed
1204
{
1205
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
adstraw's avatar
adstraw committed
1206 1207 1208 1209

    auto low = std::numeric_limits<float>::lowest();

    Shape shape{2, 3};
1210
    auto x0 = backend->create_tensor(element::f32, shape);
adstraw's avatar
adstraw committed
1211 1212 1213 1214 1215 1216 1217
    copy_data(x0, vector<float>{low, 1, 2, 3, 4, 5});

    auto make_graph = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Softmax>(X0, AxisSet{0, 1}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
1218
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0}, .01f, .01f));
adstraw's avatar
adstraw committed
1219 1220
}

1221
NGRAPH_TEST(${BACKEND_NAME}, backwards_softmax_3d)
adstraw's avatar
adstraw committed
1222
{
1223
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
adstraw's avatar
adstraw committed
1224 1225 1226

    test::Uniform<float> rng(-1.0f, 1.0f);
    Shape shape{2, 3, 4};
1227
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
adstraw's avatar
adstraw committed
1228 1229 1230 1231 1232 1233

    auto make_graph0 = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Softmax>(X0, AxisSet{0}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
1234
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph0, {x0}, .01f, .01f));
adstraw's avatar
adstraw committed
1235 1236 1237 1238 1239 1240

    auto make_graph1 = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Softmax>(X0, AxisSet{1}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
1241
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph1, {x0}, .01f, .01f));
adstraw's avatar
adstraw committed
1242 1243 1244 1245 1246 1247

    auto make_graph2 = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Softmax>(X0, AxisSet{2}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
1248
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph2, {x0}, .01f, .01f));
adstraw's avatar
adstraw committed
1249 1250 1251 1252 1253 1254

    auto make_graph01 = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Softmax>(X0, AxisSet{0, 1}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
1255
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph01, {x0}, .01f, .01f));
adstraw's avatar
adstraw committed
1256 1257 1258 1259 1260 1261

    auto make_graph02 = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Softmax>(X0, AxisSet{0, 2}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
1262
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph02, {x0}, .01f, .01f));
adstraw's avatar
adstraw committed
1263 1264 1265 1266 1267 1268

    auto make_graph12 = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Softmax>(X0, AxisSet{1, 2}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
1269
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph12, {x0}, .01f, .01f));
adstraw's avatar
adstraw committed
1270 1271 1272 1273 1274 1275

    auto make_graph012 = [shape]() {
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Softmax>(X0, AxisSet{0, 1, 2}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X0});
    };
1276
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph012, {x0}, .01f, .01f));
1277 1278
}

1279
NGRAPH_TEST(${BACKEND_NAME}, backwards_subtract)
Scott Cyphers's avatar
Scott Cyphers committed
1280
{
1281
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
Scott Cyphers's avatar
Scott Cyphers committed
1282

1283
    test::Uniform<float> rng(-1.0f, 1.0f);
1284
    Shape shape{2, 3};
1285 1286
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape));
Scott Cyphers's avatar
Scott Cyphers committed
1287 1288

    auto make_graph = [shape]() {
1289 1290
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
1291
        return make_shared<Function>(X0 - X1, std::vector<std::shared_ptr<op::Parameter>>{X0, X1});
Scott Cyphers's avatar
Scott Cyphers committed
1292
    };
1293
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1}, .01f, .01f));
Scott Cyphers's avatar
Scott Cyphers committed
1294
}
Scott Cyphers's avatar
Scott Cyphers committed
1295

1296
NGRAPH_TEST(${BACKEND_NAME}, backwards_sum_v2s)
1297
{
1298
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1299 1300

    test::Uniform<float> rng(-1.0f, 1.0f);
1301
    Shape shape{8};
1302
    auto x = rng.initialize(backend->create_tensor<float>(shape));
1303 1304

    auto make_graph = [shape]() {
1305
        auto X = make_shared<op::Parameter>(element::f32, shape);
1306 1307 1308
        return make_shared<Function>(make_shared<op::Sum>(X, AxisSet{0}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
    };
1309
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
1310 1311
}

1312
NGRAPH_TEST(${BACKEND_NAME}, backwards_sum_m2s)
1313
{
1314
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1315 1316

    test::Uniform<float> rng(-1.0f, 1.0f);
1317
    Shape shape{8, 9};
1318
    auto x = rng.initialize(backend->create_tensor<float>(shape));
1319 1320

    auto make_graph = [shape]() {
1321
        auto X = make_shared<op::Parameter>(element::f32, shape);
1322 1323 1324
        return make_shared<Function>(make_shared<op::Sum>(X, AxisSet{0, 1}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
    };
1325
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
1326 1327
}

1328
NGRAPH_TEST(${BACKEND_NAME}, backwards_sum_m2v_0)
1329
{
1330
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1331 1332

    test::Uniform<float> rng(-1.0f, 1.0f);
1333
    Shape shape{8, 9};
1334
    auto x = rng.initialize(backend->create_tensor<float>(shape));
1335 1336

    auto make_graph = [shape]() {
1337
        auto X = make_shared<op::Parameter>(element::f32, shape);
1338 1339 1340
        return make_shared<Function>(make_shared<op::Sum>(X, AxisSet{0}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
    };
1341
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
1342 1343
}

1344
NGRAPH_TEST(${BACKEND_NAME}, backwards_sum_m2v_1)
1345
{
1346
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1347 1348

    test::Uniform<float> rng(-1.0f, 1.0f);
1349
    Shape shape{8, 9};
1350
    auto x = rng.initialize(backend->create_tensor<float>(shape));
1351 1352

    auto make_graph = [shape]() {
1353
        auto X = make_shared<op::Parameter>(element::f32, shape);
1354 1355 1356
        return make_shared<Function>(make_shared<op::Sum>(X, AxisSet{1}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
    };
1357
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
1358 1359
}

1360
NGRAPH_TEST(${BACKEND_NAME}, backwards_tan)
1361
{
1362
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1363 1364 1365 1366 1367 1368 1369 1370

    auto pi = 3.14159f;

    // Stay away from the asymptotes at 6 and 12 o'clock.
    auto slop = 0.1f;
    test::Uniform<float> rng_r(-pi / 2 + slop, pi / 2 - slop);
    test::Uniform<float> rng_l(pi / 2 + slop, (3 * pi) / 2 - slop);

1371
    Shape shape{2, 3};
1372 1373

    auto make_graph = [shape]() {
1374
        auto X = make_shared<op::Parameter>(element::f32, shape);
1375 1376
        return make_shared<Function>(make_shared<op::Tan>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
1377 1378
    };

1379
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
1380
    {
1381
        auto x_r = rng_r.initialize(backend->create_tensor<float>(shape));
1382

1383
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_r}, .01f, .01f));
1384

1385
        auto x_l = rng_l.initialize(backend->create_tensor<float>(shape));
1386

1387
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x_l}, .01f, .01f));
1388 1389 1390
    }
}

1391
NGRAPH_TEST(${BACKEND_NAME}, backwards_tanh)
1392
{
1393
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1394 1395

    test::Uniform<float> rng(-10.0f, 10.0f);
1396
    Shape shape{2, 3};
1397
    auto make_graph = [shape]() {
1398
        auto X = make_shared<op::Parameter>(element::f32, shape);
1399 1400
        return make_shared<Function>(make_shared<op::Tanh>(X),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
1401 1402
    };

1403
    for (auto i = 0; i < ${TEST_LOOPS}; i++)
1404
    {
1405
        auto x = rng.initialize(backend->create_tensor<float>(shape));
1406

1407
        EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
1408 1409 1410
    }
}

1411
NGRAPH_TEST(${BACKEND_NAME}, backwards_abc)
Scott Cyphers's avatar
Scott Cyphers committed
1412
{
1413
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
Scott Cyphers's avatar
Scott Cyphers committed
1414

1415
    test::Uniform<float> rng(-1.0f, 1.0f);
1416
    Shape shape{2, 3};
1417 1418 1419
    auto x0 = rng.initialize(backend->create_tensor<float>(shape));
    auto x1 = rng.initialize(backend->create_tensor<float>(shape));
    auto x2 = rng.initialize(backend->create_tensor<float>(shape));
Scott Cyphers's avatar
Scott Cyphers committed
1420 1421

    auto make_graph = [shape]() {
1422 1423 1424
        auto X0 = make_shared<op::Parameter>(element::f32, shape);
        auto X1 = make_shared<op::Parameter>(element::f32, shape);
        auto X2 = make_shared<op::Parameter>(element::f32, shape);
1425 1426
        return make_shared<Function>((X0 + X1) * X2,
                                     std::vector<std::shared_ptr<op::Parameter>>{X0, X1, X2});
Scott Cyphers's avatar
Scott Cyphers committed
1427
    };
1428
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x0, x1, x2}, .01f, .01f));
Scott Cyphers's avatar
Scott Cyphers committed
1429
}
1430

1431
NGRAPH_TEST(${BACKEND_NAME}, backwards_reverse_3d_02)
1432
{
1433
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1434 1435

    test::Uniform<float> rng(-1.0f, 1.0f);
1436
    Shape shape{2, 4, 5};
1437
    auto x = rng.initialize(backend->create_tensor(element::f32, shape));
1438 1439 1440 1441 1442 1443

    auto make_graph = [shape]() {
        auto X = make_shared<op::Parameter>(element::f32, shape);
        return make_shared<Function>(make_shared<op::Reverse>(X, AxisSet{0, 2}),
                                     std::vector<std::shared_ptr<op::Parameter>>{X});
    };
1444
    EXPECT_TRUE(autodiff_numeric_compare<float>(backend, make_graph, {x}, .01f, .01f));
1445
}
1446

1447
NGRAPH_TEST(${BACKEND_NAME}, backwards_maxpool_n4c1h4w4_kh2kw2_sh1sw1)
1448
{
1449
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1450
    Shape shape_a{4, 1, 4, 4}; //in NCHW
1451 1452 1453 1454 1455
    Shape maxpool_shape{4, 1, 3, 3};

    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape window_shape{2, 2};
    auto window_movement_strides = Strides{1, 1};
1456
    auto maxpool = make_shared<op::MaxPool>(A, window_shape, window_movement_strides);
1457
    auto f = make_shared<Function>(maxpool, op::ParameterVector{A});
1458
    shared_ptr<runtime::TensorView> ep = backend->create_tensor(element::f32, maxpool_shape);
1459 1460
    vector<float> dataEp(shape_size(maxpool_shape), 4);

1461 1462
    shared_ptr<runtime::TensorView> input = backend->create_tensor(element::f32, shape_a);
    shared_ptr<runtime::TensorView> output = backend->create_tensor(element::f32, shape_a);
1463 1464

    vector<float> dataInput{11, 65, 44, 28, 31, 33, 21, 66, 40, 49, 69, 57, 47, 30, 24, 27,
pthoreho's avatar
pthoreho committed
1465 1466 1467
                            13, 56, 46, 60, 61, 41, 25, 42, 48, 53, 51, 43, 59, 58, 29, 71,
                            17, 22, 72, 18, 39, 35, 15, 38, 64, 52, 73, 67, 62, 50, 10, 68,
                            45, 63, 16, 14, 55, 54, 37, 20, 36, 12, 70, 34, 19, 26, 32, 23};
1468 1469

    vector<float> expected{//delta
1470 1471 1472
                           0, 8, 0, 0, 0, 0, 0, 4, 0, 8, 16, 0, 0, 0, 0,  0, 0, 4, 0, 4, 8,  0,
                           0, 0, 0, 4, 4, 0, 4, 4, 0, 4, 0,  0, 8, 0, 4,  0, 0, 0, 8, 0, 16, 0,
                           0, 0, 0, 0, 0, 8, 0, 0, 4, 0, 4,  0, 4, 0, 16, 0, 0, 0, 0, 0};
1473 1474 1475 1476 1477 1478

    copy_data(ep, dataEp);
    copy_data(input, dataInput);

    auto C = make_shared<op::Parameter>(element::f32, maxpool_shape);
    auto df = autodiff::backprop_function(f);
1479
    backend->call(df, {output}, {input, ep});
1480 1481 1482
    ASSERT_TRUE(read_vector<float>(output) == expected);
}

1483
NGRAPH_TEST(${BACKEND_NAME}, backwards_maxpool_n2c1h5w5_kh3kw3_sh2sw2)
1484
{
1485
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1486

1487
    Shape shape_a{1, 2, 5, 5}; //in NCHW
1488 1489 1490 1491 1492
    Shape maxpool_shape{1, 2, 2, 2};

    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape window_shape{3, 3};
    auto window_movement_strides = Strides{2, 2};
1493
    auto maxpool = make_shared<op::MaxPool>(A, window_shape, window_movement_strides);
1494
    auto f = make_shared<Function>(maxpool, op::ParameterVector{A});
1495

1496
    shared_ptr<runtime::TensorView> ep = backend->create_tensor(element::f32, maxpool_shape);
1497 1498
    vector<float> dataEp(shape_size(maxpool_shape), 4);

1499 1500
    shared_ptr<runtime::TensorView> input = backend->create_tensor(element::f32, shape_a);
    shared_ptr<runtime::TensorView> output = backend->create_tensor(element::f32, shape_a);
1501 1502

    vector<float> dataInput{58, 15, 51, 35, 18, 47, 31, 32, 52, 21, 36, 38, 57, 54, 25, 45, 23,
pthoreho's avatar
pthoreho committed
1503 1504
                            30, 16, 27, 48, 20, 41, 37, 43, 39, 22, 28, 33, 29, 12, 17, 44, 42,
                            19, 40, 10, 46, 34, 53, 26, 55, 50, 13, 24, 14, 49, 56, 59, 11};
1505 1506

    vector<float> expected{//delta
1507 1508 1509
                           4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0,
                           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,
                           0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0,  4, 4, 0};
1510 1511 1512 1513 1514 1515

    copy_data(ep, dataEp);
    copy_data(input, dataInput);

    auto C = make_shared<op::Parameter>(element::f32, maxpool_shape);
    auto df = autodiff::backprop_function(f);
1516
    backend->call(df, {output}, {input, ep});
1517
    ASSERT_TRUE(read_vector<float>(output) == expected);
1518
}