5719301a7e1386aa9ce7065fcb6944ee94f91169
[platform/upstream/dldt.git] / ngraph / test / copy.cpp
1 //*****************************************************************************
2 // Copyright 2017-2020 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //*****************************************************************************
16
17 #include <memory>
18 #include <string>
19
20 #include "gtest/gtest.h"
21
22 #include "ngraph/ngraph.hpp"
23 #include "ngraph/opsets/opset5.hpp"
24 #include "util/ndarray.hpp"
25 #include "util/test_tools.hpp"
26
27 NGRAPH_SUPPRESS_DEPRECATED_START
28
29 using namespace std;
30 using namespace ngraph;
31
32 template <typename OP>
33 bool check_unary()
34 {
35     Shape shape{1};
36     auto arg0 = make_shared<op::Parameter>(element::f32, shape);
37     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape)};
38
39     auto node = make_shared<OP>(arg0);
40     auto new_node = node->copy_with_new_inputs(new_args);
41
42     return (nullptr != new_node) && (new_args == new_node->input_values());
43 }
44
45 template <typename OP>
46 bool check_binary()
47 {
48     Shape shape{1};
49     auto arg0 = make_shared<op::Parameter>(element::f32, shape);
50     auto arg1 = make_shared<op::Parameter>(element::f32, shape);
51     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape),
52                           make_shared<op::Parameter>(element::f32, shape)};
53
54     auto node = make_shared<OP>(arg0, arg1);
55     auto new_node = node->copy_with_new_inputs(new_args);
56
57     return (nullptr != new_node) && (new_args == new_node->input_values());
58 }
59
60 TEST(copy, abs)
61 {
62     ASSERT_TRUE(check_unary<op::Abs>());
63 }
64
65 TEST(copy, acos)
66 {
67     ASSERT_TRUE(check_unary<op::Acos>());
68 }
69
70 TEST(copy, add)
71 {
72     ASSERT_TRUE(check_binary<op::Add>());
73 }
74
75 TEST(copy, asin)
76 {
77     ASSERT_TRUE(check_unary<op::Asin>());
78 }
79
80 TEST(copy, atan)
81 {
82     ASSERT_TRUE(check_unary<op::Atan>());
83 }
84
85 TEST(copy, broadcast)
86 {
87     Shape shape1{1};
88     auto arg0 = make_shared<op::Parameter>(element::f32, shape1);
89     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape1)};
90
91     Shape shape{4, 1, 3};
92     AxisSet axes{0, 2};
93
94     auto node = make_shared<op::Broadcast>(arg0, shape, axes);
95     auto new_node = node->copy_with_new_inputs(new_args);
96     auto node_cast = as_type_ptr<op::Broadcast>(new_node);
97     ASSERT_NE(node_cast, nullptr);
98
99     ASSERT_TRUE(nullptr != new_node);
100     ASSERT_TRUE(new_args == new_node->input_values());
101     ASSERT_TRUE(shape == node_cast->get_broadcast_shape());
102     ASSERT_TRUE(axes == node_cast->get_broadcast_axes());
103 }
104
105 TEST(copy, ceiling)
106 {
107     ASSERT_TRUE(check_unary<op::Ceiling>());
108 }
109
110 TEST(copy, concat)
111 {
112     Shape shape{1};
113     auto arg0 = make_shared<op::Parameter>(element::f32, shape);
114     auto arg1 = make_shared<op::Parameter>(element::f32, shape);
115     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape),
116                           make_shared<op::Parameter>(element::f32, shape)};
117     size_t axis = 0;
118     auto node = make_shared<op::Concat>(NodeVector{arg0, arg1}, axis);
119     auto new_node = node->clone_with_new_inputs(new_args);
120     auto node_cast = as_type_ptr<op::Concat>(new_node);
121     ASSERT_NE(node_cast, nullptr);
122
123     ASSERT_TRUE(nullptr != new_node);
124     ASSERT_TRUE(new_args == new_node->input_values());
125     ASSERT_TRUE(node_cast->get_concatenation_axis() == axis);
126 }
127
128 TEST(copy, constant)
129 {
130     Shape shape{};
131     vector<float> c{2.4f};
132     auto& et = element::f32;
133     auto node = op::Constant::create(et, shape, c);
134     auto new_node = node->clone_with_new_inputs(OutputVector{});
135     auto node_cast = as_type_ptr<op::Constant>(new_node);
136     ASSERT_NE(node_cast, nullptr);
137     ASSERT_TRUE(nullptr != new_node);
138     ASSERT_TRUE(OutputVector{} == new_node->input_values());
139     ASSERT_TRUE(node_cast->get_vector<float>() == c);
140     ASSERT_TRUE(node_cast->get_shape() == shape);
141     ASSERT_TRUE(node_cast->get_element_type() == et);
142 }
143
144 TEST(copy, convert)
145 {
146     Shape shape;
147     auto& et = element::f64;
148     auto arg0 = make_shared<op::Parameter>(element::f32, shape);
149     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape)};
150
151     auto node = make_shared<op::Convert>(arg0, et);
152     auto new_node = node->clone_with_new_inputs(new_args);
153     auto node_cast = as_type_ptr<op::Convert>(new_node);
154     ASSERT_NE(node_cast, nullptr);
155
156     ASSERT_TRUE(nullptr != new_node);
157     ASSERT_TRUE(new_args == new_node->input_values());
158     ASSERT_TRUE(et == node_cast->get_convert_element_type());
159 }
160
161 TEST(copy, cos)
162 {
163     ASSERT_TRUE(check_unary<op::Cos>());
164 }
165
166 TEST(copy, cosh)
167 {
168     ASSERT_TRUE(check_unary<op::Cosh>());
169 }
170
171 TEST(copy, divide)
172 {
173     ASSERT_TRUE(check_binary<op::Divide>());
174 }
175
176 TEST(copy, dot)
177 {
178     ASSERT_TRUE(check_binary<op::Dot>());
179 }
180
181 TEST(copy, equal)
182 {
183     ASSERT_TRUE(check_binary<op::Equal>());
184 }
185
186 TEST(copy, exp)
187 {
188     ASSERT_TRUE(check_unary<op::Exp>());
189 }
190
191 TEST(copy, floor)
192 {
193     ASSERT_TRUE(check_unary<op::Floor>());
194 }
195
196 TEST(copy, greater_eq)
197 {
198     ASSERT_TRUE(check_binary<op::GreaterEq>());
199 }
200
201 TEST(copy, greater)
202 {
203     ASSERT_TRUE(check_binary<op::Greater>());
204 }
205
206 TEST(copy, less_eq)
207 {
208     ASSERT_TRUE(check_binary<op::LessEq>());
209 }
210
211 TEST(copy, less)
212 {
213     ASSERT_TRUE(check_binary<op::Less>());
214 }
215
216 TEST(copy, log)
217 {
218     ASSERT_TRUE(check_unary<op::Log>());
219 }
220
221 TEST(copy, maximum)
222 {
223     ASSERT_TRUE(check_binary<op::Maximum>());
224 }
225
226 TEST(copy, minimum)
227 {
228     ASSERT_TRUE(check_binary<op::Minimum>());
229 }
230
231 TEST(copy, multiply)
232 {
233     ASSERT_TRUE(check_binary<op::Multiply>());
234 }
235
236 TEST(copy, negative)
237 {
238     ASSERT_TRUE(check_unary<op::Negative>());
239 }
240
241 TEST(copy, not_equal)
242 {
243     ASSERT_TRUE(check_binary<op::NotEqual>());
244 }
245
246 TEST(copy, parameter)
247 {
248     Shape shape{1};
249     auto node = make_shared<op::Parameter>(element::f32, shape);
250     auto new_node = node->clone_with_new_inputs({});
251     auto node_cast = as_type_ptr<op::Parameter>(new_node);
252     ASSERT_NE(node_cast, nullptr);
253
254     ASSERT_TRUE(nullptr != new_node);
255     ASSERT_TRUE(new_node->input_values().size() == 0);
256     ASSERT_TRUE(node->has_same_type(new_node));
257 }
258
259 TEST(copy, power)
260 {
261     ASSERT_TRUE(check_binary<op::Power>());
262 }
263
264 TEST(copy, reshape)
265 {
266     Shape shape_in{2, 3, 4};
267     AxisVector axes{0, 1, 2};
268     Shape shape_out{6, 4};
269
270     auto arg0 = make_shared<op::Parameter>(element::f32, shape_in);
271     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape_in)};
272
273     auto node = make_shared<op::Reshape>(arg0, axes, shape_out);
274     auto new_node = node->clone_with_new_inputs(new_args);
275     auto node_cast = as_type_ptr<op::Reshape>(new_node);
276     ASSERT_NE(node_cast, nullptr);
277
278     ASSERT_TRUE(nullptr != new_node);
279     ASSERT_TRUE(new_args == new_node->input_values());
280     ASSERT_TRUE(axes == node_cast->get_input_order());
281     ASSERT_TRUE(shape_out == node_cast->get_output_shape(0));
282 }
283
284 TEST(copy, select)
285 {
286     Shape shape{1};
287     auto arg0 = make_shared<op::Parameter>(element::boolean, shape);
288     auto arg1 = make_shared<op::Parameter>(element::f32, shape);
289     auto arg2 = make_shared<op::Parameter>(element::f32, shape);
290     OutputVector new_args{make_shared<op::Parameter>(element::boolean, shape),
291                           make_shared<op::Parameter>(element::f32, shape),
292                           make_shared<op::Parameter>(element::f32, shape)};
293
294     auto node = make_shared<op::Select>(arg0, arg1, arg2);
295     auto new_node = node->clone_with_new_inputs(new_args);
296     auto node_cast = as_type_ptr<op::Select>(new_node);
297     ASSERT_NE(node_cast, nullptr);
298
299     ASSERT_TRUE(nullptr != new_node);
300     ASSERT_TRUE(new_args == new_node->input_values());
301 }
302
303 TEST(copy, sign)
304 {
305     ASSERT_TRUE(check_unary<op::Sign>());
306 }
307
308 TEST(copy, sin)
309 {
310     ASSERT_TRUE(check_unary<op::Sin>());
311 }
312
313 TEST(copy, sinh)
314 {
315     ASSERT_TRUE(check_unary<op::Sinh>());
316 }
317
318 TEST(copy, slice)
319 {
320     Shape shape_in{2, 3, 4};
321     Coordinate lower{0, 0, 0};
322     Coordinate upper{2, 3, 4};
323     Strides strides{1, 1, 1};
324
325     auto arg0 = make_shared<op::Parameter>(element::f32, shape_in);
326     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape_in)};
327
328     auto node = make_shared<op::Slice>(arg0, lower, upper, strides);
329     auto new_node = node->clone_with_new_inputs(new_args);
330     auto node_cast = as_type_ptr<op::Slice>(new_node);
331     ASSERT_NE(node_cast, nullptr);
332
333     ASSERT_TRUE(nullptr != new_node);
334     ASSERT_TRUE(new_args == new_node->input_values());
335     ASSERT_TRUE(lower == node_cast->get_lower_bounds());
336     ASSERT_TRUE(upper == node_cast->get_upper_bounds());
337     ASSERT_TRUE(strides == node_cast->get_strides());
338 }
339
340 TEST(copy, subtract)
341 {
342     ASSERT_TRUE(check_binary<op::Subtract>());
343 }
344
345 TEST(copy, sum)
346 {
347     Shape shape{4, 3};
348     AxisSet axes{1};
349     auto arg0 = make_shared<op::Parameter>(element::f32, shape);
350
351     auto node = make_shared<op::Sum>(arg0, axes);
352     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape),
353                           node->input_value(1).get_node_shared_ptr()};
354     auto new_node = node->clone_with_new_inputs(new_args);
355     auto node_cast = as_type_ptr<op::Sum>(new_node);
356     ASSERT_NE(node_cast, nullptr);
357
358     ASSERT_TRUE(nullptr != new_node);
359     ASSERT_TRUE(new_args == new_node->input_values());
360     ASSERT_TRUE(axes == node_cast->get_reduction_axes());
361 }
362
363 TEST(copy, tan)
364 {
365     ASSERT_TRUE(check_unary<op::Tan>());
366 }
367
368 TEST(copy, tanh)
369 {
370     ASSERT_TRUE(check_unary<op::Tanh>());
371 }
372
373 TEST(copy, loop)
374 {
375     // That which we iterate over
376     auto X = make_shared<opset5::Parameter>(element::f32, Shape{32, 1, 10});
377     auto Y = make_shared<opset5::Parameter>(element::f32, Shape{32, 1, 10});
378     auto M = make_shared<opset5::Parameter>(element::f32, Shape{32, 1, 10});
379
380     // Set up the cell body, a function from (Xi, Yi) -> (Zo)
381     // Body parameters
382     auto current_iteration = make_shared<opset5::Parameter>(element::i64, Shape{});
383     auto Xi = make_shared<opset5::Parameter>(element::f32, PartialShape::dynamic());
384     auto Yi = make_shared<opset5::Parameter>(element::f32, PartialShape::dynamic());
385     auto M_body = make_shared<opset5::Parameter>(element::f32, PartialShape::dynamic());
386     auto body_condition =
387         std::make_shared<ngraph::opset5::Constant>(ngraph::element::boolean, ngraph::Shape{}, true);
388
389     auto trip_count =
390         std::make_shared<ngraph::opset5::Constant>(ngraph::element::i64, ngraph::Shape{}, 10);
391     auto exec_condition =
392         std::make_shared<ngraph::opset5::Constant>(ngraph::element::boolean, ngraph::Shape{}, true);
393     // Body
394     auto sum = make_shared<ngraph::opset5::Add>(Xi, Yi);
395     auto Zo = make_shared<ngraph::opset5::Multiply>(sum, M_body);
396     auto body = make_shared<ngraph::Function>(OutputVector{Zo, body_condition},
397                                               ParameterVector{Xi, current_iteration, Yi, M_body});
398
399     auto loop = make_shared<opset5::Loop>(trip_count, exec_condition);
400     loop->set_function(body);
401     loop->set_special_body_ports(ngraph::opset5::Loop::SpecialBodyPorts{1, 1});
402
403     loop->set_invariant_input(Xi, X);
404     loop->set_invariant_input(Yi, Y);
405     loop->set_merged_input(M_body, M, Zo);
406
407     // Output 0 is last Zo
408     auto out0 = loop->get_iter_value(body_condition, -1);
409     auto out1 = loop->get_iter_value(Zo, -1);
410     // Output 1 is concat of Zos
411     // start=0, stride=1, part_size=1, end=-1, axis=1
412     auto out2 = loop->get_concatenated_slices(Zo, 0, 1, 1, -1, 1);
413     loop->validate_and_infer_types();
414     // That which we iterate over
415     auto X_new = make_shared<opset5::Parameter>(element::f32, Shape{3, 2, 5});
416     auto Y_new = make_shared<opset5::Parameter>(element::f32, Shape{3, 2, 5});
417     auto M_new = make_shared<opset5::Parameter>(element::f32, Shape{3, 2, 5});
418     OutputVector new_args = {trip_count, exec_condition, X_new, Y_new, M_new};
419     auto loop_copy = loop->clone_with_new_inputs(new_args);
420
421     auto node_cast = std::dynamic_pointer_cast<opset5::Loop>(loop_copy);
422     ASSERT_NE(node_cast, nullptr);
423     ASSERT_TRUE(nullptr != loop_copy);
424     EXPECT_EQ(loop->get_num_iterations(), node_cast->get_num_iterations());
425     EXPECT_EQ(loop->get_special_body_ports().body_condition_output_idx,
426               node_cast->get_special_body_ports().body_condition_output_idx);
427     EXPECT_EQ(loop->get_special_body_ports().current_iteration_input_idx,
428               node_cast->get_special_body_ports().current_iteration_input_idx);
429     ASSERT_TRUE(new_args == loop_copy->input_values());
430
431     loop_copy->validate_and_infer_types();
432     Shape out0_shape{};
433     Shape out1_shape{3, 2, 5};
434     Shape out2_shape{3, 20, 5};
435     EXPECT_EQ(loop_copy->get_output_shape(0), out0_shape);
436     EXPECT_EQ(loop_copy->get_output_shape(1), out1_shape);
437     EXPECT_EQ(loop_copy->get_output_shape(2), out2_shape);
438 }