Remove obsoleted v0::Broadcast and BroadcastLike operators (#2779)
[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 shape{1, 3};
88     Shape new_shape{4, 1, 3};
89     AxisSet axes{1, 2};
90     auto arg0 = make_shared<op::Parameter>(element::f32, shape);
91     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape),
92                           op::Constant::create(element::u64, Shape{new_shape.size()}, new_shape),
93                           op::Constant::create(element::i64, Shape{axes.size()}, axes.to_vector())};
94
95     auto node = make_shared<op::v1::Broadcast>(
96         arg0,
97         op::Constant::create(element::u64, Shape{new_shape.size()}, new_shape),
98         op::Constant::create(element::i64, Shape{axes.size()}, axes.to_vector()));
99     auto new_node = node->copy_with_new_inputs(new_args);
100     auto node_cast = as_type_ptr<op::v1::Broadcast>(new_node);
101     ASSERT_NE(node_cast, nullptr);
102
103     ASSERT_NE(nullptr, new_node);
104     ASSERT_EQ(new_args, new_node->input_values());
105     bool axes_determined;
106     AxisSet broadcast_axes;
107     std::tie(axes_determined, broadcast_axes) = node_cast->get_broadcast_axes();
108     ASSERT_EQ(true, axes_determined);
109     ASSERT_EQ(AxisSet{0}, broadcast_axes);
110 }
111
112 TEST(copy, ceiling)
113 {
114     ASSERT_TRUE(check_unary<op::Ceiling>());
115 }
116
117 TEST(copy, concat)
118 {
119     Shape shape{1};
120     auto arg0 = make_shared<op::Parameter>(element::f32, shape);
121     auto arg1 = make_shared<op::Parameter>(element::f32, shape);
122     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape),
123                           make_shared<op::Parameter>(element::f32, shape)};
124     size_t axis = 0;
125     auto node = make_shared<op::Concat>(NodeVector{arg0, arg1}, axis);
126     auto new_node = node->clone_with_new_inputs(new_args);
127     auto node_cast = as_type_ptr<op::Concat>(new_node);
128     ASSERT_NE(node_cast, nullptr);
129
130     ASSERT_TRUE(nullptr != new_node);
131     ASSERT_TRUE(new_args == new_node->input_values());
132     ASSERT_TRUE(node_cast->get_concatenation_axis() == axis);
133 }
134
135 TEST(copy, constant)
136 {
137     Shape shape{};
138     vector<float> c{2.4f};
139     auto& et = element::f32;
140     auto node = op::Constant::create(et, shape, c);
141     auto new_node = node->clone_with_new_inputs(OutputVector{});
142     auto node_cast = as_type_ptr<op::Constant>(new_node);
143     ASSERT_NE(node_cast, nullptr);
144     ASSERT_TRUE(nullptr != new_node);
145     ASSERT_TRUE(OutputVector{} == new_node->input_values());
146     ASSERT_TRUE(node_cast->get_vector<float>() == c);
147     ASSERT_TRUE(node_cast->get_shape() == shape);
148     ASSERT_TRUE(node_cast->get_element_type() == et);
149 }
150
151 TEST(copy, convert)
152 {
153     Shape shape;
154     auto& et = element::f64;
155     auto arg0 = make_shared<op::Parameter>(element::f32, shape);
156     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape)};
157
158     auto node = make_shared<op::Convert>(arg0, et);
159     auto new_node = node->clone_with_new_inputs(new_args);
160     auto node_cast = as_type_ptr<op::Convert>(new_node);
161     ASSERT_NE(node_cast, nullptr);
162
163     ASSERT_TRUE(nullptr != new_node);
164     ASSERT_TRUE(new_args == new_node->input_values());
165     ASSERT_TRUE(et == node_cast->get_convert_element_type());
166 }
167
168 TEST(copy, cos)
169 {
170     ASSERT_TRUE(check_unary<op::Cos>());
171 }
172
173 TEST(copy, cosh)
174 {
175     ASSERT_TRUE(check_unary<op::Cosh>());
176 }
177
178 TEST(copy, divide)
179 {
180     ASSERT_TRUE(check_binary<op::Divide>());
181 }
182
183 TEST(copy, dot)
184 {
185     ASSERT_TRUE(check_binary<op::Dot>());
186 }
187
188 TEST(copy, equal)
189 {
190     ASSERT_TRUE(check_binary<op::Equal>());
191 }
192
193 TEST(copy, exp)
194 {
195     ASSERT_TRUE(check_unary<op::Exp>());
196 }
197
198 TEST(copy, floor)
199 {
200     ASSERT_TRUE(check_unary<op::Floor>());
201 }
202
203 TEST(copy, greater_eq)
204 {
205     ASSERT_TRUE(check_binary<op::GreaterEq>());
206 }
207
208 TEST(copy, greater)
209 {
210     ASSERT_TRUE(check_binary<op::Greater>());
211 }
212
213 TEST(copy, less_eq)
214 {
215     ASSERT_TRUE(check_binary<op::LessEq>());
216 }
217
218 TEST(copy, less)
219 {
220     ASSERT_TRUE(check_binary<op::Less>());
221 }
222
223 TEST(copy, log)
224 {
225     ASSERT_TRUE(check_unary<op::Log>());
226 }
227
228 TEST(copy, maximum)
229 {
230     ASSERT_TRUE(check_binary<op::Maximum>());
231 }
232
233 TEST(copy, minimum)
234 {
235     ASSERT_TRUE(check_binary<op::Minimum>());
236 }
237
238 TEST(copy, multiply)
239 {
240     ASSERT_TRUE(check_binary<op::Multiply>());
241 }
242
243 TEST(copy, negative)
244 {
245     ASSERT_TRUE(check_unary<op::Negative>());
246 }
247
248 TEST(copy, not_equal)
249 {
250     ASSERT_TRUE(check_binary<op::NotEqual>());
251 }
252
253 TEST(copy, parameter)
254 {
255     Shape shape{1};
256     auto node = make_shared<op::Parameter>(element::f32, shape);
257     auto new_node = node->clone_with_new_inputs({});
258     auto node_cast = as_type_ptr<op::Parameter>(new_node);
259     ASSERT_NE(node_cast, nullptr);
260
261     ASSERT_TRUE(nullptr != new_node);
262     ASSERT_TRUE(new_node->input_values().size() == 0);
263     ASSERT_TRUE(node->has_same_type(new_node));
264 }
265
266 TEST(copy, power)
267 {
268     ASSERT_TRUE(check_binary<op::Power>());
269 }
270
271 TEST(copy, reshape)
272 {
273     Shape shape_in{2, 3, 4};
274     AxisVector axes{0, 1, 2};
275     Shape shape_out{6, 4};
276
277     auto arg0 = make_shared<op::Parameter>(element::f32, shape_in);
278     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape_in)};
279
280     auto node = make_shared<op::Reshape>(arg0, axes, shape_out);
281     auto new_node = node->clone_with_new_inputs(new_args);
282     auto node_cast = as_type_ptr<op::Reshape>(new_node);
283     ASSERT_NE(node_cast, nullptr);
284
285     ASSERT_TRUE(nullptr != new_node);
286     ASSERT_TRUE(new_args == new_node->input_values());
287     ASSERT_TRUE(axes == node_cast->get_input_order());
288     ASSERT_TRUE(shape_out == node_cast->get_output_shape(0));
289 }
290
291 TEST(copy, select)
292 {
293     Shape shape{1};
294     auto arg0 = make_shared<op::Parameter>(element::boolean, shape);
295     auto arg1 = make_shared<op::Parameter>(element::f32, shape);
296     auto arg2 = make_shared<op::Parameter>(element::f32, shape);
297     OutputVector new_args{make_shared<op::Parameter>(element::boolean, shape),
298                           make_shared<op::Parameter>(element::f32, shape),
299                           make_shared<op::Parameter>(element::f32, shape)};
300
301     auto node = make_shared<op::Select>(arg0, arg1, arg2);
302     auto new_node = node->clone_with_new_inputs(new_args);
303     auto node_cast = as_type_ptr<op::Select>(new_node);
304     ASSERT_NE(node_cast, nullptr);
305
306     ASSERT_TRUE(nullptr != new_node);
307     ASSERT_TRUE(new_args == new_node->input_values());
308 }
309
310 TEST(copy, sign)
311 {
312     ASSERT_TRUE(check_unary<op::Sign>());
313 }
314
315 TEST(copy, sin)
316 {
317     ASSERT_TRUE(check_unary<op::Sin>());
318 }
319
320 TEST(copy, sinh)
321 {
322     ASSERT_TRUE(check_unary<op::Sinh>());
323 }
324
325 TEST(copy, slice)
326 {
327     Shape shape_in{2, 3, 4};
328     Coordinate lower{0, 0, 0};
329     Coordinate upper{2, 3, 4};
330     Strides strides{1, 1, 1};
331
332     auto arg0 = make_shared<op::Parameter>(element::f32, shape_in);
333     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape_in)};
334
335     auto node = make_shared<op::Slice>(arg0, lower, upper, strides);
336     auto new_node = node->clone_with_new_inputs(new_args);
337     auto node_cast = as_type_ptr<op::Slice>(new_node);
338     ASSERT_NE(node_cast, nullptr);
339
340     ASSERT_TRUE(nullptr != new_node);
341     ASSERT_TRUE(new_args == new_node->input_values());
342     ASSERT_TRUE(lower == node_cast->get_lower_bounds());
343     ASSERT_TRUE(upper == node_cast->get_upper_bounds());
344     ASSERT_TRUE(strides == node_cast->get_strides());
345 }
346
347 TEST(copy, subtract)
348 {
349     ASSERT_TRUE(check_binary<op::Subtract>());
350 }
351
352 TEST(copy, sum)
353 {
354     Shape shape{4, 3};
355     AxisSet axes{1};
356     auto arg0 = make_shared<op::Parameter>(element::f32, shape);
357
358     auto node = make_shared<op::Sum>(arg0, axes);
359     OutputVector new_args{make_shared<op::Parameter>(element::f32, shape),
360                           node->input_value(1).get_node_shared_ptr()};
361     auto new_node = node->clone_with_new_inputs(new_args);
362     auto node_cast = as_type_ptr<op::Sum>(new_node);
363     ASSERT_NE(node_cast, nullptr);
364
365     ASSERT_TRUE(nullptr != new_node);
366     ASSERT_TRUE(new_args == new_node->input_values());
367     ASSERT_TRUE(axes == node_cast->get_reduction_axes());
368 }
369
370 TEST(copy, tan)
371 {
372     ASSERT_TRUE(check_unary<op::Tan>());
373 }
374
375 TEST(copy, tanh)
376 {
377     ASSERT_TRUE(check_unary<op::Tanh>());
378 }
379
380 TEST(copy, loop)
381 {
382     // That which we iterate over
383     auto X = make_shared<opset5::Parameter>(element::f32, Shape{32, 1, 10});
384     auto Y = make_shared<opset5::Parameter>(element::f32, Shape{32, 1, 10});
385     auto M = make_shared<opset5::Parameter>(element::f32, Shape{32, 1, 10});
386
387     // Set up the cell body, a function from (Xi, Yi) -> (Zo)
388     // Body parameters
389     auto current_iteration = make_shared<opset5::Parameter>(element::i64, Shape{});
390     auto Xi = make_shared<opset5::Parameter>(element::f32, PartialShape::dynamic());
391     auto Yi = make_shared<opset5::Parameter>(element::f32, PartialShape::dynamic());
392     auto M_body = make_shared<opset5::Parameter>(element::f32, PartialShape::dynamic());
393     auto body_condition =
394         std::make_shared<ngraph::opset5::Constant>(ngraph::element::boolean, ngraph::Shape{}, true);
395
396     auto trip_count =
397         std::make_shared<ngraph::opset5::Constant>(ngraph::element::i64, ngraph::Shape{}, 10);
398     auto exec_condition =
399         std::make_shared<ngraph::opset5::Constant>(ngraph::element::boolean, ngraph::Shape{}, true);
400     // Body
401     auto sum = make_shared<ngraph::opset5::Add>(Xi, Yi);
402     auto Zo = make_shared<ngraph::opset5::Multiply>(sum, M_body);
403     auto body = make_shared<ngraph::Function>(OutputVector{Zo, body_condition},
404                                               ParameterVector{Xi, current_iteration, Yi, M_body});
405
406     auto loop = make_shared<opset5::Loop>(trip_count, exec_condition);
407     loop->set_function(body);
408     loop->set_special_body_ports(ngraph::opset5::Loop::SpecialBodyPorts{1, 1});
409
410     loop->set_invariant_input(Xi, X);
411     loop->set_invariant_input(Yi, Y);
412     loop->set_merged_input(M_body, M, Zo);
413
414     // Output 0 is last Zo
415     auto out0 = loop->get_iter_value(body_condition, -1);
416     auto out1 = loop->get_iter_value(Zo, -1);
417     // Output 1 is concat of Zos
418     // start=0, stride=1, part_size=1, end=-1, axis=1
419     auto out2 = loop->get_concatenated_slices(Zo, 0, 1, 1, -1, 1);
420     loop->validate_and_infer_types();
421     // That which we iterate over
422     auto X_new = make_shared<opset5::Parameter>(element::f32, Shape{3, 2, 5});
423     auto Y_new = make_shared<opset5::Parameter>(element::f32, Shape{3, 2, 5});
424     auto M_new = make_shared<opset5::Parameter>(element::f32, Shape{3, 2, 5});
425     OutputVector new_args = {trip_count, exec_condition, X_new, Y_new, M_new};
426     auto loop_copy = loop->clone_with_new_inputs(new_args);
427
428     auto node_cast = std::dynamic_pointer_cast<opset5::Loop>(loop_copy);
429     ASSERT_NE(node_cast, nullptr);
430     ASSERT_TRUE(nullptr != loop_copy);
431     EXPECT_EQ(loop->get_num_iterations(), node_cast->get_num_iterations());
432     EXPECT_EQ(loop->get_special_body_ports().body_condition_output_idx,
433               node_cast->get_special_body_ports().body_condition_output_idx);
434     EXPECT_EQ(loop->get_special_body_ports().current_iteration_input_idx,
435               node_cast->get_special_body_ports().current_iteration_input_idx);
436     ASSERT_TRUE(new_args == loop_copy->input_values());
437
438     loop_copy->validate_and_infer_types();
439     Shape out0_shape{};
440     Shape out1_shape{3, 2, 5};
441     Shape out2_shape{3, 20, 5};
442     EXPECT_EQ(loop_copy->get_output_shape(0), out0_shape);
443     EXPECT_EQ(loop_copy->get_output_shape(1), out1_shape);
444     EXPECT_EQ(loop_copy->get_output_shape(2), out2_shape);
445 }