Deprecate nGraph v0 ops and builders (#1856)
[platform/upstream/dldt.git] / ngraph / core / include / ngraph / builder / autobroadcast.hpp
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 #pragma once
18
19 #include <memory>
20 #include <utility>
21
22 #include "ngraph/except.hpp"
23 #include "ngraph/node.hpp"
24 #include "ngraph/op/broadcast.hpp"
25
26 namespace ngraph
27 {
28     namespace builder
29     {
30         class NGRAPH_API numpy_autobroadcast_incompatible_shapes : public ngraph::ngraph_error
31         {
32         public:
33             numpy_autobroadcast_incompatible_shapes(const ngraph::Shape& shape1,
34                                                     const ngraph::Shape& shape2);
35
36         private:
37             const ngraph::Shape m_shape1;
38             const ngraph::Shape m_shape2;
39
40             static std::string error_str(const ngraph::Shape& shape1, const ngraph::Shape& shape2);
41         };
42
43         ///
44         /// \brief      Broadcast all values, if necessary, to obtain equal shapes according
45         ///             to NumPy's auto-broadcasting scheme.
46         ///
47         /// \note       There are some shape combinations which the autobroadcast algoritm cannot
48         ///             handle. An exception is thrown when such combinations are provided to this
49         ///             function.
50         ///
51         /// \param      values  Vector of output values.
52         ///
53         /// \exception  ngraph::builder::numpy_autobroadcast_incompatible_shapes
54         ///
55         /// \return     Vector of broadcasted values.
56         ///
57         NGRAPH_DEPRECATED("This builder was deprecated.")
58         NGRAPH_API
59         OutputVector numpy_broadcast_outputs(const OutputVector& values);
60
61         ///
62         /// \brief      Broadcast input value to provided shape using NumPy's auto-broadcasting
63         ///             rules.
64         ///
65         /// \param      value  Input value
66         /// \param      shape  Requested output shape
67         ///
68         /// \return     Node producing values with requested shape.
69         ///
70         NGRAPH_DEPRECATED("This builder was deprecated.")
71         NGRAPH_API
72         std::shared_ptr<Node> numpy_broadcast(const Output<Node>& value, const Shape& shape);
73
74         /// \brief Wrap two graph values, if necessary, to obtain values with identical shapes,
75         /// using NumPy's auto-broadcast rules.
76         ///
77         /// The elements in the std::pair returned by this function correspond to those supplied
78         /// in the std::pair provided via \p args.
79         ///
80         /// If \p args.first and \p args.second produce identical shapes, then the returned
81         /// std::pair will have the same value as \p args.
82         ///
83         /// If \p args.first and \p args.second produce different shapes, then this function creates
84         /// new ngraph::op::Reshape and/or ngraph::op::Broadcast nodes, as needed, to wrap
85         /// \p args.first and/or \p args.second in a manner that yields values with the same shape.
86         ///
87         /// There are some shape combinations which the autobroadcast algoritm cannot handle.
88         /// An exception is thrown when such combinations are provided to this function.
89         ///
90         /// \pre
91         /// - \p args.first is not null
92         /// - \p args.second is not null
93         ///
94         /// \post
95         /// - The ngraph::Node objects pointed to by \p args.first and \p args.second have not been
96         ///   altered by this function, except by possibly having added consumers of their values.
97         ///
98         /// - If an exception was not thrown, then the return value's \p first and \p second
99         ///   elements point to ngraph::Node objects whose output values have the same shape.
100         ///
101         /// \exception ngraph::builder::numpy_autobroadcast_incompatible_shapes
102         NGRAPH_DEPRECATED("This builder was deprecated.")
103         NGRAPH_API
104         std::pair<std::shared_ptr<Node>, std::shared_ptr<Node>>
105             numpy_broadcast(const std::pair<Output<Node>, Output<Node>>& args);
106
107         /// Create a new \p NodeType node, and any additional nodes required to simulate NumPy-style
108         /// autobroadcast semantics.  Intended for binary operations such as "Add".
109         ///
110         /// \param [in] operand1_reshapeable The first operand to supply to the \p NodeType
111         ///                                  constructor.  Subject to being wrapped with additional
112         ///                                  nodes required for autobroadcasting.  Must not be null.
113         ///
114         /// \param [in] operand2_reshapeable The second operand to supply to the \p NodeType
115         ///                                  constructor.  Subject to being wrapped with additional
116         ///                                  nodes required for autobroadcasting.  Must not be null.
117         ///
118         /// \return The sink node of any/all nodes created by this function.  Will never be null.
119         ///
120         /// \exception ngraph::builder::numpy_autobroadcast_incompatible_shapes
121         template <typename NodeType>
122         NGRAPH_DEPRECATED("This builder was deprecated.")
123         std::shared_ptr<NodeType> make_with_numpy_broadcast(
124             const Output<Node>& operand1_reshapeable, const Output<Node>& operand2_reshapeable)
125         {
126             NGRAPH_SUPPRESS_DEPRECATED_START
127             auto shaped_op1_op2 = numpy_broadcast({operand1_reshapeable, operand2_reshapeable});
128             return std::make_shared<NodeType>(shaped_op1_op2.first, shaped_op1_op2.second);
129             NGRAPH_SUPPRESS_DEPRECATED_END
130         }
131
132         /// Create a new \p NodeType node, and any additional nodes required to simulate NumPy-style
133         /// autobroadcast semantics.  Intended for non-binary operations such as "Select", where
134         /// precisely the second and third operands are subject to autobroadcast semantics.
135         ///
136         /// \param [in] operand1 This operand is not subject to autobraodcast logic, and will be
137         ///                      passed as-is as the first argument to the \p NodeType constructor.
138         ///
139         /// \param [in] operand2_reshapeable The second operand to supply to the \p NodeType
140         ///                                  constructor.  Subject to being wrapped with additional
141         ///                                  nodes required for autobroadcasting.  Must not be null.
142         ///
143         /// \param [in] operand3_reshapeable The third operand to supply to the \p NodeType
144         ///                                  constructor.  Subject to being wrapped with additional
145         ///                                  nodes required for autobroadcasting.  Must not be null.
146         ///
147         /// \return The sink node of any/all nodes created by this function.  Will never be null.
148         ///
149         /// \exception ngraph::builder::numpy_autobroadcast_incompatible_shapes
150         template <typename NodeType>
151         NGRAPH_DEPRECATED("This builder was deprecated.")
152         std::shared_ptr<Node> make_with_numpy_broadcast(const Output<Node>& operand1,
153                                                         const Output<Node>& operand2_reshapeable,
154                                                         const Output<Node>& operand3_reshapeable)
155         {
156             NGRAPH_SUPPRESS_DEPRECATED_START
157             auto shaped_op2_op3 = numpy_broadcast({operand2_reshapeable, operand3_reshapeable});
158             return std::make_shared<NodeType>(
159                 operand1, shaped_op2_op3.first, shaped_op2_op3.second);
160             NGRAPH_SUPPRESS_DEPRECATED_END
161         }
162
163         /// \brief      Broadcast shape of two nodes to make them compatible for a matrix
164         ///             multiplication.
165         ///
166         /// \note       This function is reflecting broadcasting behaviour of NumPy's `matmul`
167         ///             operation.
168         ///             (https://docs.scipy.org/doc/numpy/reference/generated/numpy.matmul.html)
169         ///             This mean that only \"stack of matrices\" axes are bidirectionally
170         ///             broadcasted. The last two dimension are left untouched.
171         ///
172         /// \param[in]  left   The Node providing data for the left-hand side of matrix
173         ///                    multiplication.
174         /// \param[in]  right  The Node providing data for the right-hand side of matrix
175         ///                    multiplication.
176         ///
177         /// \return     The vector containing both outputs broadcasted.
178         ///
179         NGRAPH_DEPRECATED("This builder was deprecated.")
180         NGRAPH_API
181         OutputVector numpy_broadcast_for_matmul_operation(const Output<Node>& left,
182                                                           const Output<Node>& right);
183
184         /// \brief Cast shape of all input nodes for an element-wise operation that requires
185         ///        shape-compatibility
186         ///
187         /// \param inputs Original list of inputs
188         /// \param axis Index starting to align
189         ///
190         /// \return pdpd-style broadcasted list of nodes.
191         NGRAPH_DEPRECATED("This builder was deprecated.")
192         NGRAPH_API
193         OutputVector pdpd_broadcast(const OutputVector& inputs, int64_t axis);
194
195         /// \brief Generate a list of broadcast axes.
196         ///
197         /// \details Informally, a broadcast "adds" axes to the input tensor, replicating
198         ///          elements from the input tensor as needed to fill the new dimensions.
199         ///          Function calculate which of the output axes are added in this way.
200         ///
201         /// \param output_shape      The new shape for the output tensor.
202         /// \param input_shape       The shape of input tensor.
203         /// \param start_match_axis  The axis along which we want to replicate elements.
204         ///                          The starting axis position (0-based) int the output
205         ///                          shape from which the current shape of the tensor
206         ///                          matches the desired new shape.
207         ///
208         /// \return The indices of added axes.
209         NGRAPH_DEPRECATED("This builder was deprecated.")
210         NGRAPH_API
211         AxisSet calculate_broadcast_axes(const Shape& output_shape,
212                                          const Shape& input_shape,
213                                          std::size_t start_match_axis);
214
215         ///
216         /// \brief      Calculate the output shape of numpy-style broadcast operation for all input
217         ///             shapes.
218         ///
219         ///             This function finds the maximum tensor shape that will be the result of
220         ///             element-wise operation that will be applied to the input shapes vector.
221         ///             The function also prepares the shape of each input for the element-wise
222         ///             operation by left-padding those shapes so that their rank is equal to the
223         ///             left_shape's rank.
224         ///
225         /// \param      input_shapes  A vector of input shapes for which a common shape should be
226         ///                           found
227         ///
228         /// \return     A pair that contains the target shape as its first object and a vector of
229         ///             padded input shapes ready to be broadcasted as the second object
230         ///
231         NGRAPH_DEPRECATED("This builder was deprecated.")
232         NGRAPH_API
233         std::pair<Shape, std::vector<Shape>>
234             get_numpy_broadcast_shapes(const std::vector<Shape>& input_shapes);
235
236         /// \brief Generate a list of broadcast along axes.
237         ///
238         /// \details Broadcast "adds" elements along axes to the input tensor, replicating
239         ///          elements from the input tensor as needed to fill the new dimensions.
240         ///          Function calculate which of the output axes are added in this way.
241         ///
242         ///          This function will attempt to match shapes, assuming the current shape
243         ///          matches the rightmost positions of the desired new shape. This behaviour
244         ///          is similar to NumPy's broadcasting.
245         ///
246         /// \param output_shape The new shape for the output tensor.
247         /// \param input_shape  The shape of input tensor.
248         ///
249         /// \return             The indices of added axes.
250         NGRAPH_DEPRECATED("This builder was deprecated.")
251         inline AxisSet calculate_broadcast_axes(const Shape& output_shape, const Shape& input_shape)
252         {
253             NGRAPH_SUPPRESS_DEPRECATED_START
254             return calculate_broadcast_axes(
255                 output_shape, input_shape, output_shape.size() - input_shape.size());
256             NGRAPH_SUPPRESS_DEPRECATED_END
257         }
258
259         NGRAPH_DEPRECATED("This builder was deprecated.")
260         inline std::shared_ptr<Node> make_broadcast_node(const Output<Node>& output,
261                                                          Shape new_shape)
262         {
263             NGRAPH_SUPPRESS_DEPRECATED_START
264             return std::make_shared<op::Broadcast>(
265                 output, new_shape, calculate_broadcast_axes(new_shape, output.get_shape()));
266             NGRAPH_SUPPRESS_DEPRECATED_END
267         }
268
269         NGRAPH_DEPRECATED("This builder was deprecated.")
270         inline std::shared_ptr<Node> make_broadcast_node(const Output<Node>& value,
271                                                          const Shape& new_shape,
272                                                          std::size_t start_match_axis)
273         {
274             NGRAPH_SUPPRESS_DEPRECATED_START
275             return std::make_shared<op::Broadcast>(
276                 value,
277                 new_shape,
278                 calculate_broadcast_axes(new_shape, value.get_shape(), start_match_axis));
279             NGRAPH_SUPPRESS_DEPRECATED_END
280         }
281
282         namespace opset1
283         {
284             ///
285             /// \brief      Broadcast right node to left node's shape using legacy scheme.
286             ///
287             /// \param[in]  left              The left hand side node of binary operation.
288             /// \param[in]  right             The right hand side node of binary operation. The one
289             ///                               to be broadcasted.
290             /// \param[in]  start_match_axis  The axis index starting mutually equal shapes
291             ///                               of both nodes.
292             ///
293             /// \return     The Output object connected to node producing broadcasted right node.
294             ///
295             NGRAPH_API
296             Output<Node> legacy_broadcast_for_binary_operation(const Output<Node>& left,
297                                                                const Output<Node>& right,
298                                                                size_t start_match_axis);
299
300             ///
301             /// \brief      Reconstructs axes mapping vector for Broadcast:v1 operation.
302             ///
303             /// \param[in]  output_shape    The output shape of Broadcast operation.
304             /// \param[in]  broadcast_axes  The broadcast axes used for Broadcast:v0 operator.
305             ///
306             /// \return     The vector with axes indexes mapping .
307             ///
308             NGRAPH_API
309             std::vector<std::size_t> get_axes_mapping(const Shape& output_shape,
310                                                       const AxisSet& broadcast_axes);
311
312             ///
313             /// \brief      Creates Node returning the axes mapping for Broadcast:v1 operation.
314             ///
315             /// \param[in]  output_shape      The output shape of Broadcast operation.
316             /// \param[in]  input_shape       The input shape.
317             /// \param[in]  start_match_axis  The axis index at which input shape starts to be
318             ///                               identical as the output shape.
319             ///
320             /// \return     Returns the Output object pointing to node with the axes mapping.
321             ///
322             NGRAPH_API
323             Output<Node> get_axes_mapping_output(const Shape& output_shape,
324                                                  const Shape& input_shape,
325                                                  std::size_t start_match_axis);
326
327             ///
328             /// \brief      Creates Node returning the axes mapping for Broadcast:v1 operation.
329             ///
330             /// \param[in]  output_shape    The output shape of Broadcast operation.
331             /// \param[in]  broadcast_axes  The broadcast axes used for Broadcast:v0 operator.
332             ///
333             /// \return     The Output object with Node returning axes mapping.
334             ///
335             NGRAPH_API
336             Output<Node> get_axes_mapping_output(const Shape& output_shape,
337                                                  const AxisSet& broadcast_axes);
338
339             NGRAPH_API
340             Output<Node> make_broadcast(const Output<Node>& node,
341                                         const Shape& target_shape,
342                                         const AxisSet& broadcast_axes);
343
344             NGRAPH_API
345             Output<Node> make_broadcast(const Output<Node>& node,
346                                         const Shape& target_shape,
347                                         std::size_t start_match_axis);
348
349         } // namespace opset1
350     }     // namespace builder
351 } // namespace ngraph