Add a layer to the network
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(network_type), | intent(inout) | :: | this |
Instance of network |
||
| class(base_layer_type), | intent(in) | :: | layer |
Layer to add to the network |
||
| integer, | intent(in), | optional, | dimension(:) | :: | input_list |
List of input layers |
| integer, | intent(in), | optional, | dimension(:) | :: | output_list |
List of output layers |
| class(*), | intent(in), | optional | :: | operator |
Operator to use to connect the layers |
module subroutine add(this, layer, input_list, output_list, operator) !! Add a layer to the network implicit none ! Arguments class(network_type), intent(inout) :: this !! Instance of network class(base_layer_type), intent(in) :: layer !! Layer to add to the network integer, dimension(:), optional, intent(in) :: input_list !! List of input layers integer, dimension(:), optional, intent(in) :: output_list !! List of output layers class(*), optional, intent(in) :: operator !! Operator to use to connect the layers ! Local variables integer :: i, vertex_index !! Loop index integer :: operator_ !! Operator to use to connect the layers character(256) :: err_msg !! Error message integer, dimension(2) :: vertex_indices !! Indices of the vertices to connect type(container_layer_type), allocatable, dimension(:) :: model !! Model to add the layer to if(.not.allocated(this%model))then this%model = [container_layer_type()] this%num_layers = 1 else allocate(model(size(this%model,dim=1)+1)) do i = 1, size(this%model,dim=1) allocate(model(i)%layer, source=this%model(i)%layer) end do call move_alloc(model, this%model) this%num_layers = this%num_layers + 1 end if allocate(this%model(size(this%model,dim=1))%layer, source=layer) this%model(size(this%model,dim=1))%layer%id = this%num_layers operator_ = 1 if(present(operator))then select type(operator) type is(integer) operator_ = operator type is(character(*)) select case(trim(to_lower(operator))) case("||", "concat", "concatenate", "append") operator_ = 1 case("+", "add") operator_ = 2 case("*", "x", "mul", "multiply") operator_ = 3 end select end select end if if(operator_.gt.2.or.operator_.lt.1)then call stop_program("invalid operator") return end if ! edge_index(1) = index of the previous layer ! abs(edge_index(2)) = index of the current layer ! the -ve sign of edge_index(2) indicates that the edge goes from the ! previous layer to the current layer ! i.e. forward pass flows from positive to negative ! adjacency(i,:) is all of the layers that i feeds forward to ! adjacency(:,i) is all of the layers that feed forward to i ! (i.e. the backward pass) this%auto_graph%directed = .true. call this%auto_graph%add_vertex( & feature=[1._real32], id=this%num_layers, update_adjacency=.true. & ) if(present(input_list))then do i = 1, size(input_list), 1 if(input_list(i).eq.0)then vertex_index = 0 elseif( & input_list(i).le.-this%auto_graph%num_vertices .or. & input_list(i).gt.this%auto_graph%num_vertices & )then write(err_msg, & '("input vertex index ",I0," out of range (",I0,":",I0,")")' & ) & input_list(i), & -this%auto_graph%num_vertices +1, & this%auto_graph%num_vertices call stop_program(err_msg) return elseif(input_list(i).lt.0)then vertex_index = this%auto_graph%num_vertices + input_list(i) else vertex_index = findloc( & [this%auto_graph%vertex(:)%id], & input_list(i), 1 & ) end if vertex_indices = [ vertex_index, -this%auto_graph%num_vertices ] call this%auto_graph%add_edge( & index = vertex_indices, & feature = [ 1._real32 ], & id = operator_, & update_adjacency = .true. & ) end do elseif(trim(layer%type).ne."inpt".and.this%auto_graph%num_vertices.gt.1)then vertex_indices = [ & this%auto_graph%num_vertices - 1, & -this%auto_graph%num_vertices & ] call this%auto_graph%add_edge( & index = vertex_indices, & feature = [ 1._real32 ], & id = operator_, & update_adjacency = .true. & ) end if if(present(output_list))then do i = 1, size(output_list), 1 vertex_index = findloc( & [this%auto_graph%vertex(:)%id], & output_list(i), 1 & ) vertex_indices = [ this%auto_graph%num_vertices, -vertex_index ] call this%auto_graph%add_edge( & index = vertex_indices, & feature = [ 1._real32 ], & id = operator_, & update_adjacency = .true. & ) end do end if end subroutine add