1 //*****************************************************************************
2 // Copyright 2017-2020 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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 //*****************************************************************************
22 #include "ngraph/except.hpp"
23 #include "ngraph/node.hpp"
24 #include "ngraph/op/broadcast.hpp"
30 class NGRAPH_API numpy_autobroadcast_incompatible_shapes : public ngraph::ngraph_error
33 numpy_autobroadcast_incompatible_shapes(const ngraph::Shape& shape1,
34 const ngraph::Shape& shape2);
37 const ngraph::Shape m_shape1;
38 const ngraph::Shape m_shape2;
40 static std::string error_str(const ngraph::Shape& shape1, const ngraph::Shape& shape2);
44 /// \brief Broadcast all values, if necessary, to obtain equal shapes according
45 /// to NumPy's auto-broadcasting scheme.
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
51 /// \param values Vector of output values.
53 /// \exception ngraph::builder::numpy_autobroadcast_incompatible_shapes
55 /// \return Vector of broadcasted values.
57 NGRAPH_DEPRECATED("This builder was deprecated.")
59 OutputVector numpy_broadcast_outputs(const OutputVector& values);
62 /// \brief Broadcast input value to provided shape using NumPy's auto-broadcasting
65 /// \param value Input value
66 /// \param shape Requested output shape
68 /// \return Node producing values with requested shape.
70 NGRAPH_DEPRECATED("This builder was deprecated.")
72 std::shared_ptr<Node> numpy_broadcast(const Output<Node>& value, const Shape& shape);
74 /// \brief Wrap two graph values, if necessary, to obtain values with identical shapes,
75 /// using NumPy's auto-broadcast rules.
77 /// The elements in the std::pair returned by this function correspond to those supplied
78 /// in the std::pair provided via \p args.
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.
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.
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.
91 /// - \p args.first is not null
92 /// - \p args.second is not null
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.
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.
101 /// \exception ngraph::builder::numpy_autobroadcast_incompatible_shapes
102 NGRAPH_DEPRECATED("This builder was deprecated.")
104 std::pair<std::shared_ptr<Node>, std::shared_ptr<Node>>
105 numpy_broadcast(const std::pair<Output<Node>, Output<Node>>& args);
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".
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.
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.
118 /// \return The sink node of any/all nodes created by this function. Will never be null.
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)
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
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.
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.
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.
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.
147 /// \return The sink node of any/all nodes created by this function. Will never be null.
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)
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
163 /// \brief Broadcast shape of two nodes to make them compatible for a matrix
166 /// \note This function is reflecting broadcasting behaviour of NumPy's `matmul`
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.
172 /// \param[in] left The Node providing data for the left-hand side of matrix
174 /// \param[in] right The Node providing data for the right-hand side of matrix
177 /// \return The vector containing both outputs broadcasted.
179 NGRAPH_DEPRECATED("This builder was deprecated.")
181 OutputVector numpy_broadcast_for_matmul_operation(const Output<Node>& left,
182 const Output<Node>& right);
184 /// \brief Cast shape of all input nodes for an element-wise operation that requires
185 /// shape-compatibility
187 /// \param inputs Original list of inputs
188 /// \param axis Index starting to align
190 /// \return pdpd-style broadcasted list of nodes.
191 NGRAPH_DEPRECATED("This builder was deprecated.")
193 OutputVector pdpd_broadcast(const OutputVector& inputs, int64_t axis);
195 /// \brief Generate a list of broadcast axes.
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.
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.
208 /// \return The indices of added axes.
209 NGRAPH_DEPRECATED("This builder was deprecated.")
211 AxisSet calculate_broadcast_axes(const Shape& output_shape,
212 const Shape& input_shape,
213 std::size_t start_match_axis);
216 /// \brief Calculate the output shape of numpy-style broadcast operation for all input
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.
225 /// \param input_shapes A vector of input shapes for which a common shape should be
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
231 NGRAPH_DEPRECATED("This builder was deprecated.")
233 std::pair<Shape, std::vector<Shape>>
234 get_numpy_broadcast_shapes(const std::vector<Shape>& input_shapes);
236 /// \brief Generate a list of broadcast along axes.
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.
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.
246 /// \param output_shape The new shape for the output tensor.
247 /// \param input_shape The shape of input tensor.
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)
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
259 NGRAPH_DEPRECATED("This builder was deprecated.")
260 inline std::shared_ptr<Node> make_broadcast_node(const Output<Node>& output,
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
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)
274 NGRAPH_SUPPRESS_DEPRECATED_START
275 return std::make_shared<op::Broadcast>(
278 calculate_broadcast_axes(new_shape, value.get_shape(), start_match_axis));
279 NGRAPH_SUPPRESS_DEPRECATED_END
285 /// \brief Broadcast right node to left node's shape using legacy scheme.
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
293 /// \return The Output object connected to node producing broadcasted right node.
296 Output<Node> legacy_broadcast_for_binary_operation(const Output<Node>& left,
297 const Output<Node>& right,
298 size_t start_match_axis);
301 /// \brief Reconstructs axes mapping vector for Broadcast:v1 operation.
303 /// \param[in] output_shape The output shape of Broadcast operation.
304 /// \param[in] broadcast_axes The broadcast axes used for Broadcast:v0 operator.
306 /// \return The vector with axes indexes mapping .
309 std::vector<std::size_t> get_axes_mapping(const Shape& output_shape,
310 const AxisSet& broadcast_axes);
313 /// \brief Creates Node returning the axes mapping for Broadcast:v1 operation.
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.
320 /// \return Returns the Output object pointing to node with the axes mapping.
323 Output<Node> get_axes_mapping_output(const Shape& output_shape,
324 const Shape& input_shape,
325 std::size_t start_match_axis);
328 /// \brief Creates Node returning the axes mapping for Broadcast:v1 operation.
330 /// \param[in] output_shape The output shape of Broadcast operation.
331 /// \param[in] broadcast_axes The broadcast axes used for Broadcast:v0 operator.
333 /// \return The Output object with Node returning axes mapping.
336 Output<Node> get_axes_mapping_output(const Shape& output_shape,
337 const AxisSet& broadcast_axes);
340 Output<Node> make_broadcast(const Output<Node>& node,
341 const Shape& target_shape,
342 const AxisSet& broadcast_axes);
345 Output<Node> make_broadcast(const Output<Node>& node,
346 const Shape& target_shape,
347 std::size_t start_match_axis);
349 } // namespace opset1
350 } // namespace builder
351 } // namespace ngraph