Reverse propagate values from one autodiff array to another
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(array_type), | intent(in), | target | :: | a |
Upstream tensor to reverse-propagate |
|
| integer, | intent(in), | dimension(:) | :: | adj_ia |
CSR row pointers |
|
| integer, | intent(in), | dimension(:,:) | :: | adj_ja |
CSR neighbour and edge lookup indices |
|
| integer, | intent(in), | dimension(2) | :: | num_features |
Output feature and element counts |
|
| integer, | intent(in), | dimension(2) | :: | num_elements |
Output feature and element counts |
Reverse-propagated tensor
function reverse_kipf_propagate( & a, adj_ia, adj_ja, num_features, num_elements & ) result(c) !! Reverse propagate values from one autodiff array to another implicit none ! Arguments class(array_type), intent(in), target :: a !! Upstream tensor to reverse-propagate integer, dimension(:), intent(in) :: adj_ia !! CSR row pointers integer, dimension(:,:), intent(in) :: adj_ja !! CSR neighbour and edge lookup indices integer, dimension(2), intent(in) :: num_features, num_elements !! Output feature and element counts type(array_type), pointer :: c !! Reverse-propagated tensor ! Local variables integer :: v, w !! Loop indices c => a%create_result(array_shape=[ & num_features(1), num_elements(1) & ]) c%val = 0.0_real32 do concurrent(v=1:num_elements(1)) do w = adj_ia(v), adj_ia(v+1)-1 c%val(:,adj_ja(1,w)) = c%val(:,adj_ja(1,w)) + & [ a%val(:, v) ] end do end do c%indices = adj_ia c%adj_ja = adj_ja c%get_partial_left => get_partial_left_reverse_kipf_propagate c%get_partial_left_val => get_partial_left_reverse_kipf_propagate_val if(a%requires_grad)then c%requires_grad = .true. c%is_forward = a%is_forward c%operation = 'reverse_kipf_propagate' c%left_operand => a c%owns_left_operand = a%is_temporary end if end function reverse_kipf_propagate