get_partial_gno_agg_features_val Subroutine

pure subroutine get_partial_gno_agg_features_val(this, upstream_grad, output)

In-place gradient w.r.t. features

Arguments

Type IntentOptional Attributes Name
class(array_type), intent(in) :: this

Forward result node containing saved operands

real(kind=real32), intent(in), dimension(:,:) :: upstream_grad

Upstream gradient values

real(kind=real32), intent(out), dimension(:,:) :: output

Output gradient values for node features


Source Code

  pure subroutine get_partial_gno_agg_features_val( &
       this, upstream_grad, output)
    !! In-place gradient w.r.t. features
    implicit none

    ! Arguments
    class(array_type), intent(in) :: this
    !! Forward result node containing saved operands
    real(real32), dimension(:,:), intent(in)  :: upstream_grad
    !! Upstream gradient values
    real(real32), dimension(:,:), intent(out) :: output
    !! Output gradient values for node features

    ! Local variables
    integer :: F_in, F_out, num_v, i, j, jj, edge_idx
    !! Inferred dimensions and traversal indices

    ! Infer dimensions from operands
    F_in  = size(this%left_operand%val, 1)
    F_out = size(upstream_grad, 1)
    num_v = size(this%left_operand%val, 2)

    output = 0.0_real32
    do i = 1, num_v
       do jj = this%indices(i), this%indices(i+1) - 1
          j = this%adj_ja(1, jj)
          edge_idx = this%adj_ja(2, jj)
          ! grad_h(j) += kappa_e^T @ upstream(:,i)
          ! kappa_e is [F_out*F_in] → reshape to [F_out, F_in]
          ! kappa_e^T is [F_in, F_out]
          output(:, j) = output(:, j) + &
               matmul( &
                    transpose(reshape( &
                         this%right_operand%val(:, edge_idx), [F_out, F_in])), &
                    upstream_grad(:, i) &
               )
       end do
    end do

  end subroutine get_partial_gno_agg_features_val