class_docstr: Class implementing a convolutional layer in the interval/box domain.
class_docstr_tok: ["Class","implementing","a","convolutional","layer","in","the","interval\/box","domain","."]
docstr: Converts the initialised convolutional layer into an equivalent dense layer.
  
  This function was adapted from:
  https://github.com/deepmind/interval-bound-propagation/blob/217a14d12686e08ebb5cfea1f2748cce58a55913/interval_bound_propagation/src/layer_utils.py#L90
  
  Here, we adapt the tf1 functionality to work with pytorch.
  
  Original license:
  
  coding=utf-8
  
  Copyright 2019 The Interval Bound Propagation Authors.
  
  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.
  
  :return: The dense weights and bias equivalent to a Conv layer.
docstr_tok: ["Converts","the","initialised","convolutional","layer","into","an","equivalent","dense","layer",".","This","function","was","adapted","from",":","https",":","\/\/github.com\/deepmind\/interval-bound-propagation\/blob\/217a14d12686e08ebb5cfea1f2748cce58a55913\/interval_bound_propagation\/src\/layer_utils.py","#","L90","Here",",","we","adapt","the","tf1","functionality","to","work","with","pytorch",".","Original","license",":","coding=utf-8","Copyright","2019","The","Interval","Bound","Propagation","Authors",".","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",".",":","return",":","The","dense","weights","and","bias","equivalent","to","a","Conv","layer","."]
code: def convert_to_dense(
      self, device: Union[str, "torch.device"]
  ) -> Tuple["torch.Tensor", "torch.Tensor"]:
      """
      Converts the initialised convolutional layer into an equivalent dense layer.
  
      This function was adapted from:
      https://github.com/deepmind/interval-bound-propagation/blob/217a14d12686e08ebb5cfea1f2748cce58a55913/interval_bound_propagation/src/layer_utils.py#L90
  
      Here, we adapt the tf1 functionality to work with pytorch.
  
      Original license:
  
      coding=utf-8
  
      Copyright 2019 The Interval Bound Propagation Authors.
  
      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.
  
      :return: The dense weights and bias equivalent to a Conv layer.
      """
  
      diagonal_input = torch.reshape(
          torch.eye(self.input_height * self.input_width),
          shape=[
              self.input_height * self.input_width,
              1,
              self.input_height,
              self.input_width,
          ],
      ).to(device)
      conv_output = self.conv(diagonal_input)
      self.output_height = int(conv_output.shape[2])
      self.output_width = int(conv_output.shape[3])
  
      # conv is of shape (input_height * input_width, out_channels * in_channels, output_height, output_width).
      # Reshape it to (input_height * input_width * output_channels,
      #                output_height * output_width * input_channels).
  
      weights = torch.reshape(
          conv_output,
          shape=(
              [
                  self.input_height * self.input_width,
                  self.out_channels,
                  self.in_channels,
                  self.output_height,
                  self.output_width,
              ]
          ),
      )
      weights = torch.permute(weights, (2, 0, 1, 3, 4))
      weights = torch.reshape(
          weights,
          shape=(
              [
                  self.input_height
                  * self.input_width
                  * self.in_channels,
                  self.output_height
                  * self.output_width
                  * self.out_channels,
              ]
          ),
      )
  
      if self.bias_to_grad is not None:
          self.bias = torch.unsqueeze(self.bias_to_grad, dim=-1)
          bias = self.bias.expand(
              -1, self.output_height * self.output_width
          )
          bias = bias.flatten()
      else:
          bias = None
      return torch.transpose(weights, 0, 1), bias
  
imports: from typing import List, Union, Tuple, Optional
  import torch
  import numpy
label_desc: Use image node_id 3 for calling the PyTorchIntervalConv2D obj's underlying member method code with example usage: obj.convert_to_dense(device) and returns: torch,  bias